This article explains how to set up firewall high-availability using CARP and pfsync, and then link two sites over a GRE tunnel encrypted with IPsec.
The tutorial is demonstrated under VirtualBox.
Diagram of the setup:
Prerequisites/references:
In this example we deploy three OpenBSD servers, two of which participate in CARP (with a virtual IP) to provide high availability.
Scenario:
em0: WANem1: LANAdjust each OpenBSD system so it meets our requirements.
Enable IP forwarding in /etc/sysctl.conf:
net.ipv4.ip_forward=1
Enable CARP options:
net.inet.carp.preempt=1
net.inet.carp.log=3
Our LAN uses the 10.17.0.0/24 range. To deploy CARP and pfsync we need several interfaces.
/etc/hostname.carp1:
inet 10.17.0.12 255.255.255.0 NONE vhid 1 carpdev em1 \
pass unixperience advbase 1 advskew 100
/etc/hostname.carp1:
inet 10.17.0.12 255.255.255.0 NONE vhid 1 carpdev em1 \
pass unixperience advbase 1 advskew 10
The configuration means CARP advertisements are exchanged every second between gateways to elect the Master and Backup. Given identical advbase values, the gateway with the lower advskew becomes Master.
For security, place pfsync synchronization traffic on a dedicated VLAN between gateways. This VLAN is tagged as VLAN 2 on em1.
/etc/hostname.vlan2:
inet 172.21.0.31 255.255.255.0 NONE vlan 2 vlandev em1
/etc/hostname.pfsync0:
up syncdev vlan2 syncpeer 172.21.0.32
/etc/hostname.vlan2:
inet 172.21.0.32 255.255.255.0 NONE vlan 2 vlandev em1
/etc/hostname.pfsync0:
up syncdev vlan2 syncpeer 172.21.0.31
Once configured, bring up the dedicated interfaces using the OpenBSD startup scripts (specify a single interface as argument to avoid reconfiguring physical interfaces):
sh /etc/netstart
You should now have two new interfaces (carp1 and pfsync0), with the shared virtual IP attached to the CARP interface.
ifconfig carp1
ifconfig pfsync0
You can observe failover by disabling carp1 on the master. The backup should transition to master; you can see this in the console or with dmesg.
The GRE tunnel part is covered in more detail in the dedicated GRE article. Here we configure GRE interfaces on each gateway.
/etc/hostname.gre0:
172.16.0.1 172.16.0.3 netmask 0xffffffff link0 up
tunnel 192.168.56.102 192.168.56.105
/etc/hostname.gre0:
172.168.0.2 172.16.0.4 netmask 0xffffffff link0 up
tunnel 192.168.56.103 192.168.56.105
/etc/hostname.gre0:
172.168.0.3 172.16.0.1 netmask 0xffffffff link0 up
tunnel 192.168.56.105 192.168.56.102
/etc/hostname.gre1:
172.168.0.4 172.16.0.2 netmask 0xffffffff link0 up
tunnel 192.168.56.105 192.168.56.103
Each GRE interface is connected to one of the LAN gateways. Run sh /etc/netstart on each machine so the tunnels are created, then test connectivity by pinging the other end.
At this stage the remote sites are connected, but the tunnel traffic is unencrypted and routing is static. To address dynamic routing, we add OSPF.
OSPF configuration is straightforward. In this example we use OSPF area 0.0.0.1 over the GRE tunnels with MD5 authentication using the password unix-experience.
/etc/ospfd.conf on Gateway A:
router-id 192.168.56.102
redistribute connected
gre_if="gre0"
password="unix-experience"
auth-md 1 $password
auth-type crypt
auth-md-keyid 1
area 0.0.0.1 {
interface $gre_if {}
}
/etc/ospfd.conf on Gateway C:
router-id 192.168.56.103
redistribute connected
gre_if0="gre0"
gre_if1="gre1"
password="unix-experience"
auth-md 1 $password
auth-type crypt
auth-md-keyid 1
area 0.0.0.1 {
interface $gre_if0 {}
interface $gre_if1 {}
}
After a few seconds, run netstat -nrf -inet to inspect the routing table. You should see OSPF-learned routes. Do not forget to enable OSPF at boot in /etc/rc.conf.local.
Because GRE is not encrypted, add an IPsec transport layer between the sites. First enable IPsec support in the kernel:
net.inet.esp.enable=1
net.inet.ah.enable=1
Example configuration for Gateway A in /etc/ipsec.conf:
ike esp transport from 192.168.56.102 to 192.168.56.105 \
psk unix-experience
You must then exchange the public keys generated at install time in /etc/isakmpd/local.pub.
For example, to secure traffic from Gateway A to Gateway C, copy Gateway A’s local.pub file to /etc/isakmpd/pubkeys/ipv4/192.168.56.102 on Gateway C. If you use DNS names instead of IPs, use the FQDN directory and the hostname as the filename.
Start IPsec:
isakmpd -K
ipsecctl -f /etc/ipsec.conf
If you hit problems, tail -f /var/log/messages is usually enough to understand what is failing.
When the tunnel works, add the following to /etc/rc.conf.local so IPsec starts at boot:
isakmpd_flags="-K"
ipsec=YES