banip: update 0.3.0 10145/head
authorDirk Brenken <dev@brenken.org>
Fri, 4 Oct 2019 07:12:11 +0000 (09:12 +0200)
committerDirk Brenken <dev@brenken.org>
Fri, 4 Oct 2019 08:16:20 +0000 (10:16 +0200)
* new 'ca-bundle' dependency as all https connections
  are now validated by default
* automatically select the download utility: 'aria2', 'curl',
  'uclient-fetch' with libustream-* or wget are supported
* track & ban failed LuCI login attempts as well
* add a small log/banIP background monitor to block
  SSH/LuCI brute force attacks in realtime (disabled by default)
* add a config version check (please update your default config!)
* made the automatic wan detection more stable
* fix the IPv6 logfile parser
* fix the service status message
* update readme

Signed-off-by: Dirk Brenken <dev@brenken.org>
net/banip/Makefile
net/banip/files/README.md
net/banip/files/banip.conf
net/banip/files/banip.init
net/banip/files/banip.service [new file with mode: 0755]
net/banip/files/banip.sh

index 5a0da93a109a86706a7f3a5371ba1798211a6f01..897ecd8a70259c709f66da5e2db6597956dffd88 100644 (file)
@@ -6,7 +6,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=banip
-PKG_VERSION:=0.2.1
+PKG_VERSION:=0.3.0
 PKG_RELEASE:=1
 PKG_LICENSE:=GPL-3.0-or-later
 PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
@@ -17,7 +17,7 @@ define Package/banip
        SECTION:=net
        CATEGORY:=Network
        TITLE:=Ban incoming and/or outgoing ip adresses via ipsets
-       DEPENDS:=+jshn +jsonfilter +ip +ipset +iptables
+       DEPENDS:=+jshn +jsonfilter +ip +ipset +iptables +ca-bundle
        PKGARCH:=all
 endef
 
@@ -45,7 +45,7 @@ endef
 
 define Package/banip/install
        $(INSTALL_DIR) $(1)/usr/bin
-       $(INSTALL_BIN) ./files/banip.sh $(1)/usr/bin/
+       $(INSTALL_BIN) ./files/banip.sh $(1)/usr/bin
 
        $(INSTALL_DIR) $(1)/etc/init.d
        $(INSTALL_BIN) ./files/banip.init $(1)/etc/init.d/banip
@@ -54,9 +54,10 @@ define Package/banip/install
        $(INSTALL_CONF) ./files/banip.conf $(1)/etc/config/banip
 
        $(INSTALL_DIR) $(1)/etc/banip
-       $(INSTALL_CONF) ./files/banip.blacklist $(1)/etc/banip/
-       $(INSTALL_CONF) ./files/banip.whitelist $(1)/etc/banip/
-       
+       $(INSTALL_BIN) ./files/banip.service $(1)/etc/banip
+       $(INSTALL_CONF) ./files/banip.blacklist $(1)/etc/banip
+       $(INSTALL_CONF) ./files/banip.whitelist $(1)/etc/banip
+
        $(INSTALL_DIR) $(1)/etc/hotplug.d/firewall
        $(INSTALL_DATA) ./files/banip.hotplug $(1)/etc/hotplug.d/firewall/30-banip
 endef
index 3147349de16b39a089e6fd20f9d35e761a6ba7a9..b42dd5768ff0ef24dfcb8c0d65de8717ef5b3c7a 100644 (file)
@@ -1,20 +1,21 @@
 # banIP - ban incoming and/or outgoing ip adresses via ipsets
 
 ## Description
-IP address blocking is commonly used to protect against brute force attacks, prevent disruptive or unautherized address(es) from access or it can be used to restrict access to or from a particular geographic area — for example.  
+IP address blocking is commonly used to protect against brute force attacks, prevent disruptive or unauthorized address(es) from access or it can be used to restrict access to or from a particular geographic area — for example.  
 
 ## Main Features
 * support many IP blocklist sources (free for private usage, for commercial use please check their individual licenses):
 * zero-conf like automatic installation & setup, usually no manual changes needed
