Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 04 Jun 2021 09:53:17 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 256410] pf: Add pf_default_rules option
Message-ID:  <bug-256410-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D256410

            Bug ID: 256410
           Summary: pf: Add pf_default_rules option
           Product: Base System
           Version: Unspecified
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: misc
          Assignee: bugs@FreeBSD.org
          Reporter: thomas@gibfest.dk

Created attachment 225540
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=3D225540&action=
=3Dedit
The patch for /etc/rc.d/pf and /etc/defaults/rc.conf

Out of the three firewalls in FreeBSD pf is the only one without a way to m=
ake
it default to deny everything:

- IPFW has "65535 deny ip from any to any" unless IPFIREWALL_DEFAULT_TO_ACC=
EPT
is set.
- ipfilter has something called IPFILTER_DEFAULT_BLOCK, I think. I don't re=
ally
know anything about ipfilter.

With pf, if no rules are loaded all traffic is permitted. This can be
considered a feature or a problem, recently it was a very big problem in my
end.

I propose the attached patch for /etc/rc.d/pf and a couple of new rc.conf
variables pf_default_rules_enable and pf_default_rules to improve this
situation.

The patch simply checks the exit code of the pfctl command which loads the
pf.conf ruleset, and if the exit code is 1 and pf_default_rules_enable is s=
et
to YES, then it loads the rules in pf_default_rules, which defaults to a si=
ngle
rule: "block drop log all".

BACKGROUND:
A little backstory might help clear up why I think this is a valuable and
neccesary change.

We (our company) had ended up with a pf.conf with a typo in it. The typo was
that the leading "$" sign of a macro was missing. This makes pf treat it as=
 a
hostname instead of a macro, so it does a DNS lookup to process the firewall
rule. The typo could have been a missing quote or something else too, the
central point is the pf.conf was invalid, and it had been missed (humans be=
ing
human and all that).

The server in question was then rebooted, and suddently no firewall rules w=
ere
loaded, permitting all traffic to the networks behind it, leading to some b=
ad
times at the office before it was discovered.

In the postmortem clean-up it was determined that since /etc/rc.d/pf had fa=
iled
to load the ruleset during bootup, and there being no "default block
functionality", there was 0 rules loaded so it of course permitted everythi=
ng.

On these particular firewall machines it would have been MUCH better to hav=
e a
non-functional firewall than a fully open one. YMMV, and the default in my
patch is to keep the status quo, of course.

With this patch and pf_default_rules_enable set to YES I would have discove=
red
the issue much sooner and with no security incidents, which is vastly
preferable in this situation.

THE PATCH:
Mostly it is just a new "if" block around the pfctl -f call inside pf_start=
().
I included some warnings (for both cases) while here.

The only files touched are /etc/rc.d/pf and /etc/defaults/rc.conf.

EXAMPLE:
Note: All of these examples are with the attached patch applied.

I made two simple pf.conf files where one has small but significant typo:
[tykling@nuc2 ~]$ cat /etc/pf.conf=20
foo=3D"192.0.2.42"
pass in quick on em0 from any to $foo
[tykling@nuc2 ~]$ cat /etc/pf-typo.conf=20
foo=3D"192.0.2.42"
pass in quick on em0 from any to foo
[tykling@nuc2 ~]$=20

Note how "foo" is missing the leading $ sign meaning pf interprets it as a
hostname, which can't be resolved in this case.

First the default behaviour with no changes in rc.conf and a valid ruleset:

[tykling@nuc2 ~]$ sudo sysrc pf_default_rules_enable
pf_default_rules_enable: NO
[tykling@nuc2 ~]$ sudo sysrc pf_default_rules=20=20=20=20=20=20=20
pf_default_rules: block drop log all
[tykling@nuc2 ~]$ sysrc pf_rules
pf_rules: /etc/pf.conf
[tykling@nuc2 ~]$ sudo service pf restart
Password:
Enabling pf.
[tykling@nuc2 ~]$ sudo pfctl -s rules | wc -l
       1
