I’ll toss this out there: pf ruined all other firewalls for me. Once you’ve been spoiled by pf.conf, it’s awfully hard to look at any other without running away screaming. Seriously, it’s a joy, like discovering Python after you’ve learned Brainfuck.
I wish Linux’s firewalls were so easy to configure. The closest I’ve found there is with ufw, which isn’t nearly so comprehensive or straightforward, but at least goes in the right direction.
I've written firewall rules in many dialects, include Linux with ipchains and iptables, FreeBSD with ipfw and pf.
I will say, they all pretty much work, until you get into more esoteric stuff; do you want to drop syns where the last 16-bits of seq match the client's port number? Do you want to drop UDP RTP packets for a specific SSRC? If so, that need may guide your firewall choice. If you need to sync states between two stateful firewalls, that pushes you to pf with pfsync. Etc.
I guess I didn't see a big difference in perceived happiness between any of the rules systems? pf.conf is maybe more picky and checks everything at once, which is nice so you don't end up with a half baked ruleset.
Otoh, pf has the feature that OpenBSD changed the rule syntax, and the ported versions didn't; I'm not sure a forced migration of rule config would have sparked joy for OpenBSD users anyway, but it certainly doesn't spark joy when I read current documentation for the OpenBSD pf and can't apply it directly, and have to translate the config language to the original language.
Pf also has the extra special feature that Apple ported pf to MacOs but some things don't work properly for a host firewall (synproxy in mac os pf only works if the mac is operating as a router, not as a host... And mac os's tcp stack has no syn flood mitigation, beyond having a small listen backlog or not accepting syns directly from the internet). That's an Apple failing, not really a pf failing, but still, frustrating.
I'll have to look again and see if FreeBSD pf has gotten the features I need from ipfw, so maybe I don't have to run two firewalls at the same time. :(
> do you want to drop syns where the last 16-bits of seq match the client's port number?
I'm guessing this is something about a vulnerability in client sequence number selection? I'm curious about the details here for what would motivate this.
Oh I'm really sorry, this wasn't a real filter I've used. It was just an off the cuff weird, but doable request. Speculatively you want to block abusive syn floods and your abuser made a weird choice in their packet generator.
> I wish Linux’s firewalls were so easy to configure.
nft (nftables) is easy and has a similar pf-like 'feel' while offering way more functionality. After decades of `iptables` (and `ipchains` before) nft(ables) is a breath of fresh air.
I still greatly prefer pf, but yes, nftables is vastly better than iptables. Ipchains always looked like a RAM dump converted to Forth. It got the job done, mostly, but I never could understand how it got popular when the BSDs were already using nicer alternatives.
Iptables suffers from the common "it's a command line program so we are going to use getopt to parse it" I find the getopt style... tolerable at best for short commands. But for long expressions in a dsl(like find or iptables) it is noisy and ugly. Iptables would have been twice as nice to use if they got rid of all the pointless dashes(and I have written preprocessors to do just this).
The clearest example of this was the megaraid command for lsi raid cards. It's commands are documented in the getopt style but I accidentally found out that the dashes were optional. And while the syntax was still sort of ass, my scripts were much easier to read.
Nftables is a step forward in the Linux firewall. It evolved a lot in the last years and nowadays it really requires that the tooling linked to iptables setups do the migration step.
Totally agree. I rarely need to adjust my pf.conf but it's a joy when I do. The syntax is easy to read and I can easily get up to speed on my rules just by paging through the file.
FWIW I have the previous edition of the Book of PF on my bookshelf but I rarely reference it after reading through it a couple years back. Standard homelab-grade rulesets are pretty straightforward to setup.
I had a tough time even with PF. I got a basic config going for my network by copying stuff from the book of PF. When I tried to go beyond that things got frustrating. I think I was trying to set up a VPN which, I know this is a famously frustrating task, but I was hoping that PF would be somehow more legible or less opaque. There was nowhere to reference for the syntax and what it’s capable of.
I was hoping it was like a nice programming language whose internal structure made sense to an experienced developer. Where I can incrementally build things up and log things to the console as I go along and troubleshoot. But it turns out that setting up a vpn involves a big bang config with a dozen lines and it’s unclear which of them is broken.
It’s a DSL and not a programming language and often there is very little you can do to troubleshoot that’s short of reading the source code, the protocol spec, and firing up wireshark.
I found various configs on random websites or in the openbsd manual, but none seemed to do the trick. I gave up and installed Tailscale.
This isn’t a knock on PF. But years of reading glowing comments like this gave me some false hope that I could finally grok this stuff and maybe do some creative projects with it.
I wish Linux’s firewalls were so easy to configure. The closest I’ve found there is with ufw, which isn’t nearly so comprehensive or straightforward, but at least goes in the right direction.