-* supports four different download utilities: uclient-fetch, wget, curl, aria2c
+* automatically selects one of the following download utilities: aria2c, curl, uclient-fetch, wget
 * Really fast downloads & list processing as they are handled in parallel as background jobs in a configurable 'Download Queue'
 * full IPv4 and IPv6 support
 * ipsets (one per source) are used to ban a large number of IP addresses
 * supports blocking by ASN numbers
 * supports blocking by iso country codes
 * supports local white & blacklist (IPv4, IPv6 & CIDR notation), located by default in /etc/banip/banip.whitelist and /etc/banip/banip.blacklist
-* auto-add unsuccessful ssh login attempts to 'dropbear' or 'sshd' to local blacklist (see 'ban_autoblacklist' option)
+* auto-add unsuccessful LuCI and ssh login attempts via 'dropbear' or 'sshd' to local blacklist (see 'ban_autoblacklist' option)
 * auto-add the uplink subnet to local whitelist (see 'ban_autowhitelist' option)
+* provides a small background log monitor to ban unsuccessful login attempts in real-time
 * per source configuration of SRC (incoming) and DST (outgoing)
 * integrated IPSet-Lookup
 * integrated RIPE-Lookup
@@ -29,8 +30,7 @@ IP address blocking is commonly used to protect against brute force attacks, pre
 
 ## Prerequisites
 * [OpenWrt](https://openwrt.org), tested with the stable release series (19.07) and with the latest snapshot
-* a download utility:
-    * to support all blocklist sources a full version with ssl support of 'wget', 'uclient-fetch' with one of the 'libustream-*' ssl libraries, 'aria2c' or 'curl' is required
+* download utility: 'uclient-fetch' with one of the 'libustream-*' ssl libraries, 'wget',  'aria2c' or 'curl' is required
 
 ## Installation & Usage
 * install 'banip' (_opkg install banip_)
@@ -47,8 +47,8 @@ IP address blocking is commonly used to protect against brute force attacks, pre
 * the following options apply to the 'global' config section:
     * ban\_enabled => main switch to enable/disable banIP service (bool/default: '0', disabled)
     * ban\_automatic => determine the L2/L3 WAN network device automatically (bool/default: '1', enabled)
-    * ban\_fetchutil => name of the used download utility: 'uclient-fetch', 'wget', 'curl', 'aria2c', 'wget-nossl'. 'busybox' (default: 'uclient-fetch')
-    * ban\_iface => space separated list of WAN network interface(s)/device(s) used by banIP (default: automatically set by banIP ('ban_automatic'))
+    * ban\_iface => space separated list of WAN network interface(s)/device(s) used by banIP (default: not set, automatically detected)
+    * ban\_realtime => a small log/banIP background monitor to block SSH/LuCI brute force attacks in realtime (bool/default: 'false', disabled)
 
 * the following options apply to the 'extra' config section:
     * ban\_debug => enable/disable banIP debug output (bool/default: '0', disabled)
@@ -56,8 +56,9 @@ IP address blocking is commonly used to protect against brute force attacks, pre
     * ban\_triggerdelay => additional trigger delay in seconds before banIP processing begins (int/default: '2')
     * ban\_backupdir => target directory for banIP backups (default: '/tmp')
     * ban\_sshdaemon => select the SSH daemon for logfile parsing, 'dropbear' or 'sshd' (default: 'dropbear')
-    * ban\_starttype => select the used start type during boot, 'start' or 'reload' (default: 'start')
+    * ban\_starttype => select the used start type during boot, 'start', 'refresh' or 'reload' (default: 'start')
     * ban\_maxqueue => size of the download queue to handle downloads & IPSet processing in parallel (int/default: '4')
+    * ban\_fetchutil => name of the used download utility: 'uclient-fetch', 'wget', 'curl', 'aria2c' (default: not set, automatically detected)
     * ban\_fetchparm => special config options for the download utility (default: not set)
     * ban\_autoblacklist => store auto-addons temporary in ipset and permanently in local blacklist as well (bool/default: '1', enabled)
     * ban\_autowhitelist => store auto-addons temporary in ipset and permanently in local whitelist as well (bool/default: '1', enabled)
@@ -69,12 +70,12 @@ IP address blocking is commonly used to protect against brute force attacks, pre
 /etc/init.d/banip status
 ::: banIP runtime information
   + status     : enabled
-  + version    : 0.2.0
-  + fetch_info : /bin/uclient-fetch (libustream-ssl)
-  + ipset_info : 11 IPSets with overall 118359 IPs/Prefixes
+  + version    : 0.3.0
+  + util_info  : /usr/bin/aria2c, true
+  + ipset_info : 10 IPSets with overall 106729 IPs/Prefixes
   + backup_dir : /tmp
-  + last_run   : 09.09.2019 16:49:40
-  + system     : UBNT-ERX, OpenWrt SNAPSHOT r10962-c19b9f9a26
+  + last_run   : 03.10.2019 19:15:25
+  + system     : UBNT-ERX, OpenWrt SNAPSHOT r11102-ced4c0e635
 </code></pre>
   
 **cronjob for a regular IPSet blocklist update (/etc/crontabs/root):**
index f0565c91a712a0e93be0cd023a32ec73f0cca343..04f5cee8d1c4f6b4850d3bb91c3b64c94d0e970a 100644 (file)
@@ -1,9 +1,9 @@
 
 config banip 'global'
        option ban_enabled '0'
+       option ban_basever '0.3'
        option ban_automatic '1'
-       option ban_fetchutil 'uclient-fetch'
-       option ban_iface 'wan'
+       option ban_realtime 'false'
 
 config banip 'extra'
        option ban_debug '0'
index 787a4edaa77672676874c5beb2e407c414e4e9c9..25f2f72cd4feecac70207f009974f25004eb9bd3 100755 (executable)
@@ -5,7 +5,7 @@ START=30
 USE_PROCD=1
 
 EXTRA_COMMANDS="refresh status"
-EXTRA_HELP="   refresh Refresh ipsets only (no new download!)
+EXTRA_HELP="   refresh Refresh ipsets without new list downloads
        status  Print runtime information"
 
 ban_init="/etc/init.d/banip"
@@ -53,9 +53,9 @@ stop_service()
        rc_procd "${ban_script}" stop
 }
 
