# PF check state of network interface ?



## scavern (Sep 2, 2009)

I have two external interfaces configured in my PF rules. One of them is for an DSL link, the other for a diginet link. 

In a normal state, ie. when both links are working outbound RDP traffic is routed over the diginet link. 

Is it possible for me to configure PF to route RDP traffic over the DSL link when the diginet link is down and vice versa ?

I should also point out that the interface will always show as being up - so the only way to really check is to ping the diginet router at the other endpoint.

Any suggestions ?


----------



## vivek (Sep 2, 2009)

Two solutions comes in mind. First, write a custom script that will ping and if link is down update pf rules. Another and recommend is failover using pfsync and CARP. However, CRAP is more useful for firewall failover and I often used as dual firewall combination. 3rd option is pfsense.


----------



## DutchDaemon (Sep 2, 2009)

Maybe lagg(4) too, unless you want to keep those connections entirely separated.


----------



## scavern (Sep 2, 2009)

I'm curious about the first option - how do I update the pf rules ? Would that not need multiple copies of the same set of firewall rules ?


----------



## DutchDaemon (Sep 2, 2009)

You don't need different sets of rules. Just put the 'next hop / gateway' address for the RDP traffic in a table and update the table dynamically with 'pfctl -t table-name -Tr', executed by the check script. The pf rule itself (containing the call to that table) never needs changing, and the ruleset never needs reloading. See pfctl(8) for particulars about tables.


----------



## scavern (Sep 2, 2009)

I have been using tables - although clearly not to it's full potential.

Am I correct in saying that the syntax is 
	
	



```
pfctl -t <table_name> -Tr <ip_address>
```

This is an example of a policy rule I have in place:


```
pass out route-to ( $int_if $diginet ) proto tcp from { $app_server } port 3389 to $development_lan keep state

$int_if  = internal lan ip of freebsd server
$diginet = ip of diginet router, connected to the lan
$app_server = w2k3 application server
$development_lan = development lan - in another city
```

This 'forces' RDP traffic from the application server to use the diginet interface if the destination is the development lan. Normally what I would do is comment this rule out if there was a problem with the diginet - traffic would then go over the default gateway (which is the DSL).


----------



## DutchDaemon (Sep 3, 2009)

Syntax is correct, yes:


```
# pfctl -t bla -Ta 123.123.123.123
1/1 addresses added.

# pfctl -t bla -Ts
   123.123.123.123

# pfctl -t bla -Tr 234.234.234.234
1 addresses added.
1 addresses deleted.

# pfctl -t bla -Ts
   234.234.234.234
```


----------



## DutchDaemon (Sep 3, 2009)

You could simply make a pf.conf and a pf.conf.nodiginet (an exact copy of pf.conf, minus that one rule) and have the script tell pfctl which ruleset to load with the -f switch. There's always more than one way .. It just needs a bit of clever scripting.


----------



## DutchDaemon (Sep 3, 2009)

In fact, I think tables cannot be used for this, because they're only meant for lookups ('is this ip in this table, yes/no?'). You can't use them like a $variable and just cull the IP address from it. So using alternate pf.conf files would be the best avenue to take, unless you want to play around with sed to replace lines or assign new IP addresses to variables. Just switching the config files would be the KISS thing to do, I think.


----------



## scavern (Sep 3, 2009)

I'm trying to avoid multiple pf.conf files.. because that means if any changes need to be made, it needs to be made to each file.


----------



## DutchDaemon (Sep 3, 2009)

Untested, just a wild idea:

Make $diginet a local hostname, and put its hostname and IP address in /etc/hosts. Have the ping script alter the IP address for that hostname in /etc/hosts when the routing needs to change, and then reload pf. It should pick up the new IP address (pf only resolves hostnames on startup). Not sure it can be done this way (will pf actually use hosts?), but it's something to try. This is assuming that you can use the IP address of either gateway as the next hop for your route-to statement.


----------

