Chapter 3. Configuring IPFILTER

Table of Contents

3.1. Introduction
3.2. Understanding The ipf.conf File
3.3. The Syntax
3.3.1. The quick Keyword
3.3.2. The proto Keyword
3.3.3. The port Keyword
3.3.4. The keep state Keyword
3.4. Example Entries
3.4.1. Blocking Reserved & Local Machine Addresses
3.4.2. Paranoia Block
3.4.3. Make the Firewall Act like an Internet Client
3.4.4. Passing the Rest
3.5. IP Filter for Dial Ups

3.1. Introduction

NetBSD ships with IPfilter as its default firewall and packet filtering software.

3.2. Understanding The ipf.conf File

The file that controls firewall rules for ipfilter is /etc/ipf.conf for IPv4 and /etc/ipf6.conf for IPv6. In this section we will go over the settings we need and how I chose to implement them. However, by far the most authoritative document(s) concerning how ipfilter works can be found at http://www.obfuscation.org/ipf/ in a variety of formats.

Basically ipfilter operates on two basic principles:

  1. match the current line

  2. the last line supersedes previous ones

Following is a very rudimentary ipf.conf file:

pass in on any all
block in on any all

According to the first line, on any interface, all traffic may be passed. On the second line, however, all traffic on any interface is blocked.

3.3. The Syntax

For the most part, ipfilter syntax is generally easy to follow, it is almost natural. To pass in certain traffic, one says pass in, to pass out, pass out. The interface can be specified or it can be all by saying something like:

pass out on all . . .

If one wanted to specify the interface:

pass out on ep0 . . .

So far so good, now lets look at the configuration we need for our firewall, first we already know we want SSH traffic to be able to pass and connect:

# sshd in from any
pass in quick on ep0 proto tcp from any to 216.68.250.60/32 port = 22 keep state

You have probably already noticed some very new syntax here, let us take a look at that now before we go any further.

3.3.1. The quick Keyword

The quick keyword overrides any previous settings. It is most convenient when large and complex firewalls are built with up to 100 rules in them. In our case it is not so, however, we are including to be absolutely sure that the rule will be processed.

3.3.2. The proto Keyword

The proto keyword dictates, you guessed it, the protocol. In the case of this firewall the protocol is always TCP.

3.3.3. The port Keyword

The port keyword can be either the port number or the name as defined in /etc/services, for posterity I have mixed and matched in this file.

3.3.4. The keep state Keyword

The keep state keywords ensure packet checking from end to end within the firewall and here is why, if you look closely at all of the rules, they all use the quick keyword, so they circumvent previous rules and hence checking on both sides of the firewall may not take place.

3.4. Example Entries

Now lets look at the rest of the file in sections since we have a slightly better idea of what we are looking at.

3.4.1. Blocking Reserved & Local Machine Addresses

There are certain address classes we already know should not pass at all through our firewall. The addresses are those specified as internal only addresses and the localhost address (not the interface addresses):

  • 127.0.0.0/8 (the localhost)

  • 192.168.0.0/16 (reserved for internal networks)

  • 172.16.0.0/12 (reserved for internal networks)

  • 10.0.0.0/8 (reserved for internal networks)

  • 169.254.0.0/16 (IANA use)

  • 192.0.2.0/24 (netblock for documentation authors)

  • 204.152.64.0/23 (Sun Microsystems cluster interconnects)

  • 224.0.0.0/3 (class D and E multicasts)

It is important to note here that on one interface, fxp0, we want to be able to pass in and out on the 172.16.0.0 network (since our internal network is 172.16..0.0). To do this we can use the following rules:

block in quick on any from 192.168.0.0/16 to any
block in quick on any from 10.0.0.0/8 to any
block in quick on any from 127.0.0.0/8 to any
block in quick on any from 0.0.0.0/8 to any
block in quick on any from 169.254.0.0/16 to any
block in quick on any from 192.0.2.0/24 to any
block in quick on any from 204.152.64.0/23 to any
block in quick on any from 224.0.0.0/3 to any

In this table you will notice the 172.16.0.0/12 is omitted (even though it should be blocked at least on ep0), you will see why in the next part of the file.

3.4.2. Paranoia Block

Next we will cut off all traffic to ep0, hence we do not need to explicitly close off 172.16.0.0 from it.

# block all
block in quick on ep0 all

3.4.3. Make the Firewall Act like an Internet Client

Next we want to make the firewall have the capability of acting like an internet client, this is pretty simple:

# pass out as if we were a single internet client
pass out quick on ep0 proto tcp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto udp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto icmp from 216.68.250.60/32 to any keep state

3.4.4. Passing the Rest

Now we ant to add all of the protocols we want to pass. It should be important to note that if you have any of these services enabled on the firewall then their port will be accessible on the firewall. It is usually a safer bet not to have anything but ssh, ipfilter and ipnat running on it, the exception this might be (as in my home setup) you simply do not have the hardware to spare and must have DNS and/or other server processes running on it as well.

# dns stuff
pass in log proto tcp from any to any port = 53 keep state
pass in log proto udp from any to any port = 53 keep state

# pass thru www and ftp
pass in log proto tcp from any to any port = www keep state
pass in proto tcp from any to any port = ftp keep state
pass in proto tcp from any to any port = ftp-data keep state
pass in proto tcp from any port = ftp-data to any port > 1023 keep state
pass in log proto icmp all keep state

3.5. IP Filter for Dial Ups

Dial up connections offer somewhat of a challenge for ipfilter in that most dial up interfaces are assigned a different IP address each time the user makes the connection.

In dial up or any dynamic address situation, the rules must be written in a slightly less secure manner. In other words, rules cannot use the internet side IP address, however, even just using the interface is normally enough to guarantee pretty good security. As an example, here is one of the rules that uses an IP address:

# pass out as if we were a single internet client
pass out quick on ep0 proto tcp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto udp from 216.68.250.60/32 to any keep state
pass out quick on ep0 proto icmp from 216.68.250.60/32 to any keep state

For our dial up connection we will have to change the ruleset to this:

# pass out as if we were a single internet client 
pass out quick on ep0 proto tcp from any to any keep state
pass out quick on ep0 proto udp from any to any keep state
pass out quick on ep0 proto icmp from any to any keep state

Now what good does this do us now? Well, first, any ports that are still blocked are *still* inaccessible. Second, if a service is not turned on and no inbound proxying is enabled, all of this traffic is just passing through. There is no way for anyone to connect to the firewall except via ssh.