-status()
+status_service()
 {
-       local key keylist value 
+       local key keylist value
        local rtfile="$(uci_get banip global ban_rtfile "/tmp/ban_runtime.json")"
 
        json_load_file "${rtfile}" >/dev/null 2>&1
@@ -76,14 +76,14 @@ status()
 
 service_triggers()
 {
-       local ban_iface="$(uci_get banip global ban_iface)"
+       local iface iface_list="$(uci_get banip global ban_iface)"
        local delay="$(uci_get banip extra ban_triggerdelay "2")"
        local type="$(uci_get banip extra ban_starttype "start")"
 
        PROCD_RELOAD_DELAY=$((${delay}*1000))
-       if [ -n "${ban_iface}" ]
+       if [ -n "${iface_list}" ]
        then
-               for iface in ${ban_iface}
+               for iface in ${iface_list}
                do
                        procd_add_interface_trigger "interface.*.up" "${iface}" "${ban_init}" "${type}"
                done
diff --git a/net/banip/files/banip.service b/net/banip/files/banip.service
new file mode 100755 (executable)
index 0000000..1c44be3
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+# log service to trace failed ssh/luci logins and conditionally refresh banIP
+# written by Dirk Brenken (dev@brenken.org)
+
+# This is free software, licensed under the GNU General Public License v3.
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+LC_ALL=C
+PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+
+if [ -r "/lib/functions.sh" ]
+then
+       . "/lib/functions.sh"
+       ban_sshdaemon="$(uci_get banip extra ban_sshdaemon "dropbear")"
+fi
+ban_ver="${1}"
+ban_log="$(command -v logread)"
+
+if [ -x "${ban_log}" ]
+then
+       logger -p "info" -t "banIP-${ban_ver}[${$}]" "log/banIP service started"
+       "${ban_log}" -f -e "${ban_sshdaemon}\|luci: failed login" | \
+               { grep -qE "Exit before auth|luci: failed login|[0-9]+ \[preauth\]$"; [ $? -eq 0 ] && /etc/init.d/banip refresh; }
+else
+       logger -p "err" -t "banIP-${ban_ver}[${$}]" "can't start log/banIP service"
+fi
index 7ab0c4970a52e5ce263a9ebe51484ba63680d5bf..8634b19df60441175004205ac0024b272308f3df 100755 (executable)
@@ -13,7 +13,8 @@
 #
 LC_ALL=C
 PATH="/usr/sbin:/usr/bin:/sbin:/bin"
-ban_ver="0.2.1"
+ban_ver="0.3.0"
+ban_basever=""
 ban_enabled=0
 ban_automatic="1"
 ban_sources=""
@@ -23,7 +24,8 @@ ban_backupdir="/mnt"
 ban_maxqueue=4
 ban_autoblacklist=1
 ban_autowhitelist=1
-ban_fetchutil="uclient-fetch"
+ban_realtime="false"
+ban_fetchutil=""
 ban_ip="$(command -v ip)"
 ban_ipt="$(command -v iptables)"
 ban_ipt_save="$(command -v iptables-save)"
@@ -36,6 +38,7 @@ ban_chain="banIP"
 ban_action="${1:-"start"}"
 ban_pidfile="/var/run/banip.pid"
 ban_rtfile="/tmp/ban_runtime.json"
+ban_logservice="/etc/banip/banip.service"
 ban_sshdaemon="dropbear"
 ban_setcnt=0
 ban_cnt=0
@@ -94,6 +97,14 @@ f_envload()
        config_load banip
        config_foreach parse_config source
 
+       # version check
+       #
+       if [ -z "${ban_basever}" ] || [ "${ban_ver%.*}" != "${ban_basever}" ]
+       then
+               f_log "info" "your banIP config seems to be too old, please update your config with the '--force-maintainer' opkg option"
+               exit 0
+       fi
+
        # create temp directory & files
        #
        f_temp
@@ -102,6 +113,7 @@ f_envload()
        #
        if [ "${ban_enabled}" -eq 0 ]
        then
+               f_bgserv "stop"
                f_jsnup disabled
                f_ipset destroy
                f_rmbackup
@@ -115,7 +127,7 @@ f_envload()
 #
 f_envcheck()
 {
-       local ssl_lib tmp
+       local util utils packages tmp cnt=0
 
        # check backup directory
        #
@@ -126,44 +138,71 @@ f_envcheck()
 
        # check fetch utility
        #
-       case "${ban_fetchutil}" in
-               "uclient-fetch")
-                       if [ -f "/lib/libustream-ssl.so" ]
+       if [ -z "${ban_fetchutil}" ]
+       then
+               utils="aria2c curl wget uclient-fetch"
+               packages="$(opkg list-installed 2>/dev/null)"
+               for util in ${utils}
+               do
+                       if { [ "${util}" = "uclient-fetch" ] && [ -n "$(printf "%s\\n" "${packages}" | grep "^libustream-")" ]; } || \
+                               { [ "${util}" = "wget" ] && [ -n "$(printf "%s\\n" "${packages}" | grep "^wget -")" ]; } || \
+                               { [ "${util}" != "uclient-fetch" ] && [ "${util}" != "wget" ]; }
                        then
-                               ban_fetchparm="${ban_fetchparm:-"--timeout=20 --no-check-certificate -O"}"
-                               ssl_lib="libustream-ssl"
+                               ban_fetchutil="$(command -v "${util}")"
+                               if [ -x "${ban_fetchutil}" ]
+                               then
+                                       break
+                               fi
                        fi
-               ;;
-               "wget")
-                       ban_fetchparm="${ban_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=20 --no-check-certificate -O"}"
-                       ssl_lib="built-in"
+                       unset ban_fetchutil util
+               done
+       else
+               util="${ban_fetchutil}"
+               ban_fetchutil="$(command -v "${util}")"
+               if [ ! -x "${ban_fetchutil}" ]
+               then
+                       unset ban_fetchutil util
+               fi
+       fi
+       case "${util}" in
+               "aria2c")
+                       ban_fetchparm="${ban_fetchparm:-"--timeout=20 --allow-overwrite=true --auto-file-renaming=false --check-certificate=true --dir=" " -o"}"
                ;;
                "curl")
