OpenBSD firewall applicance - Intro

OpenBSD firewall applicance - Intro

History

Since some time our company Eurospider was using home-grown firewalls based on OpenBSD. Our administrator at this time (Mihai Barbos, https://github.com/mbarbos) decided to use Portwell NAR-2054 hardware with 3 up to 5 ethernet ports and run a customized OpenBSD on it.

Now the company firewall is a Soekris net6501 as the Portwell firewalls started to become a little bit rusty. There is still one Portwell left in use for a control network serving access to remote management consoles of our servers.

Also at home I’m using this solution on an Alix 2D.13 with 3 ethernet ports.

Concepts

In theory you could just go with a default installation and customize from there. A well-known security principle though is to put the minimal amount of services onto a machine and add only the things really needed to do the job.

Another solution would have been to go with an appliance like PfSense, but they always provide some user interface (written in Lua, Php, etc.). Web technology is not really in the base of OpenBSD, only in the ports, so this could open a security threat.

A good security feature is to work with read-only media. In the case of the Alix and the Portwell this is a compact flash, in case of the Soekris a mini-USB-dongle. This prevents wearout and more importantly, no processes can write onto the system (but for a mfs (memory file system) for the /tmp directory.

Instead of a clicky-clicky web interface which generates a big unreadable set of configuration files (for instance firewall rules), I personally prefer a text editor and simple rules. Again, complexity in a firewall setup is a no-go, the less complex it is, the more likely you understand all rules you put in there. And understanding what you are doing is the key to a secure system.

So, we start from a build-machine running a standard OpenBSD. From there a build script (build.sh) creates a virtual filesystem (vnode disks, vnconfig, the Linux world would use loopback devices). This image is then transfered with ‘dd’ to the real media (compact flash or USB stick).

The early scripts are based on scripts from Chris Cappuccio, sadly I was not able to find the original webpage anymore.

Customization

The build.sh script takes a directory called ‘template’. This directory contains files which are copied as is to the image. Usually this directory needs synching with the host system every time you upgrade OpenBSD.

All binaries and required libraries are fetched from the host system runing OpenBSD.

The directory ‘config’ contains files per appliance you want to build.

Basic network connectivity is configured in the following files:

  rc.net
  dhclient.conf
  hosts
  networks
  rc.net

The ‘rc.net’ file is a snippet which gets added to the boot script ‘/etc/rc’. There you set up the network directly with OpenBSD commands like:

  dhclient vr0
  ifconfig bridge0 create
  ifconfig bridge0 add vr1
  ifconfig bridge0 add vr2 
  route add -net 192.168.1.0/24 192.168.1.1

The firewall lives in one file ‘pf.conf’ and contains the standard OpenBSD firewall rules:

# interfaces
ext_if = vr0
...
match out on $ext_if from <intNetworks> nat-to ($ext_if)
...
pass in quick on $ext_if proto udp from port 67 to port 68
...

The other snippet which gets added to ‘/etc/rc’ is ‘rc.services’. There you start all services you want to run on the machine:

echo unbound: starting DNS resolver..
cp -R /etc/unbound /tmp/var/unbound
/usr/sbin/unbound

You also put all required files for each service into that directory. For instance:

  • for DHCP: dhcpd.conf
shared-network LAN {
  ...

  subnet 192.168.1.0 netmask 255.255.255.0 {
    option routers 192.168.1.1;
    range 192.168.1.128 192.168.1.249;
  }
  • for NTP: ntpd.conf
servers pool.ntp.org
listen on 127.0.0.1
listen on 192.168.1.1
  • for DNS resolving and caching (unbound subdir with unbound.conf)

  • for DNS server you need a need one configuration directory per view (for a split-horizon setup):

nsd-external/
nsd-external/run
nsd-external/run/xfr
nsd-external/run/xfr/.gitkeep
nsd-external/zones
nsd-external/zones/myzone
nsd-external/zones/somebodyelseszone
nsd-external/etc
nsd-external/etc/nsd.conf

(this I will cover in another article, as it is a little bit more tricky to set up).

  • Relaying traffic with relayd, relayd.conf:
...
http protocol "http_protocol" {
	...
	match request quick header "Host" value "www.mydomain.com" \
                forward to <someinternalserver> no tag
}
...

Finally you create a file with the CHS parameters of your media (yes, this is needed for bootloading on OpenBSD) in a file called ‘hardware/myfirewall/flash_params’:

BYTES_PER_SECTOR=512
SECTORS_PER_TRACK=32
TRACKS_PER_CYLINDER=16
SECTORES_PER_CYLINDER=512
CYLINDERS=978
OFFSET=32

To create the image you simple call:

./build.sh [your config profile] [flash_params profile]

Future

I’m trying to keep up with new versions of OpenBSD.

I would like to test more things around the following topics:

  • monitoring of firewall data (pflogd), sensor logging, remote syslog
  • play with redundancy (CARP)
  • automatic acme and relayd certificate renewal for HTTPS relaying
  • in-situ updates: currently I have to open the device, remove the flash, stuff it into a floppy to compact flash adapter, write the image, put it back. This is tedious. :-)

Github

The whole project can be found on Github:

http://github.com/andreasbaumann/OpenBSD-firewall

Feedback welcome. :-)