>>In pf nat rules also the first match wins
>>
>>__but__
>>
>>in pf filter rules the __last__ match wins.
>>
>>In fact that is the one thing I don't like in pf, but to have a "first
>>match win" you can use the magic word quick in all your pass and block
>>rules. (e.g "pass in quick")

>And thereby end up with yards of quick rules that can catch you later.

Ah, but the matching engine doesn't have to traverse the whole rule
list that way.  Unless pf is doing something really tricky, every
packet will have to traverse every firewall rule without use of
quicks.  On a complicated, busy firewall setup, this might have a
noticable performance impact.

>You should think of it this way:
>Default security is best with block everything and then pass what
>selected few things you need.
>So:
>block all
>pass in on $int_if from $safe1 to $ok2 keep state
>pass in on $ext_if from any to $ext_if port ssh keep state

I agree, with the added use of quick on each of the pass rules.

In fact, you can probably use quick on virtually every rule other than
that default without any loss of expressiveness.  Thanks to negations,
having two different precedences is largely unnecessary (previously
you'd have to pass nonquick for some set of packets, then block again
for some subset to get the same effect as a negation).

It's probably not necessary, and I may offend purists by my
performance optimizations, but I actually have this as my first rule:

pass quick on lo0

I also find it useful to use the following rule right after "default deny":

block return on $lan_if

I do have some questions about pf though.  How come you can only
modify source IP/ports outbound, and destination IP/ports inbound?
Why not the other two alternatives?

I also don't see why NAT should necessarily occur before the filtering
rules.  It makes more sense to my intuition to have the order in the
pf.conf control the order of operations, but I admit implementation
issues may make this less elegant.

Also, I find supporting $macros in pf.conf a little crufty.  Why not
just do something like this:

#! /bin/sh
lan_if=xl1
wan_if=ex0
pfctl -f /dev/stdin <<EOM
pass quick on lo0
block all
pass quick in on $lan_if all keep state
pass in quick on $wan_if from any to $wan_if proto tcp port = 22 keep state
[...]
EOM

That way, you have the full expressive power of the shell, including
command substitution, arithmetic substitution, variable substitution,
trimming suffixes and prefixes, and all kinds of shell magic.  It
doesn't replace lists or tables of course.  But you can easily do
conditional inclusion of rules, and that's useful for cases like DHCP.
 The interface comes up with IP 0.0.0.0/0, which I think means it will
accept any packet as destined for this interface, no matter what the
destination IP.  I only allow in replies from my ISP's DHCP server
during this stage, and only those destined to 255.255.255.255 (I don't
want rogue servers answering my DHCP requests, which are sent via
local broadcast (hence to all my neighbors).  It was also pretty
useful before things supported the (interface) notation for looking up
IP addresses each time.

That having been said, pf is way cool.  Keep up the good work.
--
http://www.lightconsulting.com/~travis/  -><-
GPG fingerprint: 50A1 15C5 A9DE 23B9 ED98 C93E 38E9 204A 94C2 641B

Reply via email to