Redundant OpenBSD Firewalls

Part 5 - Redundant Network Services

In Part 5 we will configure the internal redundant services. Most of these steps take place on fw2, but not all. As we go along, we will have to modify some of our existing configurations on fw1. You’ll have to pay close attention so you don’t do stuff on the wrong server.

Time server

We configure NTP exactly the way we did on fw1 with the exception of the IP address we listen on.

Enable the ntp daemon:

fw2# rcctl enable ntpd

Now add a few lines to /etc/sync-fw-config:

# ntpd configuration
dosync /etc/ntpd.conf
sed -i "/^listen on $FW1/s/$FW1/$FW2/" /etc/ntpd.conf
rcctl restart ntpd

With the second time server running, we now need to modify our DHCP server configuration on fw1 so it will give out both time servers to the clients on our internal network. Change the following line in /etc/dhcpd.conf:

option ntp-servers,;

And restart the service:

fw1# rcctl restart dhcpd

Sync the changes on fw2, which will start the NTP service for us:

fw2# sh /etc/sync-fw-config

Authoritative name server

We have a couple of options for how to create a redundant authoritative name server. One option would be to set up zone transfers between the two instances of nsd. The other option is to have our sync-fw-config script do it. I chose to use the script, which keeps nsd only listening on localhost.

Start by enabling nsd on fw2:

fw2# nsd-control-setup
fw2# rcctl enable nsd

On fw2 add the following lines to /etc/sync-fw-config:

# sync nsd
dosync /var/nsd/etc/nsd.conf
dosync /var/nsd/zones/
rcctl restart nsd

And then resync:

fw2# sh /etc/sync-fw-config

Caching resolver

When we set up fw1 we created CARP addresses for our two name service IP addresses. We now need to add fw2 to those CARP groups.

On fw2 put the following into /etc/hostname.carp1:

inet vhid 132 carpdev vr0 pass vhid132passwd advskew 128 description "name server 1"

And this into /etc/hostname.carp2:

inet vhid 133 carpdev vr0 pass vhid133passwd advskew 128 description "name server 2"

Bring up the interfaces:

fw2# sh /etc/netstart carp1 carp2

Configure unbound:

fw2# rcctl enable unbound
fw2# unbound-control-setup

Add a few lines to /etc/sync-fw-config:

# unbound
dosync /var/unbound/etc/unbound.conf
sed -r -i "/^[[:space:]]*interface:[[:space:]]*$FW1/s/$FW1/$FW2/" /var/unbound/etc/unbound.conf
dosync /var/unbound/etc/root.hints
rcctl restart unbound

And resync our configs:

fw2# sh /etc/sync-fw-configs

To properly test this new redundant configuration we need to do it from another host on the internal network.

$ dig @ www.eff.org
$ dig @ fw2.kotfu.net

Force the carp interfaces to fail over to fw2 by shutting them down on fw1:

fw1# ifconfig carp1 down
fw1# ifconfig carp2 down

Then test again from our internal network host.

$ dig @ www.eff.org
$ dig @ fw2.kotfu.net

Make fw1 the primary again:

fw1# ifconfig carp1 up
fw1# ifconfig carp2 up


We’ll start with some modifications to our configuration on fw1. The first thing we need is a secret key used to compute a message digest of the synchronization messages exchanged between the DHCP servers. On fw1 use the following incantation to create a key file with 2048 bits of random content:

fw1# dd if=/dev/random of=/var/db/dhcpd.key bs=2048 count=

You have to put the file in /var/db/dhcpd.key, there is no configuration settings to put this file in a different location. If the file is present, it will be used.

/etc/dhcpd.conf can be identical between our two servers.

Finally, we need to set the proper command line options to instruct the DHCP servers how to exchange messages with each other. There are two command line arguments for this purpose: -Y controls where the daemon sends synchronization messages, and -y tells the daemon where to listen for synchronization messages. You can configure a mix of multicast and unicast options, see the dhcpd man page for more details.

For our example we will use multicast messages on the dedicated network segment connecting our two firewalls. For a refresher on how we set that up see Part 4 - Redundant Routing and Packet Filter. This command will add the proper flags to dhcpd:

fw1# rcctl set dhcpd flags "-Y em2 -y em2 em0"

Notice that in addition to the sync flags, we tell dhcpd to only listen on the em0 network interface. Finally, restart the DHCP server:

fw1# rcctl restart dhcpd

Now we turn our attention to fw2. This one is pretty easy. We need to enable the dhcpd server on fw2, and set the synchronization flags to point to fw1:

fw2# rcctl enable dhcpd
fw2# rcctl set dhcpd flags "-Y vr2 -y vr2 vr0"

Now add the following lines to /etc/sync-fw-config:

# dhcpd
dosync /etc/dhcpd.conf
dosync /var/db/dhcpd.key
rcctl restart dhcpd

Then run the sync script:

fw2# sh /etc/sync-fw-config

To verify that it’s working, need to force a device on the internal network to renew it’s DHCP lease. Look in /var/log/daemon on both servers, and you should see a message from dhcpd that starts with “sending DHCP_SYNC_LEASE”. Then go look in /var/db/dhcpd.leases on fw2 and you should see a lease entry for the device which you just renewed the lease on.

Now you have redundant time servers, name servers, caching resolvers, and DHCP servers.

Redundant OpenBSD Firewall Guide