]> git.99rst.org Git - openwrt-packages.git/commitdiff
banip: release 1.8.13
authorDirk Brenken <redacted>
Tue, 8 Sep 2026 15:58:17 +0000 (17:58 +0200)
committerDirk Brenken <redacted>
Tue, 8 Sep 2026 15:58:17 +0000 (17:58 +0200)
- f_getup() collects the wan state in one pass and diffs the uplink against
  the local allowlist
- new f_refresh() patches only the changed allowlist Set elements
   in a single atomic nft transaction, without touching the running instance
- the procd trigger calls start refresh, start_service() picks the path, a manual start is unaffected
- wan6 in ban_trigger is supported now
- updatted the README and moved to the package root
- LuCI: reworked the feed editor, get rid of custom css

Signed-off-by: Dirk Brenken dev@brenken.org
Signed-off-by: Dirk Brenken <redacted>
net/banip/Makefile
net/banip/README.md [moved from net/banip/files/README.md with 99% similarity]
net/banip/files/banip-functions.sh
net/banip/files/banip.init

index cb4a1f62599672c59133c96519b13a067fce869d..30ce292bcdccd1aceeb20fc18910046a04ad0cae 100644 (file)
@@ -5,8 +5,8 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=banip
-PKG_VERSION:=1.8.12
-PKG_RELEASE:=3
+PKG_VERSION:=1.8.13
+PKG_RELEASE:=1
 PKG_LICENSE:=GPL-3.0-or-later
 PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
 
@@ -23,7 +23,7 @@ endef
 define Package/banip/description
 banIP blocks IPs via named nftables Sets.
 banIP supports many IP blocklist feeds and provides a log service to block suspicious IPs in realtime.
-Please see https://github.com/openwrt/packages/blob/master/net/banip/files/README.md for further information.
+Please see https://github.com/openwrt/packages/blob/master/net/banip/README.md for further information.
 
 endef
 
similarity index 99%
rename from net/banip/files/README.md
rename to net/banip/README.md
index b53078221608511554daf1fcd8af02978daf3e31..373033fab7f7f8b638c1ed1c6b523b2e5ec6d0c0 100644 (file)
@@ -25,7 +25,7 @@ IP address blocking is commonly used to protect against brute force attacks, pre
 ## Quick Start
 For a typical setup these few steps are enough to get banIP up and running — see the sections below for details:
 1. Install the LuCI companion package: `apk update && apk add luci-app-banip` (this pulls in the `banip` backend as a dependency).
-2. Open LuCI under `Services → banIP`, tick `Enabled` and (recommended) set a `Startup Trigger Interface` to your WAN interface (avoid IPv6/wan6).
+2. Open LuCI under `Services → banIP`, tick `Enabled` and (recommended) set a `Startup Trigger Interface` to your WAN interface(s).
 3. Activate a small, sensible feed selection to start with, e.g. `cinsscore`, `debl`, `turris` and `doh` in their default chains (≈20K IPs).
 4. Start and verify the service:
 
@@ -147,7 +147,7 @@ For a typical setup these few steps are enough to get banIP up and running — s
 * Install the LuCI companion package `luci-app-banip` which also installs the main banIP package as a dependency
 * Enable the banIP system service (System -> Startup) and enable banIP itself (banIP -> General Settings)
 * It's strongly recommended to use the LuCI frontend to easily configure all aspects of banIP, the application is located in LuCI under the `Services` menu
-* It's also recommended to configure a `Startup Trigger Interface` to depend on your WAN ifup events during boot or restart of your router. Avoid IPv6 (wan6) interfaces here, as IPv6/netifd is chatty and would trigger frequent unnecessary banIP restarts
+* It's also recommended to configure a `Startup Trigger Interface` to depend on your WAN interface events during boot or restart of your router. Listing IPv6 interfaces (wan6) is fine as well: an interface event that only changed the uplink addresses refreshes the auto-allowed uplink entries in place, without a full banIP restart. This keeps the allowlist in sync with a dynamic IPv6 prefix
 * To be able to use banIP in a meaningful way, you must activate the service and possibly also activate a few blocklist feeds
 * If you're using a complex network setup, e.g. special tunnel interfaces, then untick the `Auto Detection` option under the `General Settings` tab and set the required options manually
 * Start the service with `/etc/init.d/banip start` and check everything is working by running `/etc/init.d/banip status`, also check the `Processing Log` tab
