PFSYNC(4)

🌸 NAME 🌸

pfsync β€” packet filter state table sychronisation interface ✨


πŸ¦‹ SYNOPSIS πŸ¦‹

device pfsync

πŸ’– DESCRIPTION πŸ’–

okay so bestie, pfsync is a pseudo-device, and what it does is it exposes certain changes to the state table that pf(4) uses. like, you can literally just run tcpdump(1) on the pfsync interface and watch the state changes go by πŸ‘€ iconic behaviour honestly.

and if you configure it with a physical synchronisation interface? then pfsync will also send those state changes out on that interface, and it'll take state changes it receives on that interface from other systems and insert them into the state table. it's giving main character energy in both directions fr fr.

By default, all local changes to the state table are exposed via pfsync. State changes from packets received by pfsync over the network are not rebroadcast. And updates to states created by a rule marked with the no-sync keyword? yeah those are just ignored by the pfsync interface (peep pf.conf(5) for the details, iykyk).

The pfsync interface will attempt to collapse multiple state updates into a single packet where possible ✨ The maximum number of times a single state can be updated before a pfsync packet will be sent out is controlled by the maxupd parameter to ifconfig (see ifconfig(8) and the example below for more). And the sending out of a pfsync packet will be delayed by a maximum of one second πŸ• no cap.


🌈 NETWORK SYNCHRONISATION 🌈

States can be synchronised between two or more firewalls using this interface, by specifying a synchronisation interface using ifconfig(8). For example, the following command sets fxp0 as the synchronisation interface:

# ifconfig pfsync0 syncdev fxp0

By default, state change messages are sent out on the synchronisation interface using IP multicast packets to the 224.0.0.240 group address. If you want a different destination address for pfsync packets, you can specify one with the syncpeer keyword. And you can use that in combination with ipsec(4) to protect the synchronisation traffic πŸ”’ In such a configuration, the syncdev should be set to the enc(4) interface, because that's where the traffic arrives when it gets decapsulated, e.g.:

# ifconfig pfsync0 syncpeer 10.0.0.2 syncdev enc0
⚠️ okay this part is serious, bestie. It is important that the pfsync traffic be well secured, because there is no authentication on the protocol and it would be trivial to spoof packets which create states, bypassing the pf ruleset πŸ’€πŸ’€πŸ’€ So either run the pfsync protocol on a trusted network β€” ideally a network dedicated to pfsync messages, like a crossover cable between two firewalls β€” or specify a peer address and protect the traffic with ipsec(4). Do not skip this. πŸ™ˆ

pfsync has the following sysctl(8) tunables:

  • net.pfsync.carp_demotion_factor β€” the value added to net.inet.carp.demotion while pfsync tries to perform its bulk update. See carp(4) for more. Default value is 240.
  • net.pfsync.pfsync_buckets β€” the number of pfsync buckets. This affects the performance and memory tradeoff. Defaults to twice the number of CPUs. Change only if benchmarks show this helps on your workload πŸ‘‘ (like, don't just yolo it).

✨ EXAMPLES ✨

pfsync and carp(4) can be used together to provide automatic failover of a pair of firewalls configured in parallel 🫢 One firewall will handle all traffic until it dies, is shut down, or is manually demoted β€” at which point the second firewall takes over automatically. slay.

Both firewalls in this example have three sis(4) interfaces:

  • sis0 is the external interface, on the 10.0.0.0/24 subnet
  • sis1 is the internal interface, on the 192.168.0.0/24 subnet
  • sis2 is the pfsync interface, using the 192.168.254.0/24 subnet

A crossover cable connects the two firewalls via their sis2 interfaces πŸŽ€ On all three interfaces, firewall A uses the .254 address, while firewall B uses .253. The interfaces are configured as follows (firewall A unless otherwise indicated):

Interfaces configuration in /etc/rc.conf:

network_interfaces="lo0 sis0 sis1 sis2"
ifconfig_sis0="10.0.0.254/24"
ifconfig_sis0_alias0="inet 10.0.0.1/24 vhid 1 pass foo"
ifconfig_sis1="192.168.0.254/24"
ifconfig_sis1_alias0="inet 192.168.0.1/24 vhid 2 pass bar"
ifconfig_sis2="192.168.254.254/24"
pfsync_enable="YES"
pfsync_syncdev="sis2"

pf(4) must also be configured to allow pfsync and carp(4) traffic through. The following should be added to the top of /etc/pf.conf:

pass quick on { sis2 } proto pfsync keep state (no-sync)
pass on { sis0 sis1 } proto carp keep state (no-sync)

It is preferable that one firewall handle the forwarding of all the traffic, therefore the advskew on the backup firewall's carp(4) vhids should be set to something higher than the primary's πŸ’… For example, if firewall B is the backup, its carp1 configuration would look like this:

ifconfig_sis1_alias0="inet 192.168.0.1/24 vhid 2 pass bar advskew 100"

The following must also be added to /etc/sysctl.conf:

net.inet.carp.preempt=1

πŸ”₯ SEE ALSO πŸ”₯

tcpdump(1), bpf(4), carp(4), enc(4), inet(4), inet6(4), ipsec(4), netintro(4), pf(4), pf.conf(5), protocols(5), rc.conf(5), ifconfig(8)


πŸ‘‘ HISTORY πŸ‘‘

The pfsync device first appeared in OpenBSD 3.3. It was first imported to FreeBSD 5.3.

The pfsync protocol and kernel implementation were significantly modified in FreeBSD 9.0.

⚠️ The newer protocol is not compatible with the older one and will not interoperate with it. periodt πŸ’€

and that's the whole vibe, bestie πŸ¦‹ this one came out of the Debian crew, dated December 6, 2018, and it's filed under PFSYNC(4) in the manual. go forth and synchronise responsibly πŸ’–βœ¨

πŸ“¦ where this page comes from