-                       ban_fetchparm="${ban_fetchparm:-"--connect-timeout 20 --insecure -o"}"
-                       ssl_lib="built-in"
+                       ban_fetchparm="${ban_fetchparm:-"--connect-timeout 20 -o"}"
                ;;
-               "aria2c")
-                       ban_fetchparm="${ban_fetchparm:-"--timeout=20 --allow-overwrite=true --auto-file-renaming=false --check-certificate=false -o"}"
-                       ssl_lib="built-in"
+               "uclient-fetch")
+                       ban_fetchparm="${ban_fetchparm:-"--timeout=20 -O"}"
+               ;;
+               "wget")
+                       ban_fetchparm="${ban_fetchparm:-"--no-cache --no-cookies --max-redirect=0 --timeout=20 -O"}"
                ;;
        esac
-       ban_fetchutil="$(command -v "${ban_fetchutil}")"
-       ban_fetchinfo="${ban_fetchutil:-"-"} (${ssl_lib:-"-"})"
-
-       if [ ! -x "${ban_fetchutil}" ] || [ -z "${ban_fetchutil}" ] || [ -z "${ban_fetchparm}" ]
+       if [ -z "${ban_fetchutil}" ] || [ -z "${ban_fetchparm}" ]
        then
-               f_log "err" "download utility not found, please install 'uclient-fetch' with the 'libustream-mbedtls' ssl library or the full 'wget' package"
+               f_log "err" "download utility with SSL support not found, please install 'uclient-fetch' with a 'libustream-*' variant or another download utility like 'wget', 'curl' or 'aria2'"
        fi
 
        # get wan device and wan subnets
        #
        if [ "${ban_automatic}" = "1" ]
        then