@@ -220,7 +220,7 @@ The `report` sub-command accepts an output mode: `text` (default, human-readable
 | ban_dev                 | list   | - / autodetect                | wan device(s), e.g. `eth2`                                                                                        |
 | ban_vlanallow           | list   | -                             | always allow certain VLAN forwards, e.g. br-lan.20                                                                |
 | ban_vlanblock           | list   | -                             | always block certain VLAN forwards, e.g. br-lan.10                                                                |
-| ban_trigger             | list   | -                             | logical reload trigger interface(s), e.g. `wan` (avoid IPv6 interfaces)                                           |
+| ban_trigger             | list   | -                             | logical reload trigger interface(s), e.g. `wan` and `wan6`                                                        |
 | ban_triggerdelay        | option | 20                            | trigger timeout during interface reload and boot                                                                  |
 | ban_deduplicate         | option | 1                             | deduplicate IP addresses across all active Sets (see optional feed flag `dup` below)                              |
 | ban_splitsize           | option | 0                             | split the processing/loading of Sets in chunks of n lines/members (saves RAM)                                     |
index 80d9a4e70efb35723156306533f8a8b1843616ec..2565612aea79d6de6c7c911abd1e1d92740ec8bc 100644 (file)
@@ -92,6 +92,9 @@ ban_dev=""
 ban_vlanallow=""
 ban_vlanblock=""
 ban_uplink=""
+ban_uplink_add=""
+ban_uplink_del=""
+ban_devup=""
 ban_fetchcmd=""
 ban_fetchparm=""
 ban_fetchinsecure=""
@@ -721,59 +724,170 @@ f_getdev() {
 # get local uplink
 #
 f_getup() {
-       local uplink iface timestamp ip
+       local uplink dev iface timestamp ip old
+
+       ban_uplink=""
+       ban_uplink_add=""
+       ban_uplink_del=""
+       ban_devup=""
+
+       # single pass over the wan interfaces, collects the current
+       # devices and uplink addresses
+       #
+       network_flush_cache
+       for iface in ${ban_ifv4} ${ban_ifv6}; do
+               network_get_device dev "${iface}"
+               if [ -n "${dev}" ]; then
+                       case " ${ban_devup} " in
+                       *" ${dev} "*) ;;
+
+                       *)
+                               ban_devup="${ban_devup}${dev} "
+                               ;;
+                       esac
+               fi
+               [ "${ban_autoallowlist}" = "1" ] && [ "${ban_autoallowuplink}" != "disable" ] || continue
+               if [ "${ban_autoallowuplink}" = "subnet" ]; then
+                       network_get_subnet uplink "${iface}"
+               elif [ "${ban_autoallowuplink}" = "ip" ]; then
+                       network_get_ipaddr uplink "${iface}"
+               fi
+               if [ -n "${uplink}" ]; then
+                       case " ${ban_uplink} " in
+                       *" ${uplink} "*) ;;
+
+                       *)
+                               ban_uplink="${ban_uplink}${uplink} "
+                               ;;
+                       esac
+               fi
+               if [ "${ban_autoallowuplink}" = "subnet" ]; then
+                       network_get_subnet6 uplink "${iface}"
+               elif [ "${ban_autoallowuplink}" = "ip" ]; then
+                       network_get_ipaddr6 uplink "${iface}"
+               fi
+               if [ -n "${uplink%fe80::*}" ]; then
+                       case " ${ban_uplink} " in
+                       *" ${uplink} "*) ;;
+
+                       *)
+                               ban_uplink="${ban_uplink}${uplink} "
+                               ;;
+                       esac
+               fi
+       done
+       ban_uplink="$(f_trim "${ban_uplink}")"
 
        if [ "${ban_autoallowlist}" = "1" ] && [ "${ban_autoallowuplink}" != "disable" ]; then
