From nobody Mon Sep 5 02:18:02 2022 X-Original-To: questions@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 4MLXHX6wnBz4bhpp for ; Mon, 5 Sep 2022 02:18:16 +0000 (UTC) (envelope-from freebsd@gushi.org) Received: from prime.gushi.org (prime.gushi.org [IPv6:2620:137:6000:10::142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "prime.gushi.org", Issuer "RapidSSL TLS DV RSA Mixed SHA256 2020 CA-1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MLXHW2ZyQz3tWm for ; Mon, 5 Sep 2022 02:18:15 +0000 (UTC) (envelope-from freebsd@gushi.org) Received: from smtpclient.apple ([IPv6:2601:602:87f:b05d:b920:bbbd:43e0:cf48]) (authenticated bits=0) by prime.gushi.org (8.16.1/8.16.1) with ESMTPSA id 2852I7CD010691 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Sun, 4 Sep 2022 19:18:11 -0700 (PDT) (envelope-from freebsd@gushi.org) DKIM-Filter: OpenDKIM Filter v2.10.3 prime.gushi.org 2852I7CD010691 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gushi.org; s=prime2014; t=1662344292; bh=02UbGTWJK/Gal4WGXyGceUvDypZB9olRKSaW9VVK/E4=; h=Subject:From:In-Reply-To:Date:Cc:References:To; z=Subject:=20Re:=20Firewall=20rules=20in=20a=20directory|From:=20"D an=20Mahoney=20(Ports)"=20|In-Reply-To:=20|Date:=20Sun,=204=2 0Sep=202022=2019:18:02=20-0700|Cc:=20questions@freebsd.org,=0D=0A= 20kpn@neutralgood.org|References:=20<3FAB82EC-2C82-4201-AA47-B1AA9 2B89677@gushi.org>=0D=0A=20=0D=0A=20|To:=20Ian=20Smith=20; b=X4z1XhapjoRp0kuynuZ8m3cLSs2N9mZeffL9k2cwd2sxoYcFnevthtOrrFAtQfGot 9SGOLAqiHYXYcE9m77T3Nul+exBkrxQWpssyrJ3680tmTuRvl02v4fVhCS6s0S6Y1c X/T5dCC5mCDcpCHMR2slqvQWDCDvs2eVG6xP/ibClnIVhupp3rArq2Xyb8ON83M6dH vde3I62fsNeq76rOLLPnGeJ6oIUL8eFW0wLo9cwnrSX8zEL9rXi9f2SPWmsDf3UhdJ UwoxqYCl/EFz+Fwg5yNpVshB7RmLQYgTIVEunm32hnfJkMgLkAwBEVZJQkguGZPvWF XnZpUiCf5lL/Q== X-Authentication-Warning: prime.gushi.org: Host [IPv6:2601:602:87f:b05d:b920:bbbd:43e0:cf48] claimed to be smtpclient.apple Content-Type: text/plain; charset=utf-8 List-Id: User questions List-Archive: https://lists.freebsd.org/archives/freebsd-questions List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-questions@freebsd.org X-BeenThere: freebsd-questions@freebsd.org Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.1\)) Subject: Re: Firewall rules in a directory From: "Dan Mahoney (Ports)" In-Reply-To: Date: Sun, 4 Sep 2022 19:18:02 -0700 Cc: questions@freebsd.org, kpn@neutralgood.org Content-Transfer-Encoding: quoted-printable Message-Id: <9BFB27DC-BA45-49B5-8EAD-B5BE7BC14E20@gushi.org> References: <3FAB82EC-2C82-4201-AA47-B1AA92B89677@gushi.org> To: Ian Smith X-Mailer: Apple Mail (2.3696.120.41.1.1) X-Rspamd-Queue-Id: 4MLXHW2ZyQz3tWm X-Spamd-Bar: ------ Authentication-Results: mx1.freebsd.org; dkim=pass header.d=gushi.org header.s=prime2014 header.b=X4z1Xhap; dmarc=pass (policy=none) header.from=gushi.org; spf=pass (mx1.freebsd.org: domain of freebsd@gushi.org designates 2620:137:6000:10::142 as permitted sender) smtp.mailfrom=freebsd@gushi.org X-Spamd-Result: default: False [-6.20 / 15.00]; DWL_DNSWL_MED(-2.00)[gushi.org:dkim]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; NEURAL_HAM_SHORT(-1.00)[-0.998]; MV_CASE(0.50)[]; RCVD_DKIM_ARC_DNSWL_MED(-0.50)[]; DMARC_POLICY_ALLOW(-0.50)[gushi.org,none]; R_DKIM_ALLOW(-0.20)[gushi.org:s=prime2014]; RCVD_IN_DNSWL_MED(-0.20)[2620:137:6000:10::142:from]; R_SPF_ALLOW(-0.20)[+a:prime.gushi.org]; MIME_GOOD(-0.10)[text/plain]; MLMMJ_DEST(0.00)[questions@freebsd.org]; TO_MATCH_ENVRCPT_SOME(0.00)[]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[3]; RCVD_VIA_SMTP_AUTH(0.00)[]; ASN(0.00)[asn:393507, ipnet:2620:137:6000::/44, country:US]; MID_RHS_MATCH_FROM(0.00)[]; HAS_XAW(0.00)[]; TO_DN_SOME(0.00)[]; ARC_NA(0.00)[]; DKIM_TRACE(0.00)[gushi.org:+]; MIME_TRACE(0.00)[0:+]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; RCVD_TLS_ALL(0.00)[] X-ThisMailContainsUnwantedMimeParts: N > On Aug 31, 2022, at 10:47 AM, Ian Smith wrote: >=20 > On 30 August 2022 2:40:34 pm AEST, "Dan Mahoney (Ports)" = wrote: >> Note, this wasn=E2=80=99t intended to be =E2=80=9Chere=E2=80=99s a = diff, please put it in=E2=80=9D, >> just an illustration of how trivial an addition it is. >>=20 >>> On Aug 29, 2022, at 9:36 PM, Dan Mahoney (Ports) >> wrote: >>>=20 >>> All, >>>=20 >>> At the dayjob, we=E2=80=99ve taken to putting our ipfw rules into a >> directory using rcorder=E2=80=99able files. This way, each of our = puppet >> manifests can drop its own rules into place without having to manage >> a monolithic file. >>>=20 >>> It=E2=80=99s a simple patch to rc.firewall, where if you set = firewall_type >> to a file, it just runs it, but if it=E2=80=99s a directory, it would = treat >> it as such: >>>=20 >>> *) >>> if [ -r "${firewall_type}" ]; then >>> if [ -f "${firewall_type}" ]; then >>> ${fwcmd} ${firewall_flags} ${firewall_type} >>> else >>> if [ -d "${firewall_type}" ]; then >>> for fwfile in `rcorder $firewall_type/*` >>> do >>> ipfw -q $fwfile; >>> done >>> fi >>> fi >>>=20 >>> Is there a possibility of getting this into base? >>>=20 >>> -Dan >=20 > Getting code into rc.firewall has proven difficult over the years, for = me impossible. It even took julian@ a couple of years to get a sensible = use of tables into firewall_type 'simple' - but things may have changed. >=20 > I've tried rendering your code into the usual format below, saving a = level of indenting with 'elif', and noting that '-q' and path is = included in ${fwcmd} earlier in rc.firewall. >=20 > If it's really intended to launch multiple instances of ipfw, it may = win more favour - as a bug / feature request as Kevin suggests - if = you're sure how things like 'service ipfw status' or 'restart' handle = them in /etc/rc.d/ipfw? >=20 > Good Luck, Ian >=20 > > *) > if [ -r "${firewall_type}" ]; then > if [ -f "${firewall_type}" ]; then > ${fwcmd} ${firewall_flags} ${firewall_type} > elif [ -d "${firewall_type}" ]; then > for fwfile in `rcorder ${firewall_type}/*` > do > ${fwcmd} ${firewall_flags} = ${fwfile} > done > fi > fi > ;; > So, right now, there are two knobs you can tweak in /etc/rc.conf -- = firewall_type, and firewall_script. Firewall_script defaults to = /etc/rc.firewall which understands things like "open" or "client" or = "unknown", or a file. The last bit of the stock rc.firewall looks like = this: [Cc][Ll][Oo][Ss][Ee][Dd]) ${fwcmd} add 65000 deny ip from any to any ;; [Uu][Nn][Kk][Nn][Oo][Ww][Nn]) ;; *) if [ -r "${firewall_type}" ]; then ${fwcmd} ${firewall_flags} ${firewall_type} fi ;; esac Two problems there. 1) -r only checks for readability, not for it being = an actual file. and 2) For us, we *like* it being a directory. Here's an output of rcorder: rcorder /etc/ipfw.d/* /etc/ipfw.d/setup /etc/ipfw.d/production_networks /etc/ipfw.d/production_static /etc/ipfw.d/routing /etc/ipfw.d/services /etc/ipfw.d/snmp_agent /etc/ipfw.d/ssh_service /etc/ipfw.d/tftp_service /etc/ipfw.d/mosh_service /etc/ipfw.d/node_exporter_agent /etc/ipfw.d/nrpe_agent /etc/ipfw.d/ssh_vpn /etc/ipfw.d/outbound /etc/ipfw.d/local /etc/ipfw.d/krb5_client /etc/ipfw.d/dns_client /etc/ipfw.d/syslog_client /etc/ipfw.d/ntp_client /etc/ipfw.d/final And...as an example, here's some of /etc/ipfw.d/setup (note the PROVIDE = and BEFORE entries at top, like rcorder wants). # # PROVIDE: setup blocked bogons # BEFORE: services routing outbound final # # remove all existing tables table all destroy table blocked create # standard (non-service specific) tables table bogons create table bogons add 0.0.0.0/8 table bogons add 10.0.0.0/8 table bogons add 172.12.0.0/12 table bogons add 192.168.0.0/16 table bogons add 169.254.0.0/16 table bogons add 240.0.0.0/4 # permit existing TCP sessions add allow tcp from any to any established # permit existing stateful traffic add check-state :default // permit stateful traffic # permit internal loopback traffic add allow ip from any to any via lo0 add allow ip from any to any via lo1 # deny directed loopback traffic add deny ip from any to 127.0.0.0/8 in add deny ip from any to ::/64 in # deny unexpected sources add deny ip from table(bogons) to me in // unexpected sources # deny explicitly disabled (non-persistent) sources add deny ip from table(blocked) to me in // emergency (non-persistent) = blocklist # allow bsd-standard-port traceroutes add allow udp from me to any 33434-33600 // traceroute in add allow udp from any to me 33434-33600 // traceroute out # moderately permissive ICMPv4 add allow icmp from any to any icmptypes 0,3,8,11,13,14 // safe ICMPv4 # link-local ICMPv6 (RS, RA, NS, NA) - per FreeBSD standard rules add allow ipv6-icmp from :: to fe80::/10 // ICMPv6 DAD add allow ipv6-icmp from fe80::/10 to fe80::/10 // ICMPv6 NDP add allow ipv6-icmp from fe80::/10 to ff02::/16 // ICMPv6 NDP add allow ipv6-icmp from any to any icmp6types 1,2,3,128,129,135,136 // = safe ICMPv6 .... And here's a service entry... more /etc/ipfw.d/ssh_service # REQUIRE: services # PROVIDE: ssh_service ssh_clients # BEFORE: outbound table ssh_clients create table ssh_clients add 1.2.3.4 table ssh_clients add 2001:dead:beef:cafe::d00d add allow tcp from table(ssh_clients) to me 22 in setup // = inbound SSH =3D=3D Also unique to our setup: the "local" script is created by puppet but = not managed by it, so if you need to drop an emergency override in there = for something (i.e. block an attacker, or open a port that you haven't = added to automation yet, add a counter to debug an issue, you can, = quickly). Some of our scripts are placeholders, just existing as a no-op to anchor = things like BEFORE. If people wanted things to put in /usr/share/examples (say = /usr/share/examples/ipfw/client, or /usr/share/examples/ipfw/closed?) = that mimic'd the main setup, I'd be happy to contribute them. (I'm also not thrilled with the fact that the stock firewall script adds = rules before it determines what kind of firewall you want, and then = applies your rules...that could perhaps be a different bug though). If there's a diffferent list I should be posting this to, let me know. -Dan=