OpenBSD pf rule numbers and tcpdump filtering

June 8, 2011

OpenBSD's pf packet filter can log packets to a pflog virtual network device if you ask it to; in normal configurations such logged packets appear on pflog0 and then wind up saved in /var/log/pflog. Around here we log most rejections and some stuff that we accept, partly because this makes tracking down firewall issues much easier.

If you use 'tcpdump -e' on a pflog device or log file, it will print the rule number of the rule that caused the packet to be logged (or possibly the last rule number, I'm not sure) as part of the output. It will also try to print some information about the rule itself, but I suspect that this can become inaccurate for saved log files if you add, delete, or reorder rules in your pf.conf.

(Well, if you use OpenBSD's tcpdump. I doubt anyone else's version understands this stuff.)

In theory you can use tcpdump to filter by rule number, with the 'rnr' or 'rulenum' filtering condition. In practice this is tricky to use because of two issues. First, you need to determine the number of the pf rule that you want to match against, which is not as simple as counting rule lines in your pf.conf. The authoritative source of rule numbers is to use 'pfctl -vv' when dumping either the filter rules or the NAT rules (and who knows, maybe queue rules too). You want the lines that start with '@'; the number after the '@' is the rule number. Thus:

pfctl -vvsn | fgrep @
pfctl -vvsr | fgrep @

If you do this you will immediately discover the second issue: separate sorts of rules number their rules independently. I believe that block and pass rules share one sequence, and then nat, rdr, and binat rules are each numbered separately; I don't know about scrub rules. (This is what we see on our OpenBSD firewalls, at least; on some of them, we have four different rules that are all 'rule number 0'.)

You can restrict which sort of rule you are matching with the filter 'action <TYPE>', eg 'action rdr and (rnr ...)'. Helpfully (or not), you can match blocks and passes separately.

On the whole I think that it's easier to match with IP addresses and the like, and I expect this to be more robust for looking through old logged data. If you have to keep extra logging that is making this verbose, action filter rules may help.

(One of the things that may make this necessary is that, to the best of my understanding, rules that rewrite packet addresses log the post-rewrite address. Thus, using 'action rdr and ...' can help you see only the packets that got rewritten to an active host's address, instead of all traffic involving that host's regular address that you're logging.)

Written on 08 June 2011.
« Databases as a compromise damage limiter in web applications
More impressions of Google Chrome »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed Jun 8 00:05:58 2011
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.