IPFilter on OpenBSDby Mike DeGraw-Bertsch
Have a new wireless gateway set up for your community, but don't want the local script kiddies on your network? Maybe you've just set up your new broadband connection and want to protect your LAN. Or maybe you simply want to deny access to all but a few ports on your PC. There are many potential solutions, ranging from an expensive Cisco PIX firewall to the cheap-and-scary, hope-and-pray solution. A great compromise that provides security and peace of mind while going easy on the pocketbook is OpenBSD running IPFilter.
What is IPFilter? Very simply, a package for permitting (or passing) and denying IP packets based on a range of criteria. It can also provide Network Address Translation (NAT) services, if desired. The IPFilter web site has more details.
The available rules range from quite simple -- for example, deny all traffic on any interface; to relatively complex -- pass and log all ICMP traffic of type
ICMP-QUERY from the
188.8.131.52/29 subnet on interface
fxp0. Each rule is one-way only, meaning you can block inbound HTTP requests without disrupting outbound requests. When bridging two cards together, OpenBSD's bridge device only checks incoming filter rules. Bidirectional rules are easily created by setting the inbound rules on the other NIC.
How do you start?
First, get a machine running OpenBSD. Any ol' 486 or even 386 will do. The IPFilter package was removed from the source code on May 30th, 2001, so you'll need an earlier build than that. However, it was replaced by PF, the OpenBSD packet filter, which was designed to be syntactically compatible to IPFilter so most of this document will still apply. Although IPFilter has been removed from OpenBSD, it is still in use by FreeBSD and NetBSD.
You'll also need two network cards. A secure firewall or bridge cannot be built with only one network card. However, you are not limited to just two network cards. IPFilter scales to meet your needs.
When building the OpenBSD kernel, be sure to include
option IPFILTER in the configuration file. If you wish to log actual IP packets, also include
option IPFILTER_LOG. This is useful when combined with the
ipmon utility, which logs packets from
/dev/ipl. If you want to build your own Carnivore, this is where to start.
Share your experiences using IPFilter.
With OpenBSD, it's possible to create an invisible bridging firewall. It will act as a filter and firewall, yet won't decrement the TTL on packets passed through it. This makes it invisible to outsiders. It doesn't even have to have IP addresses assigned to its network cards.
/etc/rc.conf to include the line
ipfilter=YES. For NAT support, you'll also need
ipnat=YES. The example below does not address NAT, which is generally evil and bad.
Your network cards will not need to have an IP address, but you can set this up, if desired. For example, on a
system with two Intel EtherExpress cards,
the files may look like:
/etc/hostname.fxp0 inet 184.108.40.206 255.255.255.248 /etc/hostname.fxp1 media 10BaseT up
Now set up a bridge between the two NICs. Do this by creating
add fxp0 add fxp1 up
thus linking the two devices, creating a transparent firewall that you are able to access remotely. This is very convenient if you don't have a spare monitor or a KVM switch.
You're now ready to start configuring your firewall! We'll discuss the rules and options available to you below.
Setting up the rules
By default, your firewall rules live in
/etc/ipf.rules. There are a number of example configurations provided in
/usr/share/ipf/examples/. We'll look line-by-line at a slightly modified version of
/usr/share/ipf/examples/firewall.2. The modifications allow access to the firewall box via SSh, and will be noted below.
pass out from any to any pass in from any to any
IP filter rules work on a last-matched basis (unless
quick is specified -- more on that below). Therefore, any packet that does not match an upcoming rule is accepted by these two rules.
block in log quick on fxp0 proto icmp from any to any icmp-type redir
block in log quick on fxp0 proto tcp/udp all with short
block in log quick on fxp0 from any to any with ipopts
Any packet coming in on interface
fxp0 (which is connected to the Internet) is immediately
blocked and logged if it is an ICMP redirect request, an IP fragment that won't allow the
filter to examine the header, or if it contains IP options.
block in log quick on fxp0 from 220.127.116.11/29 to any block in log quick on fxp0 from localhost to any block in log quick on fxp0 from 0.0.0.0/32 to any block in log quick on fxp0 from 255.255.255.255/32 to any
Block and log IP spoofing attempts to match packets coming from outside the firewall that claim to be "from" a machine that's behind this firewall, localhost,
block in log quick from 10.0.0.0/8 to any group 100 block in log quick from 192.168.0.0/16 to any group 100 block in log quick from 172.16.0.0/12 to any group 100
Further IP spoofing rulesets match any packet "originating" from a reserved address block.
block in log quick on fxp1 from any to 18.104.22.168/29
Don't allow the firewall to talk to any of the machines it protects, or them to talk to it. This provides less of a beachhead if one machine is cracked, and won't prevent other machines behind the firewall from talking to each other, as they're connected by a switch or hub.
block in on fxp0 proto udp from any to any block in log on fxp0 proto udp from any to any port = sunrpc block in log on fxp0 proto udp from any to any port = 2049 pass in on fxp0 proto udp from any to any port = domain
Block all UDP traffic from the Internet except DNS. If the UDP traffic is an NFS or portmap request, block it and log it. Again, the last matched rule wins, so the
pass...domain line ensures that DNS traffic gets through.
block return-rst in log on fxp0 proto tcp from any to any flags S/SA
block return-rst in on fxp0 proto tcp from any to any port = auth flags S/SA
You will also need to lock and log all incoming TCP setup requests. Because
ident requests are so frequent,
they are blocked but not logged.
pass in on fxp0 proto tcp from any to any port = domain
pass in on fxp0 proto tcp from any to 22.214.171.124 port = smtp
pass in on fxp0 proto tcp from any to 126.96.36.199 port = www
pass in on fxp0 proto tcp from any to 188.8.131.52 port = ssh
pass in on fxp0 proto tcp from any to 184.108.40.206 port = ssh
Finally, allow DNS traffic to any machine; web and SMTP traffic to
220.127.116.11; and SSh to both
IPFilter on OpenBSD provides a simple, effective method of building a firewall. The hardware requirements are minimal, and the protection provided is well worth the already low costs. The rulesets are very easy to read and look very much like English.
Mike DeGraw-Bertsch is a security and Unix system administration consultant in the Boston, Mass. area. When he's not at a job, writing, hacking with Perl, or playing with his wireless network, he can usually be found playing goal in ice hockey.
Return to ONLamp.com.