I recently spent a couple of days reading various pf documentation,
including the man pages, the faq, and some guides (including Peter
Hansteen's), and fiddling with my firewall configuration, and there are
a few subtleties that I haven't found addressed anywhere.
1) The big one is what I would call the 'double state problem'. It
seems to me that the big disadvantage of a default-deny ruleset is that
because explicit pass rules are required on all interfaces, traffic
passing through the firewall machine needs state on all interfaces.
This isn't a problem for most applications, but it seems like it would
be a memory issue for large routers.
Supposing you have the following in your pf.conf [note: all rules in my
(simplified) examples will omit the implicit 'keep state']:
---
block all
pass on $int_if
pass out on $ext_if
pass in on $ext_if from any to $ext_if port 22
---
If you now initiate a web connection from a machine on the internal
network to one on the internet, two states are created, one on each
interface, to allow return packets through.
The same problem, less obviously, occurs with a default-deny-in ruleset
like:
---
block in all
pass out all
pass in on $int_if
pass in on $ext_if from any to $ext_if port 22
---
or even with rules like
pass from $int_if:network to $ext_if:network
If you have
---
block all
pass on $int_if no state
pass out on $ext_if
pass in on $ext_if from any to $ext_if port 22
---
then the ruleset is effectively the same, and there is only one state
per connection, but traffic is (slightly) slower because return traffic
through $int_if needs to be checked against the ruleset instead of the
state table.
But if you create a default-permit ruleset with wide-ranging block
rules, like:
---
block in on $ext_if
pass in on $ext_if from any to $ext_if port 22
---
you get the same filtering results with fewer rules, one state per
connection, and no need for ruleset lookups on established streams.
The most obvious benefit of a default-deny ruleset is that it saves you
if you make a block rule too narrow, or comment it out by accident or
something. But is there a way to have only one state per connection
with a default-deny ruleset? And if not, does it ever actually matter,
or am I just being pedantic?
2) The other (shorter) question:
If I want one of my internal networks to be able to access the internet,
but not be able to access my other internal networks, is
---
table <non_local> { 0.0.0.0/0 !$int_net1 !$int_net2 }
block all
pass in on $int_net3 from any to <non_local>
[etc]
---
better or worse in speed and resources than
---
block all
pass in on $int_net3
block in on $int_net3 from any to $int_net1:network
block in on $int_net3 from any to $int_net2:network
[etc]
---
?
Any enlightenment from the pf gurus?
Thanks.
PS: please cc me on replies; I can't seem to get the list server to
accept my subscribe requests. It bounces them as spam. (!?)