Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/bsd/blocklist TODO and ipfilter improvements from G...



details:   https://anonhg.NetBSD.org/src/rev/89396771f851
branches:  trunk
changeset: 953348:89396771f851
user:      christos <christos%NetBSD.org@localhost>
date:      Sun Mar 07 00:46:39 2021 +0000

description:
TODO and ipfilter improvements from Greg A. Woods

diffstat:

 external/bsd/blocklist/TODO                      |   88 ++++++++++++++++-
 external/bsd/blocklist/etc/rc.d/blocklistd       |    4 +-
 external/bsd/blocklist/libexec/blocklistd-helper |  125 +++++++++++++++++++++-
 3 files changed, 205 insertions(+), 12 deletions(-)

diffs (truncated from 323 to 300 lines):

diff -r 9aabd9378307 -r 89396771f851 external/bsd/blocklist/TODO
--- a/external/bsd/blocklist/TODO       Sun Mar 07 00:23:06 2021 +0000
+++ b/external/bsd/blocklist/TODO       Sun Mar 07 00:46:39 2021 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: TODO,v 1.1.1.1 2020/06/15 01:52:52 christos Exp $
+# $NetBSD: TODO,v 1.2 2021/03/07 00:46:39 christos Exp $
 
 - don't poll periodically, find the next timeout
 - use the socket also for commands? Or separate socket?
@@ -19,3 +19,89 @@
        unblock
 - do we need an api in blocklistctl to perform maintenance
 - fix the blocklistctl output to be more user friendly
+
+- figure out some way to do distributed operation securely (perhaps with
+  a helper daemon that authenticates local sockets and then communicates
+  local DB changes to the central server over a secure channel --
+  perhaps blocklistd-helper can have a back-end that can send updates to
+  a central server)
+
+- add "blocklistd -l" to enable filter logging on all rules by default
+
+- add some new options in the config file
+
+       "/all"  - block both TCP and UDP (on the proto field?)
+
+       "/log"  - enable filter logging (if not the default) (on the name field?)
+       "/nolog"- disable filter logging (if not the default) (on the name field?)
+
+  The latter two probably require a new parameter for blocklistd-helper.
+
+- "blocklistd -f" should (also?) be a blocklistctl function!?!?!
+
+- if blocklistd was started with '-r' then a SIGHUP should also do a
+  "control flush $rulename" and then re-add all the filter rules?
+
+- should/could /etc/rc.conf.d/ipfilter be created with the following?
+
+       reload_postcmd=blocklistd_reload
+       start_postcmd=blocklistd_start
+       stop_precmd=blocklistd_stop
+       blocklistd_reload ()
+       {
+               /etc/rc.d/blocklistd reload     # IFF SIGHUP does flush/re-add
+               # /etc/rc.d/blocklistd restart
+       }
+       blocklistd_stop ()
+       {
+               /etc/rc.d/blocklistd stop
+       }
+       blocklistd_start ()
+       {
+               /etc/rc.d/blocklistd start
+       }
+
+  or is there a better way?
+
+- figure out some way to do distributed operation securely (perhaps with
+  a helper daemon that authenticates local sockets and then communicates
+  local DB changes to the central server over a secure channel --
+  perhaps blocklistd-helper can have a back-end that can send updates to
+  a central server)
+
+- add "blocklistd -l" to enable filter logging on all rules by default
+
+- add some new options in the config file
+
+       "/all"  - block both TCP and UDP (on the proto field?)
+
+       "/log"  - enable filter logging (if not the default) (on the name field?)
+       "/nolog"- disable filter logging (if not the default) (on the name field?)
+
+  The latter two probably require a new parameter for blocklistd-helper.
+
+- "blocklistd -f" should (also?) be a blocklistctl function!?!?!
+
+- if blocklistd was started with '-r' then a SIGHUP should also do a
+  "control flush $rulename" and then re-add all the filter rules?
+
+- should/could /etc/rc.conf.d/ipfilter be created with the following?
+
+       reload_postcmd=blocklistd_reload
+       start_postcmd=blocklistd_start
+       stop_precmd=blocklistd_stop
+       blocklistd_reload ()
+       {
+               /etc/rc.d/blocklistd reload     # IFF SIGHUP does flush/re-add
+               # /etc/rc.d/blocklistd restart
+       }
+       blocklistd_stop ()
+       {
+               /etc/rc.d/blocklistd stop
+       }
+       blocklistd_start ()
+       {
+               /etc/rc.d/blocklistd start
+       }
+
+  or is there a better way?
diff -r 9aabd9378307 -r 89396771f851 external/bsd/blocklist/etc/rc.d/blocklistd
--- a/external/bsd/blocklist/etc/rc.d/blocklistd        Sun Mar 07 00:23:06 2021 +0000
+++ b/external/bsd/blocklist/etc/rc.d/blocklistd        Sun Mar 07 00:46:39 2021 +0000
@@ -1,10 +1,10 @@
 #!/bin/sh
 #
-# $NetBSD: blocklistd,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $
+# $NetBSD: blocklistd,v 1.2 2021/03/07 00:46:39 christos Exp $
 #
 
 # PROVIDE: blocklistd
-# REQUIRE: npf
+# REQUIRE: npf pf ipfilter
 # BEFORE:  SERVERS
 
 $_rc_subr_loaded . /etc/rc.subr
diff -r 9aabd9378307 -r 89396771f851 external/bsd/blocklist/libexec/blocklistd-helper
--- a/external/bsd/blocklist/libexec/blocklistd-helper  Sun Mar 07 00:23:06 2021 +0000
+++ b/external/bsd/blocklist/libexec/blocklistd-helper  Sun Mar 07 00:46:39 2021 +0000
@@ -17,7 +17,7 @@
 fi
 
 if [ -z "$pf" ]; then
-       for f in npf pf ipf; do
+       for f in npf pf ipfilter; do
                if [ -f "/etc/$f.conf" ]; then
                        pf="$f"
                        break
@@ -25,16 +25,26 @@
        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
 
@@ -52,11 +62,59 @@
 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
+               # N.B.:  If you reload /etc/ipf.conf then you need to stop and
+               # restart blocklistd (and make sure blocklistd_flags="-r"):
+               #
+               #       /etc/rc.d/ipfilter reload
+               #       /etc/rc.d/blocklistd restart
+               #
+               # XXX we assume the following rule is present in /etc/ipf.conf:
+               #
+               #       block in proto tcp/udp from any to any head blocklistd
+               #
+               # where "blocklistd" 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 blocklistd will
+               # actually block packets, and prevent logging of them as
+               # connections, because they include the "quick" flag.
+               #
+               # N.b.:  $port is not included -- 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
+               # 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 generated must exactly match the 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 +127,23 @@
                        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,40 +154,76 @@
                /sbin/pfctl -a "$2/$6" -t "port$6" -T add "$addr/$mask" && \
                    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
+               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 -a "$2/$6" -t "port$6" -T delete "$addr/$mask" && \
                    echo OK
                ;;
+
        esac
        ;;
 flush)
        case "$pf" in
        ipf)
+               #
+               # XXX this is a slightly convoluted way to remove all the rules
+               # in the group added for "$2" (i.e. normally by default
+               # "blocklistd").
+               #
+               # N.B. WARNING:  This is obviously not reentrant!
+               #
+               /sbin/ipf -I -F a
+               /usr/sbin/ipfstat -io | fgrep -v "group $2" | \
+                   /sbin/ipf -I -f - >/dev/null 2>&1
+               # XXX this MUST be done last and separately as "-s" is executed



Home | Main Index | Thread Index | Old Index