-               network_find_wan ban_iface
-               if [ -z "${ban_iface}" ]
-               then
-                       network_find_wan6 ban_iface
-               fi
+               while [ "${cnt}" -le 30 ]
+               do
+                       network_find_wan ban_iface
+                       if [ -z "${ban_iface}" ]
+                       then
+                               network_find_wan6 ban_iface
+                       fi
+                       if [ -z "${ban_iface}" ]
+                       then
+                               network_flush_cache
+                               cnt=$((cnt+1))
+                               sleep 1
+                       else
+                               break
+                       fi
+               done
        fi
 
        for iface in ${ban_iface}
@@ -194,13 +233,11 @@ f_envcheck()
        if [ -z "${ban_iface}" ] || [ -z "${ban_dev}" ]
        then
                f_log "err" "wan interface(s)/device(s) (${ban_iface:-"-"}/${ban_dev:-"-"}) not found, please please check your configuration"
+       else
+               ban_dev_all="$(${ban_ip} link show | awk 'BEGIN{FS="[@: ]"}/^[0-9:]/{if(($3!="lo")&&($3!="br-lan")){print $3}}')"
+               f_jsnup "running"
+               f_log "info" "start banIP processing (${ban_action})"
        fi
-       ban_dev_all="$(${ban_ip} link show | awk 'BEGIN{FS="[@: ]"}/^[0-9:]/{if(($3!="lo")&&($3!="br-lan")){print $3}}')"
-       uci_set banip global ban_iface "${ban_iface}"
-       uci_commit banip
-
-       f_jsnup "running"
-       f_log "info" "start banIP processing (${ban_action})"
 }
 
 # create temporary files and directories
@@ -488,36 +525,54 @@ f_log()
 
        if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${ban_debug}" -eq 1 ]; }
        then
-               logger -p "${class}" -t "banIP-[${ban_ver}]" "${log_msg}"
+               logger -p "${class}" -t "banIP-${ban_ver}[${$}]" "${log_msg}"
                if [ "${class}" = "err" ]
                then
                        f_jsnup error
                        f_ipset destroy
                        f_rmbackup
                        f_rmtemp
-                       logger -p "${class}" -t "banIP-[${ban_ver}]" "Please also check 'https://github.com/openwrt/packages/blob/master/net/banip/files/README.md'"
+                       logger -p "${class}" -t "banIP-${ban_ver}[${$}]" "Please also check 'https://github.com/openwrt/packages/blob/master/net/banip/files/README.md'"
                        exit 1
                fi
        fi
 }
 
