Pages

Sunday, March 4, 2012

Setting up a simple firewall with pf and NetBSD

Today I deceided to setup a simple firewall for my NetBSD machine. The following output shows my network interfaces:

# ifconfig -a
tlp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
...
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33192
...

tlp0 is a simple 100MB network card and lo0 is the loopback device. Before you can start you must load the pf module:

# modload /usr/lkm/pf.o

And check that it was loaded:

# modstat
Type    Id   Offset Loadaddr Size Info     Rev Module Name
DEV       0  -1/161 cbab0000 0094 cbad1a40   2 pf

To setup a basic firewall edit the file /etc/pf.conf:

# vi /etc/pf.conf
block all
set skip on lo0
pass out on tlp0 to any
pass in  on tlp0 proto tcp from any to tlp0 port 22

The first line 'block all' will block all traffic on all network interfaces. The second line 'set skip on lo0' will allow network traffic for the loopback device. The third line 'pass out on tlp0 to any' will allow outgoing network traffic on the tlp0 interface. The last line will allow incoming tcp traffic on port 22 (SSH) on the tlp0 interface.
To start the firewall use the pfctl command:

# pfctl -f /etc/pf.conf

Eveytime you change your firewall ruleset you have to reload the configuration using the pfctl command.
To reduce network connectivity to your local network use the following ruleset:

# vi /etc/pf.conf
block all
set skip on lo0
pass out on tlp0 to 192.168.1.64/26
pass in  on tlp0 proto tcp from 192.168.1.64/26 to tlp0 port 22

This will reduce outgoing and incoming network connectivity to the local network 192.168.1.64/26. With this ruleset it is not possible to access the internet anymore, this might get nasty if you use pkgsrc.
As you maybe have recognized already, pinging the NetBSD machine is not possible anymore. To allow pinging the machine use the following ruleset and allow ICMP traffic:

# vi /etc/pf.conf
block all
set skip on lo0
pass in  on tlp0 proto icmp from 192.168.1.64/26
pass out on tlp0 to 192.168.1.64/26
pass in  on tlp0 proto tcp from 192.168.1.64/26 to tlp0 port 22

It also common to use macros for networks, hosts and interfaces:

# vi /etc/pf.conf
int_net="192.168.1.64/26"
int_if="tlp0"
block all
set skip on lo0
pass in  on $int_if proto icmp from $int_net
pass out on $int_if to $int_net
pass in  on $int_if proto tcp from $int_net to $int_if port 22

The above ruleset substitutes the network and the tlp0 interface to the macros int_net and int_if.
To enable the firewall during booting add pf, network and lkm to /etc/rc.conf:

# vi /etc/rc.conf
...
lkm=YES
network=YES
pf=YES
...

lkm is used to load the pf module during booting. Next add the pf module to /etc/lkm.conf:

# vi /etc/lkm.conf
...
/usr/lkm/pf.o   -       -       -       -       BEFORENET

When you reboot your NetBSD machine then the pf module will be loaded and the firewall will be activated.
You can also see your current ruleset with pfctl:

# pfctl -sr
block drop all
pass in on tlp0 inet proto icmp from 192.168.1.64/26 to any keep state
pass in on tlp0 inet proto tcp from 192.168.1.64/26 to 192.168.1.74 port = ssh flags S/SA keep state
pass out on tlp0 inet from any to 192.168.1.64/26 flags S/SA keep state

The above examples are just very simple configuration. You should definetly check out the current documentation:

http://www.openbsd.org/faq/pf/