# Running PF & IPFW Together



## dk9322 (Nov 4, 2010)

I'm currently setting up a firewall that I absolutely need to use IPFW's pipe capabilities on. However, at some point in my ruleset, I'd like to be able to efficiently process large IP lists, which pf certainly excels at. An added of bonus of PF, would be full packet monitoring capability of logged packets via the pflog interface as opposed to IPFW's syslog out. 

I'm wondering if it's possible to run both IPFW and PF (FreeBSD 8.x) simultaneously, passing off traffic from one to the other. I feel like this would give me the benefit of both of these great firewalls. Like I said my primary needs are IPFW's piping and large IP lists, where blocked packet capture/analysis is a bonus.

I understand there were some changes in 8.x, and was also wondering how they've affected the performance of both these firewalls, and if there's any general on advice on avoiding one or the other?

Thanks in advance!


----------



## phoenix (Nov 5, 2010)

IPFW supports tables, which allows you to quickly compare against large numbers of IPs.  Similar to how PF works with lists.  Tables can be updated without reloading the rules, as well.

IPFW in 8.1 (or maybe 8.0?) or newer also supports logging via the *ipfw0* pseudo-interface, exactly like how pflog0 works.

IOW, why use PF?  Everything you need is already there in ipfw(8).


----------



## DutchDaemon (Nov 5, 2010)

The way ipfw works with IP lists is still quite ancient, isn't it? Or has this improved by now as well? Last thing I saw was still all manual: http://forums.freebsd.org/showthread.php?t=5896 - so no IP lists in files which can be addressed directly, no in-memory editing of IP lists, etc.


----------



## phoenix (Nov 5, 2010)

You can't pass it a file with IPs in it.  However, you can use a script to populate a table, which is almost the same thing.  And you most certainly can edit a table at run-time, without affecting the ruleset currently loaded.

For example, here's how we use tables:

```
#!/bin/sh

# Pull in the global config file
. ./firewall.conf


# Clear out all existing tables
for I in $BAD_SITES $BANNED_IPS $PRIV_NETS $SD_NETS $VIDCONF_NETS $ELLUMINATE_IPS $FIRSTCLASS_IPS $MINED_IPS $CVSUP_IPS $WEBCT_IPS $FTP_IPS; do
        $IPFW table $I flush
done


# Populate the tables

### Block all access to these sites (in/out)
# kproxy.com
$IPFW table $BAD_SITES add 69.46.17.168
$IPFW table $BAD_SITES add 62.193.226.74
$IPFW table $BAD_SITES add 62.193.235.46
$IPFW table $BAD_SITES add 62.193.236.96
$IPFW table $BAD_SITES add 62.193.236.100
$IPFW table $BAD_SITES add 62.193.245.234
$IPFW table $BAD_SITES add 62.193.249.41
$IPFW table $BAD_SITES add 66.232.102.157
$IPFW table $BAD_SITES add 66.232.107.140
$IPFW table $BAD_SITES add 66.232.113.212
$IPFW table $BAD_SITES add 66.232.117.243
$IPFW table $BAD_SITES add 66.232.118.93
$IPFW table $BAD_SITES add 66.232.118.195
$IPFW table $BAD_SITES add 66.232.118.237

# Facebook
$IPFW table $BAD_SITES add 69.63.176.10
$IPFW table $BAD_SITES add 69.63.176.11
$IPFW table $BAD_SITES add 69.63.176.139
$IPFW table $BAD_SITES add 69.63.176.140
$IPFW table $BAD_SITES add 69.63.178.11 
$IPFW table $BAD_SITES add 69.63.181.11
$IPFW table $BAD_SITES add 69.63.181.12
$IPFW table $BAD_SITES add 69.63.184.29 
$IPFW table $BAD_SITES add 69.63.184.142
$IPFW table $BAD_SITES add 69.63.184.143
$IPFW table $BAD_SITES add 69.63.186.11 
$IPFW table $BAD_SITES add 69.63.187.16
$IPFW table $BAD_SITES add 69.63.187.17
$IPFW table $BAD_SITES add 69.63.187.18
$IPFW table $BAD_SITES add 69.63.187.19
$IPFW table $BAD_SITES add 63.135.80.49
$IPFW table $BAD_SITES add 92.48.78.50
$IPFW table $BAD_SITES add 204.15.20.80
$IPFW table $BAD_SITES add 206.220.43.92
$IPFW table $BAD_SITES add 216.178.38.116
<snip long list of tables, IPs, and subnets>
```
firewall.conf, among other things, assigns the table numbers to variables, and tables.sh (above) uses the variable names.  tables.sh (along with separate scripts for each server with a public IP) is called by our firewall.sh, but it can be run manually at any time.  Just edit the file, run `# ./tables.sh` and the tables are all reloaded in memory, without editing any of the IPFW rules.

firewall.sh has rules similar to:

```
# These stations should not access the Internet
$IPFW add 2 unreach host log ip from table\($BANNED_IPS\) to any in  recv $PRIVATE
$IPFW add 2 unreach host log ip from any to table\($BANNED_IPS\) out xmit $PRIVATE

# No one should be able to access these sites on the Internet
$IPFW add 3 unreach host log ip from table\($BAD_SITES\) to any in  recv $PUBLIC
$IPFW add 3 unreach host log ip from any to table\($BAD_SITES\) in  recv $PRIVATE
```


----------



## dk9322 (Nov 5, 2010)

Great news on the new ipfw0 pseudo interface logging feature. I'll move forward with testing that my environment. Does any know if there are still caveats with this or divert in bridged environments? 

In regards to the IP lists, according to phoneix's ipfw link above, the lookup tables use FreeBSD routing table method (radix tree). However, I'm not sure if this is new/improved behavior or not.


----------

