IPFW or PF?

I use both. I like to use PF for a server where I only want to open certain ports and on my desktop PC I just prefer to use IPFW since you can use the preset "workstation".
 
Wow - he wants something that is "readable" and where he doesn't need to understand what it does.

I, for the contrary, wanted something where I precisely understand what it does, so that I can make it do exactly what I want to be done. And even with IPFW, which is native to FreeBSD, I need three kernel patches to make it actually do what one would expect it to do. I wonder how many fixes it might need to make a foreign import like PF work correctly...
 
I guess it depends also on what kind of "config language" bests suits a sysadmin's mind-map.

It is like programming, one may favoured C or Perl, one Haskell, or Erlang, etc.

To me, in the end, features do count a bit more than language. If I may ask, what kind of extra functionality requiring kernel patches you need to have from IPFW?
 
If I may ask, what kind of extra functionality requiring kernel patches you need to have from IPFW?
You're welcome.
As it just ruined my sunday (and was probably the first time I had to fully abandon and revert a planned change), take this one, for starters,
plus subsequent mails, plus a couple of bugreports, eg. 256828 (bottomline is, this is just broken throughout R.13).

What I originally meant, is e.g. bug 165190 or 260796, among others.

Now You may ask, what am I specifically doing. In fact, I am just using the features, to maintain flows throughout arbitrarily weird network topologies. Here is a demo ipfw config in JSON format:
Code:
{"name":"demo","skiplines":10,"startline":10,"icmptypes":"0,3,8,11,12","icmp6intf":"1,133,134,143","icmp6regn":"128,129","created_at":"2021-09-15T00:04:27.257Z","updated_at":"2022-03-28T11:20:28.877Z","discarded_at":null,"connects":[{"id":62,"name":"lo0","local":true,"icmp6":false,"icmp6types":"","created_at":"2021-09-15T00:05:42.098Z","updated_at":"2021-09-15T00:08:59.542Z","discarded_at":null,"regions":[{"id":140,"name":"self.all","icmp":true,"icmptypes":"","icmp6":false,"icmp6types":"","me":true,"notme":false,"me6":false,"notme6":false,"created_at":"2021-09-15T00:06:25.021Z","updated_at":"2021-11-09T10:11:09.991Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[],"tableentries":[],"_vv":"001.000"}],"netifs":[],"_vv":"001.000"},{"id":63,"name":"tun0","local":false,"icmp6":true,"icmp6types":"","created_at":"2021-11-17T10:05:40.697Z","updated_at":"2021-11-17T10:05:40.697Z","discarded_at":null,"regions":[{"id":141,"name":"lan","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-17T10:05:46.351Z","updated_at":"2021-11-17T10:05:46.351Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":256,"addr":"192.168.0.0/22","negate":false,"created_at":"2021-11-17T10:05:55.573Z","updated_at":"2022-03-28T11:24:02.550Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"},{"id":150,"name":"portfwd","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-18T11:59:42.785Z","updated_at":"2021-11-18T12:05:01.726Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":263,"addr":"192.168.3.41/32","negate":false,"created_at":"2021-11-18T12:01:08.751Z","updated_at":"2022-03-28T11:24:14.649Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"},{"id":148,"name":"lcnk","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-18T23:27:48.304Z","updated_at":"2022-03-28T11:31:31.335Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":261,"addr":"198.51.100.3/32","negate":false,"created_at":"2021-11-18T23:28:02.429Z","updated_at":"2022-03-28T11:26:21.092Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"},{"id":143,"name":"lcnk.local","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-19T00:05:15.661Z","updated_at":"2022-03-28T11:31:44.181Z","forward_id":null,"discarded_at":null,"filtercalls":[{"id":16,"filter_id":14,"recv":true,"xmit":true,"seq":1,"created_at":"2021-11-19T00:21:00.847Z","updated_at":"2021-11-19T00:21:00.847Z","discarded_at":null,"_vv":"001.000"}],"networks":[{"id":257,"addr":"198.51.100.3/32","negate":false,"created_at":"2021-11-19T00:05:33.228Z","updated_at":"2022-03-28T11:26:58.331Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"}],"netifs":[],"_vv":"001.000"},{"id":64,"name":"vtnet0","local":false,"icmp6":false,"icmp6types":"","created_at":"2021-09-15T00:09:50.827Z","updated_at":"2021-11-09T10:14:28.429Z","discarded_at":null,"regions":[{"id":142,"name":"portfwd","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":true,"me6":false,"notme6":false,"created_at":"2021-11-18T11:54:36.561Z","updated_at":"2021-11-18T11:54:50.844Z","forward_id":null,"discarded_at":null,"filtercalls":[{"id":17,"filter_id":14,"recv":true,"xmit":true,"seq":1,"created_at":"2021-11-18T11:57:48.247Z","updated_at":"2021-11-18T11:57:48.247Z","discarded_at":null,"_vv":"001.000"}],"networks":[],"tableentries":[],"_vv":"001.000"},{"id":144,"name":"internet","icmp":true,"icmptypes":"","icmp6":false,"icmp6types":"","me":false,"notme":true,"me6":false,"notme6":false,"created_at":"2021-10-16T14:15:42.562Z","updated_at":"2021-11-09T10:15:02.226Z","forward_id":null,"discarded_at":null,"filtercalls":[{"id":18,"filter_id":15,"recv":true,"xmit":false,"seq":1,"created_at":"2021-11-18T12:16:03.578Z","updated_at":"2021-11-18T12:16:03.578Z","discarded_at":null,"_vv":"001.000"}],"networks":[],"tableentries":[],"_vv":"001.000"},{"id":147,"name":"internet.lcnk","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":true,"me6":false,"notme6":true,"created_at":"2021-11-18T23:59:44.664Z","updated_at":"2022-03-28T11:32:32.931Z","forward_id":4,"discarded_at":null,"filtercalls":[],"networks":[{"id":260,"addr":"192.168.0.0/22","negate":true,"created_at":"2021-11-19T00:00:04.441Z","updated_at":"2022-03-28T11:28:05.153Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"},{"id":145,"name":"lbnk","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-18T22:32:27.364Z","updated_at":"2022-03-28T11:33:00.915Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":258,"addr":"203.0.113.142/32","negate":false,"created_at":"2021-11-18T22:32:42.122Z","updated_at":"2022-03-28T11:29:25.974Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"}],"netifs":[],"_vv":"001.000"},{"id":65,"name":"gif0","local":false,"icmp6":true,"icmp6types":"","created_at":"2021-11-18T23:31:38.684Z","updated_at":"2021-11-18T23:31:38.684Z","discarded_at":null,"regions":[{"id":146,"name":"remote","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-19T00:00:46.731Z","updated_at":"2021-11-19T00:00:46.731Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":259,"addr":"10.0.0.150/32","negate":false,"created_at":"2021-11-19T00:00:58.450Z","updated_at":"2022-03-28T11:23:49.957Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"},{"id":149,"name":"lbnk.intra","icmp":true,"icmptypes":"","icmp6":true,"icmp6types":"","me":false,"notme":false,"me6":false,"notme6":false,"created_at":"2021-11-18T23:41:33.679Z","updated_at":"2022-03-28T11:30:59.085Z","forward_id":null,"discarded_at":null,"filtercalls":[],"networks":[{"id":262,"addr":"192.168.3.0/28","negate":false,"created_at":"2021-11-18T23:41:42.974Z","updated_at":"2022-03-28T11:23:23.089Z","discarded_at":null,"_vv":"001.000"}],"tableentries":[],"_vv":"001.000"}],"netifs":[],"_vv":"001.000"}],"flows":[{"id":193,"name":"all.local","comment":"","primacy":"normal","orig_ports":"","resp_ports":"","proto":"any","direction":"originate","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":1,"origin_id":140,"respond_id":140,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-09-15T00:08:00.954Z","updated_at":"2021-09-15T00:08:00.954Z","discarded_at":null,"_vv":"001.000"},{"id":187,"name":"INFRA.inet","comment":"pkg-audit (braucht http)","primacy":"normal","orig_ports":"","resp_ports":"https,http,domain","proto":"tcp","direction":"roundtrip","keepstate":true,"setup":true,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":8,"origin_id":140,"respond_id":144,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-10-16T14:14:58.046Z","updated_at":"2021-11-09T12:14:54.885Z","discarded_at":null,"_vv":"001.000"},{"id":188,"name":"INFRA.inet","comment":"","primacy":"normal","orig_ports":"","resp_ports":"domain,ntp","proto":"udp","direction":"roundtrip","keepstate":true,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":23,"origin_id":140,"respond_id":144,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-09T12:15:20.131Z","updated_at":"2021-11-09T12:15:20.131Z","discarded_at":null,"_vv":"001.000"},{"id":185,"name":"INFRA.maint","comment":"","primacy":"normal","orig_ports":"","resp_ports":"ssh","proto":"tcp","direction":"roundtrip","keepstate":true,"setup":true,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":24,"origin_id":144,"respond_id":140,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-09T12:18:26.244Z","updated_at":"2021-11-17T10:08:46.705Z","discarded_at":null,"_vv":"001.000"},{"id":186,"name":"SVC.VPN","comment":"tunnel anwahl","primacy":"normal","orig_ports":"8111","resp_ports":"8106","proto":"udp","direction":"roundtrip","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":25,"origin_id":144,"respond_id":140,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-10T23:47:59.910Z","updated_at":"2022-03-28T11:35:39.961Z","discarded_at":null,"_vv":"001.000"},{"id":192,"name":"INFRA.lan","comment":"","primacy":"normal","orig_ports":"","resp_ports":"bareos-sd","proto":"tcp","direction":"roundtrip","keepstate":true,"setup":true,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":26,"origin_id":140,"respond_id":141,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-17T10:08:25.541Z","updated_at":"2021-11-17T10:08:25.541Z","discarded_at":null,"_vv":"001.000"},{"id":182,"name":"SVC.bckp","comment":"lokaler client","primacy":"normal","orig_ports":"","resp_ports":"bareos-fd","proto":"tcp","direction":"roundtrip","keepstate":true,"setup":true,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":27,"origin_id":141,"respond_id":140,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-17T10:09:40.383Z","updated_at":"2021-11-17T10:09:40.383Z","discarded_at":null,"_vv":"001.000"},{"id":184,"name":"SVC.web","comment":"http access mit portforward","primacy":"normal","orig_ports":"","resp_ports":"http","proto":"tcp","direction":"roundtrip","keepstate":true,"setup":true,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":28,"origin_id":142,"respond_id":141,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-18T11:58:45.589Z","updated_at":"2022-03-28T11:34:52.777Z","discarded_at":null,"_vv":"001.000"},{"id":189,"name":"SVC.GIF","comment":"","primacy":"normal","orig_ports":"","resp_ports":"","proto":"ipencap","direction":"roundtrip","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":29,"origin_id":140,"respond_id":145,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-18T22:33:57.102Z","updated_at":"2021-11-18T22:33:57.102Z","discarded_at":null,"_vv":"001.000"},{"id":190,"name":"GW.tunnel","comment":"nach lbnk","primacy":"normal","orig_ports":"","resp_ports":"","proto":"any","direction":"roundtrip","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":30,"origin_id":147,"respond_id":148,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-18T23:37:04.817Z","updated_at":"2022-03-28T11:37:03.136Z","discarded_at":null,"_vv":"001.000"},{"id":191,"name":"GW.tunnel","comment":"","primacy":"normal","orig_ports":"","resp_ports":"","proto":"any","direction":"roundtrip","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":31,"origin_id":149,"respond_id":141,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-18T23:42:20.277Z","updated_at":"2021-11-18T23:50:09.165Z","discarded_at":null,"_vv":"001.000"},{"id":183,"name":"SVC.lbnk","comment":"nat für tunnelendpunkt","primacy":"normal","orig_ports":"","resp_ports":"","proto":"any","direction":"roundtrip","keepstate":false,"setup":false,"setnr":null,"limitcnt":10,"limsrchost":false,"limsrcport":false,"limdsthost":false,"limdstport":false,"seqnr":32,"origin_id":140,"respond_id":143,"ori_in_shp_id":null,"ori_out_shp_id":null,"rsp_in_shp_id":null,"rsp_out_shp_id":null,"created_at":"2021-11-19T00:07:00.540Z","updated_at":"2022-03-28T11:36:12.460Z","discarded_at":null,"_vv":"001.000"}],"filters":[{"id":15,"name":"blacklist","mode":"rules","rewrite":"norew","port":"","localip_id":141,"entry":10,"size":1035,"blk1918":false,"created_at":"2021-11-18T12:12:33.279Z","updated_at":"2021-11-18T12:12:33.279Z","discarded_at":null,"_vv":"001.000"},{"id":14,"name":"natd.portfd","mode":"divert","rewrite":"natph","port":"8201","localip_id":140,"entry":null,"size":null,"blk1918":false,"created_at":"2021-11-18T11:57:37.511Z","updated_at":"2022-03-28T11:21:45.617Z","discarded_at":null,"_vv":"001.000"}],"forwards":[{"id":4,"name":"lbnk","remoteip_id":146,"responding_id":146,"created_at":"2021-11-19T00:02:28.952Z","updated_at":"2022-03-28T11:31:06.304Z","discarded_at":null,"_vv":"001.000"}],"tables":[],"shapers":[],"_vv":"001.000"}

You can upload this to https://flowm.daemon.contact/, optionally edit it, and then you can use this script to dynamically update it on the target. (The generated rulesets are fully dynamic and updating won't normally drop stateful connections. That works with sets - and using sets with e.g. nptv6 is a fun in itself - that is what bug 260796 is about.)

Have fun. :)
 
Last edited:
I'd like to chime in...

In other threads, it's been noted that the logic of PF and IPFW setups are actually inverses, so there's the pitfall that if you don't set up a rule correctly, it won't work as intended:
Oh, and I've seen people at my workplace struggle with IPchains about a year ago, they quoted some weird-looking IPchains rules. And it hit me only this past weekend: Yeah, that was a Windows admin who expected that the Windows Firewall logic will translate to IPchains. 😩
 
You can upload this to https://flowm.daemon.contact/, optionally edit it, and then you can use this script to dynamically update it on the target. (The generated rulesets are fully dynamic and updating won't normally drop stateful connections. That works with sets - and using sets with e.g. nptv6 is a fun in itself - that is what bug 260796 is about.)

Thank you for the thoughtful information, the demo ipfw config in JSON format, and mentioning flowm.daemon.contact and that script. Very useful.
 
Oh, and I've seen people at my workplace struggle with IPchains about a year ago, they quoted some weird-looking IPchains rules. And it hit me only this past weekend: Yeah, that was a Windows admin who expected that the Windows Firewall logic will translate to IPchains. 😩
Same here. I do IPFW and only that. The trick with IPFW is, it is NOT a wall. With the word "wall" you instinctively think two sides, an evil outside and a safe inside. You can do that (and most people actually do), but IPFW is a lot more, and in the ultimate it doesn't make sense anyway, because, you may have a public WLAN (and a secure WLAN) and an uplink and some vpn-links to other places, and so on - so now, where is the inside and outside of the wall?

IPFW copes with that, when we handle each network connection individually. A machine has some network interfaces, and these are enumerable, so that is a good place to begin. And then we decide, which flows to we have going thru that interface (and to which places do they go), and then: should it be filtered, and with which filters? Should it be NATed? Should it be rerouted and along which conditions? Should it be bandwidth-limited? Should it be stateful? etc.
These are just arbitrary building blocks that can be put together in any number; and finally the software does sort it all out and spit out a ruleset that will work.

I am quite certain any other firewall type could do similar just as well, if you know how to do it. But then, it's necessary to dive quite deep into it in order to create a ruleset generating software - and you don't want to do that multiple times.

Anyway, I had to do it, because it can be done. Most people just want a wall, they want to cave in, because outside is where the evil is. (I personally don't believe in evil.) Sometimes that's a problem - I have a plugin for security/suricata; it can run on a divert socket, but suricata folks don't want to support that further, they just want to support walls, and there are quite some performance problems.
 
I started out using ipfw before pf was available over two decades ago. Now I use pf. It's closer, IMO, to Cisco IOS ACLs which is why I use it plus you can use it for QoS. Either one will work based on your needs. I just evolved to needing pf plus it works with how my brain is wired deciphering config files and debugging output.
 
Last edited:
When I created my own little FreeBSD router which really does just some basic stuff I first looked at IPFW. It reminded me too much of Linux' iptables, which I really do loathe, so I instead switched over to Pf and never looked back since then. That's the beauty of having a choice.
 
I watched that firewall part, good introductory level stuff for the audience. He doesn't say anything particularly useful, he just prefers pf and cites an example or two. I use pf on BSD, seemed like the "go to" at the time I started with FreeBSD.

He mentions "ipchains" in 2018... he was too out of touch with "Linux" to make any mention of it and should have just stuck to the BSD side of his talk. edit: I notice someone above also referred to "ipchains", in 2022...
 
Last edited:
Back
Top