From 79f2db6cc597eb2799bab02682d5f639f28c584a Mon Sep 17 00:00:00 2001 From: Dirk Brenken Date: Sat, 11 Apr 2026 18:43:09 +0200 Subject: [PATCH] banip: update 1.8.5-2 * fixed two issues in the mail template, reported in the forum * tweak the f_report function * changed the f_actual function to reduce subshell calls * further optimize the monitor function: * fixed a possible RDAP rate-limit race condition, serialize the rdap_tsfile via flock * block_cache bounded growth, when the cache reaches 500 entries it resets to empty, preventing unbounded string growth in the monitor loop * set the printf format string in single quotes (overall) Signed-off-by: Dirk Brenken --- net/banip/Makefile | 2 +- net/banip/files/banip-functions.sh | 566 +++++++++++++++-------------- net/banip/files/banip-service.sh | 2 +- net/banip/files/banip.tpl | 24 +- 4 files changed, 314 insertions(+), 280 deletions(-) diff --git a/net/banip/Makefile b/net/banip/Makefile index d4e2b22aab..a935801d61 100644 --- a/net/banip/Makefile +++ b/net/banip/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=banip PKG_VERSION:=1.8.5 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_LICENSE:=GPL-3.0-or-later PKG_MAINTAINER:=Dirk Brenken diff --git a/net/banip/files/banip-functions.sh b/net/banip/files/banip-functions.sh index a661264d85..67b3a40430 100644 --- a/net/banip/files/banip-functions.sh +++ b/net/banip/files/banip-functions.sh @@ -119,8 +119,8 @@ f_system() { # get banIP version and system information # ban_packages="$("${ban_ubuscmd}" -S call rpc-sys packagelist '{ "all": true }' 2>>"${ban_errorlog}")" - ban_bver="$(printf "%s" "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages.banip')" - ban_fver="$(printf "%s" "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages["luci-app-banip"]')" + ban_bver="$(printf '%s' "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages.banip')" + ban_fver="$(printf '%s' "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages["luci-app-banip"]')" ban_sysver="$("${ban_ubuscmd}" -S call system board 2>>"${ban_errorlog}" | "${ban_jsoncmd}" -ql1 -e '@.model' -e '@.release.target' -e '@.release.distribution' -e '@.release.version' -e '@.release.revision' | "${ban_awkcmd}" 'BEGIN{RS="";FS="\n"}{printf "%s, %s, %s %s (%s)",$1,$2,$3,$4,$5}')" @@ -146,12 +146,12 @@ f_cmd() { cmd="$(command -v "${sec_cmd}" 2>>"${ban_errorlog}")" fi if [ -x "${cmd}" ]; then - printf "%s" "${cmd}" + printf '%s' "${cmd}" else f_log "emerg" "command '${pri_cmd:-"-"}'/'${sec_cmd:-"-"}' not found" fi else - printf "%s" "${cmd}" + printf '%s' "${cmd}" fi } @@ -206,11 +206,11 @@ f_char() { local char="${1}" if [ "${char}" = "1" ]; then - printf "%s" "✔" + printf '%s' "✔" elif [ "${char}" = "0" ] || [ -z "${char}" ]; then - printf "%s" "✘" + printf '%s' "✘" else - printf "%s" "${char}" + printf '%s' "${char}" fi } @@ -221,7 +221,7 @@ f_trim() { string="${string#"${string%%[![:space:]]*}"}" string="${string%"${string##*[![:space:]]}"}" - printf "%s" "${string}" + printf '%s' "${string}" } # remove log monitor @@ -265,7 +265,7 @@ f_log() { if [ -x "${ban_logcmd}" ]; then "${ban_logcmd}" -p "${class}" -t "banIP-${ban_bver}[${$}]" "${log_msg::256}" else - printf "%s %s %s\n" "${class}" "banIP-${ban_bver}[${$}]" "${log_msg::256}" + printf '%s %s %s\n' "${class}" "banIP-${ban_bver}[${$}]" "${log_msg::256}" fi fi if [ "${class}" = "err" ] || [ "${class}" = "emerg" ]; then @@ -490,25 +490,23 @@ f_actual() { local nft monitor ppid pids pid if "${ban_nftcmd}" -t list table inet banIP >/dev/null 2>&1; then - nft="$(f_char "1")" + nft="✔" else - nft="$(f_char "0")" + nft="✘" fi + monitor="✘" ppid="$("${ban_catcmd}" "${ban_pidfile}" 2>>"${ban_errorlog}")" if [ -n "${ppid}" ]; then - monitor="$(f_char "0")" pids="${ppid} $("${ban_pgrepcmd}" -P "${ppid}" 2>>"${ban_errorlog}")" for pid in ${pids}; do if "${ban_pgrepcmd}" -f "${ban_logreadcmd##*/}" -P "${pid}" >/dev/null 2>&1; then - monitor="$(f_char "1")" + monitor="✔" break fi done - else - monitor="$(f_char "0")" fi - printf "%s" "nft: ${nft}, monitor: ${monitor}" + printf '%s' "nft: ${nft}, monitor: ${monitor}" } # get fetch utility @@ -703,7 +701,7 @@ f_getup() { 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}" + printf '%-45s%s\n' "${ip}" "# uplink added on ${timestamp}" >>"${ban_allowlist}" f_log "info" "add uplink '${ip}' to local allowlist" fi done @@ -737,7 +735,7 @@ f_getfeed() { f_getelements() { local file="${1}" - [ -s "${file}" ] && printf "%s" "elements={ $("${ban_catcmd}" "${file}" 2>>"${ban_errorlog}") };" + [ -s "${file}" ] && printf '%s' "elements={ $("${ban_catcmd}" "${file}" 2>>"${ban_errorlog}") };" } # handle etag http header @@ -748,10 +746,10 @@ f_etag() { if [ -n "${ban_etagparm}" ]; then [ ! -f "${ban_backupdir}/banIP.etag" ] && : >"${ban_backupdir}/banIP.etag" http_head="$("${ban_fetchcmd}" ${ban_etagparm} "${feed_url}" 2>&1)" - http_code="$(printf "%s" "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^http\/[0123\.]+ /{printf "%s",$2}')" - etag_id="$(printf "%s" "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^[[:space:]]*etag: /{gsub("\"","");printf "%s",$2}')" + http_code="$(printf '%s' "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^http\/[0123\.]+ /{printf "%s",$2}')" + etag_id="$(printf '%s' "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^[[:space:]]*etag: /{gsub("\"","");printf "%s",$2}')" if [ -z "${etag_id}" ]; then - etag_id="$(printf "%s" "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^[[:space:]]*last-modified: /{gsub(/[Ll]ast-[Mm]odified:|[[:space:]]|,|:/,"");printf "%s\n",$1}')" + etag_id="$(printf '%s' "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^[[:space:]]*last-modified: /{gsub(/[Ll]ast-[Mm]odified:|[[:space:]]|,|:/,"");printf "%s\n",$1}')" fi etag_cnt="$("${ban_grepcmd}" -c "^${feed} " "${ban_backupdir}/banIP.etag")" if [ "${http_code}" = "200" ] && [ "${etag_cnt}" = "${feed_cnt}" ] && [ -n "${etag_id}" ] && @@ -763,7 +761,7 @@ f_etag() { else "${ban_sedcmd}" -i "/^${feed} ${feed_suffix//\//\\/}/d" "${ban_backupdir}/banIP.etag" fi - printf "%-50s%s\n" "${feed} ${feed_suffix}" "${etag_id}" >>"${ban_backupdir}/banIP.etag" + printf '%-50s%s\n' "${feed} ${feed_suffix}" "${etag_id}" >>"${ban_backupdir}/banIP.etag" out_rc="2" fi fi @@ -800,9 +798,9 @@ f_nftload() { f_nftinit() { local wan_dev vlan_allow vlan_block log_ct log_icmp log_syn log_udp log_tcp flag tmp_proto tmp_port allow_dport feed_rc="0" file="${1}" - wan_dev="$(printf "%s" "${ban_dev}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" - [ -n "${ban_vlanallow}" ] && vlan_allow="$(printf "%s" "${ban_vlanallow%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" - [ -n "${ban_vlanblock}" ] && vlan_block="$(printf "%s" "${ban_vlanblock%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" + wan_dev="$(printf '%s' "${ban_dev}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" + [ -n "${ban_vlanallow}" ] && vlan_allow="$(printf '%s' "${ban_vlanallow%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" + [ -n "${ban_vlanblock}" ] && vlan_block="$(printf '%s' "${ban_vlanblock%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')" for flag in ${ban_allowflag}; do case "${flag}" in @@ -849,131 +847,131 @@ f_nftinit() { { # nft header (tables, base and regular chains) # - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" if "${ban_nftcmd}" -t list table inet banIP >/dev/null 2>&1; then - printf "%s\n" "delete table inet banIP" + printf '%s\n' "delete table inet banIP" fi - printf "%s\n" "add table inet banIP" + printf '%s\n' "add table inet banIP" # base chains # - printf "%s\n" "add chain inet banIP pre-routing { type filter hook prerouting priority -175; policy accept; }" - printf "%s\n" "add chain inet banIP wan-input { type filter hook input priority ${ban_nftpriority}; policy accept; }" - printf "%s\n" "add chain inet banIP wan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }" - printf "%s\n" "add chain inet banIP lan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }" + printf '%s\n' "add chain inet banIP pre-routing { type filter hook prerouting priority -175; policy accept; }" + printf '%s\n' "add chain inet banIP wan-input { type filter hook input priority ${ban_nftpriority}; policy accept; }" + printf '%s\n' "add chain inet banIP wan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }" + printf '%s\n' "add chain inet banIP lan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }" # regular chains # - printf "%s\n" "add chain inet banIP _inbound" - printf "%s\n" "add chain inet banIP _outbound" - printf "%s\n" "add chain inet banIP _reject" + printf '%s\n' "add chain inet banIP _inbound" + printf '%s\n' "add chain inet banIP _outbound" + printf '%s\n' "add chain inet banIP _reject" # named counter # - printf "%s\n" "add counter inet banIP cnt_icmpflood" - printf "%s\n" "add counter inet banIP cnt_udpflood" - printf "%s\n" "add counter inet banIP cnt_synflood" - printf "%s\n" "add counter inet banIP cnt_tcpinvalid" - printf "%s\n" "add counter inet banIP cnt_ctinvalid" - printf "%s\n" "add counter inet banIP cnt_bcp38" + printf '%s\n' "add counter inet banIP cnt_icmpflood" + printf '%s\n' "add counter inet banIP cnt_udpflood" + printf '%s\n' "add counter inet banIP cnt_synflood" + printf '%s\n' "add counter inet banIP cnt_tcpinvalid" + printf '%s\n' "add counter inet banIP cnt_ctinvalid" + printf '%s\n' "add counter inet banIP cnt_bcp38" # default reject chain rules # - printf "%s\n" "add rule inet banIP _reject iifname != { ${wan_dev} } meta l4proto tcp reject with tcp reset" - printf "%s\n" "add rule inet banIP _reject reject with icmpx host-unreachable" + printf '%s\n' "add rule inet banIP _reject iifname != { ${wan_dev} } meta l4proto tcp reject with tcp reset" + printf '%s\n' "add rule inet banIP _reject reject with icmpx host-unreachable" # default pre-routing rules # - printf "%s\n" "add rule inet banIP pre-routing iifname != { ${wan_dev} } counter accept" + printf '%s\n' "add rule inet banIP pre-routing iifname != { ${wan_dev} } counter accept" # ct state invalid # if [ "${ban_logprerouting}" = "1" ]; then - printf "%s\n" "add rule inet banIP pre-routing ct state invalid ${log_ct}" + printf '%s\n' "add rule inet banIP pre-routing ct state invalid ${log_ct}" fi - printf "%s\n" "add rule inet banIP pre-routing ct state invalid counter name cnt_ctinvalid drop" + printf '%s\n' "add rule inet banIP pre-routing ct state invalid counter name cnt_ctinvalid drop" # ICMP Flood # if [ "${ban_icmplimit}" -gt "0" ]; then if [ "${ban_logprerouting}" = "1" ]; then - printf "%s\n" "add rule inet banIP pre-routing meta nfproto . meta l4proto { ipv4 . icmp , ipv6 . icmpv6 } limit rate over ${ban_icmplimit}/second ${log_icmp}" + printf '%s\n' "add rule inet banIP pre-routing meta nfproto . meta l4proto { ipv4 . icmp , ipv6 . icmpv6 } limit rate over ${ban_icmplimit}/second ${log_icmp}" fi - printf "%s\n" "add rule inet banIP pre-routing meta nfproto . meta l4proto { ipv4 . icmp , ipv6 . icmpv6 } limit rate over ${ban_icmplimit}/second counter name cnt_icmpflood drop" + printf '%s\n' "add rule inet banIP pre-routing meta nfproto . meta l4proto { ipv4 . icmp , ipv6 . icmpv6 } limit rate over ${ban_icmplimit}/second counter name cnt_icmpflood drop" fi # UDP Flood # if [ "${ban_udplimit}" -gt "0" ]; then if [ "${ban_logprerouting}" = "1" ]; then - printf "%s\n" "add rule inet banIP pre-routing meta l4proto udp ct state new limit rate over ${ban_udplimit}/second ${log_udp}" + printf '%s\n' "add rule inet banIP pre-routing meta l4proto udp ct state new limit rate over ${ban_udplimit}/second ${log_udp}" fi - printf "%s\n" "add rule inet banIP pre-routing meta l4proto udp ct state new limit rate over ${ban_udplimit}/second counter name cnt_udpflood drop" + printf '%s\n' "add rule inet banIP pre-routing meta l4proto udp ct state new limit rate over ${ban_udplimit}/second counter name cnt_udpflood drop" fi # SYN Flood # if [ "${ban_synlimit}" -gt "0" ]; then if [ "${ban_logprerouting}" = "1" ]; then - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|ack) == syn limit rate over ${ban_synlimit}/second ${log_syn}" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|ack) == syn limit rate over ${ban_synlimit}/second ${log_syn}" fi - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|ack) == syn limit rate over ${ban_synlimit}/second counter name cnt_synflood drop" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|ack) == syn limit rate over ${ban_synlimit}/second counter name cnt_synflood drop" fi # TCP Invalid # if [ "${ban_logprerouting}" = "1" ]; then - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn) == (fin|syn) ${log_tcp}" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (syn|rst) == (syn|rst) ${log_tcp}" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) ${log_tcp}" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) ${log_tcp}" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn) == (fin|syn) ${log_tcp}" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (syn|rst) == (syn|rst) ${log_tcp}" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) ${log_tcp}" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) ${log_tcp}" fi - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn) == (fin|syn) counter name cnt_tcpinvalid drop" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (syn|rst) == (syn|rst) counter name cnt_tcpinvalid drop" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) counter name cnt_tcpinvalid drop" - printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) counter name cnt_tcpinvalid drop" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn) == (fin|syn) counter name cnt_tcpinvalid drop" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (syn|rst) == (syn|rst) counter name cnt_tcpinvalid drop" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) counter name cnt_tcpinvalid drop" + printf '%s\n' "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) counter name cnt_tcpinvalid drop" # default wan-input rules # - printf "%s\n" "add rule inet banIP wan-input ct state established,related counter accept" - printf "%s\n" "add rule inet banIP wan-input iifname != { ${wan_dev} } counter accept" - printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv4 udp sport 67-68 udp dport 67-68 counter accept" - printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 udp sport 547 udp dport 546 counter accept" - printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } ip6 hoplimit 255 counter accept" - [ -n "${allow_dport}" ] && printf "%s\n" "add rule inet banIP wan-input ${allow_dport} counter accept" + printf '%s\n' "add rule inet banIP wan-input ct state established,related counter accept" + printf '%s\n' "add rule inet banIP wan-input iifname != { ${wan_dev} } counter accept" + printf '%s\n' "add rule inet banIP wan-input meta nfproto ipv4 udp sport 67-68 udp dport 67-68 counter accept" + printf '%s\n' "add rule inet banIP wan-input meta nfproto ipv6 udp sport 547 udp dport 546 counter accept" + printf '%s\n' "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } ip6 hoplimit 255 counter accept" + [ -n "${allow_dport}" ] && printf '%s\n' "add rule inet banIP wan-input ${allow_dport} counter accept" if [ "${ban_bcp38}" = "1" ]; then - printf "%s\n" "add rule inet banIP wan-input fib saddr . iif oif missing counter name cnt_bcp38 drop" + printf '%s\n' "add rule inet banIP wan-input fib saddr . iif oif missing counter name cnt_bcp38 drop" fi if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP wan-input meta mark set 1 counter jump _inbound" + printf '%s\n' "add rule inet banIP wan-input meta mark set 1 counter jump _inbound" else - printf "%s\n" "add rule inet banIP wan-input counter jump _inbound" + printf '%s\n' "add rule inet banIP wan-input counter jump _inbound" fi # default wan-forward rules # - printf "%s\n" "add rule inet banIP wan-forward ct state established,related counter accept" - printf "%s\n" "add rule inet banIP wan-forward iifname != { ${wan_dev} } counter accept" - [ -n "${allow_dport}" ] && printf "%s\n" "add rule inet banIP wan-forward ${allow_dport} counter accept" + printf '%s\n' "add rule inet banIP wan-forward ct state established,related counter accept" + printf '%s\n' "add rule inet banIP wan-forward iifname != { ${wan_dev} } counter accept" + [ -n "${allow_dport}" ] && printf '%s\n' "add rule inet banIP wan-forward ${allow_dport} counter accept" if [ "${ban_bcp38}" = "1" ]; then - printf "%s\n" "add rule inet banIP wan-forward fib saddr . iif oif missing counter name cnt_bcp38 drop" + printf '%s\n' "add rule inet banIP wan-forward fib saddr . iif oif missing counter name cnt_bcp38 drop" fi if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP wan-forward meta mark set 2 counter jump _inbound" + printf '%s\n' "add rule inet banIP wan-forward meta mark set 2 counter jump _inbound" else - printf "%s\n" "add rule inet banIP wan-forward counter jump _inbound" + printf '%s\n' "add rule inet banIP wan-forward counter jump _inbound" fi # default lan-forward rules # - printf "%s\n" "add rule inet banIP lan-forward ct state established,related counter accept" - printf "%s\n" "add rule inet banIP lan-forward oifname != { ${wan_dev} } counter accept" - [ -n "${vlan_allow}" ] && printf "%s\n" "add rule inet banIP lan-forward iifname { ${vlan_allow} } counter accept" - [ -n "${vlan_block}" ] && printf "%s\n" "add rule inet banIP lan-forward iifname { ${vlan_block} } counter goto _reject" + printf '%s\n' "add rule inet banIP lan-forward ct state established,related counter accept" + printf '%s\n' "add rule inet banIP lan-forward oifname != { ${wan_dev} } counter accept" + [ -n "${vlan_allow}" ] && printf '%s\n' "add rule inet banIP lan-forward iifname { ${vlan_allow} } counter accept" + [ -n "${vlan_block}" ] && printf '%s\n' "add rule inet banIP lan-forward iifname { ${vlan_block} } counter goto _reject" if [ "${ban_bcp38}" = "1" ]; then - printf "%s\n" "add rule inet banIP lan-forward fib saddr . iif oif missing counter name cnt_bcp38 drop" + printf '%s\n' "add rule inet banIP lan-forward fib saddr . iif oif missing counter name cnt_bcp38 drop" fi - printf "%s\n" "add rule inet banIP lan-forward counter jump _outbound" + printf '%s\n' "add rule inet banIP lan-forward counter jump _outbound" } >"${file}" # load initial banIP table/rules to nftset @@ -1024,7 +1022,7 @@ f_down() { element_count="counter" fi -# set feed complete flag + # set feed complete flag # case " ${ban_feedcomplete} " in *" ${feed%%.*} "*) @@ -1086,7 +1084,7 @@ f_down() { esac fi -# prepare feed flags + # prepare feed flags # for flag in ${feed_flag}; do case "${flag}" in @@ -1139,14 +1137,14 @@ f_down() { { for chain in _inbound _outbound; do for expr in 0 1 2; do - handles="$(printf "%s\n" "${table_json}" | "${ban_jsoncmd}" -q -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${feed}\"].handle" | "${ban_xargscmd}")" + handles="$(printf '%s\n' "${table_json}" | "${ban_jsoncmd}" -q -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${feed}\"].handle" | "${ban_xargscmd}")" for handle in ${handles}; do - printf "%s\n" "delete rule inet banIP ${chain} handle ${handle}" + printf '%s\n' "delete rule inet banIP ${chain} handle ${handle}" done done done - printf "%s\n" "flush set inet banIP ${feed}" - printf "%s\n\n" "delete set inet banIP ${feed}" + printf '%s\n' "flush set inet banIP ${feed}" + printf '%s\n\n' "delete set inet banIP ${feed}" } >"${tmp_flush}" fi @@ -1164,7 +1162,7 @@ f_down() { etag_rc="${?}" else etag_rc="0" - etag_cnt="$(printf "%s" "${ban_country}" | "${ban_wccmd}" -w)" + etag_cnt="$(printf '%s' "${ban_country}" | "${ban_wccmd}" -w)" for country in ${ban_country}; do if ! f_etag "${feed}" "${feed_url}${country}-aggregated.zone" ".${country}" "${etag_cnt}"; then etag_rc="$((etag_rc + 1))" @@ -1180,7 +1178,7 @@ f_down() { etag_rc="${?}" else etag_rc="0" - etag_cnt="$(printf "%s" "${ban_asn}" | "${ban_wccmd}" -w)" + etag_cnt="$(printf '%s' "${ban_asn}" | "${ban_wccmd}" -w)" for asn in ${ban_asn}; do if ! f_etag "${feed}" "${feed_url}AS${asn}" ".${asn}" "${etag_cnt}"; then etag_rc="$((etag_rc + 1))" @@ -1236,64 +1234,64 @@ f_down() { # if [ "${feed%%.*}" = "allowlist" ]; then { - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}" case "${feed_ipv}" in "4MAC") "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}(\/([0-9]|[1-3][0-9]|4[0-8]))?([[:space:]]+([1-9][0-9]?[0-9]?\.){1}([0-9]{1,3}\.){2}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/(1?[0-9]|2?[0-9]|3?[0-2]))?([[:space:]]+#.*$|[[:space:]]*$)|[[:space:]]+#.*$|$)/{if(!$2||$2~/#/)$2="0.0.0.0/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${tmp_allow}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" - [ -z "${feed_direction##*outbound*}" ] && printf "%s\n" "add rule inet banIP _outbound ether saddr . ip saddr @${feed} counter accept" + printf '%s\n' "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + [ -z "${feed_direction##*outbound*}" ] && printf '%s\n' "add rule inet banIP _outbound ether saddr . ip saddr @${feed} counter accept" ;; "6MAC") "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}(\/([0-9]|[1-3][0-9]|4[0-8]))?([[:space:]]+([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?([[:space:]]+#.*$|[[:space:]]*$)|[[:space:]]+#.*$|$)/{if(!$2||$2~/#/)$2="::/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${tmp_allow}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" - [ -z "${feed_direction##*outbound*}" ] && printf "%s\n" "add rule inet banIP _outbound ether saddr . ip6 saddr @${feed} counter accept" + printf '%s\n' "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + [ -z "${feed_direction##*outbound*}" ] && printf '%s\n' "add rule inet banIP _outbound ether saddr . ip6 saddr @${feed} counter accept" ;; "4") f_chkip ${feed_ipv} local 1 < "${tmp_allow}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_allowlistonly}" = "1" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ip saddr != @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ip saddr != @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ip saddr != @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ip saddr != @${feed} counter ${feed_target}" else - printf "%s\n" "add rule inet banIP _inbound ip saddr @${feed} counter accept" + printf '%s\n' "add rule inet banIP _inbound ip saddr @${feed} counter accept" fi fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_allowlistonly}" = "1" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ip daddr != @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ip daddr != @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ip daddr != @${feed} counter goto _reject" + printf '%s\n' "add rule inet banIP _outbound ip daddr != @${feed} counter goto _reject" else - printf "%s\n" "add rule inet banIP _outbound ip daddr @${feed} counter accept" + printf '%s\n' "add rule inet banIP _outbound ip daddr @${feed} counter accept" fi fi ;; "6") f_chkip ${feed_ipv} local 1 < "${tmp_allow}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_allowlistonly}" = "1" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ip6 saddr != @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ip6 saddr != @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ip6 saddr != @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ip6 saddr != @${feed} counter ${feed_target}" else - printf "%s\n" "add rule inet banIP _inbound ip6 saddr @${feed} counter accept" + printf '%s\n' "add rule inet banIP _inbound ip6 saddr @${feed} counter accept" fi fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_allowlistonly}" = "1" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ip6 daddr != @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ip6 daddr != @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ip6 daddr != @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _outbound ip6 daddr != @${feed} counter ${feed_target}" else - printf "%s\n" "add rule inet banIP _outbound ip6 daddr @${feed} counter accept" + printf '%s\n' "add rule inet banIP _outbound ip6 daddr @${feed} counter accept" fi fi ;; @@ -1303,49 +1301,49 @@ f_down() { feed_rc="0" elif [ "${feed%%.*}" = "blocklist" ]; then { - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}" case "${feed_ipv}" in "4MAC") "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}(\/([0-9]|[1-3][0-9]|4[0-8]))?([[:space:]]+([1-9][0-9]?[0-9]?\.){1}([0-9]{1,3}\.){2}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/(1?[0-9]|2?[0-9]|3?[0-2]))?([[:space:]]+#.*$|[[:space:]]*$)|[[:space:]]+#.*$|$)/{if(!$2||$2~/#/)$2="0.0.0.0/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${ban_blocklist}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" - [ -z "${feed_direction##*outbound*}" ] && printf "%s\n" "add rule inet banIP _outbound ether saddr . ip saddr @${feed} counter goto _reject" + printf '%s\n' "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + [ -z "${feed_direction##*outbound*}" ] && printf '%s\n' "add rule inet banIP _outbound ether saddr . ip saddr @${feed} counter goto _reject" ;; "6MAC") "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}(\/([0-9]|[1-3][0-9]|4[0-8]))?([[:space:]]+([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?([[:space:]]+#.*$|[[:space:]]*$)|[[:space:]]+#.*$|$)/{if(!$2||$2~/#/)$2="::/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${ban_blocklist}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" - [ -z "${feed_direction##*outbound*}" ] && printf "%s\n" "add rule inet banIP _outbound ether saddr . ip6 saddr @${feed} counter goto _reject" + printf '%s\n' "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + [ -z "${feed_direction##*outbound*}" ] && printf '%s\n' "add rule inet banIP _outbound ether saddr . ip6 saddr @${feed} counter goto _reject" ;; "4") f_chkip ${feed_ipv} local 1 < "${ban_blocklist}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv4_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ip saddr @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ip saddr @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ip saddr @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ip saddr @${feed} counter ${feed_target}" fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ip daddr @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ip daddr @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ip daddr @${feed} counter goto _reject" + printf '%s\n' "add rule inet banIP _outbound ip daddr @${feed} counter goto _reject" fi ;; "6") f_chkip ${feed_ipv} local 1 < "${ban_blocklist}" >"${tmp_file}" - printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv6_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ip6 saddr @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ip6 saddr @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ip6 saddr @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ip6 saddr @${feed} counter ${feed_target}" fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ip6 daddr @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ip6 daddr @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ip6 daddr @${feed} counter goto _reject" + printf '%s\n' "add rule inet banIP _outbound ip6 daddr @${feed} counter goto _reject" fi ;; esac @@ -1480,40 +1478,40 @@ f_down() { { # nft header (IPv4 Set) incl. inbound and outbound rules # - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}" - printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}.1") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}.1") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ${feed_dport} ip saddr @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ${feed_dport} ip saddr @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ${feed_dport} ip saddr @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ${feed_dport} ip saddr @${feed} counter ${feed_target}" fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ${feed_dport} ip daddr @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ${feed_dport} ip daddr @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ${feed_dport} ip daddr @${feed} counter goto _reject" + printf '%s\n' "add rule inet banIP _outbound ${feed_dport} ip daddr @${feed} counter goto _reject" fi } >"${tmp_nft}" elif [ "${feed_ipv}" = "6" ]; then { # nft header (IPv6 Set) incl. inbound and outbound rules # - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}" - printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}.1") }" + printf '%s\n' "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; ${element_count}; $(f_getelements "${tmp_file}.1") }" if [ -z "${feed_direction##*inbound*}" ]; then if [ "${ban_loginbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _inbound ${feed_dport} ip6 saddr @${feed} ${log_inbound}" + printf '%s\n' "add rule inet banIP _inbound ${feed_dport} ip6 saddr @${feed} ${log_inbound}" fi - printf "%s\n" "add rule inet banIP _inbound ${feed_dport} ip6 saddr @${feed} counter ${feed_target}" + printf '%s\n' "add rule inet banIP _inbound ${feed_dport} ip6 saddr @${feed} counter ${feed_target}" fi if [ -z "${feed_direction##*outbound*}" ]; then if [ "${ban_logoutbound}" = "1" ]; then - printf "%s\n" "add rule inet banIP _outbound ${feed_dport} ip6 daddr @${feed} ${log_outbound}" + printf '%s\n' "add rule inet banIP _outbound ${feed_dport} ip6 daddr @${feed} ${log_outbound}" fi - printf "%s\n" "add rule inet banIP _outbound ${feed_dport} ip6 daddr @${feed} counter goto _reject" + printf '%s\n' "add rule inet banIP _outbound ${feed_dport} ip6 daddr @${feed} counter goto _reject" fi } >"${tmp_nft}" fi @@ -1545,7 +1543,7 @@ f_down() { for split_file in "${tmp_file}".*; do if [ -s "${split_file}" ]; then "${ban_sedcmd}" -i "1 i #!${ban_nftcmd} -f\nadd element inet banIP ${feed} { " "${split_file}" - printf "%s\n" "}" >>"${split_file}" + printf '%s\n' "}" >>"${split_file}" # load split file to nftset # @@ -1605,9 +1603,9 @@ f_rmset() { json_get_keys feedlist tmp_del="${ban_tmpfile}.final.delete" table_json="$("${ban_nftcmd}" -tj list table inet banIP 2>>"${ban_errorlog}")" - table_sets="$(printf "%s\n" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" + table_sets="$(printf '%s\n' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" { - printf "%s\n\n" "#!${ban_nftcmd} -f" + printf '%s\n\n' "#!${ban_nftcmd} -f" for feed in ${table_sets}; do _rmset_skip="0" case " allowlist blocklist ${ban_feed} " in @@ -1706,14 +1704,14 @@ f_rmset() { "${ban_rmcmd}" -f "${ban_backupdir}/banIP.${feed}.gz" for chain in _inbound _outbound; do for expr in 0 1 2; do - handles="$(printf "%s\n" "${table_json}" | "${ban_jsoncmd}" -q -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${feed}\"].handle" | "${ban_xargscmd}")" + handles="$(printf '%s\n' "${table_json}" | "${ban_jsoncmd}" -q -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${feed}\"].handle" | "${ban_xargscmd}")" for handle in ${handles}; do - printf "%s\n" "delete rule inet banIP ${chain} handle ${handle}" + printf '%s\n' "delete rule inet banIP ${chain} handle ${handle}" done done done - printf "%s\n" "flush set inet banIP ${feed}" - printf "%s\n\n" "delete set inet banIP ${feed}" + printf '%s\n' "flush set inet banIP ${feed}" + printf '%s\n\n' "delete set inet banIP ${feed}" fi done } >"${tmp_del}" @@ -1736,25 +1734,25 @@ f_genstatus() { local mem_free nft_ver chain_cnt set_cnt rule_cnt object end_time duration table table_sets element_cnt="0" custom_feed="0" split="0" status="${1}" mem_free="$("${ban_awkcmd}" '/^MemAvailable/{printf "%.2f", $2/1024}' "/proc/meminfo" 2>>"${ban_errorlog}")" - nft_ver="$(printf "%s" "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages["nftables-json"]')" + nft_ver="$(printf '%s' "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages["nftables-json"]')" [ -z "${ban_dev}" ] && f_conf if [ "${status}" = "active" ]; then table="$("${ban_nftcmd}" -tj list table inet banIP 2>>"${ban_errorlog}")" - table_sets="$(printf "%s" "${table}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" + table_sets="$(printf '%s' "${table}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" for object in ${table_sets}; do element_cnt="$((element_cnt + $("${ban_nftcmd}" -j list set inet banIP "${object}" 2>>"${ban_errorlog}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")))" done - chain_cnt="$(printf "%s" "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].chain.name' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" - set_cnt="$(printf "%s" "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.name' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" - rule_cnt="$(printf "%s" "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].rule' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" + chain_cnt="$(printf '%s' "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].chain.name' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" + set_cnt="$(printf '%s' "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.name' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" + rule_cnt="$(printf '%s' "${table}" | "${ban_jsoncmd}" -qe '@.nftables[*].rule' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" element_cnt="$("${ban_awkcmd}" -v cnt="${element_cnt}" 'BEGIN{res="";pos=0;for(i=length(cnt);i>0;i--){res=substr(cnt,i,1)res;pos++;if(pos==3&&i>1){res=" "res;pos=0;}}; printf"%s",res}')" - if [ -n "${ban_starttime}" ] && [ "${ban_action}" != "boot" ]; then + if [ -n "${ban_starttime}" ]; then read -r end_time _ < "/proc/uptime" end_time="${end_time%%.*}" duration="$(((end_time - ban_starttime) / 60))m $(((end_time - ban_starttime) % 60))s" fi - runtime="mode: ${ban_action}, $(date "+%d/%m/%Y %H:%M:%S"), duration: ${duration:-"-"}, memory: ${mem_free} MB available" + runtime="mode: ${ban_action}, date / time: $(date "+%d/%m/%Y %H:%M:%S"), duration: ${duration:-"-"}, memory: ${mem_free} MB available" fi [ -s "${ban_customfeedfile}" ] && custom_feed="1" [ "${ban_splitsize:-"0"}" -gt "0" ] && split="1" @@ -1812,7 +1810,7 @@ f_getstatus() { [ -z "${ban_dev}" ] && f_conf json_load_file "${ban_rtfile}" >/dev/null 2>&1 if json_get_keys keylist; then - printf "%s\n" "::: banIP runtime information" + printf '%s\n' "::: banIP runtime information" for key in ${keylist}; do if [ "${key}" = "active_feeds" ] || [ "${key}" = "active_uplink" ]; then json_get_values values "${key}" >/dev/null 2>&1 @@ -1834,11 +1832,11 @@ f_getstatus() { fi fi if [ "${key}" != "wan_interfaces" ] && [ "${key}" != "vlan_allow" ] && [ "${key}" != "vlan_block" ]; then - printf " + %-17s : %s\n" "${key}" "${value:-"-"}" + printf ' + %-17s : %s\n' "${key}" "${value:-"-"}" fi done else - printf "%s\n" "::: no banIP runtime information available" + printf '%s\n' "::: no banIP runtime information available" fi } @@ -1892,7 +1890,7 @@ f_lookup() { # table statistics # f_report() { - local report_jsn report_txt tmp_val table_json item table_sets set_cnt set_inbound set_outbound set_cntinbound set_cntoutbound set_proto set_dport set_details + local report_jsn report_txt tmp_val table_json item sep table_sets set_cnt set_inbound set_outbound set_cntinbound set_cntoutbound set_proto set_dport set_details local expr detail jsnval timestamp autoadd_allow autoadd_block sum_sets sum_setinbound sum_setoutbound sum_cntelements sum_cntinbound sum_cntoutbound quantity local chunk map_jsn chain set_elements set_json sum_setelements sum_synflood sum_udpflood sum_icmpflood sum_ctinvalid sum_tcpinvalid sum_setports sum_bcp38 output="${1}" @@ -1908,7 +1906,7 @@ f_report() { : >"${report_jsn}" : >"${map_jsn}" table_json="$("${ban_nftcmd}" -tj list table inet banIP 2>>"${ban_errorlog}")" - table_sets="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" + table_sets="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.family="inet"].set.name')" sum_sets="0" sum_cntelements="0" sum_setinbound="0" @@ -1917,19 +1915,19 @@ f_report() { sum_cntoutbound="0" sum_setports="0" sum_setelements="0" - sum_synflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_synflood"].*.packets')" - sum_udpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_udpflood"].*.packets')" - sum_icmpflood="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_icmpflood"].*.packets')" - sum_ctinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_ctinvalid"].*.packets')" - sum_tcpinvalid="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_tcpinvalid"].*.packets')" - sum_bcp38="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_bcp38"].*.packets')" + sum_synflood="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_synflood"].*.packets')" + sum_udpflood="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_udpflood"].*.packets')" + sum_icmpflood="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_icmpflood"].*.packets')" + sum_ctinvalid="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_ctinvalid"].*.packets')" + sum_tcpinvalid="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_tcpinvalid"].*.packets')" + sum_bcp38="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt_bcp38"].*.packets')" timestamp="$(date "+%Y-%m-%d %H:%M:%S")" cnt="1" for item in ${table_sets}; do ( set_json="$("${ban_nftcmd}" -j list set inet banIP "${item}" 2>>"${ban_errorlog}")" - set_cnt="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" + set_cnt="$(printf '%s' "${set_json}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | "${ban_wccmd}" -l 2>>"${ban_errorlog}")" set_cntinbound="" set_cntoutbound="" set_inbound="" @@ -1940,16 +1938,16 @@ f_report() { for chain in _inbound _outbound; do for expr in 0 1 2; do if [ "${chain}" = "_inbound" ] && [ -z "${set_cntinbound}" ]; then - set_cntinbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")" + set_cntinbound="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")" elif [ "${chain}" = "_outbound" ] && [ -z "${set_cntoutbound}" ]; then - set_cntoutbound="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")" + set_cntoutbound="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")" fi - [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[0].match.right.set")" - [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.left.payload.protocol")" - [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right.set")" - [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right")" - [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right.set")" - [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right")" + [ -z "${set_proto}" ] && set_proto="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[0].match.right.set")" + [ -z "${set_proto}" ] && set_proto="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.left.payload.protocol")" + [ -z "${set_dport}" ] && set_dport="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right.set")" + [ -z "${set_dport}" ] && set_dport="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[2].match.right=\"@${item}\"].expr[1].match.right")" + [ -z "${set_dport}" ] && set_dport="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right.set")" + [ -z "${set_dport}" ] && set_dport="$(printf '%s' "${table_json}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.chain=\"${chain}\"][@.expr[1].match.right=\"@${item}\"].expr[0].match.right")" done done if [ -n "${set_proto}" ] && [ -n "${set_dport}" ]; then @@ -1962,7 +1960,7 @@ f_report() { set_dport="${set_proto}: $(f_trim "${set_dport}")" fi if [ "${ban_nftcount}" = "1" ]; then - set_elements="$(printf "%s" "${set_json}" | "${ban_jsoncmd}" -l50 -qe '@.nftables[*].set.elem[*][@.counter.packets>0].val' | + set_elements="$(printf '%s' "${set_json}" | "${ban_jsoncmd}" -l50 -qe '@.nftables[*].set.elem[*][@.counter.packets>0].val' | "${ban_awkcmd}" -F '[ ,]' '{ORS=" ";if($2=="\"range\":"||$2=="\"concat\":")printf"%s, ",$4;else if($2=="\"prefix\":")printf"%s, ",$5;else printf"\"%s\", ",$1}')" fi if [ -n "${set_cntinbound}" ]; then @@ -1977,33 +1975,33 @@ f_report() { set_outbound="-" set_cntoutbound="" fi - if [ "${cnt}" = "1" ]; then - printf "%s\n" "{ \ - \"sets\":{ \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \ - \"cnt_inbound\": \"${set_cntinbound}\", \ - \"inbound\": \"${set_inbound}\", \ - \"cnt_outbound\": \"${set_cntoutbound}\", \ - \"outbound\": \"${set_outbound}\", \ - \"port\": \"${set_dport:-"-"}\", \ - \"set_elements\": [ ${set_elements%%??} ] \ - }" >>"${report_jsn}" - else - printf "%s\n" ", \ - \"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \ - \"cnt_inbound\": \"${set_cntinbound}\", \ - \"inbound\": \"${set_inbound}\", \ - \"cnt_outbound\": \"${set_cntoutbound}\", \ - \"outbound\": \"${set_outbound}\", \ - \"port\": \"${set_dport:-"-"}\", \ - \"set_elements\": [ ${set_elements%%??} ] \ - }" >>"${report_jsn}" - fi + printf '%s\n' "\"${item}\":{ \"cnt_elements\": \"${set_cnt}\", \ + \"cnt_inbound\": \"${set_cntinbound}\", \ + \"inbound\": \"${set_inbound}\", \ + \"cnt_outbound\": \"${set_cntoutbound}\", \ + \"outbound\": \"${set_outbound}\", \ + \"port\": \"${set_dport:-"-"}\", \ + \"set_elements\": [ ${set_elements%%??} ] \ + }" >"${report_jsn}.${item}" ) & - [ "${cnt}" -eq "1" ] || [ "${cnt}" -gt "${ban_cores}" ] && wait -n + [ "${cnt}" -gt "${ban_cores}" ] && wait -n cnt="$((cnt + 1))" done wait - printf "\n%s\n" "} }" >>"${report_jsn}" + + # assemble JSON from per-set fragments + # + printf '%s' "{ \"sets\":{ " >"${report_jsn}" + sep="" + for item in ${table_sets}; do + if [ -s "${report_jsn}.${item}" ]; then + printf '%s' "${sep}" >>"${report_jsn}" + "${ban_catcmd}" "${report_jsn}.${item}" >>"${report_jsn}" + "${ban_rmcmd}" -f "${report_jsn}.${item}" + sep=", " + fi + done + printf '\n%s\n' "} }" >>"${report_jsn}" # add sum statistics # @@ -2025,7 +2023,7 @@ f_report() { "set_elements") json_get_values jsnval "${detail}" >/dev/null 2>&1 if [ -n "${jsnval}" ]; then - jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)" + jsnval="$(printf '%s' "${jsnval}" | "${ban_wccmd}" -w)" sum_setelements="$((sum_setelements + jsnval))" fi ;; @@ -2057,7 +2055,7 @@ f_report() { json_get_var jsnval "${detail}" >/dev/null 2>&1 if [ "${jsnval}" != "-" ]; then jsnval="${jsnval//[^0-9 ]/}" - jsnval="$(printf "%s" "${jsnval}" | "${ban_wccmd}" -w)" + jsnval="$(printf '%s' "${jsnval}" | "${ban_wccmd}" -w)" sum_setports="$((sum_setports + jsnval))" fi ;; @@ -2066,7 +2064,7 @@ f_report() { json_select ".." done "${ban_sedcmd}" -i ':a;$!N;1,1ba;P;$d;D' "${report_jsn}" - printf "%s\n" "}, \ + printf '%s\n' "}, \ \"timestamp\": \"${timestamp}\", \ \"autoadd_allow\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_allowlist}")\", \ \"autoadd_block\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_blocklist}")\", \ @@ -2101,7 +2099,7 @@ f_report() { jsnval="\"${jsnval// /\", \"}\"" if [ "${jsnval}" != '""' ]; then { - printf "%s" ",[{}" + printf '%s' ",[{}" "${ban_fetchcmd}" ${ban_geoparm} "[ ${jsnval} ]" "${ban_geourl}" 2>>"${ban_errorlog}" | "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="homeIP" '{printf ",{\"%s\": %s}\n",feed,$0}' } >>"${map_jsn}" @@ -2124,22 +2122,22 @@ f_report() { fi done if [ "${jsnval}" != '""' ]; then - quantity="0" - chunk="" ( + quantity="0" + chunk="" for ip in ${jsnval}; do chunk="${chunk} ${ip}" quantity="$((quantity + 1))" if [ "${quantity}" -eq "100" ]; then "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk%%?} ]" "${ban_geourl}" 2>>"${ban_errorlog}" | - "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item//_v/.v}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}" + "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item//_v/.v}" '{printf ",{\"%s\": %s}\n",feed,$0}' >"${map_jsn}.${item}" chunk="" quantity="0" fi done if [ "${quantity}" -gt "0" ]; then "${ban_fetchcmd}" ${ban_geoparm} "[ ${chunk} ]" "${ban_geourl}" 2>>"${ban_errorlog}" | - "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item//_v/.v}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}" + "${ban_jsoncmd}" -qe '@[*&&@.status="success"]' | "${ban_awkcmd}" -v feed="${item//_v/.v}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}.${item}" fi ) & [ "${cnt}" -gt "${ban_cores}" ] && wait -n @@ -2148,6 +2146,15 @@ f_report() { json_select ".." done wait + + # assemble map data from per-set fragments + # + for item in ${table_sets}; do + if [ -s "${map_jsn}.${item}" ]; then + "${ban_catcmd}" "${map_jsn}.${item}" >>"${map_jsn}" + "${ban_rmcmd}" -f "${map_jsn}.${item}" + fi + done fi fi fi @@ -2176,33 +2183,33 @@ f_report() { json_get_var sum_setports "sum_setports" >/dev/null 2>&1 json_get_var sum_setelements "sum_setelements" >/dev/null 2>&1 { - printf "%s\n%s\n%s\n" ":::" "::: banIP Set Statistics" ":::" - printf "%s\n" " Timestamp: ${timestamp}" - printf "%s\n" " ------------------------------" - printf "%s\n" " blocked syn-flood packets : ${sum_synflood}" - printf "%s\n" " blocked udp-flood packets : ${sum_udpflood}" - printf "%s\n" " blocked icmp-flood packets : ${sum_icmpflood}" - printf "%s\n" " blocked invalid ct packets : ${sum_ctinvalid}" - printf "%s\n" " blocked invalid tcp packets: ${sum_tcpinvalid}" - printf "%s\n" " blocked bcp38 packets : ${sum_bcp38}" - printf "%s\n" " ---" - printf "%s\n" " auto-added IPs to allowlist: ${autoadd_allow}" - printf "%s\n\n" " auto-added IPs to blocklist: ${autoadd_block}" + printf '%s\n%s\n%s\n' ":::" "::: banIP Set Statistics" ":::" + printf '%s\n' " Timestamp: ${timestamp}" + printf '%s\n' " ------------------------------" + printf '%s\n' " blocked syn-flood packets : ${sum_synflood}" + printf '%s\n' " blocked udp-flood packets : ${sum_udpflood}" + printf '%s\n' " blocked icmp-flood packets : ${sum_icmpflood}" + printf '%s\n' " blocked invalid ct packets : ${sum_ctinvalid}" + printf '%s\n' " blocked invalid tcp packets: ${sum_tcpinvalid}" + printf '%s\n' " blocked bcp38 packets : ${sum_bcp38}" + printf '%s\n' " ---" + printf '%s\n' " auto-added IPs to allowlist: ${autoadd_allow}" + printf '%s\n\n' " auto-added IPs to blocklist: ${autoadd_block}" json_select "sets" >/dev/null 2>&1 json_get_keys table_sets >/dev/null 2>&1 - table_sets="$(printf "%s\n" ${table_sets} | "${ban_sortcmd}")" + table_sets="$(printf '%s\n' ${table_sets} | "${ban_sortcmd}")" if [ -n "${table_sets}" ]; then - printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" " Set" "| Count " "| Inbound (packets)" "| Outbound (packets)" "| Port/Protocol " "| Elements (max. 50) " - printf "%s\n" " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------" + printf '%-25s%-15s%-24s%-24s%-24s%-24s\n' " Set" "| Count " "| Inbound (packets)" "| Outbound (packets)" "| Port/Protocol " "| Elements (max. 50) " + printf '%s\n' " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------" for item in ${table_sets}; do - printf " %-21s" "${item//_v/.v}" + printf ' %-21s' "${item//_v/.v}" json_select "${item}" json_get_keys set_details for detail in ${set_details}; do case "${detail}" in "cnt_elements") json_get_var jsnval "${detail}" >/dev/null 2>&1 - printf "%-15s" "| ${jsnval}" + printf '%-15s' "| ${jsnval}" ;; "cnt_inbound" | "cnt_outbound") json_get_var jsnval "${detail}" >/dev/null 2>&1 @@ -2211,25 +2218,25 @@ f_report() { "set_elements") json_get_values jsnval "${detail}" >/dev/null 2>&1 jsnval="${jsnval// /, }" - printf "%-24s" "| ${jsnval:0:24}" + printf '%-24s' "| ${jsnval:0:24}" jsnval="${jsnval:24}" while [ -n "${jsnval}" ]; do - printf "\n%-25s%-15s%-24s%-24s%-24s%-24s" "" "|" "|" "|" "|" "| ${jsnval:0:24}" + printf '\n%-25s%-15s%-24s%-24s%-24s%-24s' "" "|" "|" "|" "|" "| ${jsnval:0:24}" jsnval="${jsnval:24}" done ;; *) json_get_var jsnval "${detail}" >/dev/null 2>&1 - printf "%-24s" "| ${jsnval}${tmp_val}" + printf '%-24s' "| ${jsnval}${tmp_val}" tmp_val="" ;; esac done - printf "\n" + printf '\n' json_select ".." done - printf "%s\n" " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------" - printf "%-25s%-15s%-24s%-24s%-24s%-24s\n" " ${sum_sets}" "| ${sum_cntelements}" "| ${sum_setinbound} (${sum_cntinbound})" "| ${sum_setoutbound} (${sum_cntoutbound})" "| ${sum_setports}" "| ${sum_setelements}" + printf '%s\n' " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------" + printf '%-25s%-15s%-24s%-24s%-24s%-24s\n' " ${sum_sets}" "| ${sum_cntelements}" "| ${sum_setinbound} (${sum_cntinbound})" "| ${sum_setoutbound} (${sum_cntoutbound})" "| ${sum_setports}" "| ${sum_setelements}" fi } >>"${report_txt}" fi @@ -2246,10 +2253,10 @@ f_report() { "json") if [ "${ban_nftcount}" = "1" ] && [ "${ban_map}" = "1" ]; then jsn="$("${ban_catcmd}" ${report_jsn} ${map_jsn} 2>>"${ban_errorlog}")" - [ -n "${jsn}" ] && printf "[%s]]\n" "${jsn}" + [ -n "${jsn}" ] && printf '[%s]]\n' "${jsn}" else jsn="$("${ban_catcmd}" ${report_jsn} 2>>"${ban_errorlog}")" - [ -n "${jsn}" ] && printf "[%s]\n" "${jsn}" + [ -n "${jsn}" ] && printf '[%s]\n' "${jsn}" fi ;; "mail") @@ -2257,7 +2264,7 @@ f_report() { : >"${report_txt}" ;; "gen") - printf "%s\n" "1" >"/var/run/banIP/banIP.report" + printf '%s\n' "1" >"/var/run/banIP/banIP.report" ;; *) : >"${report_txt}" @@ -2277,15 +2284,15 @@ f_search() { # case "${input}" in ''|*[!0-9A-Fa-f:/.]*) - printf "%s\n%s\n%s\n" ":::" "::: no valid search input" ":::" - printf "%s\n%s\n%s\n" ":::" "::: no valid search input" ":::" >"${result}" + printf '%s\n%s\n%s\n' ":::" "::: no valid search input" ":::" + printf '%s\n%s\n%s\n' ":::" "::: no valid search input" ":::" >"${result}" return ;; esac # determine protocol via awk # - res="$(printf "%s" "${input}" | "${ban_awkcmd}" ' + res="$(printf '%s' "${input}" | "${ban_awkcmd}" ' { if (match($0,/([1-9][0-9]{0,2}\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/([12]?[0-9]|3[012]))?[[:space:]]*$/)) { printf "v4 %s",substr($0,RSTART,RLENGTH) @@ -2303,17 +2310,17 @@ f_search() { table_sets="$("${ban_nftcmd}" -tj list table inet banIP 2>>"${ban_errorlog}" | \ "${ban_jsoncmd}" -qe "@.nftables[@.set.type=\"ip${proto}_addr\"].set.name")" else - printf "%s\n%s\n%s\n" ":::" "::: no valid search input" ":::" - printf "%s\n%s\n%s\n" ":::" "::: no valid search input" ":::" >"${result}" + printf '%s\n%s\n%s\n' ":::" "::: no valid search input" ":::" + printf '%s\n%s\n%s\n' ":::" "::: no valid search input" ":::" >"${result}" return fi # initial output # { - printf "%s\n%s\n%s\n" ":::" "::: banIP Search" ":::" - printf " %s\n" "Looking for IP '${ip}' on $(date "+%Y-%m-%d %H:%M:%S")" - printf " %s\n" "---" + printf '%s\n%s\n%s\n' ":::" "::: banIP Search" ":::" + printf ' %s\n' "Looking for IP '${ip}' on $(date "+%Y-%m-%d %H:%M:%S")" + printf ' %s\n' "---" } >"${tmp_result}" # search for IP in Sets @@ -2327,7 +2334,7 @@ f_search() { esac ( if "${ban_nftcmd}" get element inet banIP "${item}" "{ ${ip} }" >/dev/null 2>&1; then - printf " %s\n" "IP found in Set '${item}'" >>"${tmp_result}" + printf ' %s\n' "IP found in Set '${item}'" >"${tmp_result}.${item}" fi ) & [ "${cnt}" -gt "${ban_cores}" ] && wait -n @@ -2335,10 +2342,19 @@ f_search() { done wait + # assemble search results from per-set fragments + # + for item in ${table_sets}; do + if [ -s "${tmp_result}.${item}" ]; then + "${ban_catcmd}" "${tmp_result}.${item}" >>"${tmp_result}" + "${ban_rmcmd}" -f "${tmp_result}.${item}" + fi + done + # output result # if ! "${ban_grepcmd}" -qm1 "found" "${tmp_result}"; then - printf " %s\n" "IP not found" >>"${tmp_result}" + printf ' %s\n' "IP not found" >>"${tmp_result}" fi "${ban_mvcmd}" -f "${tmp_result}" "${result}" "${ban_catcmd}" "${result}" @@ -2353,7 +2369,7 @@ f_content() { # case "${input}" in ""|*[!a-zA-Z0-9_.]*) - printf "%s\n%s\n%s\n" ":::" "::: no valid Set input" ":::" + printf '%s\n%s\n%s\n' ":::" "::: no valid Set input" ":::" return ;; esac @@ -2366,7 +2382,7 @@ f_content() { filter="true" ;; *) - printf "%s\n%s\n%s\n" ":::" "::: no valid filter input" ":::" + printf '%s\n%s\n%s\n' ":::" "::: no valid filter input" ":::" return ;; esac @@ -2374,7 +2390,7 @@ f_content() { # check if Set exists # if ! "${ban_nftcmd}" -t list set inet banIP "${input}" >/dev/null 2>&1; then - printf "%s\n%s\n%s\n" ":::" "::: Set '${input}' not found" ":::" + printf '%s\n%s\n%s\n' ":::" "::: Set '${input}' not found" ":::" return fi @@ -2383,22 +2399,22 @@ f_content() { set_raw="$("${ban_nftcmd}" -j list set inet banIP "${input}" 2>>"${ban_errorlog}")" if [ "$(uci_get banip global ban_nftcount)" = "1" ]; then if [ "${filter}" = "true" ]; then - set_elements="$(printf "%s" "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*][@.counter.packets>0].*' | + set_elements="$(printf '%s' "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*][@.counter.packets>0].*' | "${ban_awkcmd}" 'NR%2==1{ip=$0;next}BEGIN{FS="[:,{}\"]+"}{print ip ", packets: "$4 }')" else - set_elements="$(printf "%s" "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*].elem["val","counter"]' | + set_elements="$(printf '%s' "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*].elem["val","counter"]' | "${ban_awkcmd}" 'NR%2==1{ip=$0;next}BEGIN{FS="[:,{}\"]+"}{print ip ", packets: "$4 }')" fi else - set_elements="$(printf "%s" "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]')" + set_elements="$(printf '%s' "${set_raw}" | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]')" fi # output result # - printf "%s\n%s\n%s\n" ":::" "::: banIP Set Content" ":::" - printf " %s\n" "List elements of the Set '${input}' on $(date "+%Y-%m-%d %H:%M:%S")" - printf " %s\n" "---" - [ -n "${set_elements}" ] && printf "%s\n" "${set_elements}" || printf " %s\n" "empty Set" + printf '%s\n%s\n%s\n' ":::" "::: banIP Set Content" ":::" + printf ' %s\n' "List elements of the Set '${input}' on $(date "+%Y-%m-%d %H:%M:%S")" + printf ' %s\n' "---" + [ -n "${set_elements}" ] && printf '%s\n' "${set_elements}" || printf ' %s\n' "no elements in Set" } # send status mail @@ -2419,7 +2435,7 @@ f_mail() { # send mail # ban_mailhead="From: ${ban_mailsender}\nTo: ${ban_mailreceiver}\nSubject: ${ban_mailtopic}\nReply-to: ${ban_mailsender}\nMime-Version: 1.0\nContent-Type: text/html;charset=utf-8\nContent-Disposition: inline\n\n" - printf "%b" "${ban_mailhead}${mail_text}" | "${ban_mailcmd}" --timeout=10 ${msmtp_debug} -a "${ban_mailprofile}" "${ban_mailreceiver}" >/dev/null 2>&1 + printf '%b' "${ban_mailhead}${mail_text}" | "${ban_mailcmd}" --timeout=10 ${msmtp_debug} -a "${ban_mailprofile}" "${ban_mailreceiver}" >/dev/null 2>&1 f_log "debug" "f_mail ::: notification: ${ban_mailnotification}, template: ${ban_mailtemplate}, profile: ${ban_mailprofile}, receiver: ${ban_mailreceiver}, rc: ${?}" } @@ -2428,14 +2444,15 @@ f_mail() { # f_monitor() { local nft_expiry ip proto idx base cidr rdap_log rdap_rc rdap_idx rdap_info log_type allow_v4 allow_v6 block_v4 block_v6 - local block_cache file cache_ts date_stamp time_now time_elapsed cache_interval rdap_interval rdap_tsfile rdap_lock rdap_jobs + local file cache_ts date_stamp time_now time_elapsed cache_interval rdap_interval rdap_tsfile rdap_lock rdap_jobs + local block_cache block_cache_limit block_cache_cnt # intervals for periodic cache refresh and RDAP queries # cache_interval=300 rdap_interval=2 rdap_tsfile="/var/run/banIP/banIP_rdap_ts" - printf "%s" "0" > "${rdap_tsfile}" + printf '%s' "0" > "${rdap_tsfile}" # determine log reader type # @@ -2452,9 +2469,9 @@ f_monitor() { # determine nft timeout expression and cache interval # - if printf "%s" "${ban_nftexpiry}" | grep -qE '^([1-9][0-9]*(ms|s|m|h|d|w))+$'; then + if printf '%s' "${ban_nftexpiry}" | grep -qE '^([1-9][0-9]*(ms|s|m|h|d|w))+$'; then nft_expiry="timeout ${ban_nftexpiry}" - cache_interval="$(printf "%s" "${ban_nftexpiry}" | "${ban_awkcmd}" '{ + cache_interval="$(printf '%s' "${ban_nftexpiry}" | "${ban_awkcmd}" '{ s = 0 str = $0 while (match(str, /([0-9]+)(ms|s|m|h|d|w)/, a)) { @@ -2493,6 +2510,8 @@ f_monitor() { cache_ts="${cache_ts%%.*}" date_stamp="$(date "+%Y-%m-%d %H:%M:%S")" block_cache="" + block_cache_limit="500" + block_cache_cnt="0" # clean up stale RDAP lock/done markers from previous runs # @@ -2571,6 +2590,7 @@ f_monitor() { date_stamp="$(date "+%Y-%m-%d %H:%M:%S")" cache_ts="${time_now}" block_cache="" + block_cache_cnt="0" "${ban_rmcmd}" -f "${ban_rdapfile}".*.done >/dev/null 2>&1 f_log "debug" "f_monitor ::: refreshed monitor cache at ${date_stamp}" fi @@ -2599,6 +2619,12 @@ f_monitor() { # CIDR-aware allowlist lookup (only at block-time, not every IP) # if "${ban_nftcmd}" get element inet banIP "allowlist${proto}" { ${ip} } >/dev/null 2>&1; then + block_cache_cnt="$((block_cache_cnt + 1))" + if [ "${block_cache_cnt}" -ge "${block_cache_limit}" ]; then + block_cache="" + block_cache_cnt="1" + f_log "debug" "f_monitor ::: refreshed local monitor cache at ${date_stamp}" + fi block_cache="${block_cache} ${ip} " f_log "debug" "f_monitor ::: skip IP '${ip}', found via allowlist CIDR lookup" continue @@ -2607,6 +2633,12 @@ f_monitor() { # try to add IP to the blocklist Set with appropriate expiry # if "${ban_nftcmd}" add element inet banIP "blocklist${proto}" { ${ip} ${nft_expiry} } >/dev/null 2>&1; then + block_cache_cnt="$((block_cache_cnt + 1))" + if [ "${block_cache_cnt}" -ge "${block_cache_limit}" ]; then + block_cache="" + block_cache_cnt="1" + f_log "debug" "f_monitor ::: refreshed local monitor cache at ${date_stamp}" + fi block_cache="${block_cache} ${ip} " f_log "info" "add IP '${ip}' (cnt: ${ban_logcount}, expiry: ${ban_nftexpiry:-"0"}) to blocklist${proto} Set" else @@ -2639,18 +2671,20 @@ f_monitor() { # rate limiting via shared timestamp file # : >"${rdap_lock}" - read -r rdap_ts < "${rdap_tsfile}" 2>/dev/null - rdap_ts="${rdap_ts:-0}" - read -r time_now _ < "/proc/uptime" - time_now="${time_now%%.*}" - time_elapsed=$((time_now - rdap_ts)) - if [ "${time_elapsed}" -lt "${rdap_interval}" ]; then - sleep "$((rdap_interval - time_elapsed))" - fi - read -r rdap_ts _ < "/proc/uptime" - rdap_ts="${rdap_ts%%.*}" - printf '%s' "${rdap_ts}" > "${rdap_tsfile}" - + ( + flock -x 9 + read -r rdap_ts < "${rdap_tsfile}" 2>/dev/null + rdap_ts="${rdap_ts:-0}" + read -r time_now _ < "/proc/uptime" + time_now="${time_now%%.*}" + time_elapsed=$((time_now - rdap_ts)) + if [ "${time_elapsed}" -lt "${rdap_interval}" ]; then + sleep "$((rdap_interval - time_elapsed))" + fi + read -r rdap_ts _ < "/proc/uptime" + rdap_ts="${rdap_ts%%.*}" + printf '%s' "${rdap_ts}" > "${rdap_tsfile}" + ) 9>"${rdap_tsfile}.lock" : >"${ban_rdapfile}.${ip}" rdap_log="$("${ban_fetchcmd}" ${ban_rdapparm} "${ban_rdapfile}.${ip}" "${ban_rdapurl}${ip}" 2>&1)" rdap_rc="${?}" @@ -2694,7 +2728,7 @@ f_monitor() { # persist to local blocklist file if no expiry # if [ -z "${ban_nftexpiry}" ] && [ "${ban_autoblocklist}" = "1" ] && ! "${ban_grepcmd}" -q "^${ip}[[:space:]]" "${ban_blocklist}"; then - printf "%-45s%s\n" "${ip}" "# added on ${date_stamp}" >>"${ban_blocklist}" + printf '%-45s%s\n' "${ip}" "# added on ${date_stamp}" >>"${ban_blocklist}" f_log "info" "add IP '${ip}' to local blocklist" fi ;; @@ -2724,7 +2758,7 @@ fi # reference required system utilities # -ban_awkcmd="$(f_cmd gawk awk)" +ban_awkcmd="$(f_cmd gawk)" ban_catcmd="$(f_cmd cat)" ban_grepcmd="$(f_cmd grep)" ban_jsoncmd="$(f_cmd jsonfilter)" diff --git a/net/banip/files/banip-service.sh b/net/banip/files/banip-service.sh index b0952f0330..4882bd373d 100755 --- a/net/banip/files/banip-service.sh +++ b/net/banip/files/banip-service.sh @@ -44,7 +44,7 @@ fi # f_log "info" "start banIP download processes" f_getfeed -[ "${ban_deduplicate}" = "1" ] && printf "\n" >"${ban_tmpfile}.deduplicate" +[ "${ban_deduplicate}" = "1" ] && printf '\n' >"${ban_tmpfile}.deduplicate" # handle downloads # diff --git a/net/banip/files/banip.tpl b/net/banip/files/banip.tpl index cd786a5d61..e46c859a33 100644 --- a/net/banip/files/banip.tpl +++ b/net/banip/files/banip.tpl @@ -7,7 +7,7 @@ local banip_info report_info log_info system_info mail_text # log info preparation # if [ -f "${ban_logreadfile}" ] && [ -x "${ban_logreadcmd}" ] && [ "${ban_logreadcmd##*/}" = "tail" ]; then - log_info="$("${ban_logreadcmd}" -qn "${ban_loglimit}" "${ban_logreadfile}" 2>/dev/null | "${ban_grepcmd}" -e "banIP/" 2>/dev/null)" + log_info="$("${ban_logreadcmd}" -qn "${ban_loglimit}" "${ban_logreadfile}" 2>/dev/null | "${ban_grepcmd}" -e "banIP-" 2>/dev/null)" elif [ -x "${ban_logreadcmd}" ] && [ "${ban_logreadcmd##*/}" = "logread" ]; then log_info="$("${ban_logreadcmd}" -l "${ban_loglimit}" -e "banIP-" 2>/dev/null)" fi @@ -15,33 +15,33 @@ fi # banIP status and report info preparation # banip_info="$(/etc/init.d/banip status 2>/dev/null)" -report_info="$(< "${ban_reportdir}/ban_report.txt")" 2>/dev/null +report_info="$("${ban_catcmd}" "${ban_reportdir}/ban_report.txt" 2>/dev/null)" system_info="$(strings /etc/banner 2>/dev/null; "${ban_ubuscmd}" call system board | \ "${ban_awkcmd}" 'BEGIN{FS="[{}\"]"}{if($2=="kernel"||$2=="hostname"||$2=="system"||$2=="model"||$2=="description")printf " + %-12s: %s\n",$2,$4}')" # mail text preparation # mail_text="$( - printf "%s\n" "
"
-	printf "\n%s\n" "++
+	printf '%s\n' "
"
+	printf '\n%s\n' "++
 ++ System Information ++
 ++"
-	printf "%s\n" "${system_info:-"-"}"
-	printf "\n%s\n" "++
+	printf '%s\n' "${system_info:-"-"}"
+	printf '\n%s\n' "++
 ++ banIP Status ++
 ++"
-	printf "%s\n" "${banip_info:-"-"}"
+	printf '%s\n' "${banip_info:-"-"}"
 	[ -n "${report_info}" ] && {
-		printf "\n%s\n" "++
+		printf '\n%s\n' "++
 ++ banIP Report ++
 ++"
-		printf "%s\n" "${report_info}"
+		printf '%s\n' "${report_info}"
 	}
 	[ -n "${log_info}" ] && {
-		printf "\n%s\n" "++
+		printf '\n%s\n' "++
 ++ Logfile Information ++
 ++"
-		printf "%s\n" "${log_info}"
+		printf '%s\n' "${log_info}"
 	}
-	printf "%s\n" "
" + printf '%s\n' "
" )"