Date: Tue, 15 Sep 2009 13:45:42 -0400 From: Maxim Khitrov <mkhitrov@gmail.com> To: Doug Barton <dougb@freebsd.org> Cc: kan@freebsd.org, bzeeb-lists@lists.zabbadoz.net, Gert Doering <gert@greenie.muc.de>, freebsd-pf@freebsd.org Subject: Re: Moving the pf rc.d scripts to run before netif Message-ID: <26ddd1750909151045ia8bc7f1r9abfccb360538c8@mail.gmail.com> In-Reply-To: <4A36A051.3040007@FreeBSD.org> References: <4A242035.8010101@FreeBSD.org> <20090615065817.GJ290@greenie.muc.de> <4A36A051.3040007@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Jun 15, 2009 at 3:26 PM, Doug Barton <dougb@freebsd.org> wrote: > Gert Doering wrote: >> Hi Doug, >> >> thanks for taking this up - and sorry for not responding more timely. >> >> I can't answer all the questions but might have a yet-unmentioned idea >> that could solve all this in one go :-) >> >> On Mon, Jun 01, 2009 at 11:38:45AM -0700, Doug Barton wrote: >>> 2. The previous rcorder for the pf script was right after netif (the >>> network coming up) and before routing .... why? Is this related to how >>> pf does its work? The reason I ask this question is that in order to >>> fix the IPv6 rcorder problem in the pr the way that Gert is suggesting >>> the "BEFORE: routing" would have to be removed because our IPv6 >>> startup depends on RA which depends on routing being up. (Side note, >>> in the long term I'd like to revise this so that an IPv6-only host >>> and/or a host with statically assigned IPv6 addresses can easily be >>> configured within rc.d, but that's another thing altogether.) >>> >>> 3. Is the need to be able to use $ext_if after the network is up so >>> overwhelmingly important that it justifies running pf after netif? Or >>> is using ($ext_if) a reasonable solution? >> >> Well - let's turn this one around: since we *have* the functionality in >> pf(4), let's not cripple it by building a framework that makes using thi= s >> functionality effectively impossible. =C2=A0If I understand Bjoern right= , this >> is also a performance issue - ($ext_if) needs a per-packet lookup to >> get the now-current address, while $ext_if reads the address at pf setup >> time. >> >> >> I can see the arguments for having the firewall initialization right at >> the start - to avoid opening an window of opportunity where services are >> "up" but the firewall hasn't yet been loaded. >> >> >> So what about the following approach: >> >> =C2=A0- split the firewall initialization into two halves >> >> =C2=A0- the first half is run before any other networking stuff is confi= gured >> =C2=A0 =C2=A0and basically sets up a "deny everything incoming" filter (= with >> =C2=A0 =C2=A0exceptions for IPv6 RD/ND, of course). >> >> =C2=A0 =C2=A0Optionally this could permit outbound connections (with sta= te), to >> =C2=A0 =C2=A0enable things like bgpd to run. >> >> =C2=A0- after this, run interface configuration, set up routing, ... >> >> =C2=A0- when all this is finished, load the "real" set of firewall rules= , >> =C2=A0 =C2=A0which can now (if so desired) safely use $ext_if > > I already said I support this solution, I'm just waiting for someone > with some real pf knowledge to propose something. > > Doug Hello all, I just ran into this problem of pf start-up order on 7.2. I have a number of nat and rdr rules that allow people on the outside to access some internal servers (web, mail, etc.). To avoid having to specify public and private IPs once in the DNS server, which is on the internal interface, and a second time in the pf configuration, all of these rules use host names. During start-up, the DNS server cannot be reached, so pf.conf is not loaded due to unresolved hostnames. The solution I used is basically as explained by Gert. It works for me, but would be much better if someone could commit a more permanent fix. The idea is to have two separate pf configuration files and rc scripts. One rc script (I called mine pf_init and put it into /usr/local/etc/rc.d/ for now) runs instead of the current /etc/rc.d/pf (before routing is enabled). This script loads /etc/pf.init which contains the following configuration: # pf configuration that is loaded before routing set skip on lo scrub in block in Just a basic filter that has no external dependencies and blocks all incoming traffic. Outgoing traffic, like DNS queries, would be allowed by the default pass rule. The second rc script is a modified version of the current /etc/rc.d/pf. All I did was change two lines: --- /usr/src/etc/rc.d/pf 2009-04-14 23:14:26.000000000 -0400 +++ /etc/rc.d/pf 2009-09-15 13:06:07.000000000 -0400 @@ -7,2 +7,2 @@ -# REQUIRE: FILESYSTEMS netif pflog pfsync -# BEFORE: routing +# REQUIRE: FILESYSTEMS netif pflog pfsync named +# BEFORE: DAEMON ntpdate I added named to the REQUIRE list, which in my case is provided by dnsmasq. This allows the firewall to query ISP and internal DNS servers before the real pf.conf is loaded. I also wanted pf.conf loaded before other network-related scripts like ntpdate. Not sure if there are some other things that need to be included for a more general solution, but this works for me. My pf_init script is at the bottom of this message. Feel free to take any of my work, improve it, and commit to the source tree. You would need to move pf_init_rules variable, which is currently defined in pf_init to /etc/defaults/rc.conf. That would allow people to specify a config to use other than /etc/pf.init. The only thing I wasn't sure about is if there is a better way to disable stop and restart rc commands than to set stop_cmd and restart_cmd to an empty function. We don't want to use pf_init to reload or restart the firewall, since that would replace the correct ruleset with the pre-routing one. - Max /usr/local/etc/rc.d/pf_init: #!/bin/sh # # PROVIDE: pf_init # REQUIRE: FILESYSTEMS netif pflog pfsync # BEFORE: routing # KEYWORD: nojail . /etc/rc.subr name=3D"pf_init" rcvar=3D`set_rcvar` load_rc_config "pf" start_cmd=3D"" stop_cmd=3D"pf_pass" restart_cmd=3D"pf_pass" pf_init_rules=3D"/etc/pf.init" required_files=3D"$pf_init_rules" required_modules=3D"pf" pf_start() { echo "Enabling pf (init)." $pf_program -F all > /dev/null 2>&1 $pf_program -f "$pf_init_rules" $pf_flags if ! $pf_program -s info | grep -q "Enabled" ; then $pf_program -e fi } pf_pass() { } run_rc_command "$1"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?26ddd1750909151045ia8bc7f1r9abfccb360538c8>