-               for iface in ${ban_ifv4} ${ban_ifv6}; do
-                       network_flush_cache
-                       if [ "${ban_autoallowuplink}" = "subnet" ]; then
-                               network_get_subnet uplink "${iface}"
-                       elif [ "${ban_autoallowuplink}" = "ip" ]; then
-                               network_get_ipaddr uplink "${iface}"
-                       fi
-                       if [ -n "${uplink}" ]; then
+               # compare the detected uplink with the local allowlist and
+               # track the differences for an in-place refresh (see f_refresh)
+               #
+               if [ -n "${ban_uplink}" ]; then
+                       for ip in $("${ban_sedcmd}" -n "/# uplink added on /s/[[:space:]].*$//p" "${ban_allowlist}" 2>/dev/null); do
+                               old="${old}${ip} "
+                       done
+                       for ip in ${old}; do
                                case " ${ban_uplink} " in
-                               *" ${uplink} "*) ;;
+                               *" ${ip} "*) ;;
 
                                *)
-                                       ban_uplink="${ban_uplink}${uplink} "
+                                       ban_uplink_del="${ban_uplink_del}${ip} "
                                        ;;
                                esac
-                       fi
-                       if [ "${ban_autoallowuplink}" = "subnet" ]; then
-                               network_get_subnet6 uplink "${iface}"
-                       elif [ "${ban_autoallowuplink}" = "ip" ]; then
-                               network_get_ipaddr6 uplink "${iface}"
-                       fi
-                       if [ -n "${uplink%fe80::*}" ]; then
-                               case " ${ban_uplink} " in
-                               *" ${uplink} "*) ;;
+                       done
+                       for ip in ${ban_uplink}; do
+                               case " ${old} " in
+                               *" ${ip} "*) ;;
 
                                *)
-                                       ban_uplink="${ban_uplink}${uplink} "
+                                       ban_uplink_add="${ban_uplink_add}${ip} "
                                        ;;
                                esac
-                       fi
-               done
-               ban_uplink="$(f_trim "${ban_uplink}")"
-               for ip in ${ban_uplink}; do
-                       if ! "${ban_grepcmd}" -q "${ip} " "${ban_allowlist}"; then
+                       done
+                       if [ -n "${ban_uplink_add}" ] || [ -n "${ban_uplink_del}" ]; then
                                "${ban_sedcmd}" -i "/# uplink added on /d" "${ban_allowlist}"
-                               break
-                       fi
-               done
-               timestamp="$(date "+%Y-%m-%d %H:%M:%S")"
-               for ip in ${ban_uplink}; do
-                       if ! "${ban_grepcmd}" -q "${ip} " "${ban_allowlist}"; then
-                               printf '%-45s%s\n' "${ip}" "# uplink added on ${timestamp}" >>"${ban_allowlist}"
-                               f_log "info" "add uplink '${ip}' to local allowlist"
+                               timestamp="$(date "+%Y-%m-%d %H:%M:%S")"
+                               for ip in ${ban_uplink}; do
+                                       printf '%-45s%s\n' "${ip}" "# uplink added on ${timestamp}" >>"${ban_allowlist}"
+                               done
+                               for ip in ${ban_uplink_add}; do
+                                       f_log "info" "add uplink '${ip}' to local allowlist"
+                               done
+                               for ip in ${ban_uplink_del}; do
+                                       f_log "info" "remove uplink '${ip}' from local allowlist"
+                               done
                        fi
-               done
+               fi
        elif [ "${ban_autoallowlist}" = "1" ] && [ "${ban_autoallowuplink}" = "disable" ]; then
-               "${ban_sedcmd}" -i "/# uplink added on /d" "${ban_allowlist}"
+               if "${ban_grepcmd}" -q "# uplink added on " "${ban_allowlist}"; then
+                       "${ban_sedcmd}" -i "/# uplink added on /d" "${ban_allowlist}"
+               fi
        fi
 
