5. The pfsync protocol

Pfsync is the protocol used by Packet Filter to manage and update state tables, which allow for stateful inspection and NAT. By default, state change messages are sent out on the synchronization interface using IP multicast packets. The protocol is IP protocol 240 and the multicast group used is 224.0.0.240. We will use it to synchronize state tables among firewalls of the same redundancy group and, in the event of a failover, allow network traffic to flow uninterrupted through the new master firewall.

pfsync(4) is also the name of the pseudo-device on which PF state table changes are sent (except states created by rules marked with the no-sync keyword or by pfsync(4) packets). pfsync(4) can be configured to use a physical interface, in order to merge and keep in sync the state tables among multiple firewalls.

The physical synchronization interface can be set through ifconfig(8), using the syncdev parameter; for example, on our firewalls, we can write:

# ifconfig pfsync0 syncdev rl2

assuming that the rl2 interface is, on each host (see picture), the interface on the 192.168.1.0/24 subnet (for Mickey and Minnie) or 192.168.2.0/24 (for Donald and Daisy) and cross-cabled to the "beloved" firewall.

Crossover cables are recommended because the pfsync protocol doesn't provide any cryptography or authentication mechanism; if you don't use a secure network, like a crossover cable, an attacker may use spoofed pfsync packets to alter the firewalls state tables and bypass filter rules.

Alternatively, you can use the syncpeer keyword to specify the address of the firewall to synchronize with. The system will use this address, instead of multicast, as the destination of pfsync(4) messages, allowing the use of IPsec to protect the communication. In this case, syncdev must be set to the enc(4) pseudo-device, which encapsulates/decapsulates ipsec(4) traffic. E.g.:

# ifconfig pfsync0 syncpeer 192.168.1.101 syncdev enc0

To make these settings permanent after reboot, we need to edit the /etc/hostname.pfsync0 file on each firewall:

/etc/hostname.pfsync0
up syncdev rl2