diff options
author | Dirk Brenken <dev@brenken.org> | 2023-02-13 17:56:57 +0100 |
---|---|---|
committer | Dirk Brenken <dev@brenken.org> | 2023-02-18 21:06:26 +0100 |
commit | 82a491bac85b8d106dc6057c1bd58c8e5dc3ed53 (patch) | |
tree | 805d6a1bbd990b66509686623be45c2a265418bc /net/banip/files/banip.init | |
parent | 33d32450b406e83e7eb908c58eecab0cff043622 (diff) |
banip: release 0.8.0 (nft rewrite)
- complete rewrite of banIP to support nftables
- all sets are handled in a separate nft table/namespace 'banIP'
- for incoming blocking it uses the inet input hook, for outgoing blocking it uses the inet forward hook
- full IPv4 and IPv6 support
- supports nft atomic set loading
- supports blocking by ASN numbers and by iso country codes
- 42 preconfigured external feeds are available, plus local allow- and blocklist
- supports local allow- and blocklist (IPv4, IPv6, CIDR notation or domain names)
- auto-add the uplink subnet to the local allowlist
- provides a small background log monitor to ban unsuccessful login attempts in real-time
- the logterms for the log monitor service can be freely defined via regex
- auto-add unsuccessful LuCI, nginx, Asterisk or ssh login attempts to the local blocklist
- fast feed processing as they are handled in parallel as background jobs
- per feed it can be defined whether the input chain or the forward chain should be blocked (default: both chains)
- automatic blocklist backup & restore, the backups will be used in case of download errors or during startup
- automatically selects one of the following download utilities with ssl support: aria2c, curl, uclient-fetch or wget
- supports a 'allowlist only' mode, this option restricts internet access from/to a small number of secure websites/IPs
- provides comprehensive runtime information
- provides a detailed set report
- provides a set search engine for certain IPs
- feed parsing by fast & flexible regex rulesets
- minimal status & error logging to syslog, enable debug logging to receive more output
- procd based init system support (start/stop/restart/reload/status/report/search)
- procd network interface trigger support
- ability to add new banIP feeds on your own
- add a readme with all available options/feeds to customize your installation to your needs
- a new LuCI frontend will be available in due course
Signed-off-by: Dirk Brenken <dev@brenken.org>
Diffstat (limited to 'net/banip/files/banip.init')
-rwxr-xr-x | net/banip/files/banip.init | 282 |
1 files changed, 44 insertions, 238 deletions
diff --git a/net/banip/files/banip.init b/net/banip/files/banip.init index 08405e608..ab126f230 100755 --- a/net/banip/files/banip.init +++ b/net/banip/files/banip.init @@ -1,202 +1,69 @@ #!/bin/sh /etc/rc.common -# Copyright (c) 2018-2021 Dirk Brenken (dev@brenken.org) +# banIP init script - ban incoming and outgoing ip adresses/subnets via sets in nftables +# Copyright (c) 2018-2023 Dirk Brenken (dev@brenken.org) # This is free software, licensed under the GNU General Public License v3. # (s)hellcheck exceptions -# shellcheck disable=1091,2034,3043,3057,3060 +# shellcheck disable=all START=30 USE_PROCD=1 -if type extra_command >/dev/null 2>&1; then - extra_command "refresh" "Refresh ipsets without new list downloads" - extra_command "suspend" "Suspend banIP processing" - extra_command "resume" "Resume banIP processing" - extra_command "query" "<IP> Query active banIP IPSets for a specific IP address" - extra_command "report" "[<cli>|<mail>|<gen>|<json>] Print banIP related IPset statistics" - extra_command "list" "[<add>|<add_asn>|<add_country>|<remove>|<remove_asn>|<remove_country>] <source(s)> List/Edit available sources" - extra_command "timer" "[<add> <tasks> <hour> [<minute>] [<weekday>]]|[<remove> <line no.>] List/Edit cron update intervals" -else - EXTRA_COMMANDS="status refresh suspend resume query report list timer version" - EXTRA_HELP=" status Service status - refresh Refresh ipsets without new list downloads - suspend Suspend banIP processing - resume Resume banIP processing - query <IP> Query active banIP IPSets for a specific IP address - report [<cli>|<mail>|<gen>|<json>] Print banIP related IPset statistics - list [<add>|<add_asn>|<add_country>|<remove>|<remove_asn>|<remove_country>] <source(s)> List/Edit available sources - timer [<add> <tasks> <hour> [<minute>] [<weekday>]]|[<remove> <line no.>] List/Edit cron update intervals" -fi +extra_command "report" "[text|json|mail] Print banIP related set statistics" +extra_command "search" "[<IPv4 address>|<IPv6 address>] Check if an element exists in the banIP sets" ban_init="/etc/init.d/banip" -ban_script="/usr/bin/banip.sh" +ban_service="/usr/bin/banip-service.sh" +ban_funlib="/usr/lib/banip-functions.sh" ban_pidfile="/var/run/banip.pid" +ban_lock="/var/run/banip.lock" -if [ -s "${ban_pidfile}" ] && { [ "${action}" = "start" ] || [ "${action}" = "stop" ] || - [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "refresh" ] || - [ "${action}" = "suspend" ] || [ "${action}" = "resume" ] || [ "${action}" = "query" ] || - { [ "${action}" = "list" ] && [ -n "${1}" ]; } || { [ "${action}" = "report" ] && [ "${1}" != "json" ]; }; }; then - exit 0 -fi +[ ! -r "${ban_funlib}" ] && exit 1 +[ "${action}" = "stop" ] && ! /etc/init.d/banip running && exit 0 +[ -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && exit 1 +[ ! -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && mkdir -p "${ban_lock}" boot() { : >"${ban_pidfile}" - rc_procd start_service + rc_procd start_service "boot" } start_service() { if "${ban_init}" enabled; then - if [ "${action}" = "boot" ]; then - return 0 - fi - procd_open_instance "banip" - procd_set_param command "${ban_script}" "${@}" + [ "${action}" = "boot" ] && [ -n "$(uci_get banip global ban_trigger)" ] && return 0 + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_rmpid + procd_open_instance "banip-service" + procd_set_param command "${ban_service}" "${@:-"${action}"}" procd_set_param pidfile "${ban_pidfile}" - procd_set_param nice "$(uci_get banip global ban_nice "0")" + procd_set_param nice "$(uci_get banip global ban_nicelimit "0")" + procd_set_param limits nofile="$(uci_get banip global ban_filelimit "1024")" procd_set_param stdout 1 procd_set_param stderr 1 procd_close_instance + else + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_log "err" "banIP service autostart is currently disabled, please enable the service autostart with '/etc/init.d/banip enable'" + rm -rf "${ban_lock}" fi } -version() { - rc_procd "${ban_script}" version -} - -refresh() { - rc_procd start_service refresh -} - reload_service() { - rc_procd start_service reload + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_rmpid + rc_procd start_service "reload" } stop_service() { - rc_procd "${ban_script}" stop + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + "${ban_nftcmd}" delete table inet banIP >/dev/null 2>&1 + f_genstatus "stopped" + f_rmpid } restart() { - rc_procd start_service restart -} - -suspend() { - rc_procd start_service suspend -} - -resume() { - rc_procd start_service resume -} - -query() { - rc_procd "${ban_script}" query "${1}" -} - -list() { - local src_archive src_file src_enabled key name enabled focus descurl url_4 rule_4 url_6 rule_6 action="${1}" - - if [ "${action%_*}" = "add" ] || [ "${action%_*}" = "remove" ]; then - shift - for name in "${@}"; do - case "${action}" in - "add") - if ! uci_get banip global ban_sources | grep -q "${name}"; then - uci_add_list banip global ban_sources "${name}" - printf "%s\n" "::: banIP source '${name}' added to config" - fi - ;; - "remove") - if uci_get banip global ban_sources | grep -q "${name}"; then - uci_remove_list banip global ban_sources "${name}" - printf "%s\n" "::: banIP source '${name}' removed from config" - fi - ;; - "add_asn") - if ! uci_get banip global ban_asns | grep -q "${name}"; then - uci_add_list banip global ban_asns "${name}" - printf "%s\n" "::: banIP asn '${name}' added to config" - fi - ;; - "remove_asn") - if uci_get banip global ban_asns | grep -q "${name}"; then - uci_remove_list banip global ban_asns "${name}" - printf "%s\n" "::: banIP asn '${name}' removed from config" - fi - ;; - "add_country") - if ! uci_get banip global ban_countries | grep -q "${name}"; then - uci_add_list banip global ban_countries "${name}" - printf "%s\n" "::: banIP country '${name}' added to config" - fi - ;; - "remove_country") - if uci_get banip global ban_countries | grep -q "${name}"; then - uci_remove_list banip global ban_countries "${name}" - printf "%s\n" "::: banIP country '${name}' removed from config" - fi - ;; - esac - done - if [ -n "$(uci -q changes banip)" ]; then - uci_commit banip - "${ban_init}" start - fi - else - src_archive="$(uci_get banip global ban_srcarc "/etc/banip/banip.sources.gz")" - src_file="$(uci_get banip global ban_srcfile "/tmp/ban_sources.json")" - src_enabled="$(uci -q show banip.global.ban_sources)" - if [ -r "${src_archive}" ]; then - zcat "${src_archive}" >"${src_file}" - else - printf "%s\n" "::: banIP source archive '${src_archive}' not found" - fi - if [ -r "${src_file}" ]; then - src_enabled="${src_enabled#*=}" - src_enabled="${src_enabled//\'/}" - printf "%s\n" "::: Available banIP sources" - printf "%s\n" ":::" - printf "%-25s%-10s%-36s%s\n" " Name" "Enabled" "Focus" "Info URL" - printf "%s\n" " ---------------------------------------------------------------------------" - json_load_file "${src_file}" - json_get_keys keylist - for key in ${keylist}; do - json_select "${key}" - json_get_var focus "focus" - json_get_var descurl "descurl" - json_get_var url_4 "url_4" - json_get_var rule_4 "rule_4" - json_get_var url_6 "url_6" - json_get_var rule_6 "rule_6" - if { [ -n "${url_4}" ] && [ -n "${rule_4}" ]; } || { [ -n "${url_6}" ] && [ -n "${rule_6}" ]; }; then - if printf "%s" "${src_enabled}" | grep -q "${key}"; then - enabled="x" - else - enabled=" " - fi - src_enabled="${src_enabled/${key}/}" - printf " + %-21s%-10s%-36s%s\n" "${key:0:20}" "${enabled}" "${focus:0:35}" "${descurl:0:50}" - else - src_enabled="${src_enabled} ${key}" - fi - json_select .. - done - asn_list="$(uci_get banip global ban_asns "-")" - country_list="$(uci_get banip global ban_countries "-")" - printf "%s\n" " ---------------------------------------------------------------------------" - printf " * %s\n" "Configured ASNs: ${asn_list// /, }" - printf " * %s\n" "Configured Countries: ${country_list// /, }" - - if [ -n "${src_enabled// /}" ]; then - printf "%s\n" " ---------------------------------------------------------------------------" - printf "%s\n" " Sources without valid configuration" - printf "%s\n" " ---------------------------------------------------------------------------" - for key in ${src_enabled}; do - printf " - %s\n" "${key:0:20}" - done - fi - else - printf "%s\n" "::: banIP source file '${src_file}' not found" - fi - fi + stop_service + rc_procd start_service "restart" } status() { @@ -204,90 +71,29 @@ status() { } status_service() { - local key keylist type value index_value values rtfile - - rtfile="$(uci_get banip global ban_rtfile "/tmp/ban_runtime.json")" - - json_load_file "${rtfile}" >/dev/null 2>&1 - json_get_keys keylist - if [ -n "${keylist}" ]; then - printf "%s\n" "::: banIP runtime information" - for key in ${keylist}; do - json_get_var value "${key}" >/dev/null 2>&1 - if [ "${key%_*}" = "active" ]; then - printf " + %-15s : " "${key}" - json_select "${key}" >/dev/null 2>&1 - values="" - index=1 - while json_get_type type "${index}" && [ "${type}" = "object" ]; do - json_get_values index_value "${index}" >/dev/null 2>&1 - if [ "${index}" = "1" ]; then - values="${index_value}" - else - values="${values}, ${index_value}" - fi - index=$((index + 1)) - done - values="$(printf "%s" "${values}" | awk '{NR=1;max=98;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{printf"%-22s%s\n","",substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')" - printf "%s\n" "${values:-"-"}" - json_select ".." - else - printf " + %-15s : %s\n" "${key}" "${value:-"-"}" - fi - done - else - printf "%s\n" "::: no banIP runtime information available" - fi + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_getstatus } report() { - rc_procd "${ban_script}" report "${1:-"cli"}" + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_report "${1:-"text"}" } -timer() { - local cron_file cron_content cron_lineno action="${1:-"list"}" cron_tasks="${2}" hour="${3}" minute="${4:-0}" weekday="${5:-"*"}" - - cron_file="/etc/crontabs/root" - - if [ -s "${cron_file}" ] && [ "${action}" = "list" ]; then - awk '{print NR "> " $0}' "${cron_file}" - elif [ "${action}" = "add" ]; then - hour="${hour//[[:alpha:]]/}" - minute="${minute//[[:alpha:]]/}" - if [ -n "${cron_tasks}" ] && [ -n "${hour}" ] && [ -n "${minute}" ] && [ -n "${weekday}" ] && - [ "${hour}" -ge 0 ] && [ "${hour}" -le 23 ] && - [ "${minute}" -ge 0 ] && [ "${minute}" -le 59 ]; then - printf "%02d %02d %s\n" "${minute}" "${hour}" "* * ${weekday} ${ban_init} ${cron_tasks}" >>"${cron_file}" - /etc/init.d/cron restart - fi - elif [ -s "${cron_file}" ] && [ "${action}" = "remove" ]; then - cron_tasks="${cron_tasks//[[:alpha:]]/}" - cron_lineno="$(awk 'END{print NR}' "${cron_file}")" - cron_content="$(awk '{print $0}' "${cron_file}")" - if [ "${cron_tasks:-"0"}" -le "${cron_lineno:-"1"}" ] && [ -n "${cron_content}" ]; then - printf "%s\n" "${cron_content}" | awk "NR!~/^${cron_tasks}$/" >"${cron_file}" - /etc/init.d/cron restart - fi - fi +search() { + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_search "${1}" } service_triggers() { - local iface delay + local iface trigger delay - iface="$(uci_get banip global ban_trigger)" + trigger="$(uci_get banip global ban_trigger)" delay="$(uci_get banip global ban_triggerdelay "5")" PROCD_RELOAD_DELAY=$((delay * 1000)) - if [ -z "${iface}" ]; then - . "/lib/functions/network.sh" - network_find_wan iface - if [ -n "${iface}" ]; then - uci_set banip global ban_trigger "${iface}" - uci_commit "banip" - fi - fi - if [ -n "${iface}" ]; then + for iface in ${trigger}; do procd_add_interface_trigger "interface.*.up" "${iface}" "${ban_init}" "start" - fi + done procd_add_reload_trigger "banip" } |