-       f_log "debug" "f_getup   ::: auto-allow/auto-uplink: ${ban_autoallowlist}/${ban_autoallowuplink}, uplink: ${ban_uplink:-"-"}"
+       f_log "debug" "f_getup   ::: auto-allow/auto-uplink: ${ban_autoallowlist}/${ban_autoallowuplink}, devices: ${ban_devup:-"-"}, uplink: ${ban_uplink:-"-"}, add/remove: ${ban_uplink_add:-"-"}/${ban_uplink_del:-"-"}"
+}
+
+# refresh the wan state in place, triggered by an interface event
+# return 0 if handled, 1 to escalate to a full service run
+#
+f_refresh() {
+       local dev ip addv4 addv6 delv4 delv6 set_list set_name
+
+       # require an initialized nft namespace
+       #
+       "${ban_nftcmd}" list chain inet banIP pre-routing >/dev/null 2>&1 || return 1
+
+       f_getup
+
+       # escalate on new or renamed wan devices, the rulesets match on
+       # ban_dev - a device that is merely gone means the interface is
+       # currently down, that is handled by the uplink diff below
+       #
+       for dev in ${ban_devup}; do
+               case " ${ban_dev} " in
+               *" ${dev} "*) ;;
+
+               *)
+                       return 1
+                       ;;
+               esac
+       done
+       [ -z "${ban_uplink_add}" ] && [ -z "${ban_uplink_del}" ] && return 0
+
+       # update the allowlist Sets in a single atomic transaction,
+       # a rejected batch escalates to a full run
+       #
+       for ip in ${ban_uplink_del}; do
+               if [ "${ip##*:}" = "${ip}" ]; then
+                       delv4="${delv4}${ip}, "
+               else
+                       delv6="${delv6}${ip}, "
+               fi
+       done
+       for ip in ${ban_uplink_add}; do
+               if [ "${ip##*:}" = "${ip}" ]; then
+                       addv4="${addv4}${ip}, "
+               else
+                       addv6="${addv6}${ip}, "
+               fi
+       done
+       set_list="allowlist"
+       if [ "${ban_allowlistonly}" = "1" ] && [ "${ban_monitorallowed}" = "1" ]; then
+               set_list="${set_list} allowlist.local"
+       fi
+       if ! {
+               for set_name in ${set_list}; do
+                       [ -n "${delv4}" ] && printf 'delete element inet banIP %s.v4 { %s }\n' "${set_name}" "${delv4%, }"
+                       [ -n "${delv6}" ] && printf 'delete element inet banIP %s.v6 { %s }\n' "${set_name}" "${delv6%, }"
+                       [ -n "${addv4}" ] && printf 'add element inet banIP %s.v4 { %s }\n' "${set_name}" "${addv4%, }"
+                       [ -n "${addv6}" ] && printf 'add element inet banIP %s.v6 { %s }\n' "${set_name}" "${addv6%, }"
+               done
+       } | "${ban_nftcmd}" -f - >/dev/null 2>&1; then
+               return 1
+       fi
+
+       f_log "debug" "f_refresh ::: devices: ${ban_devup}, uplink: ${ban_uplink}"
+       return 0
 }
 
 # get feed information
index fd128e75feded41f48e70e64d63093e97b2d0c8b..3ae275a3fc333f55d7de80461bf78190e397c1b5 100755 (executable)
@@ -58,9 +58,16 @@ boot() {
 
 start_service() {
        if "${ban_init}" enabled; then
+               if [ "${1}" = "refresh" ]; then
+                       f_conf
+                       if f_refresh; then
+                               rm -rf "${ban_lock}"
+                               return 0
+                       fi
+               fi
                f_rmpid
                procd_open_instance "banip-service"
-               procd_set_param command "${ban_service}" "${@:-"${action}"}"
+               procd_set_param command "${ban_service}" "${action}"
                procd_set_param pidfile "${ban_pidfile}"
                procd_set_param nice "$(uci_get banip global ban_nicelimit "0")"
                procd_set_param limits nofile="$(uci_get banip global ban_filelimit "1024")"
@@ -122,6 +129,6 @@ service_triggers() {
 
        PROCD_RELOAD_DELAY="$((delay * 1000))"
        for iface in ${trigger}; do
-               procd_add_interface_trigger "interface.*.up" "${iface}" "${ban_init}" start
+               procd_add_interface_trigger "interface.*" "${iface}" "${ban_init}" start refresh
        done
 }
git clone https://git.99rst.org/PROJECT