1 # banIP shared function library/include - ban incoming and outgoing IPs via named nftables Sets
2 # Copyright (c) 2018-2024 Dirk Brenken (dev@brenken.org)
3 # This is free software, licensed under the GNU General Public License v3.
5 # (s)hellcheck exceptions
6 # shellcheck disable=all
11 export PATH
="/usr/sbin:/usr/bin:/sbin:/bin"
16 ban_backupdir
="/tmp/banIP-backup"
17 ban_reportdir
="/tmp/banIP-report"
18 ban_feedfile
="/etc/banip/banip.feeds"
19 ban_countryfile
="/etc/banip/banip.countries"
20 ban_customfeedfile
="/etc/banip/banip.custom.feeds"
21 ban_allowlist
="/etc/banip/banip.allowlist"
22 ban_blocklist
="/etc/banip/banip.blocklist"
23 ban_mailtemplate
="/etc/banip/banip.tpl"
24 ban_pidfile
="/var/run/banip.pid"
25 ban_rtfile
="/var/run/banip_runtime.json"
26 ban_rdapfile
="/var/run/banip_rdap.json"
27 ban_rdapurl
="https://rdap.db.ripe.net/ip/"
28 ban_lock
="/var/run/banip.lock"
29 ban_logreadfile
="/var/log/messages"
31 ban_mailsender
="no-reply@banIP"
33 ban_mailtopic
="banIP notification"
34 ban_mailprofile
="ban_notify"
35 ban_mailnotification
="0"
36 ban_reportelements
="1"
39 ban_nftloglevel
="warn"
40 ban_nftpriority
="-100"
41 ban_nftpolicy
="memory"
60 ban_autoallowuplink
="subnet"
62 ban_autoblocksubnet
="0"
70 ban_blockforwardwan
=""
71 ban_blockforwardlan
=""
94 # gather system information
99 if [ -z "${ban_dev}" ]; then
100 ban_debug
="$(uci_get banip global ban_debug "0")"
101 ban_cores
="$(uci_get banip global ban_cores)"
103 ban_packages
="$("${ban_ubuscmd}" -S call rpc-sys packagelist '{ "all
": true }' 2>/dev/null)"
104 ban_memory
="$("${ban_awkcmd}" '/^MemAvailable/{printf "%s
",int($2/1000)}' "/proc
/meminfo
" 2>/dev/null)"
105 ban_ver
="$(printf "%s
" "${ban_packages}" | "${ban_jsoncmd}" -ql1 -e '@.packages.banip')"
106 ban_sysver
="$("${ban_ubuscmd}" -S call system board 2>/dev/null | "${ban_jsoncmd}" -ql1 -e '@.model' -e '@.release.description' |
107 "${ban_awkcmd}" 'BEGIN{RS="";FS="\n"}{printf "%s
, %s
",$1,$2}')"
108 if [ -z "${ban_cores}" ]; then
109 cpu
="$("${ban_grepcmd}" -c '^processor' /proc/cpuinfo 2>/dev/null)"
110 core
="$("${ban_grepcmd}" -cm1 '^core id' /proc/cpuinfo 2>/dev/null)"
111 [ "${cpu}" = "0" ] && cpu
="1"
112 [ "${core}" = "0" ] && core
="1"
113 ban_cores
="$((cpu * core))"
114 [ "${ban_cores}" -gt "16" ] && ban_cores
="16"
121 local cmd pri_cmd
="${1}" sec_cmd
="${2}"
123 cmd
="$(command -v "${pri_cmd}" 2>/dev/null)"
124 if [ ! -x "${cmd}" ]; then
125 if [ -n "${sec_cmd}" ]; then
126 [ "${sec_cmd}" = "true" ] && return
127 cmd
="$(command -v "${sec_cmd}" 2>/dev/null)"
129 if [ -x "${cmd}" ]; then
132 f_log
"emerg" "command '${pri_cmd:-"-"}'/'${sec_cmd:-"-"}' not found"
144 if [ ! -d "${dir}" ]; then
147 f_log
"debug" "f_mkdir ::: directory: ${dir}"
156 if [ ! -f "${file}" ]; then
158 f_log
"debug" "f_mkfile ::: file: ${file}"
162 # create temporary files and directories
165 f_mkdir
"${ban_basedir}"
166 ban_tmpdir
="$(mktemp -p "${ban_basedir}" -d)"
167 ban_tmpfile
="$(mktemp -p "${ban_tmpdir}" -tu)"
169 f_log
"debug" "f_tmp ::: base_dir: ${ban_basedir:-"-"}, tmp_dir: ${ban_tmpdir:-"-"}"
177 if [ -d "${dir}" ]; then
179 f_log
"debug" "f_rmdir ::: directory: ${dir}"
188 if [ "${char}" = "1" ]; then
190 elif [ "${char}" = "0" ] ||
[ -z "${char}" ]; then
193 printf "%s" "${char}"
202 string
="${string#"${string%%[![:space:]]*}"}"
203 string
="${string%"${string##*[![:space:]]}"}"
204 printf "%s" "${string}"
212 ppid
="$("${ban_catcmd}" "${ban_pidfile}" 2>/dev/null)"
213 if [ -n "${ppid}" ]; then
214 pids
="$("${ban_pgrepcmd}" -P "${ppid}" 2>/dev/null)"
215 for pid
in ${pids}; do
216 pids
="${pids} $("${ban_pgrepcmd}" -P "${pid}" 2>/dev
/null
)"
218 for pid in ${pids}; do
219 kill -INT "${pid}" >/dev/null 2>&1
222 : >"${ban_rdapfile}" >"${ban_pidfile}"
228 local class="${1}" log_msg="${2}"
230 if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${ban_debug}" = "1" ]; }; then
231 if [ -x "${ban_logcmd}" ]; then
232 "${ban_logcmd}" -p "${class}" -t "banIP-${ban_ver}[${$}]" "${log_msg::512}"
234 printf "%s %s %s\n" "${class}" "banIP-${ban_ver}[${$}]" "${log_msg::512}"
237 if [ "${class}" = "err" ] ||
[ "${class}" = "emerg" ]; then
238 if [ "${class}" = "err" ]; then
239 "${ban_nftcmd}" delete table inet banIP
>/dev
/null
2>&1
240 if [ "$(uci_get banip global ban_enabled)" = "1" ]; then
242 [ "${ban_mailnotification}" = "1" ] && [ -n "${ban_mailreceiver}" ] && [ -x "${ban_mailcmd}" ] && f_mail
244 f_genstatus
"disabled"
247 f_rmdir
"${ban_tmpdir}"
257 local rir ccode region country
259 unset ban_dev ban_vlanallow ban_vlanblock ban_ifv4 ban_ifv6 ban_feed ban_allowurl ban_blockinput ban_blockforwardwan ban_blockforwardlan ban_logterm ban_region ban_country ban_asn
264 eval "${option}=\"${value}\""
271 eval "${option}=\"$(printf "%s" "${ban_ifv4}")${value} \""
274 eval "${option}=\"$(printf "%s" "${ban_ifv6}")${value} \""
277 eval "${option}=\"$(printf "%s" "${ban_dev}")${value} \""
280 eval "${option}=\"$(printf "%s" "${ban_vlanallow}")${value} \""
283 eval "${option}=\"$(printf "%s" "${ban_vlanblock}")${value} \""
286 eval "${option}=\"$(printf "%s" "${ban_trigger}")${value} \""
289 eval "${option}=\"$(printf "%s" "${ban_feed}")${value} \""
292 eval "${option}=\"$(printf "%s" "${ban_allowurl}")${value} \""
295 eval "${option}=\"$(printf "%s" "${ban_blockinput}")${value} \""
297 "ban_blockforwardwan")
298 eval "${option}=\"$(printf "%s" "${ban_blockforwardwan}")${value} \""
300 "ban_blockforwardlan")
301 eval "${option}=\"$(printf "%s" "${ban_blockforwardlan}")${value} \""
304 eval "${option}=\"$(printf "%s" "${ban_logterm}")${value}\\|\""
307 eval "${option}=\"$(printf "%s" "${ban_region}")${value} \""
310 eval "${option}=\"$(printf "%s" "${ban_country}")${value} \""
313 eval "${option}=\"$(printf "%s" "${ban_asn}")${value} \""
319 [ -f "${ban_logreadfile}" ] && ban_logreadcmd
="$(command -v tail)" || ban_logreadcmd
="$(command -v logread)"
321 for rir
in ${ban_region}; do
322 while read -r ccode region country
; do
323 if [ "${rir}" = "${region}" ] && ! printf "%s" "${ban_country}" | "${ban_grepcmd}" -qw "${ccode}"; then
324 ban_country
="${ban_country} ${ccode}"
326 done <"${ban_countryfile}"
330 # get nft/monitor actuals
333 local nft monitor ppid pids pid
335 if "${ban_nftcmd}" -t list
set inet banIP allowlistv4MAC
>/dev
/null
2>&1; then
341 ppid
="$("${ban_catcmd}" "${ban_pidfile}" 2>/dev/null)"
342 if [ -n "${ppid}" ]; then
343 pids
="$("${ban_pgrepcmd}" -P "${ppid}" 2>/dev/null)"
344 for pid
in ${pids}; do
345 if "${ban_pgrepcmd}" -f "${ban_logreadcmd##*/}" -P "${pid}" >/dev
/null
2>&1; then
346 monitor
="$(f_char "1")"
349 monitor
="$(f_char "0")"
353 monitor
="$(f_char "0")"
355 printf "%s" "nft: ${nft}, monitor: ${monitor}"
361 local item utils insecure update
="0"
363 if { [ "${ban_fetchcmd}" = "uclient-fetch" ] && printf "%s" "${ban_packages}" | "${ban_grepcmd}" -q '"libustream-'; } ||
364 { [ "${ban_fetchcmd}" = "wget" ] && printf "%s" "${ban_packages}" | "${ban_grepcmd}" -q '"wget-ssl'; } ||
365 [ "${ban_fetchcmd}" = "curl" ] ||
[ "${ban_fetchcmd}" = "aria2c" ]; then
366 ban_fetchcmd
="$(f_cmd "${ban_fetchcmd}" "true
")"
369 if [ "${ban_autodetect}" = "1" ] && [ ! -x "${ban_fetchcmd}" ]; then
370 utils
="aria2c curl wget uclient-fetch"
371 for item
in ${utils}; do
372 if { [ "${item}" = "uclient-fetch" ] && printf "%s" "${ban_packages}" | "${ban_grepcmd}" -q '"libustream-'; } ||
373 { [ "${item}" = "wget" ] && printf "%s" "${ban_packages}" | "${ban_grepcmd}" -q '"wget-ssl'; } ||
374 [ "${item}" = "curl" ] ||
[ "${item}" = "aria2c" ]; then
375 ban_fetchcmd
="$(command -v "${item}")"
376 if [ -x "${ban_fetchcmd}" ]; then
378 uci_set banip global ban_fetchcmd
"${item}"
386 [ ! -x "${ban_fetchcmd}" ] && f_log
"err" "no download utility with SSL support"
387 case "${ban_fetchcmd##*/}" in
389 [ "${ban_fetchinsecure}" = "1" ] && insecure
="--check-certificate=false"
390 ban_fetchparm
="${ban_fetchparm:-"${insecure} --timeout=20 --retry-wait=10 --max-tries=${ban_fetchretry} --max-file-not-found=${ban_fetchretry} --allow-overwrite=true --auto-file-renaming=false --log-level=warn --dir=/ -o"}"
391 ban_rdapparm
="--timeout=5 --allow-overwrite=true --auto-file-renaming=false --dir=/ -o"
392 ban_etagparm
="--timeout=5 --allow-overwrite=true --auto-file-renaming=false --dir=/ --dry-run --log -"
395 [ "${ban_fetchinsecure}" = "1" ] && insecure
="--insecure"
396 ban_fetchparm
="${ban_fetchparm:-"${insecure} --connect-timeout 20 --retry-delay 10 --retry ${ban_fetchretry} --retry-max-time $((ban_fetchretry * 20)) --retry-all-errors --fail --silent --show-error --location -o"}"
397 ban_rdapparm
="--connect-timeout 5 --silent --location -o"
398 ban_etagparm
="--connect-timeout 5 --silent --location --head"
401 [ "${ban_fetchinsecure}" = "1" ] && insecure
="--no-check-certificate"
402 ban_fetchparm
="${ban_fetchparm:-"${insecure} --no-cache --no-cookies --timeout=20 --waitretry=10 --tries=${ban_fetchretry} --retry-connrefused -O"}"
403 ban_rdapparm
="--timeout=5 -O"
404 ban_etagparm
="--timeout=5 --spider --server-response"
407 [ "${ban_fetchinsecure}" = "1" ] && insecure
="--no-check-certificate"
408 ban_fetchparm
="${ban_fetchparm:-"${insecure} --timeout=20 -O"}"
409 ban_rdapparm
="--timeout=5 -O"
413 f_log
"debug" "f_getfetch ::: auto/update: ${ban_autodetect}/${update}, cmd: ${ban_fetchcmd:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}, rdap_parm: ${ban_rdapparm:-"-"}, etag_parm: ${ban_etagparm:-"-"}"
419 local iface iface_del update
="0"
421 if [ "${ban_autodetect}" = "1" ]; then
423 network_find_wan iface
424 if [ -n "${iface}" ] && [ "${iface}" != "$(f_trim "${ban_ifv4}")" ] && "${ban_ubuscmd}" -t 10 wait_for network.interface."${iface}" >/dev
/null
2>&1; then
425 for iface_del
in ${ban_ifv4}; do
426 uci_remove_list banip global ban_ifv4
"${iface_del}"
427 f_log
"info" "remove IPv4 interface '${iface_del}' from config"
431 uci_set banip global ban_protov4
"1"
432 uci_add_list banip global ban_ifv4
"${iface}"
433 f_log
"info" "add IPv4 interface '${iface}' to config"
435 network_find_wan6 iface
436 if [ -n "${iface}" ] && [ "${iface}" != "$(f_trim "${ban_ifv6}")" ] && "${ban_ubuscmd}" -t 10 wait_for network.interface."${iface}" >/dev
/null
2>&1; then
437 for iface_del
in ${ban_ifv6}; do
438 uci_remove_list banip global ban_ifv6
"${iface_del}"
439 f_log
"info" "remove IPv6 interface '${iface_del}' from config"
443 uci_set banip global ban_protov6
"1"
444 uci_add_list banip global ban_ifv6
"${iface}"
445 f_log
"info" "add IPv6 interface '${iface}' to config"
448 if [ -n "$(uci -q changes "banip
")" ]; then
452 for iface
in ${ban_ifv4} ${ban_ifv6}; do
453 if ! "${ban_ubuscmd}" -t 10 wait_for network.interface.
"${iface}" >/dev
/null
2>&1; then
454 f_log
"err" "no wan interface '${iface}'"
458 ban_ifv4
="$(f_trim "${ban_ifv4}")"
459 ban_ifv6
="$(f_trim "${ban_ifv6}")"
460 [ -z "${ban_ifv4}" ] && [ -z "${ban_ifv6}" ] && f_log
"err" "no wan interfaces"
462 f_log
"debug" "f_getif ::: auto/update: ${ban_autodetect}/${update}, interfaces (4/6): ${ban_ifv4}/${ban_ifv6}, protocols (4/6): ${ban_protov4}/${ban_protov6}"
468 local dev dev_del iface update
="0"
470 if [ "${ban_autodetect}" = "1" ]; then
473 for iface
in ${ban_ifv4} ${ban_ifv6}; do
474 network_get_device dev
"${iface}"
475 if [ -n "${dev}" ]; then
476 dev_del
="${dev_del/${dev} / }"
477 if ! printf " %s " "${ban_dev}" | "${ban_grepcmd}" -q " ${dev} "; then
478 ban_dev
="${ban_dev}${dev} "
479 uci_add_list banip global ban_dev
"${dev}"
480 f_log
"info" "add device '${dev}' to config"
484 for dev
in ${dev_del}; do
485 ban_dev
="${ban_dev/${dev} / }"
486 uci_remove_list banip global ban_dev
"${dev}"
487 f_log
"info" "remove device '${dev}' from config"
490 if [ -n "$(uci -q changes "banip
")" ]; then
494 ban_dev
="$(f_trim "${ban_dev}")"
495 [ -z "${ban_dev}" ] && f_log
"err" "no wan devices"
497 f_log
"debug" "f_getdev ::: auto/update: ${ban_autodetect}/${update}, wan_devices: ${ban_dev}"
503 local uplink iface ip update
="0"
505 if [ "${ban_autoallowlist}" = "1" ] && [ "${ban_autoallowuplink}" != "disable" ]; then
506 for iface
in ${ban_ifv4} ${ban_ifv6}; do
508 if [ "${ban_autoallowuplink}" = "subnet" ]; then
509 network_get_subnet uplink
"${iface}"
510 elif [ "${ban_autoallowuplink}" = "ip" ]; then
511 network_get_ipaddr uplink
"${iface}"
513 if [ -n "${uplink}" ] && ! printf " %s " "${ban_uplink}" | "${ban_grepcmd}" -q " ${uplink} "; then
514 ban_uplink
="${ban_uplink}${uplink} "
516 if [ "${ban_autoallowuplink}" = "subnet" ]; then
517 network_get_subnet6 uplink
"${iface}"
518 elif [ "${ban_autoallowuplink}" = "ip" ]; then
519 network_get_ipaddr6 uplink
"${iface}"
521 if [ -n "${uplink}" ] && ! printf " %s " "${ban_uplink}" | "${ban_grepcmd}" -q " ${uplink} "; then
522 ban_uplink
="${ban_uplink}${uplink} "
525 for ip
in ${ban_uplink}; do
526 if ! "${ban_grepcmd}" -q "${ip} " "${ban_allowlist}"; then
527 if [ "${update}" = "0" ]; then
528 "${ban_sedcmd}" -i "/# uplink added on /d" "${ban_allowlist}"
530 printf "%-42s%s\n" "${ip}" "# uplink added on $(date "+%Y-
%m-
%d
%H
:%M
:%S
")" >>"${ban_allowlist}"
531 f_log
"info" "add uplink '${ip}' to local allowlist"
535 ban_uplink
="$(f_trim "${ban_uplink}")"
536 elif [ "${ban_autoallowlist}" = "1" ] && [ "${ban_autoallowuplink}" = "disable" ]; then
537 "${ban_sedcmd}" -i "/# uplink added on /d" "${ban_allowlist}"
541 f_log
"debug" "f_getuplink ::: auto/update: ${ban_autoallowlist}/${update}, uplink: ${ban_uplink:-"-"}"
544 # get feed information
548 if [ -s "${ban_customfeedfile}" ]; then
549 if json_load_file
"${ban_customfeedfile}" >/dev
/null
2>&1; then
552 f_log
"info" "can't load banIP custom feed file"
555 if [ -s "${ban_feedfile}" ] && json_load_file
"${ban_feedfile}" >/dev
/null
2>&1; then
558 f_log
"err" "can't load banIP feed file"
567 [ -s "${file}" ] && printf "%s" "elements={ $("${ban_catcmd}" "${file}" 2>/dev/null) };"
570 # handle etag http header
573 local http_head http_code etag_id etag_rc out_rc
="4" feed
="${1}" feed_url="${2}" feed_suffix="${3}"
575 if [ -n "${ban_etagparm}" ]; then
576 [ ! -f "${ban_backupdir}/banIP.etag" ] && : >"${ban_backupdir}/banIP.etag"
577 http_head
="$("${ban_fetchcmd}" ${ban_etagparm} "${feed_url}" 2>&1)"
578 http_code
="$(printf "%s
" "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^http\/[0123\.]+ /{printf "%s",$2}')"
579 etag_id="$(printf "%s" "${http_head}" | "${ban_awkcmd}" 'tolower($0)~/^[[:space:]]*etag: /{gsub("\"","");printf "%s",$2}')"
582 if [ "${http_code}" = "404" ] || { [ "${etag_rc}" = "0" ] && [ -n "${etag_id}" ] && "${ban_grepcmd}" -q "^${feed}${feed_suffix}[[:space:]]\+${etag_id}\$" "${ban_backupdir}/banIP.etag"; }; then
584 elif [ "${etag_rc}" = "0" ] && [ -n "${etag_id}" ] && ! "${ban_grepcmd}" -q "^${feed}${feed_suffix}[[:space:]]\+${etag_id}\$" "${ban_backupdir}/banIP.etag"; then
585 "${ban_sedcmd}" -i "/^${feed}${feed_suffix}/d" "${ban_backupdir}/banIP.etag"
586 printf "%-20s%s\n" "${feed}${feed_suffix}" "${etag_id}" >>"${ban_backupdir}/banIP.etag"
591 f_log
"debug" "f_etag ::: feed: ${feed}, suffix: ${feed_suffix:-"-"}, http_code: ${http_code:-"-"}, etag_id: ${etag_id:-"-"} , etag_rc: ${etag_rc:-"-"}, rc: ${out_rc}"
595 # build initial nft file with base table, chains and rules
598 local wan_dev vlan_allow vlan_block log_ct log_icmp log_syn log_udp log_tcp feed_log feed_rc flag tmp_proto tmp_port allow_dport
file="${1}"
600 wan_dev
="$(printf "%s
" "${ban_dev}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')"
601 [ -n "${ban_vlanallow}" ] && vlan_allow="$(printf "%s" "${ban_vlanallow%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')"
602 [ -n "${ban_vlanblock}" ] && vlan_block="$(printf "%s" "${ban_vlanblock%%?}" | "${ban_sedcmd}" 's/^/\"/;s/$/\"/;s/ /\", \"/g')"
604 for flag
in ${ban_allowflag}; do
605 if [ "${flag}" = "tcp" ] ||
[ "${flag}" = "udp" ]; then
606 if [ -z "${tmp_proto}" ]; then
608 elif ! printf "%s" "${tmp_proto}" | "${ban_grepcmd}" -qw "${flag}"; then
609 tmp_proto
="${tmp_proto}, ${flag}"
611 elif [ -n "${flag//[![:digit:]-]/}" ]; then
612 if [ -z "${tmp_port}" ]; then
614 elif ! printf "%s" "${tmp_port}" | "${ban_grepcmd}" -qw "${flag}"; then
615 tmp_port
="${tmp_port}, ${flag}"
619 if [ -n "${tmp_proto}" ] && [ -n "${tmp_port}" ]; then
620 allow_dport
="meta l4proto { ${tmp_proto} } th dport { ${tmp_port} }"
623 if [ "${ban_logprerouting}" = "1" ]; then
624 log_icmp
="log level ${ban_nftloglevel} prefix \"banIP/pre-icmp/drop: \""
625 log_syn
="log level ${ban_nftloglevel} prefix \"banIP/pre-syn/drop: \""
626 log_udp
="log level ${ban_nftloglevel} prefix \"banIP/pre-udp/drop: \""
627 log_tcp
="log level ${ban_nftloglevel} prefix \"banIP/pre-tcp/drop: \""
628 log_ct
="log level ${ban_nftloglevel} prefix \"banIP/pre-ct/drop: \""
632 # nft header (tables and chains)
634 printf "%s\n\n" "#!/usr/sbin/nft -f"
635 if "${ban_nftcmd}" -t list
set inet banIP allowlistv4MAC
>/dev
/null
2>&1; then
636 printf "%s\n" "delete table inet banIP"
638 printf "%s\n" "add table inet banIP"
639 printf "%s\n" "add counter inet banIP cnt-icmpflood"
640 printf "%s\n" "add counter inet banIP cnt-udpflood"
641 printf "%s\n" "add counter inet banIP cnt-synflood"
642 printf "%s\n" "add counter inet banIP cnt-tcpinvalid"
643 printf "%s\n" "add counter inet banIP cnt-ctinvalid"
644 printf "%s\n" "add chain inet banIP pre-routing { type filter hook prerouting priority -150; policy accept; }"
645 printf "%s\n" "add chain inet banIP wan-input { type filter hook input priority ${ban_nftpriority}; policy accept; }"
646 printf "%s\n" "add chain inet banIP wan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }"
647 printf "%s\n" "add chain inet banIP lan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }"
648 printf "%s\n" "add chain inet banIP reject-chain"
650 # default reject chain rules
652 printf "%s\n" "add rule inet banIP reject-chain meta l4proto tcp reject with tcp reset"
653 printf "%s\n" "add rule inet banIP reject-chain reject"
655 # default pre-routing rules
657 printf "%s\n" "add rule inet banIP pre-routing iifname != { ${wan_dev} } counter accept"
658 printf "%s\n" "add rule inet banIP pre-routing ct state invalid ${log_ct} counter name cnt-ctinvalid drop"
659 if [ "${ban_icmplimit}" -gt "0" ]; then
660 printf "%s\n" "add rule inet banIP pre-routing ip protocol icmp limit rate over ${ban_icmplimit}/second ${log_icmp} counter name cnt-icmpflood drop"
661 printf "%s\n" "add rule inet banIP pre-routing ip6 nexthdr icmpv6 limit rate over ${ban_icmplimit}/second ${log_icmp} counter name cnt-icmpflood drop"
663 [ "${ban_udplimit}" -gt "0" ] && printf "%s\n" "add rule inet banIP pre-routing meta l4proto udp ct state new limit rate over ${ban_udplimit}/second ${log_udp} counter name cnt-udpflood drop"
664 [ "${ban_synlimit}" -gt "0" ] && printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|ack) == syn limit rate over ${ban_synlimit}/second ${log_syn} counter name cnt-synflood drop"
665 printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn) == (fin|syn) ${log_tcp} counter name cnt-tcpinvalid drop"
666 printf "%s\n" "add rule inet banIP pre-routing tcp flags & (syn|rst) == (syn|rst) ${log_tcp} counter name cnt-tcpinvalid drop"
667 printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) < (fin) ${log_tcp} counter name cnt-tcpinvalid drop"
668 printf "%s\n" "add rule inet banIP pre-routing tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|psh|urg) ${log_tcp} counter name cnt-tcpinvalid drop"
670 # default wan-input rules
672 printf "%s\n" "add rule inet banIP wan-input iifname != { ${wan_dev} } counter accept"
673 printf "%s\n" "add rule inet banIP wan-input ct state established,related counter accept"
674 printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv4 udp sport 67-68 udp dport 67-68 counter accept"
675 printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 udp sport 547 udp dport 546 counter accept"
676 printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-advert, nd-neighbor-solicit, nd-router-advert} ip6 hoplimit 1 counter accept"
677 printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-advert, nd-neighbor-solicit, nd-router-advert} ip6 hoplimit 255 counter accept"
678 [ -n "${allow_dport}" ] && printf "%s\n" "add rule inet banIP wan-input ${allow_dport} counter accept"
680 # default wan-forward rules
682 printf "%s\n" "add rule inet banIP wan-forward iifname != { ${wan_dev} } counter accept"
683 printf "%s\n" "add rule inet banIP wan-forward ct state established,related counter accept"
684 [ -n "${allow_dport}" ] && printf "%s\n" "add rule inet banIP wan-forward ${allow_dport} counter accept"
686 # default lan-forward rules
688 printf "%s\n" "add rule inet banIP lan-forward oifname != { ${wan_dev} } counter accept"
689 printf "%s\n" "add rule inet banIP lan-forward ct state established,related counter accept"
690 [ -n "${vlan_allow}" ] && printf "%s\n" "add rule inet banIP lan-forward iifname { ${vlan_allow} } counter accept"
691 [ -n "${vlan_block}" ] && printf "%s\n" "add rule inet banIP lan-forward iifname { ${vlan_block} } counter goto reject-chain"
694 # load initial banIP table within nft (atomic load)
696 feed_log
="$("${ban_nftcmd}" -f "${file}" 2>&1)"
699 if [ "${feed_rc}" = "0" ]; then
700 f_log
"info" "initialize banIP nftables namespace"
702 f_log
"err" "can't initialize banIP nftables namespace (rc: ${feed_rc}, log: ${feed_log})"
705 f_log
"debug" "f_nftinit ::: wan_dev: ${wan_dev}, vlan_allow: ${vlan_allow:-"-"}, vlan_block: ${vlan_block:-"-"}, allowed_dports: ${allow_dport:-"-"}, priority: ${ban_nftpriority}, policy: ${ban_nftpolicy}, icmp_limit: ${ban_icmplimit}, syn_limit: ${ban_synlimit}, udp_limit: ${ban_udplimit}, loglevel: ${ban_nftloglevel}, rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}"
713 local log_input log_forwardwan log_forwardlan start_ts end_ts tmp_raw tmp_load tmp_file split_file ruleset_raw handle rc etag_rc
714 local expr cnt_set cnt_dl restore_rc feed_direction feed_rc feed_log feed_comp feed_target feed_dport tmp_proto tmp_port flag
715 local feed
="${1}" proto="${2}" feed_url="${3}" feed_rule="${4}" feed_flag="${5}"
717 start_ts
="$(date +%s)"
718 feed
="${feed}v${proto}"
719 tmp_load
="${ban_tmpfile}.${feed}.load"
720 tmp_raw
="${ban_tmpfile}.${feed}.raw"
721 tmp_split
="${ban_tmpfile}.${feed}.split"
722 tmp_file
="${ban_tmpfile}.${feed}.file"
723 tmp_flush
="${ban_tmpfile}.${feed}.flush"
724 tmp_nft
="${ban_tmpfile}.${feed}.nft"
725 tmp_allow
="${ban_tmpfile}.${feed%v*}"
727 [ "${ban_loginput}" = "1" ] && log_input="log level ${ban_nftloglevel} prefix \"banIP/inp-wan/${ban_blocktype}/${feed}: \""
728 [ "${ban_logforwardwan}" = "1" ] && log_forwardwan="log level ${ban_nftloglevel} prefix \"banIP/fwd-wan/${ban_blocktype}/${feed}: \""
729 [ "${ban_logforwardlan}" = "1" ] && log_forwardlan="log level ${ban_nftloglevel} prefix \"banIP/fwd-lan/reject/${feed}: \""
733 if [ "${ban_blocktype}" = "reject" ]; then
734 feed_target
="goto reject-chain"
739 # set feed block direction
741 if [ "${ban_blockpolicy}" = "input" ]; then
742 if ! printf "%s" "${ban_blockinput}" | "${ban_grepcmd}" -q "${feed%v*}" &&
743 ! printf "%s" "${ban_blockforwardwan}" | "${ban_grepcmd}" -q "${feed%v*}" &&
744 ! printf "%s" "${ban_blockforwardlan}" | "${ban_grepcmd}" -q "${feed%v*}"; then
745 ban_blockinput
="${ban_blockinput} ${feed%v*}"
747 elif [ "${ban_blockpolicy}" = "forwardwan" ]; then
748 if ! printf "%s" "${ban_blockinput}" | "${ban_grepcmd}" -q "${feed%v*}" &&
749 ! printf "%s" "${ban_blockforwardwan}" | "${ban_grepcmd}" -q "${feed%v*}" &&
750 ! printf "%s" "${ban_blockforwardlan}" | "${ban_grepcmd}" -q "${feed%v*}"; then
751 ban_blockforwardwan
="${ban_blockforwardwan} ${feed%v*}"
753 elif [ "${ban_blockpolicy}" = "forwardlan" ]; then
754 if ! printf "%s" "${ban_blockinput}" | "${ban_grepcmd}" -q "${feed%v*}" &&
755 ! printf "%s" "${ban_blockforwardwan}" | "${ban_grepcmd}" -q "${feed%v*}" &&
756 ! printf "%s" "${ban_blockforwardlan}" | "${ban_grepcmd}" -q "${feed%v*}"; then
757 ban_blockforwardlan
="${ban_blockforwardlan} ${feed%v*}"
760 if printf "%s" "${ban_blockinput}" | "${ban_grepcmd}" -q "${feed%v*}"; then
761 feed_direction
="input"
763 if printf "%s" "${ban_blockforwardwan}" | "${ban_grepcmd}" -q "${feed%v*}"; then
764 feed_direction
="${feed_direction} forwardwan"
766 if printf "%s" "${ban_blockforwardlan}" | "${ban_grepcmd}" -q "${feed%v*}"; then
767 feed_direction
="${feed_direction} forwardlan"
772 for flag
in ${feed_flag}; do
773 if [ "${flag}" = "gz" ]; then
775 elif [ "${flag}" = "tcp" ] ||
[ "${flag}" = "udp" ]; then
776 if [ -z "${tmp_proto}" ]; then
778 elif ! printf "%s" "${tmp_proto}" | "${ban_grepcmd}" -qw "${flag}"; then
779 tmp_proto
="${tmp_proto}, ${flag}"
781 elif [ -n "${flag//[![:digit:]-]/}" ]; then
782 if [ -z "${tmp_port}" ]; then
784 elif ! printf "%s" "${tmp_port}" | "${ban_grepcmd}" -qw "${flag}"; then
785 tmp_port
="${tmp_port}, ${flag}"
789 if [ -n "${tmp_proto}" ] && [ -n "${tmp_port}" ]; then
790 feed_dport
="meta l4proto { ${tmp_proto} } th dport { ${tmp_port} }"
793 # chain/rule maintenance
795 if [ "${ban_action}" = "reload" ] && "${ban_nftcmd}" -t list set inet banIP "${feed}" >/dev
/null
2>&1; then
796 ruleset_raw
="$("${ban_nftcmd}" -tj list ruleset 2>/dev/null)"
798 printf "%s\n" "flush set inet banIP ${feed}"
800 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-input\"][@.expr[${expr}].match.right=\"@${feed}\"].handle
")"
801 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-input handle ${handle}"
802 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-forward\"][@.expr[${expr}].match.right=\"@${feed}\"].handle
")"
803 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-forward handle ${handle}"
804 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"lan-forward\"][@.expr[${expr}].match.right=\"@${feed}\"].handle
")"
805 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP lan-forward handle ${handle}"
810 # restore local backups
812 if [ "${feed%v*}" != "blocklist" ]; then
813 if [ -n "${ban_etagparm}" ] && [ "${ban_action}" = "reload" ] && [ "${feed_url}" != "local" ] && [ "${feed%v*}" != "allowlist" ]; then
815 if [ "${feed%v*}" = "country" ]; then
816 for country
in ${ban_country}; do
817 f_etag
"${feed}" "${feed_url}${country}-aggregated.zone" ".${country}"
819 [ "${rc}" = "4" ] && break
820 etag_rc
="$((etag_rc + rc))"
822 elif [ "${feed%v*}" = "asn" ]; then
823 for asn
in ${ban_asn}; do
824 f_etag
"${feed}" "${feed_url}AS${asn}" ".${asn}"
826 [ "${rc}" = "4" ] && break
827 etag_rc
="$((etag_rc + rc))"
830 f_etag
"${feed}" "${feed_url}"
834 if [ "${etag_rc}" = "0" ] || [ "${ban_action}" != "reload" ] || [ "${feed_url}" = "local" ]; then
835 if [ "${feed%v*}" = "allowlist" ] && [ ! -f "${tmp_allow}" ]; then
836 f_restore
"allowlist" "-" "${tmp_allow}" "${etag_rc}"
838 f_restore
"${feed}" "${feed_url}" "${tmp_load}" "${etag_rc}"
841 feed_rc
="${restore_rc}"
845 # prepare local/remote allowlist
847 if [ "${feed%v*}" = "allowlist" ] && [ ! -f "${tmp_allow}" ]; then
848 "${ban_catcmd}" "${ban_allowlist}" 2>/dev/null >"${tmp_allow}"
850 for feed_url
in ${ban_allowurl}; do
851 feed_log
="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_load}" "${feed_url}" 2>&1)"
853 if [ "${feed_rc}" = "0" ] && [ -s "${tmp_load}" ]; then
854 "${ban_catcmd}" "${tmp_load}" 2>/dev/null >>"${tmp_allow}"
856 f_log
"info" "download for feed '${feed%v*}' failed (rc: ${feed_rc:-"-"}/log: ${feed_log})"
861 if [ "${feed_rc}" = "0" ]; then
862 f_backup
"allowlist" "${tmp_allow}"
863 elif [ -z "${restore_rc}" ] && [ "${feed_rc}" != "0" ]; then
864 f_restore
"allowlist" "-" "${tmp_allow}" "${feed_rc}"
871 if [ "${feed%v*}" = "allowlist" ]; then
873 printf "%s\n\n" "#!/usr/sbin/nft -f"
874 [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}"
875 if [ "${proto}" = "4MAC" ]; then
876 "${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:]]+$|$)/{if(!$2)$2="0.0.0.0/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${tmp_allow}" >"${tmp_file}"
877 printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
878 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ether saddr . ip saddr @${feed} counter accept"
879 elif [ "${proto}" = "6MAC" ]; then
880 "${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:]]+$|$)/{if(!$2)$2="::/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${tmp_allow}" >"${tmp_file}"
881 printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
882 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ether saddr . ip6 saddr @${feed} counter accept"
883 elif [ "${proto}" = "4" ]; then
884 "${ban_awkcmd}" '/^127\./{next}/^(([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:]].*|$)/{printf "%s, ",$1}' "${tmp_allow}" >"${tmp_file}"
885 printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
886 if [ -z "${feed_direction##*input*}" ]; then
887 if [ "${ban_allowlistonly}" = "1" ]; then
888 printf "%s\n" "add rule inet banIP wan-input ip saddr != @${feed} ${log_input} counter ${feed_target}"
890 printf "%s\n" "add rule inet banIP wan-input ip saddr @${feed} counter accept"
893 if [ -z "${feed_direction##*forwardwan*}" ]; then
894 if [ "${ban_allowlistonly}" = "1" ]; then
895 printf "%s\n" "add rule inet banIP wan-forward ip saddr != @${feed} ${log_forwardwan} counter ${feed_target}"
897 printf "%s\n" "add rule inet banIP wan-forward ip saddr @${feed} counter accept"
900 if [ -z "${feed_direction##*forwardlan*}" ]; then
901 if [ "${ban_allowlistonly}" = "1" ]; then
902 printf "%s\n" "add rule inet banIP lan-forward ip daddr != @${feed} ${log_forwardlan} counter goto reject-chain"
904 printf "%s\n" "add rule inet banIP lan-forward ip daddr @${feed} counter accept"
907 elif [ "${proto}" = "6" ]; then
908 "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}.*/{printf "%s\n",$1}' "${tmp_allow}" |
909 "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]].*|$)/{printf "%s, ",tolower($1)}' >"${tmp_file}"
910 printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
911 if [ -z "${feed_direction##*input*}" ]; then
912 if [ "${ban_allowlistonly}" = "1" ]; then
913 printf "%s\n" "add rule inet banIP wan-input ip6 saddr != @${feed} ${log_input} counter ${feed_target}"
915 printf "%s\n" "add rule inet banIP wan-input ip6 saddr @${feed} counter accept"
918 if [ -z "${feed_direction##*forwardwan*}" ]; then
919 if [ "${ban_allowlistonly}" = "1" ]; then
920 printf "%s\n" "add rule inet banIP wan-forward ip6 saddr != @${feed} ${log_forwardwan} counter ${feed_target}"
922 printf "%s\n" "add rule inet banIP wan-forward ip6 saddr @${feed} counter accept"
925 if [ -z "${feed_direction##*forwardlan*}" ]; then
926 if [ "${ban_allowlistonly}" = "1" ]; then
927 printf "%s\n" "add rule inet banIP lan-forward ip6 daddr != @${feed} ${log_forwardlan} counter ${feed_target}"
929 printf "%s\n" "add rule inet banIP lan-forward ip6 daddr @${feed} counter accept"
934 : >"${tmp_flush}" >"${tmp_raw}" >"${tmp_file}"
936 elif [ "${feed%v*}" = "blocklist" ]; then
938 printf "%s\n\n" "#!/usr/sbin/nft -f"
939 [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}"
940 if [ "${proto}" = "4MAC" ]; then
941 "${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:]]+$|$)/{if(!$2)$2="0.0.0.0/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${ban_blocklist}" >"${tmp_file}"
942 printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
943 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ether saddr . ip saddr @${feed} counter goto reject-chain"
944 elif [ "${proto}" = "6MAC" ]; then
945 "${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:]]+$|$)/{if(!$2)$2="::/0";if(!seen[$1]++)printf "%s . %s, ",tolower($1),$2}' "${ban_blocklist}" >"${tmp_file}"
946 printf "%s\n" "add set inet banIP ${feed} { type ether_addr . ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
947 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ether saddr . ip6 saddr @${feed} counter goto reject-chain"
948 elif [ "${proto}" = "4" ]; then
949 if [ "${ban_deduplicate}" = "1" ]; then
950 "${ban_awkcmd}" '/^127\./{next}/^(([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:]].*|$)/{printf "%s,\n",$1}' "${ban_blocklist}" >"${tmp_raw}"
951 "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null >"${tmp_split}"
952 "${ban_awkcmd}" 'BEGIN{FS="[ ,]"}NR==FNR{member[$1];next}!($1 in member)' "${ban_tmpfile}.deduplicate" "${ban_blocklist}" 2>/dev/null >"${tmp_raw}"
953 "${ban_catcmd}" "${tmp_raw}" 2>/dev/null >"${ban_blocklist}"
955 "${ban_awkcmd}" '/^127\./{next}/^(([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:]].*|$)/{printf "%s,\n",$1}' "${ban_blocklist}" >"${tmp_split}"
957 "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}"
958 printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
959 [ -z "${feed_direction##*input*}" ] && printf "%s\n" "add rule inet banIP wan-input ip saddr @${feed} ${log_input} counter ${feed_target}"
960 [ -z "${feed_direction##*forwardwan*}" ] && printf "%s\n" "add rule inet banIP wan-forward ip saddr @${feed} ${log_forwardwan} counter ${feed_target}"
961 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ip daddr @${feed} ${log_forwardlan} counter goto reject-chain"
962 elif [ "${proto}" = "6" ]; then
963 if [ "${ban_deduplicate}" = "1" ]; then
964 "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}.*/{printf "%s\n",$1}' "${ban_blocklist}" |
965 "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]].*|$)/{printf "%s,\n",tolower($1)}' >"${tmp_raw}"
966 "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null >"${tmp_split}"
967 "${ban_awkcmd}" 'BEGIN{FS="[ ,]"}NR==FNR{member[$1];next}!($1 in member)' "${ban_tmpfile}.deduplicate" "${ban_blocklist}" 2>/dev/null >"${tmp_raw}"
968 "${ban_catcmd}" "${tmp_raw}" 2>/dev/null >"${ban_blocklist}"
970 "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}.*/{printf "%s\n",$1}' "${ban_blocklist}" |
971 "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]].*|$)/{printf "%s,\n",tolower($1)}' >"${tmp_split}"
973 "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}"
974 printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval, timeout; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}") }"
975 [ -z "${feed_direction##*input*}" ] && printf "%s\n" "add rule inet banIP wan-input ip6 saddr @${feed} ${log_input} counter ${feed_target}"
976 [ -z "${feed_direction##*forwardwan*}" ] && printf "%s\n" "add rule inet banIP wan-forward ip6 saddr @${feed} ${log_forwardwan} counter ${feed_target}"
977 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ip6 daddr @${feed} ${log_forwardlan} counter goto reject-chain"
980 : >"${tmp_flush}" >"${tmp_raw}" >"${tmp_file}"
983 # handle external feeds
985 elif [ "${restore_rc}" != "0" ] && [ "${feed_url}" != "local" ]; then
986 # handle country downloads
988 if [ "${feed%v*}" = "country" ]; then
989 for country
in ${ban_country}; do
990 feed_log
="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}${country}-aggregated.zone
" 2>&1)"
992 [ "${feed_rc}" = "0" ] && "${ban_catcmd}" "${tmp_raw}" 2>/dev/null >>"${tmp_load}"
996 # handle asn downloads
998 elif [ "${feed%v*}" = "asn" ]; then
999 for asn
in ${ban_asn}; do
1000 feed_log
="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}AS${asn}" 2>&1)"
1002 [ "${feed_rc}" = "0" ] && "${ban_catcmd}" "${tmp_raw}" 2>/dev/null >>"${tmp_load}"
1006 # handle compressed downloads
1008 elif [ "${feed_comp}" = "gz" ]; then
1009 feed_log
="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}" 2>&1)"
1011 [ "${feed_rc}" = "0" ] && "${ban_zcatcmd}" "${tmp_raw}" 2>/dev/null >"${tmp_load}"
1014 # handle normal downloads
1017 feed_log
="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_load}" "${feed_url}" 2>&1)"
1021 [ "${feed_rc}" != "0" ] && f_log "info" "download for feed '${feed}' failed (rc: ${feed_rc:-"-"}/log: ${feed_log})"
1025 if [ "${restore_rc}" != "0" ] && [ "${feed_rc}" = "0" ] && [ "${feed_url}" != "local" ] && [ ! -s "${tmp_nft}" ]; then
1026 f_backup
"${feed}" "${tmp_load}"
1028 elif [ -z "${restore_rc}" ] && [ "${feed_rc}" != "0" ] && [ "${feed_url}" != "local" ] && [ ! -s "${tmp_nft}" ]; then
1029 f_restore
"${feed}" "${feed_url}" "${tmp_load}" "${feed_rc}"
1033 # final file & Set preparation for regular downloads
1035 if [ "${feed_rc}" = "0" ] && [ ! -s "${tmp_nft}" ]; then
1038 if [ "${ban_deduplicate}" = "1" ] && [ "${feed_url}" != "local" ]; then
1039 "${ban_awkcmd}" '{sub("\r$", "");print}' "${tmp_load}" 2>/dev/null | "${ban_awkcmd}" "${feed_rule}" 2>/dev/null >"${tmp_raw}"
1040 "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null | tee -a "${ban_tmpfile}.deduplicate" >"${tmp_split}"
1043 "${ban_awkcmd}" '{sub("\r$", "");print}' "${tmp_load}" 2>/dev/null | "${ban_awkcmd}" "${feed_rule}" 2>/dev/null >"${tmp_split}"
1046 : >"${tmp_raw}" >"${tmp_load}"
1050 if [ "${feed_rc}" = "0" ]; then
1051 if [ -n "${ban_splitsize//[![:digit:]]/}" ]; then
1052 [ "${ban_splitsize//[![:digit:]]/}" -lt "512" ] && ban_splitsize
="512"
1053 if ! "${ban_awkcmd}" "NR%${ban_splitsize//[![:digit:]]/}==1{file=\"${tmp_file}.\"++i;}{ORS=\" \";print > file}" "${tmp_split}" 2>/dev
/null
; then
1055 rm -f "${tmp_file}".
*
1056 f_log
"info" "can't split Set '${feed}' to size '${ban_splitsize//[![:digit:]]/}'"
1059 "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}.1"
1066 if [ "${feed_rc}" = "0" ] && [ -s "${tmp_file}.1" ]; then
1067 if [ "${proto}" = "4" ]; then
1069 # nft header (IPv4 Set) input and forward rules
1071 printf "%s\n\n" "#!/usr/sbin/nft -f"
1072 [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}"
1073 printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}.1") }"
1074 [ -z "${feed_direction##*input*}" ] && printf "%s\n" "add rule inet banIP wan-input ${feed_dport} ip saddr @${feed} ${log_input} counter ${feed_target}"
1075 [ -z "${feed_direction##*forwardwan*}" ] && printf "%s\n" "add rule inet banIP wan-forward ${feed_dport} ip saddr @${feed} ${log_forwardwan} counter ${feed_target}"
1076 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ${feed_dport} ip daddr @${feed} ${log_forwardlan} counter goto reject-chain"
1078 elif [ "${proto}" = "6" ]; then
1080 # nft header (IPv6 Set) plus input and forward rules
1082 printf "%s\n\n" "#!/usr/sbin/nft -f"
1083 [ -s "${tmp_flush}" ] && "${ban_catcmd}" "${tmp_flush}"
1084 printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy ${ban_nftpolicy}; $(f_getelements "${tmp_file}.1") }"
1085 [ -z "${feed_direction##*input*}" ] && printf "%s\n" "add rule inet banIP wan-input ${feed_dport} ip6 saddr @${feed} ${log_input} counter ${feed_target}"
1086 [ -z "${feed_direction##*forwardwan*}" ] && printf "%s\n" "add rule inet banIP wan-forward ${feed_dport} ip6 saddr @${feed} ${log_forwardwan} counter ${feed_target}"
1087 [ -z "${feed_direction##*forwardlan*}" ] && printf "%s\n" "add rule inet banIP lan-forward ${feed_dport} ip6 daddr @${feed} ${log_forwardlan} counter goto reject-chain"
1091 : >"${tmp_flush}" >"${tmp_file}.1"
1094 # load generated nft file in banIP table
1096 if [ "${feed_rc}" = "0" ]; then
1097 if [ "${feed%v*}" = "allowlist" ]; then
1098 cnt_dl
="$("${ban_awkcmd}" 'END{printf "%d
",NR}' "${tmp_allow}" 2>/dev/null)"
1100 cnt_dl
="$("${ban_awkcmd}" 'END{printf "%d
",NR}' "${tmp_split}" 2>/dev/null)"
1103 if [ "${cnt_dl:-"0"}" -gt "0" ] || [ "${feed_url}" = "local" ] || [ "${feed%v*}" = "allowlist" ] || [ "${feed%v*}" = "blocklist" ]; then
1104 feed_log
="$("${ban_nftcmd}" -f "${tmp_nft}" 2>&1)"
1107 # load additional split files
1109 if [ "${feed_rc}" = "0" ]; then
1110 for split_file
in "${tmp_file}".
*; do
1111 if [ -s "${split_file}" ]; then
1112 "${ban_sedcmd}" -i "1 i #!/usr/sbin/nft -f\nadd element inet banIP "${feed}" { " "${split_file}"
1113 printf "%s\n" "}" >>"${split_file}"
1114 if ! "${ban_nftcmd}" -f "${split_file}" >/dev
/null
2>&1; then
1115 f_log
"info" "can't add split file '${split_file##*.}' to Set '${feed}'"
1120 if [ "${ban_debug}" = "1" ] && [ "${ban_reportelements}" = "1" ]; then
1121 cnt_set
="$("${ban_nftcmd}" -j list set inet banIP "${feed}" 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)"
1124 f_log
"info" "can't initialize Set for feed '${feed}' (rc: ${feed_rc}, log: ${feed_log})"
1127 f_log
"info" "skip empty feed '${feed}'"
1131 end_ts
="$(date +%s)"
1133 f_log
"debug" "f_down ::: feed: ${feed}, cnt_dl: ${cnt_dl:-"-"}, cnt_set: ${cnt_set:-"-"}, split_size: ${ban_splitsize:-"-"}, time: $((end_ts - start_ts)), rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}"
1139 local backup_rc
="4" feed
="${1}" feed_file
="${2}"
1141 if [ -s "${feed_file}" ]; then
1142 gzip -cf "${feed_file}" >"${ban_backupdir}/banIP.${feed}.gz"
1146 f_log
"debug" "f_backup ::: feed: ${feed}, file: banIP.${feed}.gz, rc: ${backup_rc}"
1147 return "${backup_rc}"
1153 local tmp_feed restore_rc
="4" feed
="${1}" feed_url="${2}" feed_file="${3}" in_rc="${4}"
1155 [ "${feed_url}" = "local" ] && tmp_feed="${feed%v*}v4" || tmp_feed="${feed}"
1156 if [ -s "${ban_backupdir}/banIP.${tmp_feed}.gz" ]; then
1157 "${ban_zcatcmd}" "${ban_backupdir}/banIP.${tmp_feed}.gz" 2>/dev/null >"${feed_file}"
1161 f_log
"debug" "f_restore ::: feed: ${feed}, file: banIP.${tmp_feed}.gz, in_rc: ${in_rc:-"-"}, rc: ${restore_rc}"
1162 return "${restore_rc}"
1165 # remove disabled Sets
1168 local expr feedlist tmp_del ruleset_raw item table_sets handle del_set feed_log feed_rc
1171 json_get_keys feedlist
1172 tmp_del
="${ban_tmpfile}.final.delete"
1173 ruleset_raw
="$("${ban_nftcmd}" -tj list ruleset 2>/dev/null)"
1174 table_sets
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.table="banIP
"&&@.set.family="inet
"].set.name')"
1176 printf "%s\n\n" "#!/usr/sbin/nft -f"
1177 for item
in ${table_sets}; do
1178 if ! printf "%s" "allowlist blocklist ${ban_feed}" | "${ban_grepcmd}" -q "${item%v*}" ||
1179 ! printf "%s" "allowlist blocklist ${feedlist}" | "${ban_grepcmd}" -q "${item%v*}"; then
1180 [ -z "${del_set}" ] && del_set="${item}" || del_set="${del_set}, ${item}"
1181 rm -f "${ban_backupdir}/banIP.${item}.gz"
1182 printf "%s\n" "flush set inet banIP ${item}"
1184 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-input\"][@.expr[${expr}].match.right=\"@${item}\"].handle
")"
1185 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-input handle ${handle}"
1186 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].handle
")"
1187 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-forward handle ${handle}"
1188 handle
="$(printf "%s
\n" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"lan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].handle
")"
1189 [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP lan-forward handle ${handle}"
1191 printf "%s\n\n" "delete set inet banIP ${item}"
1196 if [ -n "${del_set}" ]; then
1197 feed_log
="$("${ban_nftcmd}" -f "${tmp_del}" 2>&1)"
1202 f_log
"debug" "f_rmset ::: Set: ${del_set:-"-"}, rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}"
1205 # generate status information
1208 local object end_time duration table_sets cnt_elements
="0" custom_feed
="0" split="0" status
="${1}"
1210 [ -z "${ban_dev}" ] && f_conf
1211 if [ "${status}" = "active" ]; then
1212 if [ -n "${ban_starttime}" ] && [ "${ban_action}" != "boot" ]; then
1213 end_time
="$(date "+%s
")"
1214 duration
="$(((end_time - ban_starttime) / 60))m $(((end_time - ban_starttime) % 60))s"
1216 table_sets
="$("${ban_nftcmd}" -tj list ruleset 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[@.set.table="banIP
"&&@.set.family="inet
"].set.name')"
1217 if [ "${ban_reportelements}" = "1" ]; then
1218 for object
in ${table_sets}; do
1219 cnt_elements
="$((cnt_elements + $("${ban_nftcmd}" -j list set inet banIP "${object}" 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)))"
1222 runtime
="action: ${ban_action:-"-"}, log: ${ban_logreadcmd##*/}, fetch: ${ban_fetchcmd##*/}, duration: ${duration:-"-"}, date: $(date "+%Y-
%m-
%d
%H
:%M
:%S
")"
1224 [ -s "${ban_customfeedfile}" ] && custom_feed
="1"
1225 [ "${ban_splitsize:-"0"}" -gt "0" ] && split="1"
1229 json_load_file
"${ban_rtfile}" >/dev
/null
2>&1
1230 json_add_string
"status" "${status}"
1231 json_add_string
"version" "${ban_ver}"
1232 json_add_string
"element_count" "${cnt_elements}"
1233 json_add_array
"active_feeds"
1234 for object
in ${table_sets:-"-"}; do
1235 json_add_string
"${object}" "${object}"
1238 json_add_array
"wan_devices"
1239 for object
in ${ban_dev:-"-"}; do
1240 json_add_string
"${object}" "${object}"
1243 json_add_array
"wan_interfaces"
1244 for object
in ${ban_ifv4:-"-"} ${ban_ifv6:-"-"}; do
1245 json_add_string
"${object}" "${object}"
1248 json_add_array
"vlan_allow"
1249 for object
in ${ban_vlanallow:-"-"}; do
1250 json_add_string
"${object}" "${object}"
1253 json_add_array
"vlan_block"
1254 for object
in ${ban_vlanblock:-"-"}; do
1255 json_add_string
"${object}" "${object}"
1258 json_add_array
"active_uplink"
1259 for object
in ${ban_uplink:-"-"}; do
1260 json_add_string
"${object}" "${object}"
1263 json_add_string
"nft_info" "priority: ${ban_nftpriority}, policy: ${ban_nftpolicy}, loglevel: ${ban_nftloglevel}, expiry: ${ban_nftexpiry:-"-"}, limit (icmp/syn/udp): ${ban_icmplimit}/${ban_synlimit}/${ban_udplimit}"
1264 json_add_string
"run_info" "base: ${ban_basedir}, backup: ${ban_backupdir}, report: ${ban_reportdir}"
1265 json_add_string
"run_flags" "auto: $(f_char ${ban_autodetect}), proto (4/6): $(f_char ${ban_protov4})/$(f_char ${ban_protov6}), log (pre/inp/fwd/lan): $(f_char ${ban_logprerouting})/$(f_char ${ban_loginput})/$(f_char ${ban_logforwardwan})/$(f_char ${ban_logforwardlan}), dedup: $(f_char ${ban_deduplicate}), split: $(f_char ${split}), custom feed: $(f_char ${custom_feed}), allowed only: $(f_char ${ban_allowlistonly})"
1266 json_add_string
"last_run" "${runtime:-"-"}"
1267 json_add_string
"system_info" "cores: ${ban_cores}, memory: ${ban_memory}, device: ${ban_sysver}"
1268 json_dump
>"${ban_rtfile}"
1271 # get status information
1274 local key keylist value values
1276 [ -z "${ban_dev}" ] && f_conf
1277 json_load_file
"${ban_rtfile}" >/dev
/null
2>&1
1278 if json_get_keys keylist
; then
1279 printf "%s\n" "::: banIP runtime information"
1280 for key
in ${keylist}; do
1281 if [ "${key}" = "active_feeds" ] ||
[ "${key}" = "active_uplink" ]; then
1282 json_get_values values
"${key}" >/dev
/null
2>&1
1283 value
="${values// /, }"
1284 elif [ "${key}" = "wan_devices" ]; then
1285 json_get_values values
"${key}" >/dev
/null
2>&1
1286 value
="wan: ${values// /, } / "
1287 json_get_values values
"wan_interfaces" >/dev
/null
2>&1
1288 value
="${value}wan-if: ${values// /, } / "
1289 json_get_values values
"vlan_allow" >/dev
/null
2>&1
1290 value
="${value}vlan-allow: ${values// /, } / "
1291 json_get_values values
"vlan_block" >/dev
/null
2>&1
1292 value
="${value}vlan-block: ${values// /, }"
1293 key
="active_devices"
1295 json_get_var value
"${key}" >/dev
/null
2>&1
1296 if [ "${key}" = "status" ]; then
1297 [ "${value}" = "active" ] && value="${value} ($(f_actual))" || value="${value}"
1300 if [ "${key}" != "wan_interfaces" ] && [ "${key}" != "vlan_allow" ] && [ "${key}" != "vlan_block" ]; then
1301 printf " + %-17s : %s\n" "${key}" "${value:-"-"}"
1305 printf "%s\n" "::: no banIP runtime information available"
1312 local cnt list domain lookup ip elementsv4 elementsv6 start_time end_time duration cnt_domain
="0" cnt_ip
="0" feed
="${1}"
1314 [ -z "${ban_dev}" ] && f_conf
1315 start_time
="$(date "+%s
")"
1316 if [ "${feed}" = "allowlist" ]; then
1317 list
="$("${ban_awkcmd}" '/^([[:alnum:]_-]{1,63}\.)+[[:alpha:]]+([[:space:]]|$)/{printf "%s
",tolower($1)}' "${ban_allowlist}" 2>/dev/null)"
1318 elif [ "${feed}" = "blocklist" ]; then
1319 list
="$("${ban_awkcmd}" '/^([[:alnum:]_-]{1,63}\.)+[[:alpha:]]+([[:space:]]|$)/{printf "%s
",tolower($1)}' "${ban_blocklist}" 2>/dev/null)"
1322 for domain
in ${list}; do
1323 lookup
="$("${ban_lookupcmd}" "${domain}" ${ban_resolver} 2>/dev/null | "${ban_awkcmd}" '/^Address[ 0-9]*: /{if(!seen[$NF]++)printf "%s ",$NF}' 2>/dev/null)"
1324 for ip in ${lookup}; do
1325 if [ "${ip%%.*}" = "127" ] || [ "${ip%%.*}" = "0" ] || [ -z "${ip%%::*}" ]; then
1328 [ "${ip##*:}" = "${ip}" ] && elementsv4="${elementsv4} ${ip}," || elementsv6="${elementsv6} ${ip},"
1329 if [ "${feed}" = "allowlist" ] && [ "${ban_autoallowlist}" = "1" ] && ! "${ban_grepcmd}" -q "^${ip}[[:space:]]*#" "${ban_allowlist}"; then
1330 printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_allowlist}"
1331 elif [ "${feed}" = "blocklist" ] && [ "${ban_autoblocklist}" = "1" ] && ! "${ban_grepcmd}" -q "^${ip}[[:space:]]*#" "${ban_blocklist}"; then
1332 printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_blocklist}"
1334 cnt_ip="$((cnt_ip + 1))"
1337 cnt_domain="$((cnt_domain + 1))"
1339 if [ -n "${elementsv4}" ]; then
1340 if ! "${ban_nftcmd}" add element inet banIP "${feed}v4" { ${elementsv4} } >/dev/null 2>&1; then
1341 f_log "info" "can't add lookup
file to Set
'${feed}v4'"
1344 if [ -n "${elementsv6}" ]; then
1345 if ! "${ban_nftcmd}" add element inet banIP "${feed}v6" { ${elementsv6} } >/dev
/null
2>&1; then
1346 f_log
"info" "can't add lookup file to Set '${feed}v6'"
1349 end_time
="$(date "+%s
")"
1350 duration
="$(((end_time - start_time) / 60))m $(((end_time - start_time) % 60))s"
1352 f_log
"info" "domain lookup finished in ${duration} (${feed}, ${cnt_domain} domains, ${cnt_ip} IPs)"
1358 local report_jsn report_txt tmp_val ruleset_raw item table_sets set_cnt set_input set_forwardwan set_forwardlan set_cntinput set_cntforwardwan set_cntforwardlan set_proto set_dport set_details
1359 local expr detail jsnval timestamp autoadd_allow autoadd_block sum_sets sum_setinput sum_setforwardwan sum_setforwardlan sum_setelements sum_cntinput sum_cntforwardwan sum_cntforwardlan
1360 local sum_synflood sum_udpflood sum_icmpflood sum_ctinvalid sum_tcpinvalid output
="${1}"
1362 [ -z "${ban_dev}" ] && f_conf
1363 f_mkdir
"${ban_reportdir}"
1364 report_jsn
="${ban_reportdir}/ban_report.jsn"
1365 report_txt
="${ban_reportdir}/ban_report.txt"
1367 # json output preparation
1369 ruleset_raw
="$("${ban_nftcmd}" -tj list ruleset 2>/dev/null)"
1370 table_sets
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.set.table="banIP
"&&@.set.family="inet
"].set.name')"
1373 sum_setforwardwan
="0"
1374 sum_setforwardlan
="0"
1377 sum_cntforwardwan
="0"
1378 sum_cntforwardlan
="0"
1379 sum_synflood
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt-synflood
"].*.packets')"
1380 sum_udpflood
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt-udpflood
"].*.packets')"
1381 sum_icmpflood
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt-icmpflood
"].*.packets')"
1382 sum_ctinvalid
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt-ctinvalid
"].*.packets')"
1383 sum_tcpinvalid
="$(printf "%s
" "${ruleset_raw}" | "${ban_jsoncmd}" -qe '@.nftables[@.counter.name="cnt-tcpinvalid
"].*.packets')"
1384 timestamp
="$(date "+%Y-
%m-
%d
%H
:%M
:%S
")"
1388 printf "\t%s\n" '"sets":{'
1389 for item
in ${table_sets}; do
1391 set_cntforwardwan
=""
1392 set_cntforwardlan
=""
1396 [ -z "${set_cntinput}" ] && set_cntinput="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-input\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
1397 [ "${expr}" = "1" ] && [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-input\"][@.expr[${expr}].match.right=\"@${item}\"].
expr[*].match.right.
set")"
1398 [ "${expr}" = "1" ] && [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-input\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].match.left.payload.protocol")"
1399 [ -z "${set_cntforwardwan}" ] && set_cntforwardwan="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].
expr[*].counter.packets
")"
1400 [ "${expr}" = "1" ] && [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].match.right.set")"
1401 [ "${expr}" = "1" ] && [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"wan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].
expr[*].match.left.payload.protocol
")"
1402 [ -z "${set_cntforwardlan}" ] && set_cntforwardlan="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"lan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].counter.packets")"
1403 [ "${expr}" = "1" ] && [ -z "${set_dport}" ] && set_dport="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"lan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].
expr[*].match.right.
set")"
1404 [ "${expr}" = "1" ] && [ -z "${set_proto}" ] && set_proto="$(printf "%s" "${ruleset_raw}" | "${ban_jsoncmd}" -ql1 -e "@.nftables[@.rule.table=\"banIP\"&&@.rule.chain=\"lan-forward\"][@.expr[${expr}].match.right=\"@${item}\"].expr[*].match.left.payload.protocol")"
1406 if [ "${ban_reportelements}" = "1" ]; then
1407 set_cnt="$
("${ban_nftcmd}" -j list set inet banIP "${item}" 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]' |
wc -l 2>/dev
/null
)"
1408 sum_setelements="$
((sum_setelements
+ set_cnt
))"
1411 sum_setelements="n
/a
"
1413 if [ -n "${set_dport}" ]; then
1414 set_dport="${set_dport//[\{\}\":]/}"
1415 set_dport="${set_dport#\[ *}"
1416 set_dport="${set_dport%* \]}"
1417 set_dport="${set_proto}: $
(f_trim
"${set_dport}")"
1419 if [ -n "${set_cntinput}" ]; then
1421 sum_setinput="$
((sum_setinput
+ 1))"
1422 sum_cntinput="$
((sum_cntinput
+ set_cntinput
))"
1427 if [ -n "${set_cntforwardwan}" ]; then
1429 sum_setforwardwan="$
((sum_setforwardwan
+ 1))"
1430 sum_cntforwardwan="$
((sum_cntforwardwan
+ set_cntforwardwan
))"
1433 set_cntforwardwan=""
1435 if [ -n "${set_cntforwardlan}" ]; then
1437 sum_setforwardlan="$
((sum_setforwardlan
+ 1))"
1438 sum_cntforwardlan="$
((sum_cntforwardlan
+ set_cntforwardlan
))"
1441 set_cntforwardlan=""
1443 [ "${sum_sets}" -gt "0" ] && printf "%s
\n" ","
1444 printf "\t\t%s
\n" "\"${item}\":{"
1445 printf "\t\t\t%s
\n" "\"cnt_elements
\": \"${set_cnt}\","
1446 printf "\t\t\t%s
\n" "\"cnt_input
\": \"${set_cntinput}\","
1447 printf "\t\t\t%s
\n" "\"input
\": \"${set_input}\","
1448 printf "\t\t\t%s
\n" "\"cnt_forwardwan
\": \"${set_cntforwardwan}\","
1449 printf "\t\t\t%s
\n" "\"wan_forward
\": \"${set_forwardwan}\","
1450 printf "\t\t\t%s
\n" "\"cnt_forwardlan
\": \"${set_cntforwardlan}\","
1451 printf "\t\t\t%s
\n" "\"lan_forward
\": \"${set_forwardlan}\"",
1452 printf "\t\t\t%s
\n" "\"port
\": \"${set_dport:-"-"}\""
1454 sum_sets="$
((sum_sets
+ 1))"
1456 printf "\n\t%s
\n" "},"
1457 printf "\t%s
\n" "\"timestamp
\": \"${timestamp}\","
1458 printf "\t%s
\n" "\"autoadd_allow
\": \"$
("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_allowlist}")\","
1459 printf "\t%s
\n" "\"autoadd_block
\": \"$
("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_blocklist}")\","
1460 printf "\t%s
\n" "\"sum_synflood
\": \"${sum_synflood}\","
1461 printf "\t%s
\n" "\"sum_udpflood
\": \"${sum_udpflood}\","
1462 printf "\t%s
\n" "\"sum_icmpflood
\": \"${sum_icmpflood}\","
1463 printf "\t%s
\n" "\"sum_ctinvalid
\": \"${sum_ctinvalid}\","
1464 printf "\t%s
\n" "\"sum_tcpinvalid
\": \"${sum_tcpinvalid}\","
1465 printf "\t%s
\n" "\"sum_sets
\": \"${sum_sets}\","
1466 printf "\t%s
\n" "\"sum_setinput
\": \"${sum_setinput}\","
1467 printf "\t%s
\n" "\"sum_setforwardwan
\": \"${sum_setforwardwan}\","
1468 printf "\t%s
\n" "\"sum_setforwardlan
\": \"${sum_setforwardlan}\","
1469 printf "\t%s
\n" "\"sum_setelements
\": \"${sum_setelements}\","
1470 printf "\t%s
\n" "\"sum_cntinput
\": \"${sum_cntinput}\","
1471 printf "\t%s
\n" "\"sum_cntforwardwan
\": \"${sum_cntforwardwan}\","
1472 printf "\t%s
\n" "\"sum_cntforwardlan
\": \"${sum_cntforwardlan}\""
1476 # text output preparation
1478 if [ "${output}" != "json
" ] && [ -s "${report_jsn}" ]; then
1481 if json_load_file "${report_jsn}" >/dev/null 2>&1; then
1482 json_get_var timestamp "timestamp
" >/dev/null 2>&1
1483 json_get_var autoadd_allow "autoadd_allow
" >/dev/null 2>&1
1484 json_get_var autoadd_block "autoadd_block
" >/dev/null 2>&1
1485 json_get_var sum_synflood "sum_synflood
" >/dev/null 2>&1
1486 json_get_var sum_udpflood "sum_udpflood
" >/dev/null 2>&1
1487 json_get_var sum_icmpflood "sum_icmpflood
" >/dev/null 2>&1
1488 json_get_var sum_ctinvalid "sum_ctinvalid
" >/dev/null 2>&1
1489 json_get_var sum_tcpinvalid "sum_tcpinvalid
" >/dev/null 2>&1
1490 json_get_var sum_sets "sum_sets
" >/dev/null 2>&1
1491 json_get_var sum_setinput "sum_setinput
" >/dev/null 2>&1
1492 json_get_var sum_setforwardwan "sum_setforwardwan
" >/dev/null 2>&1
1493 json_get_var sum_setforwardlan "sum_setforwardlan
" >/dev/null 2>&1
1494 json_get_var sum_setelements "sum_setelements
" >/dev/null 2>&1
1495 json_get_var sum_cntinput "sum_cntinput
" >/dev/null 2>&1
1496 json_get_var sum_cntforwardwan "sum_cntforwardwan
" >/dev/null 2>&1
1497 json_get_var sum_cntforwardlan "sum_cntforwardlan
" >/dev/null 2>&1
1499 printf "%s
\n%s
\n%s
\n" ":::" "::: banIP Set Statistics
" ":::"
1500 printf "%s
\n" " Timestamp
: ${timestamp}"
1501 printf "%s
\n" " ------------------------------"
1502 printf "%s
\n" " blocked syn-flood packets
: ${sum_synflood}"
1503 printf "%s
\n" " blocked udp-flood packets
: ${sum_udpflood}"
1504 printf "%s
\n" " blocked icmp-flood packets
: ${sum_icmpflood}"
1505 printf "%s
\n" " blocked invalid ct packets
: ${sum_ctinvalid}"
1506 printf "%s
\n" " blocked invalid tcp packets
: ${sum_tcpinvalid}"
1507 printf "%s
\n" " ---"
1508 printf "%s
\n" " auto-added IPs to allowlist
: ${autoadd_allow}"
1509 printf "%s
\n\n" " auto-added IPs to blocklist
: ${autoadd_block}"
1510 json_select "sets
" >/dev/null 2>&1
1511 json_get_keys table_sets >/dev/null 2>&1
1512 if [ -n "${table_sets}" ]; then
1513 printf "%-25s%-15s%-24s%-24s%-24s%s
\n" " Set
" "| Elements
" "| WAN-Input
(packets
)" "| WAN-Forward
(packets
)" "| LAN-Forward
(packets
)" "| Port
/Protocol Limit
"
1514 printf "%s
\n" " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
1515 for item in ${table_sets}; do
1516 printf " %-21s" "${item}"
1517 json_select "${item}"
1518 json_get_keys set_details
1519 for detail in ${set_details}; do
1520 json_get_var jsnval "${detail}" >/dev/null 2>&1
1523 printf "%-15s" "|
${jsnval}"
1525 "cnt_input
" | "cnt_forwardwan
" | "cnt_forwardlan
")
1526 [ -n "${jsnval}" ] && tmp_val=": ${jsnval}"
1529 printf "%-24s" "|
${jsnval}${tmp_val}"
1537 printf "%s
\n" " ---------------------+--------------+-----------------------+-----------------------+-----------------------+------------------------"
1538 printf "%-25s%-15s%-24s%-24s%s
\n" " ${sum_sets}" "| ${sum_setelements}" "| ${sum_setinput} (${sum_cntinput})" "| ${sum_setforwardwan} (${sum_cntforwardwan})" "| ${sum_setforwardlan} (${sum_cntforwardlan})"
1544 # output channel (text|json|mail)
1548 [ -s "${report_txt}" ] && "${ban_catcmd}" "${report_txt}"
1551 [ -s "${report_jsn}" ] && "${ban_catcmd}" "${report_jsn}"
1554 [ -n "${ban_mailreceiver}" ] && [ -x "${ban_mailcmd}" ] && f_mail
1563 local item table_sets ip proto hold cnt result_flag="/var
/run
/banIP.search
" input="${1}"
1565 if [ -n "${input}" ]; then
1566 ip="$
(printf "%s" "${input}" | "${ban_awkcmd}" 'BEGIN{RS="(([1-9][0-9]{0,2}\\.){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:]]*$)"}{printf "%s",RT
}')"
1567 [ -n "${ip}" ] && proto="v4"
1568 if [ -z "${proto}" ]; then
1569 ip="$(printf "%s" "${input}" | "${ban_awkcmd}" 'BEGIN{RS="(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]].*|$)"}{printf "%s",RT}')"
1570 [ -n "${ip}" ] && proto="v6
"
1573 if [ -n "${proto}" ]; then
1574 table_sets="$
("${ban_nftcmd}" -tj list ruleset 2>/dev/null | "${ban_jsoncmd}" -qe "@.nftables[@.set.table=\"banIP\"&&@.set.type=\"ip${proto}_addr\"].set.name")"
1576 printf "%s
\n%s
\n%s
\n" ":::" "::: no valid search input
" ":::"
1580 for item in ${table_sets}; do
1581 [ -f "${result_flag}" ] && break
1583 if "${ban_nftcmd}" get element inet banIP "${item}" "{ ${ip} }" >/dev/null 2>&1; then
1584 printf "%s
\n%s
\n%s
\n" ":::" "::: banIP Search
" ":::"
1585 printf " %s
\n" "Looking
for IP
'${ip}' on $
(date "+%Y-%m-%d %H:%M:%S")"
1586 printf " %s
\n" "---"
1587 printf " %s
\n" "IP found
in Set
'${item}'"
1591 hold="$
((cnt
% ban_cores
))"
1592 [ "${hold}" = "0" ] && wait
1596 if [ -f "${result_flag}" ]; then
1597 rm -f "${result_flag}"
1599 printf "%s
\n%s
\n%s
\n" ":::" "::: banIP Search
" ":::"
1600 printf " %s
\n" "Looking
for IP
'${ip}' on $
(date "+%Y-%m-%d %H:%M:%S")"
1601 printf " %s
\n" "---"
1602 printf " %s
\n" "IP not found
"
1609 local set_elements input="${1}"
1611 if [ -z "${input}" ]; then
1612 printf "%s
\n%s
\n%s
\n" ":::" "::: no valid survey input
" ":::"
1615 set_elements="$
("${ban_nftcmd}" -j list set inet banIP "${input}" 2>/dev/null | "${ban_jsoncmd}" -qe '@.nftables[*].set.elem[*]')"
1616 printf "%s
\n%s
\n%s
\n" ":::" "::: banIP Survey
" ":::"
1617 printf " %s
\n" "List of elements
in the Set
'${input}' on $
(date "+%Y-%m-%d %H:%M:%S")"
1618 printf " %s
\n" "---"
1619 [ -n "${set_elements}" ] && printf "%s
\n" "${set_elements}" || printf " %s
\n" "empty Set
"
1627 # load mail template
1629 if [ -r "${ban_mailtemplate}" ]; then
1630 . "${ban_mailtemplate}"
1632 f_log "info
" "no
mail template
"
1634 [ -z "${mail_text}" ] && f_log "info
" "no
mail content
"
1635 [ "${ban_debug}" = "1" ] && msmtp_debug="--debug"
1639 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"
1640 printf "%b
" "${ban_mailhead}${mail_text}" | "${ban_mailcmd}" --timeout=10 ${msmtp_debug} -a "${ban_mailprofile}" "${ban_mailreceiver}" >/dev/null 2>&1
1641 f_log "info
" "send status
mail (${?})"
1643 f_log "debug
" "f_mail
::: notification
: ${ban_mailnotification}, template: ${ban_mailtemplate}, profile: ${ban_mailprofile}, receiver: ${ban_mailreceiver}, rc: ${?}"
1649 local daemon logread_cmd loglimit_cmd nft_expiry line proto ip log_raw log_count rdap_log rdap_rc rdap_prefix rdap_length rdap_info
1651 if [ -f "${ban_logreadfile}" ]; then
1652 logread_cmd="${ban_logreadcmd} -qf ${ban_logreadfile} 2>/dev/null | ${ban_grepcmd} -e \"${ban_logterm%%??}\" 2>/dev
/null
"
1653 loglimit_cmd="${ban_logreadcmd} -qn ${ban_loglimit} ${ban_logreadfile} 2>/dev
/null
"
1654 elif printf "%s
" "${ban_packages}" | "${ban_grepcmd}" -q '"logd
'; then
1655 logread_cmd="${ban_logreadcmd} -fe \"${ban_logterm%%??}\" 2>/dev/null"
1656 loglimit_cmd="${ban_logreadcmd} -l ${ban_loglimit} 2>/dev/null"
1659 if [ -x "${ban_logreadcmd}" ] && [ -n "${logread_cmd}" ] && [ -n "${loglimit_cmd}" ] && [ -n "${ban_logterm%%??}" ] && [ "${ban_loglimit}" != "0" ]; then
1660 f_log "info" "start detached banIP log service (${ban_logreadcmd})"
1661 [ -n "${ban_nftexpiry}" ] && nft_expiry="timeout $(printf "%s" "${ban_nftexpiry}" | "${ban_grepcmd}" -oE "([0-9]+[d|h|m|s])+$")"
1662 eval "${logread_cmd}" |
1663 while read -r line; do
1665 : >"${ban_rdapfile}"
1666 if [ -z "${daemon}" ]; then
1667 daemon="$(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="dropbear"}{if(!seen[RT]++)printf "%s",RT}')"
1668 [ -z "${daemon}" ] && daemon="sshd
"
1670 ip="$
(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="(([1-9][0-9]{0,2}\\.){1}([0-9]{1,3}\\.){2}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]))+"}{if(!seen
[RT
]++)printf "%s ",RT
}')"
1671 ip="$(f_trim "${ip}")"
1673 [ -n "${ip}" ] && [ "${ip%%.*}" != "127" ] && [ "${ip%%.*}" != "0" ] && proto="v4"
1674 if [ -z "${proto}" ]; then
1675 if [ "${daemon}" = "dropbear" ]; then
1676 ip="$(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="([A-Fa-f0-9]{1,4}::?){3,7}([A-Fa-f0-9]:?)+"}{if(!seen[RT]++)printf "%s ",RT}')"
1679 ip="$
(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="([A-Fa-f0-9]{1,4}::?){3,7}[A-Fa-f0-9]{1,4}"}{if(!seen
[RT
]++)printf "%s ",RT
}')"
1681 ip="$(f_trim "${ip}")"
1683 [ -n "${ip%%::*}" ] && proto="v6"
1685 if [ -n "${proto}" ] && ! "${ban_nftcmd}" get element inet banIP allowlist"${proto}" "{ ${ip} }" >/dev/null 2>&1 && ! "${ban_nftcmd}" get element inet banIP blocklist"${proto}" "{ ${ip} }" >/dev/null 2>&1; then
1686 f_log "info" "suspicious IP '${ip}'"
1687 log_raw="$(eval ${loglimit_cmd})"
1688 log_count="$(printf "%s\n" "${log_raw}" | "${ban_grepcmd}" -c "suspicious IP '${ip}'")"
1689 if [ "${log_count}" -ge "${ban_logcount}" ]; then
1690 if "${ban_nftcmd}" add element inet banIP "blocklist${proto}" { ${ip} ${nft_expiry} } >/dev/null 2>&1; then
1691 f_log "info
" "add IP
'${ip}' (expiry: ${ban_nftexpiry:-"-"}) to blocklist${proto} set"
1693 if [ "${ban_autoblocksubnet}" = "1" ]; then
1694 rdap_log="$("${ban_fetchcmd}" ${ban_rdapparm} "${ban_rdapfile}" "${ban_rdapurl}${ip}" 2>&1)"
1696 if [ "${rdap_rc}" = "0" ] && [ -s "${ban_rdapfile}" ]; then
1697 [ "${proto}" = "v4" ] && rdap_prefix="$(jsonfilter -l1 -i "${ban_rdapfile}" -qe '@.cidr0_cidrs.
*.v4prefix
')"
1698 [ "${proto}" = "v6" ] && rdap_prefix="$(jsonfilter -l1 -i "${ban_rdapfile}" -qe '@.cidr0_cidrs.
*.v6prefix
')"
1699 rdap_length="$(jsonfilter -l1 -i "${ban_rdapfile}" -qe '@.cidr0_cidrs.
*.length
')"
1700 rdap_info="$(jsonfilter -l1 -i "${ban_rdapfile}" -qe '@.country
' -qe '@.notices
[@.title
="Source"].description
[1]' | awk 'BEGIN
{RS
="";FS
="\n"}{printf "%s, %s",$1,$2}')"
1701 [ -z "${rdap_info}" ] && rdap_info="$(jsonfilter -l1 -i "${ban_rdapfile}" -qe '@.notices[0].links[0].value' | awk 'BEGIN{FS="[/.]"}{printf"%s, %s","n/a",toupper($4)}')"
1702 if [ -n "${rdap_prefix}" ] && [ -n "${rdap_length}" ]; then
1703 if "${ban_nftcmd}" add element inet banIP "blocklist${proto}" { ${rdap_prefix}/${rdap_length} ${nft_expiry} } >/dev
/null
2>&1; then
1704 f_log
"info" "add IP range '${rdap_prefix}/${rdap_length}' (source: ${rdap_info:-"n/a"} ::: expiry: ${ban_nftexpiry:-"-"}) to blocklist${proto} set"
1708 f_log
"info" "rdap request failed (rc: ${rdap_rc:-"-"}/log: ${rdap_log})"
1711 if [ -z "${ban_nftexpiry}" ] && [ "${ban_autoblocklist}" = "1" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_blocklist}"; then
1712 printf "%-42s%s\n" "${ip}" "# added on $(date "+%Y-
%m-
%d
%H
:%M
:%S
")" >>"${ban_blocklist}"
1713 f_log
"info" "add IP '${ip}' to local blocklist"
1719 f_log
"info" "start detached no-op banIP service"
1726 if [ -r "/lib/functions.sh" ] && [ -r "/lib/functions/network.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]; then
1727 .
"/lib/functions.sh"
1728 .
"/lib/functions/network.sh"
1729 .
"/usr/share/libubox/jshn.sh"
1731 f_log
"emerg" "system libraries not found"
1734 # initial system calls
1736 ban_awkcmd
="$(f_cmd gawk awk)"
1737 ban_catcmd
="$(f_cmd cat)"
1738 ban_fw4cmd
="$(f_cmd fw4)"
1739 ban_grepcmd
="$(f_cmd grep)"
1740 ban_jsoncmd
="$(f_cmd jsonfilter)"
1741 ban_logcmd
="$(f_cmd logger)"
1742 ban_lookupcmd
="$(f_cmd nslookup)"
1743 ban_mailcmd
="$(f_cmd msmtp true)"
1744 ban_nftcmd
="$(f_cmd nft)"
1745 ban_pgrepcmd
="$(f_cmd pgrep)"
1746 ban_sedcmd
="$(f_cmd sed)"
1747 ban_ubuscmd
="$(f_cmd ubus)"
1748 ban_zcatcmd
="$(f_cmd zcat)"
1751 if [ "${ban_action}" != "stop" ]; then
1752 [ ! -d "/etc/banip" ] && f_log
"err" "no banIP config directory"
1753 [ ! -r "/etc/config/banip" ] && f_log
"err" "no banIP config"
1754 [ "$(uci_get banip global ban_enabled)" = "0" ] && f_log
"err" "banIP is disabled"