IP Filter and FreeBSD
IPF is a very robust firewall included in FreeBSD by default. This is a statefull firewall with logging capabilities that can also be used to NAT a local network in situations where the FreeBSD box is the router. The best way to get IPF working is to compile the kernel with support built in. Although the default kernel has support through the use of loadable modules, compiling the options into the kernel provide a more flexible and robust system.
The first thing you want to do is download the FreeBSD source. This can be done by using the ports tree to install cvsup, and modifying the standard-supfile for your release. Once this is done you can run the following command:
cvsup �g �L2 ./standard-supfile
Once the source tree is installed you will want to add the options to the kernel source.
#cd /usr/src/sys/conf/i386/
ee ./GENERIC
You will want to add the following line for a secure and efficient? IPF installation.
options IPFILTER
#turn on support for
IP Filter options
IPFILTER_LOG
#Turn on logging by default options
IPFILTER_DEFAULT_BLOCK
#change state from default allow to default block
The last command is very important as it tells the kernel to drop all packets on all interfaces by default. This means that you will have to explicitly allow all packets, even on loopback interfaces like LO
After these commands are entered and the file is saved you can compile the kernel by using the following commands
#cd /usr/src
#make buildkernel KERNCONF=GENERIC
#make installkernel
#shutdown �r now
Once the machine reboots you will have to edit the rc.conf file in order to set some configuration settings for IPF.
#ee /etc/rc.conf
ipfilter_enable=“YES”
Start ipf firewall
ipfilter_rules="/etc/ipf.rules"
loads rules definition text file
ipmon_enable=“YES”
Start IP monitor
logipmon_flags="-Ds"
D = start as daemon
s = log to syslog
v = log tcp window, ack, seq
n = map IP & port to names
If you have a LAN behind this firewall that uses the reserved private IP address ranges, then you need to add the following to enable NAT functionality:
gateway_enable=“YES”
Enable as LAN gateway
ipnat_enable=“YES”
Start ipnat function
ipnat_rules="/etc/ipnat.rules"
rules definition file for ipnat
Now it is time to look at a sample firewall rule file and see how IP Filter works. ? On a system with 1 network card, such as a web server or such.
#cat /etc/ipf.rules
#######################
##loop back interface, do not restrict this interface it will break system!!!#####
pass out quick on lo0
pass in quick on lo0
###interface rl0 internet and lan interface#####
Pass in quick on rl0
#needed because of implicit block in kernel
block in on rl0
#without the quick command it will match this rule but check to see if it matches others
block in quick on rl0 from 192.168.0.0/16 to any
#anti spoofing do not to use this if nic is on lan also
block in quick on rl0 from 172.16.0.0/12 to any
#anti spoofing do not to use this if nic is on lan also
block in quick on rl0 from 10.0.0.0/8 to any
#anti spoofing remember not to use this if nic is on lan also
block in log quick on rl0 from 127.0.0.0/8 to any
#anti spoofing loopback network
block in log quick on rl0 from 20.20.20.0/24 to any #anti ? spoofing
block in log quick on rl0 from any to 20.20.20.0/32 #anti spoofing
block in log quick on rl0 from any to 20.20.20.255/32 #anti� spoofing
pass out quick on rl0 proto tcp from 10.0.0.1 to any keep state
pass out quick on rl0 proto udp from 10.0.0.1 to any keep state
pass out quick on rl0 proto icmp from 10.0.0.1 to any keep state
#################################################
Now let�s break this file down one line at a time to understand what is does. Remember that we used the default block all command when we recompiled the kernel. This is secure by default because it operated on the bases that everything is blocked unless we specifically let in a packet or protocol. The first thing we have to do is tell IP Filter that it should allow everything in and out of the lo interface. Lo is the loopback interface and is used for interproccess communication. Lo is always 127.0.0.1.
pass out quick on lo0
pass in quick on lo0
The above two commands? allow traffic to flow freely in and out of the loopback interface. Let me ask you a question for the sake of learning. Look at the rules below and think about what you think will happen when a user tries to connect to this web server.
Block in on rl0 proto tcp from any to any>
Pass in on rl0 proto tcp from any to any port = 80
Now if you are familiar with Cisco access-lists and other similar firewalls you may have said: the packet is a web request packet, a syn packet to be precise. This packet will match the first rule and be dropped since all www packets are tcp.
Won�t you be surprised when the packet skips on past the first rule and connects to your web server. In IPF a packet?is evaluated against 1 rule at a time from top to bottom. But the fate of the packet is decided based on the last rule it matches. If you want a packet to match only a single rule and be passed or dropped, you need to add the keyword quick to your command. Such as �
pass out quick on lo0
pass in quick on lo0
Now you may ask �Why would this behavior be useful?� This behavior is useful for many situations but let�s consider one example. In this example the computer the firewall is protecting is a FreeBSD desktop computer which hosts� not services. So we want to block all incoming packets that have no state table entry(more on state tables later). In order to do this you have the following rule.
block in quick on rl0
The above command will work however it will not give you any information about the packet that was dropped. Now say for example you want to block all unsolicited packets but you also want to log any packets that are trying to carry out a spoof attack on your network. In this case the following commands would be more useful.
block in on rl0
block in log quick on rl0 from 127.0.0.0/8 to any
#anti spoofing loopback network
In this situation the packet will be dropped but if the packet is a packet from the internet masquerading as a loopback packet it will be dropped and logged. This is why this behavior is so important, because it gives you the flexibility to have more control over your firewall with a minimum of effort.
Keep State
Now you will notice in our example config file above we had blocked all incoming connections. You may be asking yourself? how the config works if every reply coming back is blocked. The key to that config working is in the keep state keyword. Let�s take a look at the following snippet of code:
pass out quick on rl0 proto tcp from 10.0.0.1 to any keep state
pass out quick on rl0 proto udp from 10.0.0.1 to any keep state
pass out quick on rl0 proto icmp from 10.0.0.1 to any keep state
You will notice in the above code that we allow all tcp, udp, and icmp packets to go to the internet. The important part of the above commands is the keep state command. What this does is tell the computer to track that tcp session and keep a table of all outgoing requests. When the packet hits the interface which is a reply to a session which we opened up. The computer will dynamically add a rule to allow this tcp stream to enter the computer. In this way all unsolicited ? packets are dropped except those packets responding to requests initiated by you.
Now let�s say that you want to host an apache web server on your desktop for testing purposes. It is very simple to modify the? config to allow incoming connections by adding the following line
Pass in quick on rl0 proto tcp from any to any port = 80 flags S keep state
Just make sure this line goes above the block in lines so that it is processed first to make sure that packet goes through. It is important to remember that this command can be modifies for any service you want to run. Here are some examples below
Pass in quick on rl0 proto udp from any to any port = 53 keep state
#dns server
Pass in quick on rl0 proto tcp from any to any port = 22 flags S keep state
It is also important to note that the flags S command only allows in lone syn flags on packets. What this means is that it will only let in the initial connection request not just any packet that is part of a stream. This helps protect against man in the middle attacks as well as keep packets that will be dropped from taking up resources in your tcp stack.
Back to blocking ports, there is one keyword that can help us increase the stealth of our firewall. In a typical exchange when a packet is blocked we decrement the TTL like the RFC�s say we should. But what this does is show that there is a hop here and it announces to the world that we exist. Instead of using the above rule we could rewrite it such that it does not decrement the TTL of the packet. To the rest of the world it looks as if the computer does not exist.
We can do this by changing the following commands from
block in on rl0
block in log quick on rl0 from 127.0.0.0/8 to any
#anti spoofing loopback network
to
block in on rl0
block in log quick on rl0 fastroute from 127.0.0.0/8 to any
#anti spoofing loopback network?
Notice I added the Fastroute keyword. This tells the firewall not to decrement TTL of a packet when it is blocked.
Now let me show you how to activate the rule set for IPF once you have created your file. To activate a rule set issue the following command.
The ipf command is used to load your rules file. Normally you create a file containing your custom rules and use this command to replace in mass the currently running firewall internal rules:
ipf -Fa -f /etc/ipf.rules
-Fa means flush all internal rules tables.
-f means this is the file to read for the rules to load.
This gives you the ability to make changes to your custom rules file, run the above IPF command, and thus update the running firewall with a fresh copy of all the rules without having to reboot the system. This method is very convenient for testing new rules as the procedure can be executed as many times as needed.
This is just a basic introduction to IPF rules. There are many more techniques and things that can be done such as rule groups which can speed up the rule processing on large access-lists. And variable substitution which can help make writing complex rules sets easy. I will cover NAT and the various commands to monitor the firewall such as ipfstat in another installment of the how-to. I hope you enjoyed it!