From nobody Wed Nov 05 15:21:08 2025 X-Original-To: dev-commits-src-branches@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 4d1pts4Pz9z6GSd7; Wed, 05 Nov 2025 15:21:09 +0000 (UTC) (envelope-from git@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 "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4d1ptr5bHyz4PqG; Wed, 05 Nov 2025 15:21:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762356068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Aa2NfW3SIufLYp51Ut+QtACeB+wegUe/PnkJcWj0Bzg=; b=yIHhRFid4RqJ8C4ZsUNAqMynPFFzv2VKXEaIh/b8QPE5O9d0GQ62njjgcS3MNHjgpLkTro dxSpMFpeXPnU9w5ff1qjyz4XOwOP8qvNsEyw2rA8NpP3HVIuWOdORyn+OMLOgAQ9srIKMH X/9RYGrKLwA/uWMrWV7KmtzrnlbWEhjm99Chbvy7eax2cJVY35AwtjiKkCmnaQsyKKyQEC inNX6oNTyj0av+xmVca32HeYYJ17WbwnPYlsWClTxwv7wt21zag151Zwj47AAF/qISGkm6 6AMhmeU67Hwpvc7JGzuz7fW+dMwFZYh80Ew7SdVNG9SMCjBuax3i8rPwmgV8wQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762356068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Aa2NfW3SIufLYp51Ut+QtACeB+wegUe/PnkJcWj0Bzg=; b=fBL76gjSfP3dh7x8I3RRdwLrn+TtpaLUJZ+UIFExNHxxohDWjQrEIieOh3uK441tq1BkAS UgwgsXFQhKBLhdklg8E86mil0go6p8EIVscSLUypY3WQVqPSayNmGxUgkwna4SXAbtAToe LRYTQFcJ9707kbTKQZfEVHAsx7XPDJDsIeFqFEzLPLgpVT599FlCtxPw5AYuuX+Obc/Ofc wFS6qXwzfy2fdgxWPDagiFpxeZRIs+LCOLQLuL0gFKe9KbiWlzE61KfwkATlNXAbGLMKfO kSo2XDdj9NM2wexDWO1MG4cz2J0Rt+tZsMHbr5wppfNaLFHqMv57f8JP4CeYsg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1762356068; a=rsa-sha256; cv=none; b=YSz7jG/hnJSaY9p5TRmTC/Rbk6suSUYTvGkqLJXDPeY4uJZXzZlHgAc5Evauko4V8TMfMV 3UOcYa+AU7+FHKXiKuZME7/TaJ+A7HSgOc/vpOPSVojlz07A9ExcxJfxiqSAwAfrwAprM+ Eqc7yWoIhvrWC3OFfm+1DhrhKQDieAuV50zgWISn6ixEWMX8KqnZWIXE3tSqWd4pE3mm4D 4FGVtugPQQK5GeC79CL1qk7se8nJfef1xbykvW/FkLu+AsmyKULrK7ysWCiHLDGHYUhdVw gYA5PGCd2S/5CaM6fIdE3mZK//NZOqfWI5iWe/fhfy+vC+G9N6ncCi+JGViBnQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 4d1ptr59jhzpQt; Wed, 05 Nov 2025 15:21:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 5A5FL80e010092; Wed, 5 Nov 2025 15:21:08 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 5A5FL86H010089; Wed, 5 Nov 2025 15:21:08 GMT (envelope-from git) Date: Wed, 5 Nov 2025 15:21:08 GMT Message-Id: <202511051521.5A5FL86H010089@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Jose Luis Duran Subject: git: 6985b90cd0fc - stable/14 - blocklist: Update the blacklistd-helper script List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jlduran X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 6985b90cd0fcdd6a6ddff23a87f5609d1113a187 Auto-Submitted: auto-generated The branch stable/14 has been updated by jlduran: URL: https://cgit.FreeBSD.org/src/commit/?id=6985b90cd0fcdd6a6ddff23a87f5609d1113a187 commit 6985b90cd0fcdd6a6ddff23a87f5609d1113a187 Author: Jose Luis Duran AuthorDate: 2025-11-05 15:06:17 +0000 Commit: Jose Luis Duran CommitDate: 2025-11-05 15:20:00 +0000 blocklist: Update the blacklistd-helper script Update the blacklistd-helper script, it provides a better mechanism for detecting the active packet filter. This is a direct commit to stable/14, as blacklist has been renamed to blocklist. PR: 290645 --- contrib/blocklist/libexec/blacklistd-helper | 172 +++++++++++++++++++++++++--- 1 file changed, 155 insertions(+), 17 deletions(-) diff --git a/contrib/blocklist/libexec/blacklistd-helper b/contrib/blocklist/libexec/blacklistd-helper index f92eab8b29bd..fa53c8c84932 100644 --- a/contrib/blocklist/libexec/blacklistd-helper +++ b/contrib/blocklist/libexec/blacklistd-helper @@ -17,24 +17,41 @@ if [ -f "/etc/ipfw-blacklist.rc" ]; then fi if [ -z "$pf" ]; then - for f in npf pf ipf; do - if [ -f "/etc/$f.conf" ]; then + for f in npf pf ipfilter ipfw; do + if [ -x /etc/rc.d/$f ]; then + if /etc/rc.d/$f status >/dev/null 2>&1; then + pf="$f" + break + fi + elif [ -f "/etc/$f.conf" ]; then + # xxx assume a config file means it can be enabled -- + # and the first one wins! pf="$f" break fi done fi +if [ -z "$pf" -a -x "/sbin/iptables" ]; then + pf="iptables" +fi + if [ -z "$pf" ]; then echo "$0: Unsupported packet filter" 1>&2 exit 1 fi +flags= if [ -n "$3" ]; then + raw_proto="$3" proto="proto $3" + if [ $3 = "tcp" ]; then + flags="flags S/SAFR" + fi fi if [ -n "$6" ]; then + raw_port="$6" port="port $6" fi @@ -51,12 +68,65 @@ esac case "$1" in add) case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -f - -s >/dev/null 2>&1 && echo OK + ipfilter) + # N.B.: If you reload /etc/ipf.conf then you need to stop and + # restart blacklistd (and make sure blacklistd_flags="-r"). + # This should normally already be implemented in + # /etc/rc.d/ipfilter, but if then not add the following lines to + # the end of the ipfilter_reload() function: + # + # if checkyesnox blacklistd; then + # /etc/rc.d/blacklistd restart + # fi + # + # XXX we assume the following rule is present in /etc/ipf.conf: + # (should we check? -- it probably cannot be added dynamically) + # + # block in proto tcp/udp from any to any head blacklistd + # + # where "blacklistd" is the default rulename (i.e. "$2") + # + # This rule can come before any rule that logs connections, + # etc., and should be followed by final rules such as: + # + # # log all as-yet unblocked incoming TCP connection + # # attempts + # log in proto tcp from any to any flags S/SAFR + # # last "pass" match wins for all non-blocked packets + # pass in all + # pass out all + # + # I.e. a "pass" rule which will be the final match and override + # the "block". This way the rules added by blacklistd will + # actually block packets, and prevent logging of them as + # connections, because they include the "quick" flag. + # + # N.b.: $port is not included/used in rules -- abusers are cut + # off completely from all services! + # + # Note RST packets are not returned for blocked SYN packets of + # active attacks, so the port will not appear to be closed. + # This will probably give away the fact that a firewall has been + # triggered to block connections, but it prevents generating + # extra outbound traffic, and it may also slow down the attacker + # somewhat. + # + # Note also that we don't block all packets, just new attempts + # to open connections (see $flags above). This allows us to do + # counterespionage against the attacker (or continue to make use + # of any other services that might be on the same subnet as the + # supposed attacker). However it does not kill any active + # connections -- we rely on the reporting daemon to do its own + # protection and cleanup. + # + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "rem" command below! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -f - >/dev/null 2>&1 && echo OK ;; + ipfw) # use $ipfw_offset+$port for rule number rule=$(($ipfw_offset + $6)) @@ -69,10 +139,23 @@ add) table"("$tname")" to any dst-port $6 >/dev/null && \ echo OK ;; + + iptables) + if ! /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --new-chain "$2" + fi + /sbin/iptables --append INPUT --proto "$raw_proto" \ + --dport "$raw_port" --jump "$2" + /sbin/iptables --append "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" --jump DROP + echo OK + ;; + npf) /sbin/npfctl rule "$2" add block in final $proto from \ "$addr/$mask" to any $port ;; + pf) # if the filtering rule does not exist, create it /sbin/pfctl -a "$2/$6" -sr 2>/dev/null | \ @@ -83,45 +166,100 @@ add) /sbin/pfctl -qa "$2/$6" -t "port$6" -T add "$addr/$mask" && \ /sbin/pfctl -qk "$addr" && echo OK ;; + esac ;; rem) case "$pf" in - ipf) - /sbin/ipfstat -io | /sbin/ipf -I -f - >/dev/null 2>&1 - echo block in quick $proto from $addr/$mask to \ - any port=$6 head port$6 | \ - /sbin/ipf -I -r -f - -s >/dev/null 2>&1 && echo OK + ipfilter) + # N.B.: The rule generated here must exactly match the + # corresponding rule generated for the "add" command above! + # + echo block in log quick $proto \ + from $addr/$mask to any $flags group $2 | \ + /sbin/ipf -A -r -f - >/dev/null 2>&1 && echo OK ;; + ipfw) /sbin/ipfw table "port$6" delete "$addr/$mask" 2>/dev/null && \ echo OK ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --delete "$2" --proto "$raw_proto" \ + --source "$addr/$mask" --dport "$raw_port" \ + --jump DROP + fi + echo OK + ;; + npf) /sbin/npfctl rule "$2" rem-id "$7" ;; + pf) /sbin/pfctl -qa "$2/$6" -t "port$6" -T delete "$addr/$mask" && \ echo OK ;; + esac ;; flush) case "$pf" in - ipf) - /sbin/ipf -Z -I -Fi -s > /dev/null && echo OK + ipfilter) + # + # N.B. WARNING: This is obviously not reentrant! + # + # First we flush all the rules from the inactive set, then we + # reload the ones that do not belong to the group "$2", and + # finally we swap the active and inactive rule sets. + # + /sbin/ipf -I -F a + # + # "ipf -I -F a" also flushes active accounting rules! + # + # Note that accounting rule groups are unique to accounting + # rules and have nothing to do with filter rules, though of + # course theoretically one could use the same group name for + # them too. + # + # In theory anyone using any such accounting rules should have a + # wrapper /etc/rc.conf.d/blacklistd script (and corresponding + # /etc/rc.conf.d/ipfilter script) that will record and + # consolidate the values accumulated by such accounting rules + # before they are flushed, since otherwise their counts will be + # lost forever. + # + /usr/sbin/ipfstat -io | fgrep -v "group $2" | \ + /sbin/ipf -I -f - >/dev/null 2>&1 + # + # This MUST be done last and separately as "-s" is executed + # _while_ the command arguments are being processed! + # + /sbin/ipf -s && echo OK ;; + ipfw) /sbin/ipfw table "port$6" flush 2>/dev/null && echo OK ;; + + iptables) + if /sbin/iptables --list "$2" >/dev/null 2>&1; then + /sbin/iptables --flush "$2" + fi + echo OK + ;; + npf) /sbin/npfctl rule "$2" flush ;; + pf) # dynamically determine which anchors exist - for anchor in $(/sbin/pfctl -a "$2" -s Anchors); do - /sbin/pfctl -a $anchor -t "port${anchor##*/}" -T flush - /sbin/pfctl -a $anchor -F rules + for anchor in $(/sbin/pfctl -a "$2" -s Anchors 2> /dev/null); do + /sbin/pfctl -a "$anchor" -t "port${anchor##*/}" -T flush + /sbin/pfctl -a "$anchor" -F rules done echo OK ;;