[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: pf efficiency



On Thu, Jan 20, 2005 at 10:13:53PM +0100, MauroTablo' wrote:
> My Openbsd+pf based firewall has about 90 forward filtering rules, for tcp 
> packets (about 30 rules), udp datagram (about 40 rules) and icmp messages 
> (about 20 rules). Every rule looks like: "block in proto xxx from any to yyy 
> port = zzz", where xxx is the protocol type.
> Suppose that a transit tcp packet comes into my firewall.
> The question is: pf confronts the TCP packet with all my 90 rules, or it 
> confronts the packet ONLY WITH those rules (about 30) written for tcp 
> packets ("proto tcp")?
> In other words, is there a function in pf that looks up to the protocol type 
> of a transit packet and decides which rules to confront the packet with?
If your rules are ordered by protocol, pf will evaluate no more than 32 rules
in your example.
To illustrate, let's say you put the tcp rules first, followed by the
udp and icmp ones, like this:
   1. block in proto tcp from any to yyy port = zzz
   2. block in proto tcp from any to yyy port = zzz
      ...
  30. block in proto tcp from any to yyy port = zzz
  31. block in proto udp from any to yyy port = zzz
  32. block in proto udp from any to yyy port = zzz
      ...
  70. block in proto udp from any to yyy port = zzz
  71. block in proto icmp from any to yyy port = zzz
  72. block in proto icmp from any to yyy port = zzz
      ...
  90. block in proto icmp from any to yyy port = zzz
When a tcp packet arrives in on any interface, pf will start ruleset
evaluation with the first rule, continue with the second, etc.
Once it reaches rule 31 (the first 'proto udp' rule), it sees that this
rule does not match because the protocol is wrong. It knows, thanks to
a transparent optimization called 'skip steps', that the next 39 rules
all specify the same mismatching criterion 'proto udp', and hence skips
the entire block and continues with rule 71 (the first 'proto icmp'
rule). There, again, it sees that the protocol criterion is wrong, and
knows that the next 19 rules specify the same criterion, and skips those
19 rules, ending the ruleset evaluation. In total, 32 rules were
evaluated.
This optimization is not only done for the protocol criterion, but for
most criteria. For instance, if your first 50 rules contained the same
destination address (or destination port) restriction, and the packet
does not match it when the first rule is evaluated, the next 49 rules
are skipped. Or, say, an _outgoing_ packet is being filtered. pf
evaluates the first rule, sees that the rule criterion 'in' does not
match, knows that the next 89 rules specify the same 'in' criterion, and
skips the entire rest of the ruleset, effectively only evaluating a
single rule for each outgoing packet.
It's not precisely what you had in mind, I guess, but if you properly
sort your rules, it's even more efficient. Not that it will make any
observable difference with only 90 rules, usually ;)
Daniel