Pf Configuration Incompatible With Pf Program Version Review
He pulled up the man page on his laptop. pf.conf(5) . There it was, buried in the "Migration Notes" for 7.5: The from <list> syntax has been deprecated for non-route-related filter rules. Use an anchor or table for multiple source prefixes. Direct lists in a pass in rule will now raise a fatal syntax error. A fatal error. Not a warning. Not a "this might break." A stone-cold, refuse-to-start fatal error.
Silence. Then the gentle tick of the rule counter.
He never trusted -current again.
It was clean. It had worked for eighteen months. He squinted. Then he saw it. The version banner from the last system upgrade, buried four scrolls up: pf configuration incompatible with pf program version
/var/log/messages: pfctl: /etc/pf.conf:87: syntax error /var/log/messages: pfctl: /etc/pf.conf:87: rule expands to a non-list element
The old PF (the one running on 7.4) had been lenient. It saw the curly braces, expanded the list in memory, and carried on. The new PF was a stricter grammarian. It saw the same syntax, declared it heresy, and refused to load any rules at all. Zero firewall. No state table. No blocking. No logging.
“Firewall node gw-04-dfw in CARP backup state. Packet filter service failed to start.” He pulled up the man page on his laptop
Line 87. Julian scrolled through the config. Line 87 was a routine pass in rule for a backend API subnet.
He wrote his post-mortem at dawn. Title: "PF_CONFIG_VERSION vs. PF_PROGRAM_VERSION: A Case of Silent Deprecation."
He VPN’d in, his coffee cold before he’d even poured it. The first command was ritual. Use an anchor or table for multiple source prefixes
His stomach turned to ice. Current. Not -release . Not -stable . Someone—a junior with a cowboy hat and a cron job—had pointed their package repository to the bleeding-edge snapshots. And the new PF, the one in 7.5-current , had changed.
But he knew the real story. The firewall had been working fine. Until the moment it wasn't. And the difference between those two moments was a single line in a changelog no one had read, and a list of IP addresses wrapped in the wrong kind of curly braces.
pass in on $ext_if inet proto tcp from 10.88.12.0/24, 10.88.13.0/24 to port 8080
pfctl -sr pfctl: DIOCGETRULES: Device not configured Not configured? That meant PF wasn’t even running. He checked the logs.
The alert came in at 03:14, which meant the on-call pager was now a small, vibrating god of wrath on Julian’s nightstand.