The FreeBSD Diary

The FreeBSD Diary (TM)

Providing practical examples since 1998

If you buy from Amazon USA, please support us by using this link.
[ HOME | TOPICS | INDEX | WEB RESOURCES | BOOKS | CONTRIBUTE | SEARCH | FEEDBACK | FAQ | FORUMS ]
IP Filter - an alternative firewall and NAT to ipfw/natd 23 October 1998
Need more help on this topic? Click here
This article has 1 comment
Show me similar articles
This article is now outdated.  For FreeBSD 3.* and ipf 3.3.3, see Installing IP Filter 3.3.3

See also IP Filter - second time around and Adding ipnat to FreeBSD 3.*.

You may have seen the problems I was having with natd and ipfw.   It was suggested by by Darren Reed that I drop ipfw/natd and try IP Filter.  I decided to do so.  For a trial at least.  It should also be mentioned that Darren is the author of IP Filter.

IP Filter
The main webpage is http://coombs.anu.edu.au/~avalon/.   See their list of mirrors for the latest source.  It basically does the same thing as the natd and ipfw combination, but it seems to do it better.   This is based solely upon my first impressions.  However, like most ports, the documentation on how to install it is minimal and open to some interpretation.  I have listed the steps I took.  Hopefully, they'll work for you too.

Installation | NAT | Removing natd/ipfw | Adding Rules | Conclusions

One of the best how-to guides for ipfilter is at:

http://www.obfuscation.org/ipf/

I followed the instructions supplied in INST.FreeBSD-2.2 and used the LKM (Loadable Kernel Module) option as the other option (kernel install) is unsupported.

You will be installing a new kernel.  I named my new kernel IPFILTER.   You may wish to name your kernel something else.  Keep that in mind when you see IPFILTER.

obtain the source
As mentioned above, use the http://coombs.anu.edu.au/~avalon/ site to obtain your source code.  I downloaded my file and place it in the /usr/ports/net directory.  Then I did the following to uncompress and extract the files:
  1. cd /usr/ports/net
  2. gunzip ip-fil3.2.9.tgz
  3. tar -xvf ip-fil3.2.9.tar
  4. cd ip_fil3.2.9
prepare a kernel
Prepare, but don't yet compile a new kernel.  Follow these steps to do this:
  1. cd /usr/src/sys/i386/conf/
  2. cp GENERIC IPFILTER
  3. /usr/sbin/config IPFILTER

We will compile this kernel later on.  The above steps merely create the kernel file which will be modified by the  IP Filter make.

make IP Filter
  1. cd /usr/ports/net/ip_fil3.2.9
  2. make freebsd22 IPFILKERN=IPFILTER
  3. make install-bsd
  4. FreeBSD-2.2/minstall

Step 3 may have to be done as root.  Step 4 must be done as root.

build a new kernel
You should now build the kernel you prepared above.
  1. cd /usr/src/sys/i386/conf/
  2. /usr/sbin/config IPFILTER
  3. cd ../../compile/IPFILTER
  4. make depend
  5. make
  6. make install
reboot to install the kernel
In order for the kernel to be installed, you need to reboot.  This command will do it for you:

shutdown -r now

load the module
After the new kernel boots, issue the following command to load the module:
su-2.02# modload /lkm/if_ipl.o
Module loaded as ID 0

su-2.02# modstat
Type     Id Off Loadaddr Size Info     Rev Module Name
DEV       0  79 f3c86000 0031 f3c90248   1 IP Filter v3.2.9
su-2.02# 
For a definition of NAT, see Network Address Translation.   I've summarized what I did based on the instructions supplied in the file  NAT.FreeBSD.   The following numbered sections are extracted from that file.  Please refer to the next section for a list of other steps I performed which were not included in the instructions.

NOTE: The instructions supplied with IP Filter make reference to /etc/sysconfig which has been replaced by /etc/rc.conf.

1. Load the kernel module
We did this manually above.  In order for it to run at boot-time, you should add the following line to /etc/rc.local (NOTE:  /etc/rc.local is deprecated; use /usr/local/etc/rc.d/ instead; see Starting stuff at boot time and Installing IP Filter 3.3.3 for an example):

modload /lkm/if_ipl.o

2. Setting up the NAT Rules
Rules for IP Filter are stored in the file /etc/ipnat.conf.  I took what I found in /usr/ports/net/ip_fil3.2.9/rules/nat-setup as the basis for my NAT rules.  Here they are (these may or my not be my real numbers):
map ed0 10.1.0.0/16 -> 209.23.1.5/32 portmap tcp/udp 10000:40000
map ed0 10.1.0.0/16 -> 209.23.1.5/32

Please note that the above example differs from that supplied in the file.  The second line does not contain the portmap keyword.  I could not get the rules to load otherwise.

3. Loading the NAT Rules
The above rules need to be loaded everytime the computer reboots.  This can be done by putting the following line in /etc/rc.local (NOTE:  /etc/rc.local is deprecated; use /usr/local/etc/rc.d/ instead; see Starting stuff at boot time and Installing IP Filter 3.3.3 for an example):
ipnat -f /etc/ipnat.conf

You can view the loaded rules by issuing the following command:

ipnat -ls

I have also supplied my NAT rules for those that may need an example.

As for your firewall rules, I suggest you start with the contents of the Rules directory and use either BASIC_1.FW or BASIC_1.FW as the basis for your rule set.  Also note that BNF contains the rule syntax.

4. Enable Routing between interfaces
The instructions say you should do this:

sysctl -w net.inet.ip.forwarding=1

But you can achieve the same thing by using /etc/rc.conf.  Look for the following section and ensure that the values are as shown.