[tykling@nuc2 ~]$ sudo pfctl -s rules=20=20=20=20=20=20=20=20
pass in quick on em0 inet from any to 192.0.2.42 flags S/SA keep state
[tykling@nuc2 ~]$=20

All is well, it loaded the one rule in the ruleset. Now an example with an
invalid ruleset, still with the above defaults in place:

[tykling@nuc2 ~]$ sudo service pf restart=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20
Disabling pf.
Enabling pfno IP address found for foo
/etc/pf-typo.conf:2: could not parse host specification
pfctl: Syntax error in config file: pf rules not loaded
/etc/rc.d/pf: WARNING: Unable to load pf.conf, and pf_default_rules_enable =
is
NO.
/etc/rc.d/pf: WARNING: No pf rules are loaded, this means all traffic is
permitted.
.
[tykling@nuc2 ~]$ sudo pfctl -s rules
[tykling@nuc2 ~]$=20=20=20=20

The behaviour is the same as always, but a couple of new warn() calls infor=
ms
the admin about what happened so they might spot it in /var/log/messages.

Now the same setup but with the new feature enabled:

[tykling@nuc2 ~]$ sudo sysrc pf_default_rules_enable=3D"YES"
pf_default_rules_enable: NO -> YES
[tykling@nuc2 ~]$=20

The valid ruleset behaves as always:
[tykling@nuc2 ~]$ sudo sysrc pf_rules=3D"/etc/pf.conf"=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
pf_rules: /etc/pf.conf -> /etc/pf.conf
[tykling@nuc2 ~]$ sudo service pf restart=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20
Disabling pf.
Enabling pf.
[tykling@nuc2 ~]$ sudo pfctl -s rules | wc -l=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
       1
[tykling@nuc2 ~]$=20

With the invalid ruleset the pf_default_rules are loaded:

[tykling@nuc2 ~]$ sudo sysrc pf_default_rules_enable=3D"YES"=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
pf_default_rules_enable: NO -> YES
[tykling@nuc2 ~]$ sudo service pf restart=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20
Disabling pf.
Enabling pfno IP address found for foo
/etc/pf-typo.conf:2: could not parse host specification
pfctl: Syntax error in config file: pf rules not loaded
/etc/rc.d/pf: WARNING: Unable to load pf.conf, and pf_default_rules_enable =
is
set to YES.
/etc/rc.d/pf: WARNING: Loading pf_default_rules: block drop log all
.
[tykling@nuc2 ~]$ sudo pfctl -s rules
block drop log all
[tykling@nuc2 ~]$

Say I wanted a way in, a management backdoor in case this happens, I could =
for
example choose to pass traffic on a management interface only:

[tykling@nuc2 ~]$ sudo sysrc pf_default_rules=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
pf_default_rules: block drop log all\npass quick on em0
[tykling@nuc2 ~]$ sudo service pf restart=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20
Enabling pfno IP address found for foo
/etc/pf-typo.conf:2: could not parse host specification
pfctl: Syntax error in config file: pf rules not loaded
/etc/rc.d/pf: WARNING: Unable to load pf.conf, and pf_default_rules_enable =
is
set to YES.
/etc/rc.d/pf: WARNING: Loading pf_default_rules: block drop log all\npass q=
uick
on em0
.
[tykling@nuc2 ~]$ sudo pfctl -s rules
block drop log all
pass quick on em0 all flags S/SA keep state
[tykling@nuc2 ~]$=20

I guess that is all. I hope it made sense and that the feature will find its
way into FreeBSD. I know I will be running with it locally until such a tim=
e.
Apologies in advance if I messed up the patch, I don't do this often, and I
don't have a phabricator account (yet).

Have a lovely weekend :)

ps. I know about it being FreeBSDs job to ensure a reliable delivery of bul=
let
from gun to foot. But I feel like an exception is warranted here, especially
given that the two other firewalls have similar functionality.

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-256410-227>