+# start log service to trace failed ssh/luci logins
+#
+f_bgserv()
+{
+       local bg_pid status="${1}"
+
+       bg_pid="$(pgrep -f "^/bin/sh ${ban_logservice}.*|^logread -f -e ${ban_sshdaemon}\|luci: failed login|^grep -qE Exit before auth|luci: failed login|[0-9]+ \[preauth\]$" | awk '{ORS=" "; print $1}')"
+       if [ -z "${bg_pid}" ] && [ "${status}" = "start" ] \
+               && [ -x "${ban_logservice}" ] && [ "${ban_realtime}" = "true" ]
+       then
+               ( "${ban_logservice}" "${ban_ver}" &)
+       elif [ -n "${bg_pid}" ] && [ "${status}" = "stop" ] 
+       then
+               kill -HUP "${bg_pid}" 2>/dev/null
+       fi
+       f_log "debug" "f_bgserv ::: status: ${status:-"-"}, bg_pid: ${bg_pid:-"-"}, ban_realtime: ${ban_realtime:-"-"}, log_service: ${ban_logservice:-"-"}"
+}
+
 # main function for banIP processing
 #
 f_main()
 {
        local pid pid_list start_ts end_ts ip tmp_raw tmp_cnt tmp_load tmp_file mem_total mem_free cnt=1
-       local src_name src_on src_url src_rset src_setipv src_settype src_ruletype src_cat src_log src_addon src_rc
-       local wan_input wan_forward lan_input lan_forward target_src target_dst log_content
+       local src_name src_on src_url src_rset src_setipv src_settype src_ruletype src_cat src_log src_addon src_ts src_rc
+       local wan_input wan_forward lan_input lan_forward target_src target_dst ssh_log luci_log
 
-       log_content="$(logread -e "${ban_sshdaemon}")"
+       ssh_log="$(logread -e "${ban_sshdaemon}" | grep -o "${ban_sshdaemon}.*" | sed 's/:[0-9]*$//g')"
+       luci_log="$(logread -e "luci: failed login" | grep -o "luci:.*")"
        mem_total="$(awk '/^MemTotal/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
        mem_free="$(awk '/^MemFree/ {print int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
-       f_log "debug" "f_main  ::: fetch_util: ${ban_fetchinfo:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}, ssh_daemon: ${ban_sshdaemon}, interface(s): ${ban_iface:-"-"}, device(s): ${ban_dev:-"-"}, all_devices: ${ban_dev_all:-"-"}, backup_dir: ${ban_backupdir:-"-"}, mem_total: ${mem_total:-0}, mem_free: ${mem_free:-0}, max_queue: ${ban_maxqueue}"
-
-       f_ipset initial
+       f_log "debug" "f_main  ::: fetch_util: ${ban_fetchutil:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}, ssh_daemon: ${ban_sshdaemon}, interface(s): ${ban_iface:-"-"}, device(s): ${ban_dev:-"-"}, all_devices: ${ban_dev_all:-"-"}, backup_dir: ${ban_backupdir:-"-"}, mem_total: ${mem_total:-0}, mem_free: ${mem_free:-0}, max_queue: ${ban_maxqueue}"
 
        # main loop
        #
+       f_ipset initial
        for src_name in ${ban_sources}
        do
                unset src_on
@@ -607,28 +662,30 @@ f_main()
                                                "blacklist")
                                                        if [ "${ban_sshdaemon}" = "dropbear" ]
                                                        then
-                                                               pid_list="$(printf "%s\\n" "${log_content}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                               pid_list="$(printf "%s\\n" "${ssh_log}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                                for pid in ${pid_list}
                                                                do
-                                                                       src_addon="${src_addon} $(printf "%s\\n" "${log_content}" | grep -F "${pid}" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                                       src_addon="${src_addon} $(printf "%s\\n" "${ssh_log}" | grep -F "${pid}" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}$/){ORS=" ";print substr($0,RSTART,RLENGTH);exit}')"
                                                                done
                                                        elif [ "${ban_sshdaemon}" = "sshd" ]
                                                        then
-                                                               src_addon="$(printf "%s\\n" "${log_content}" | grep -E "[0-9]+ \[preauth\]$" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                               src_addon="$(printf "%s\\n" "${ssh_log}" | grep -E "[0-9]+ \[preauth\]$" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}$/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                        fi
+                                                       src_addon="${src_addon} $(printf "%s\\n" "${luci_log}" | awk 'match($0,/([0-9]{1,3}\.){3}[0-9]{1,3}$/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                ;;
                                                "blacklist_6")
                                                        if [ "${ban_sshdaemon}" = "dropbear" ]
                                                        then