### Network routing options: ###
gateway_enable=YES
5. Static Routes to Subnet Ranges
The instructions want you to set up the following routes.  I didn't do this and it still worked.  I'm not sure what I'm missing.
static_routes="foo"
route_foo="10.0.0.0 -netmask 0xf0000000 -interface 10.0.0.1"
6. Make sure that you have your interfaces configured
In /etc/rc.conf, you should have someething which looks like this:
network_interfaces="fxp0 fxp1"
ifconfig_fxp0="inet 208.8.0.1 netmask 255.255.255.0"
ifconfig_fxp1="inet 10.0.0.1 netmask 255.0.0.0"
Prior to installing IP Filter, I was running ipfw and natd.   My first attempt failed.  I think it was because I was still running those programs.  So I made the following changes in order to get IP Filter running.
  1. removed the "options IPFIREWALL" and "options IPDIVERT" from my kernel.
  2. changed firewall_enable=YES to  firewall_enable=NO in /etc/rc.conf.
The IP Filter examples are highly recommended reading.  Of note are the sections on NAT and Rule Groups.  In short, if you do this, you will Flush existing rules and add the rules contained in the /etc/ipfrules:
ipf -Fa -f /etc/ipfrules

TIP: Another good thing to try is to add the rules, wait a bit, then restore the original rules.  This ensure that you haven't locked yourself out of your box.   This is very useful when working remotely. 

ipf -I -Fa -f /etc/ipfrules 

ipfilter has two rule lists, the active list and the inactive list.  ipfilter always works against the active list.  The options in the line above, as taken from the man ipf page are:

-I     Set the list to make changes to the inactive list.

-F     This option specifies which filter list  to  flush.
       The  parameter  should  either  be "i" (input), "o"
       (output) or "a" (remove all filter rules).   Either
       a single letter or an entire word starting with the
       appropriate letter maybe used.  This  option  maybe
       before,  or  after, any other with the order on the
       command line being that used to execute options.
-f <filename>    This option specifies which files ipf should use to
       get input from for modifying the packet filter rule
       lists.

So the above command tells ipfilter to load your rules into the inactive list but first flushes any rules which were already there.

ipf -s; sleep 10; ipf -s

The following man page extract explains the above command.

    -s     Swap the active  filter  list  in  use  to  be  the
           "other" one.

The above command line tells ipfilter to swap the active and inactive list.  This invokes the rules you added with the first command.  It then tells the system to sleep for 10 seconds.  You should type a few characters and see if they are echoed.   If they are, you haven't locked yourself out of the system.  But just in case you have, the next command tells ipfilter to swap the active/inactive lists again.   This puts you right back where you were before.

Rule Groups
The concept of a rule group is at the heart of understanding how IP Filter works.  Rules can be grouped together according to logical function.  The documentation also states that groups make for more efficient rule processing.

Each group is identified by a unique group number.  A new group is created by including a head statement such as the following:

block in log on ed0 all head 100

The above rule declares that all incoming packets on ed0 will be processed using group 100.  The default action for this group is to block all.  Note: that only packets which match the above rule will be processed by rules in group 100.

If we wish to allow people to access our webserver, we would add a rule which looks like this.

pass in quick proto tcp from any to any port = WWW keep state 
                                                          group 100
Default rules
IP Filter comes with a script which will create some default blocking rules for you.  Read rules/firewall for details. Here's what I did to invoke those rules:
  1. cd /usr/ports/net/ip_fil3.2.9
  2. ./mkfilters > rules/mkfilter_rules
  3. ipf -f rules/mkfilter_rules

To view the rules, try the following:

ipfstat -hio
Firewall rules
But for real protection, you want the firewall rules.  I started with the ones provided in rules/BASIC_1.FW.  Then I moved to rules/BASIC_1.FW because I couldn't get some of my services to run.  I struggled for 2 days trying to get traceroute to work.  I gave up.

(see below for additional information).

These conclusions are based on 3 days of working with IP Filter.  I have no doubt they are biased and based upon my lack of experience with both the product and Unix.  I like IP Filter.  It loads rules much faster than ipfw.   And the concept and use of rule groups is quite good.  For a commercial environment, I think IP Filter would be better than ipfw.  I also feel that better protection can be obtained by using IP Filter.

I found it very difficult to find out how to load rules, display the rules, and view the accounting statistics.  Once you know the commands, they are easy to do.   That said, I found it difficult to obtain this information from the documentation.  Hopefully, the information I've provided above will help. 

See the notes below for more information

traceroute solved 9 November 1998
I've been using the latest beta of IP Filter and doing some testing with the help of the author.  Darren has fixed the trace problem I initially encountered.   The utility I was using to do a trace used short packets which were being removed by the block in log quick all with short rule.  This fix will be available with IP Filter 3.2.10.
some block packets 15 November 1998
I am now using IP Filter for my firewall.  The only outstanding problem is related to packets which are being blocked.  I'll have to investigate this further now that I know how to interpret the information in the log..
Tip for updating your rule set remotely 16 November 2000
When you are changing your rule set, there is always the chance that you will lock yourself out of your box.  That's OK if you're at the console, or if you can just walk over and reset things.  But that's not very nice if the box is several hours away by car or plane.  So here's a tip on how to change the rule set, do a short test, and make sure you're not locked out.  This tip came to me from David S. Madole of Optimized Micro Devices back in April 1999 via the ipfilter mailing list, but that message is still in my mailbox.
modify /etc/ipfrules
ipf -I -Fa -f /etc/ipfrules
ipf -s; sleep 10; ipf -s

In this example, you modify the rules.  Then you load those rules into the inactive rule set.  Then you swap the rule sets, wait 10 seconds, then swap them back.  During that ten seconds, you can type a few characters to make sure you get echoes, then type ^C.

Hope this helps.


Need more help on this topic? Click here
This article has 1 comment
Show me similar articles