From nobody Fri Jun 4 09:53:17 2021 X-Original-To: bugs@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 3A14213A583D for ; Fri, 4 Jun 2021 09:53:17 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FxJ3w6Mrkz4ld3 for ; Fri, 4 Jun 2021 09:53:16 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2610:1c1:1:606c::50:1d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id C483A1AF4C for ; Fri, 4 Jun 2021 09:53:16 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org ([127.0.1.5]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id 1549rGNT082246 for ; Fri, 4 Jun 2021 09:53:16 GMT (envelope-from bugzilla-noreply@freebsd.org) Received: (from www@localhost) by kenobi.freebsd.org (8.15.2/8.15.2/Submit) id 1549rGZT082245 for bugs@FreeBSD.org; Fri, 4 Jun 2021 09:53:16 GMT (envelope-from bugzilla-noreply@freebsd.org) X-Authentication-Warning: kenobi.freebsd.org: www set sender to bugzilla-noreply@freebsd.org using -f From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 256410] pf: Add pf_default_rules option Date: Fri, 04 Jun 2021 09:53:17 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: misc X-Bugzilla-Version: Unspecified X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Some People X-Bugzilla-Who: thomas@gibfest.dk X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: bugs@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter attachments.created Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated List-Id: Bug reports List-Archive: https://lists.freebsd.org/archives/freebsd-bugs List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-bugs@freebsd.org MIME-Version: 1.0 X-ThisMailContainsUnwantedMimeParts: N 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.=