-                                                               pid_list="$(printf "%s\\n" "${log_content}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                               pid_list="$(printf "%s\\n" "${ssh_log}" | grep -F "Exit before auth" | awk 'match($0,/(\[[0-9]+\])/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                                for pid in ${pid_list}
                                                                do
-                                                                       src_addon="${src_addon} $(printf "%s\\n" "${log_content}" | grep -F "${pid}" | awk 'match($0,/([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                                       src_addon="${src_addon} $(printf "%s\\n" "${ssh_log}" | grep -F "${pid}" | awk 'match($0,/(([0-9A-f]{0,4}::?){1,7}[0-9A-f]{0,4}$)/){ORS=" ";print substr($0,RSTART,RLENGTH);exit}')"
                                                                done
                                                        elif [ "${ban_sshdaemon}" = "sshd" ]
                                                        then
-                                                               src_addon="$(printf "%s\\n" "${log_content}" | grep -E "[0-9]+ \[preauth\]$" | awk 'match($0,/([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
+                                                               src_addon="$(printf "%s\\n" "${ssh_log}" | grep -E "[0-9]+ \[preauth\]$" | awk 'match($0,/(([0-9A-f]{0,4}::?){1,7}[0-9A-f]{0,4}$)/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                        fi
+                                                       src_addon="${src_addon} $(printf "%s\\n" "${luci_log}" | awk 'match($0,/(([0-9A-f]{0,4}::?){1,7}[0-9A-f]{0,4}$)/){ORS=" ";print substr($0,RSTART,RLENGTH)}')"
                                                ;;
                                        esac
                                        for ip in ${src_addon}
@@ -639,7 +696,8 @@ f_main()
                                                        if { [ "${src_name//_*/}" = "blacklist" ] && [ "${ban_autoblacklist}" -eq 1 ]; } || \
                                                                { [ "${src_name//_*/}" = "whitelist" ] && [ "${ban_autowhitelist}" -eq 1 ]; }
                                                        then
-                                                               printf "%s\\n" "${ip}" >> "${src_url}"
+                                                               src_ts="# auto-added $(date "+%d.%m.%Y %H:%M:%S")"
+                                                               printf "%s %s\\n" "${ip}" "${src_ts}" >> "${src_url}"
                                                        fi
                                                fi
                                        done
@@ -756,6 +814,7 @@ f_main()
                ban_cnt="$((ban_cnt+cnt))"
        done
        f_log "info" "${ban_setcnt} IPSets with overall ${ban_cnt} IPs/Prefixes loaded successfully (${ban_sysver})"
+       f_bgserv "start"
        f_jsnup
        f_rmtemp
 }
@@ -766,7 +825,7 @@ f_jsnup()
 {
        local rundate status="${1:-"enabled"}"
 
-       rundate="$(/bin/date "+%d.%m.%Y %H:%M:%S")"
+       rundate="$(date "+%d.%m.%Y %H:%M:%S")"
        ban_cntinfo="${ban_setcnt} IPSets with overall ${ban_cnt} IPs/Prefixes"
 
        > "${ban_rtfile}"
@@ -775,7 +834,7 @@ f_jsnup()
        json_add_object "data"
        json_add_string "status" "${status}"
        json_add_string "version" "${ban_ver}"
-       json_add_string "fetch_info" "${ban_fetchinfo:-"-"}"
+       json_add_string "util_info" "${ban_fetchutil:-"-"}, ${ban_realtime:-"-"}"
        json_add_string "ipset_info" "${ban_cntinfo:-"-"}"
        json_add_string "backup_dir" "${ban_backupdir}"
        json_add_string "last_run" "${rundate:-"-"}"
@@ -801,12 +860,14 @@ fi
 f_envload
 case "${ban_action}" in
        "stop")
+               f_bgserv "stop"
                f_jsnup stopped
                f_ipset destroy
                f_rmbackup
                f_rmtemp
        ;;
        "start"|"restart"|"reload"|"refresh")
+               f_bgserv "stop"
                f_envcheck
                f_main
        ;;