adblock: release 4.5.2‑1
authorDirk Brenken <redacted>
Sun, 1 Mar 2026 05:44:18 +0000 (06:44 +0100)
committerDirk Brenken <redacted>
Sun, 1 Mar 2026 05:53:25 +0000 (06:53 +0100)
* added a new firewall feature: the DNS‑Bridge.
  This temporary DNS bridge ensures that an external fallback DNS server
  is automatically used during local DNS restarts, providing Zero‑Downtime DNS resolution.
* The debug mode now captures internal error output in a dedicated log file,
  located by default in the adblock base directory as /tmp/adb_error.log.
* LuCI: exposed the previously missing adb_cores option (auto‑detected by default).
* LuCI: added support for the new DNS‑Bridge options (Zero‑Downtime during DNS restarts).

Signed-off-by: Dirk Brenken <redacted>
net/adblock/Makefile
net/adblock/files/README.md
net/adblock/files/adblock.sh

index 5af5ee245de084d2b6e198a5293db5b7b2d01476..fae2a953c96239c4af7ffa442727cc5ccd51ebe2 100644 (file)
@@ -6,8 +6,8 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=adblock
-PKG_VERSION:=4.5.1
-PKG_RELEASE:=4
+PKG_VERSION:=4.5.2
+PKG_RELEASE:=1
 PKG_LICENSE:=GPL-3.0-or-later
 PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>
 
index ce5629cf25ee1f9e084f0e296890901ccc4dc469..bdbf89ef8ad7bb29ad38bc3f0f3334f6de386b0e 100644 (file)
@@ -67,7 +67,9 @@ A lot of people already use adblocker plugins within their desktop browsers, but
 * Overall duplicate removal in generated blocklist file 'adb_list.overall'
 * Additional local allowlist for manual overrides, located in '/etc/adblock/adblock.allowlist' (only exact matches).
 * Additional local blocklist for manual overrides, located in '/etc/adblock/adblock.blocklist'
-* Implements Firewall‑Based DNS Control to force DNS interfaces/ports and to redirect to external unfiltered/filtered DNS server
+* Implements firewall‑based DNS Control to force DNS interfaces/ports and to redirect to external unfiltered/filtered DNS server
+* Includes firewall‑based Remote DNS Allow, a CGI-Interface to allow certain MACs temporary bypass the local adblock DNS
+* Supports firewall‑based temporary DNS Bridging, to ensure a Zero‑Downtime during adblock-related DNS Restarts
 * Connection checks during blocklist update to ensure a reliable DNS backend service
 * Minimal status & error logging to syslog, enable debug logging to receive more output
 * Procd based init system support ('start', 'stop', 'restart', 'reload', 'enable', 'disable', 'running', 'status', 'suspend', 'resume', 'query', 'report')
@@ -76,7 +78,6 @@ A lot of people already use adblocker plugins within their desktop browsers, but
 * Provides comprehensive runtime information
 * Provides a detailed DNS Query Report with DNS related information about client requests, top (blocked) domains and more
 * Provides a powerful query function to quickly find blocked (sub-)domains, e.g. to allow certain domains
-* Contains an option to route DNS queries to the local resolver via corresponding firewall rules
 * Implements a jail mode - only domains on the allowlist are permitted, all other DNS requests are rejected
 * Automatic blocklist backup & restore, these backups will be used in case of download errors and during startup
 * Send notification E-Mails, see example configuration below
@@ -141,6 +142,7 @@ Available commands:
 | adb_enabled          | 1, enabled                         | set to 0 to disable the adblock service                                                            |
 | adb_feedfile         | /etc/adblock/adblock.feeds         | full path to the used adblock feed file                                                            |
 | adb_dns              | -, auto-detected                   | 'dnsmasq', 'unbound', 'named', 'kresd', 'smartdns' or 'raw'                                        |
+| adb_cores            | -, auto-detected                   | limit the cpu cores used by adblock to save RAM                                                    |
 | adb_fetchcmd         | -, auto-detected                   | 'uclient-fetch', 'wget' or 'curl'                                                                  |
 | adb_fetchparm        | -, auto-detected                   | manually override the config options for the selected download utility                             |
 | adb_fetchinsecure    | 0, disabled                        | don't check SSL server certificates during download                                                |
@@ -179,18 +181,21 @@ Available commands:
 | adb_nftallow         | 0, disabled                        | routes MACs or interfaces to an unfiltered external DNS resolver, bypassing local adblock          |
 | adb_nftmacallow      | -, not set                         | listed MAC addresses will always use the configured unfiltered DNS server                          |
 | adb_nftdevallow      | -, not set                         | entire interfaces or VLANs will be routed to the unfiltered DNS server                             |
-| adb_allowdnsv4       | -, not set                         | IPv4 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy                   |
-| adb_allowdnsv6       | -, not set                         | IPv6 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy                   |
+| adb_allowdnsv4       | -, not set                         | external IPv4 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy          |
+| adb_allowdnsv6       | -, not set                         | external IPv6 DNS resolver applied to MACs and interfaces using the unfiltered DNS policy          |
 | adb_nftremote        | 0, disabled                        | routes MACs to an unfiltered external DNS resolver, bypassing local adblock                        |
 | adb_nftmacremote     | -, not set                         | Allows listed MACs to remotely access an unfiltered external DNS resolver, bypassing local adblock |
 | adb_nftremotetimeout | 15                                 | Time limit in minutes for remote DNS access of the listed MAC addresses                            |
-| adb_remotednsv4      | -, not set                         | IPv4 DNS resolver applied to MACs using the unfiltered remote DNS policy                           |
-| adb_remotednsv6      | -, not set                         | IPv6 DNS resolver applied to MACs using the unfiltered remote DNS policy                           |
+| adb_remotednsv4      | -, not set                         | external IPv4 DNS resolver applied to MACs using the unfiltered remote DNS policy                  |
+| adb_remotednsv6      | -, not set                         | external IPv6 DNS resolver applied to MACs using the unfiltered remote DNS policy                  |
 | adb_nftblock         | 0, disabled                        | routes MACs or interfaces to a filtered external DNS resolver, bypassing local adblock             |
 | adb_nftmacblock      | -, not set                         | listed MAC addresses will always use the configured filtered DNS server                            |
 | adb_nftdevblock      | -, not set                         | entire interfaces or VLANs will be routed to the filtered DNS server                               |
-| adb_blockdnsv4       | -, not set                         | IPv4 DNS resolver applied to MACs and interfaces using the filtered DNS policy                     |
-| adb_blockdnsv6       | -, not set                         | IPv6 DNS resolver applied to MACs and interfaces using the filtered DNS policy                     |
+| adb_blockdnsv4       | -, not set                         | external IPv4 DNS resolver applied to MACs and interfaces using the filtered DNS policy            |
+| adb_blockdnsv6       | -, not set                         | external IPv6 DNS resolver applied to MACs and interfaces using the filtered DNS policy            |
+| adb_nftbridge        | -, not set                         | enables a temporary DNS bridge to an external DNS resolver during local DNS restarts               |
+| adb_bridgednsv4           | -, not set                         | external IPv4 DNS resolver used during bridging                                                    |
+| adb_bridgednsv6           | -, not set                         | external IPv6 DNS resolver used during bridging                                                    |
 
 <a id="examples"></a>
 ## Examples
@@ -231,16 +236,16 @@ To get the status in the CLI, just call _/etc/init.d/adblock status_ or _/etc/in
 ~# /etc/init.d/adblock status
 ::: adblock runtime information
   + adblock_status  : enabled
-  + frontend_ver    : 4.5.0-r1
-  + backend_ver     : 4.5.0-r1
-  + blocked_domains : 582 457
-  + active_feeds    : 1hosts, adguard, adguard_tracking, bitcoin, certpl, doh_blocklist, hagezi, phishing_army, smarttv_tracking, stevenblack, winspy
-  + dns_backend     : unbound (1.24.2-r1), /mnt/data/adblock/backup, 234.93 MB
+  + frontend_ver    : 4.5.2-r1
+  + backend_ver     : 4.5.2-r1
+  + blocked_domains : 753 951
+  + active_feeds    : 1hosts, adguard, adguard_tracking, bitcoin, certpl, doh_blocklist, hagezi, ipfire_dbl, phishing_army, smarttv_tracking, stevenblack, winspy
+  + dns_backend     : unbound (1.24.2-r1), /mnt/data/adblock/backup, 297.66 MB
   + run_ifaces      : trigger: wan, report: br-lan
-  + run_directories : base: /mnt/data/adblock, dns: /var/lib/unbound, backup: /mnt/data/adblock/backup, report: /mnt/data/adblock/report
-  + run_flags       : shift: ✔, custom feed: ✘, ext. DNS (std/prot): ✘/✘, force: ✔, flush: ✘, tld: ✔, search: ✘, report: ✔, mail: ✔, jail: ✘
-  + last_run        : mode: restart, 2026-01-18T16:45:23+01:00, duration: 0m 19s, 1403.59 MB available
-  + system_info     : cores: 4, fetch: curl, Bananapi BPI-R3, mediatek/filogic, OpenWrt SNAPSHOT (r32670-66b6791abe)
+  + run_information : base: /mnt/data/adblock, dns: /var/lib/unbound, backup: /mnt/data/adblock/backup, report: /mnt/data/adblock/report, error: /mnt/data/adblock/adb_error.log
+  + run_flags       : shift: ✔, custom feed: ✘, ext. DNS (std/prot/remote/bridge): ✘/✔/✔/✔, force: ✔, flush: ✘, tld: ✔, search: ✘, report: ✔, mail: ✔, jail: ✘
+  + last_run        : mode: restart, 2026-03-01T06:20:27+01:00, duration: 0m 24s, 1342.71 MB available
+  + system_info     : cores: 4, fetch: curl, Bananapi BPI-R3, mediatek/filogic, OpenWrt SNAPSHOT (r33197-cf4cd07777)
 ```
 
 <a id="best-practise-and-tweaks"></a>
@@ -251,7 +256,7 @@ adblock uses RAM by design and avoids writing to flash. On devices with 128–25
 
 * use external storage: point 'adb_basedir', 'adb_backupdir' and 'adb_reportdir' to an USB drive or SSD
 * limit CPU processing to one core: set 'adb_cores' to '1' to reduce peak memory usage during feed processing
-* enable blocklist shifting: activate 'adb_dnsshift' to store the blocklist in the backup directory and expose it via a symlink in RAM.
+* enable blocklist shifting: activate 'adb_dnsshift' to store the blocklist in the backup directory on a USB stick and only create a symlink in RAM.
 * Firewall DNS redirection: use nftables based DNS routing to external filtered DNS serves and only use a minimal set of local blocklists
 
 **Sensible choice of blocklists**  
@@ -311,6 +316,10 @@ A lightweight CGI endpoint handles the workflow:
 
 The CGI interface is mobile‑friendly and includes a LuCI‑style loading spinner during the renew process, giving immediate visual feedback while the nftables entry is created. All operations are atomic and safe even when multiple devices renew access in parallel.  
 
+**Temporary DNS Bridging (Zero‑Downtime during DNS Restarts)**  
+Adblock can optionally enable a temporary DNS bridging mode to avoid DNS downtime during DNS backend restarts.
+When this feature is enabled, all DNS queries from LAN clients are briefly redirected to an external fallback resolver until the local DNS backend becomes available again. This ensures that DNS resolution continues to work seamlessly for all clients, even while adblock reloads blocklists or restarts the DNS service. Just set the options 'adb_nftbridging', 'adb_bridgednsv4' and 'adb_bridgednsv6' accordingly.   
+
 **Jail mode (allowlist-only):**  
 Enforces a strict allowlist‑only DNS policy in which only domains listed in the allowlist file are resolved, while every other query is rejected. This mode is intended for highly restrictive environments and depends on a carefully maintained allowlist, typically managed manually.  
 
@@ -378,6 +387,9 @@ The rule consist of max. 4 individual, space separated parameters:
 3. column: the domain column within the feed file, e.g. '2' (required)
 4. separator: an optional field separator, default is the character class '[[:space:]]'
 
+**Enable debug mode**  
+Adblock provides an optional debug mode that writes diagnostic information to the system log and captures internal error output in a dedicated error logfile - by default located in the adblock base directory as '/tmp/adb_error.log'. The log file is automatically cleared at the beginning of each run. Under normal conditions, all error messages are discarded to keep regular runs clean and silent. To enable debug mode, set the option 'adb_debug' to '1'. When enabled, the script produces significantly more log output to assist with troubleshooting.  
+
 ## Support
 Please join the adblock discussion in this [forum thread](https://forum.openwrt.org/t/adblock-support-thread/507) or contact me by mail <dev@brenken.org>
 
index 613474f4498e1048fb75419bdf87997328101c08..3f88f200d325a576a3b963e32d9571fb21e27580 100755 (executable)
@@ -25,12 +25,15 @@ adb_nftdevblock=""
 adb_nftremote="0"
 adb_nftremotetimeout="15"
 adb_nftmacremote=""
+adb_nftbridge="0"
 adb_allowdnsv4=""
 adb_allowdnsv6=""
 adb_remotednsv4=""
 adb_remotednsv6=""
 adb_blockdnsv4=""
 adb_blockdnsv6=""
+adb_bridgednsv4=""
+adb_bridgednsv6=""
 adb_dnsshift="0"
 adb_dnsflush="0"
 adb_dnstimeout="20"
@@ -57,6 +60,7 @@ adb_dnsfile="adb_list.overall"
 adb_feedfile="/etc/adblock/adblock.feeds"
 adb_customfeedfile="/etc/adblock/adblock.custom.feeds"
 adb_rtfile="/var/run/adb_runtime.json"
+adb_errorlog="/dev/null"
 adb_fetchcmd=""
 adb_fetchinsecure=""
 adb_fetchparm=""
@@ -99,23 +103,38 @@ f_cmd() {
 f_load() {
        local bg_pid port filter tcpdump_filter cpu core
 
-       adb_packages="$("${adb_ubuscmd}" -S call rpc-sys packagelist '{ "all": true }' 2>/dev/null)"
+       # load adblock config and set debug log file
+       #
+       f_conf
+       if [ "${adb_debug}" = "1" ]; then
+               adb_errorlog="${adb_basedir}/adb_error.log"
+               : > "${adb_errorlog}"
+       else
+               rm -f "${adb_errorlog}"
+       fi
+
+       # fetch installed packages amd system information
+       #
+       adb_packages="$("${adb_ubuscmd}" -S call rpc-sys packagelist '{ "all": true }' 2>>"${adb_errorlog}")"
        adb_bver="$(printf "%s" "${adb_packages}" | "${adb_jsoncmd}" -ql1 -e '@.packages.adblock')"
        adb_fver="$(printf "%s" "${adb_packages}" | "${adb_jsoncmd}" -ql1 -e '@.packages["luci-app-adblock"]')"
-       adb_sysver="$("${adb_ubuscmd}" -S call system board 2>/dev/null |
+       adb_sysver="$("${adb_ubuscmd}" -S call system board 2>>"${adb_errorlog}" |
                "${adb_jsoncmd}" -ql1 -e '@.model' -e '@.release.target' -e '@.release.distribution' -e '@.release.version' -e '@.release.revision' |
                "${adb_awkcmd}" 'BEGIN{RS="";FS="\n"}{printf "%s, %s, %s %s (%s)",$1,$2,$3,$4,$5}')"
-       f_conf
 
+       # detect cpu cores for parallel processing
+       #
        if [ -z "${adb_cores}" ]; then
-               cpu="$("${adb_grepcmd}" -c '^processor' /proc/cpuinfo 2>/dev/null)"
-               core="$("${adb_grepcmd}" -cm1 '^core id' /proc/cpuinfo 2>/dev/null)"
+               cpu="$("${adb_grepcmd}" -c '^processor' /proc/cpuinfo 2>>"${adb_errorlog}")"
+               core="$("${adb_grepcmd}" -cm1 '^core id' /proc/cpuinfo 2>>"${adb_errorlog}")"
                [ "${cpu}" = "0" ] && cpu="1"
                [ "${core}" = "0" ] && core="1"
                adb_cores="$((cpu * core))"
                [ "${adb_cores}" -gt "16" ] && adb_cores="16"
        fi
 
+       # check if adblock is enabled
+       #
        if [ "${adb_enabled}" = "0" ]; then
                f_extconf
                f_temp
@@ -126,17 +145,21 @@ f_load() {
                exit 0
        fi
 
+       # load dns backend and fetch utility
+       #
        if [ "${adb_action}" != "report" ] && [ "${adb_action}" != "mail" ]; then
                f_dns
                f_fetch
        fi
 
+       # check if reporting is enabled and tcpdump is available
+       #
        if [ "${adb_report}" = "1" ] && [ ! -x "${adb_dumpcmd}" ]; then
                f_log "info" "please install the package 'tcpdump' or 'tcpdump-mini' to use the reporting feature"
        elif [ -x "${adb_dumpcmd}" ]; then
                bg_pid="$("${adb_pgrepcmd}" -nf "${adb_reportdir}/adb_report.pcap")"
                if [ -n "${bg_pid}" ] && { [ "${adb_report}" = "0" ] || [ "${adb_action}" = "stop" ] || [ "${adb_action}" = "restart" ]; }; then
-                       if kill -HUP "${bg_pid}" 2>/dev/null; then
+                       if kill -HUP "${bg_pid}" 2>>"${adb_errorlog}"; then
                                for cnt in 1 2 3; do
                                        kill -0 "${bg_pid}" >/dev/null 2>&1 || break
                                        sleep 1
@@ -168,7 +191,7 @@ f_load() {
                                )
                                sleep 1
                                bg_pid="$("${adb_pgrepcmd}" -nf "${adb_reportdir}/adb_report.pcap")"
-                               f_log "info" "tcpdump backgound process started (interface: ${adb_repiface}, port: ${adb_repport}, dir: ${adb_reportdir}, pid: ${bg_pid})"
+                               f_log "info" "tcpdump backgound process started for interface: ${adb_repiface}, port: ${adb_repport}, dir: ${adb_reportdir}, pid: ${bg_pid}"
                        else
                                f_log "info" "please set the reporting interface 'adb_repiface' and reporting directory 'adb_reportdir' manually"
                        fi
@@ -184,6 +207,7 @@ f_env() {
        f_jsnup "processing"
        f_extconf
        f_temp
+       [ "${action}" = "restart" ] && f_nftremove
        f_nftadd
        json_init
        if [ -s "${adb_customfeedfile}" ]; then
@@ -318,7 +342,7 @@ f_char() {
 f_dns() {
        local dns dns_list dns_section dns_info free_mem dir
 
-       free_mem="$("${adb_awkcmd}" '/^MemAvailable/{printf "%s",int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
+       free_mem="$("${adb_awkcmd}" '/^MemAvailable/{printf "%s",int($2/1000)}' "/proc/meminfo" 2>>"${adb_errorlog}")"
        if [ "${adb_action}" = "boot" ] && [ -z "${adb_trigger}" ]; then
                sleep ${adb_triggerdelay:-"5"}
        fi
@@ -368,7 +392,7 @@ f_dns() {
                        adb_dnssafesearch="${adb_dnssafesearch:-"${adb_awkcmd} -v item=\"\$item\" '{print \"address=/\"\$0\"/\"item\"\";print \"local=/\"\$0\"/\"}'"}"
                        adb_dnsstop="${adb_dnsstop:-"address=/#/\nlocal=/#/"}"
                        if [ -z "${adb_dnsdir}" ]; then
-                               dns_section="$("${adb_ubuscmd}" -S call uci get "{\"config\":\"dhcp\", \"section\":\"@dnsmasq[${adb_dnsinstance}]\", \"type\":\"dnsmasq\"}" 2>/dev/null)"
+                               dns_section="$("${adb_ubuscmd}" -S call uci get "{\"config\":\"dhcp\", \"section\":\"@dnsmasq[${adb_dnsinstance}]\", \"type\":\"dnsmasq\"}" 2>>"${adb_errorlog}")"
                                dns_info="$(printf "%s" "${dns_section}" | "${adb_jsoncmd}" -l1 -e '@.values["confdir"]')"
                                if [ -n "${dns_info}" ]; then
                                        adb_dnsdir="${dns_info}"
@@ -526,6 +550,7 @@ f_temp() {
 # remove temporary files and directories
 #
 f_rmtemp() {
+       [ -f "${adb_errorlog}" ] && [ ! -s "${adb_errorlog}" ] && rm -f "${adb_errorlog}"
        rm -rf "${adb_tmpdir}"
        : >"${adb_pidfile}"
 }
@@ -564,17 +589,17 @@ f_count() {
 
        adb_cnt="0"
        if [ -s "${file}" ]; then
-               adb_cnt="$("${adb_wccmd}" -l 2>/dev/null <"${file}")"
+               adb_cnt="$("${adb_wccmd}" -l 2>>"${adb_errorlog}" <"${file}")"
                if [ -n "${var}" ]; then
                        printf "%s" "${adb_cnt}"
                else
                        if [ "${mode}" = "final" ]; then
                                if [ -s "${adb_tmpdir}/tmp.add.allowlist" ]; then
-                                       adb_cnt="$((adb_cnt - $("${adb_wccmd}" -l 2>/dev/null <"${adb_tmpdir}/tmp.add.allowlist")))"
+                                       adb_cnt="$((adb_cnt - $("${adb_wccmd}" -l 2>>"${adb_errorlog}" <"${adb_tmpdir}/tmp.add.allowlist")))"
                                fi
                                for file in "${adb_tmpdir}/tmp.safesearch".*; do
                                        if [ -r "${file}" ]; then
-                                               adb_cnt="$((adb_cnt - $("${adb_wccmd}" -l 2>/dev/null <"${file}")))"
+                                               adb_cnt="$((adb_cnt - $("${adb_wccmd}" -l 2>>"${adb_errorlog}" <"${file}")))"
                                        fi
                                done
                                [ -n "${adb_dnsheader}" ] && adb_cnt="$(((adb_cnt - $(printf "%b" "${adb_dnsheader}" | "${adb_grepcmd}" -c "^")) / 2))"
@@ -626,17 +651,38 @@ f_extconf() {
 # restart dns backend
 #
 f_dnsup() {
-       local restart_rc cnt="0" out_rc="4"
+       local restart_rc nft_rc cnt="0" out_rc="4"
 
        adb_dnspid=""
        if [ "${adb_dns}" = "raw" ] || [ -z "${adb_dns}" ]; then
                out_rc="0"
        else
+               # load external dns bridge
+               #
+               if { [ -n "${adb_bridgednsv4}" ] || [ -n "${adb_bridgednsv6}" ]; } && [ "${adb_nftbridge}" = "1" ]; then
+                       if "${adb_nftcmd}" list chain inet adblock dns-bridge >/dev/null 2>&1; then
+                               if [ -n "${adb_bridgednsv4}" ]; then
+                                       "${adb_nftcmd}" add rule inet adblock dns-bridge meta nfproto ipv4 meta l4proto { udp, tcp } th dport 53 counter dnat to ${adb_bridgednsv4}:53 2>>"${adb_errorlog}"
+                                       nft_rc="${?}"
+                               fi
+                               if [ -n "${adb_bridgednsv6}" ]; then
+                                       "${adb_nftcmd}" add rule inet adblock dns-bridge meta nfproto ipv6 meta l4proto { udp, tcp } th dport 53 counter dnat to [${adb_bridgednsv6}]:53 2>>"${adb_errorlog}"
+                                       nft_rc="$(( nft_rc + $? ))"
+                               fi
+                               if [ "${nft_rc}" = "0" ]; then
+                                       f_log "info" "external DNS bridge loaded: ${adb_bridgednsv4:-"-"} / ${adb_bridgednsv6:-"-"}"
+                               else
+                                       f_log "err" "failed to load external DNS bridge: ${adb_bridgednsv4:-"-"} / ${adb_bridgednsv6:-"-"}"
+                               fi
+                       fi
+               fi
+               # restart dns backend
+               #
                if [ "${adb_dnsflush}" = "0" ]; then
                        case "${adb_dns}" in
                                "unbound")
                                        if [ -x "${adb_dnscachecmd}" ] && [ -d "${adb_tmpdir}" ] && [ -f "${adb_dnsdir}/unbound.conf" ]; then
-                                               "${adb_dnscachecmd}" -c "${adb_dnsdir}/unbound.conf" dump_cache >"${adb_tmpdir}/adb_cache.dump" 2>/dev/null
+                                               "${adb_dnscachecmd}" -c "${adb_dnsdir}/unbound.conf" dump_cache >"${adb_tmpdir}/adb_cache.dump" 2>>"${adb_errorlog}"
                                        fi
                                        "/etc/init.d/${adb_dns}" restart >/dev/null 2>&1
                                        restart_rc="${?}"
@@ -662,6 +708,9 @@ f_dnsup() {
                        restart_rc="${?}"
                fi
        fi
+
+       # check if dns backend is responsive, restore dns cache for unbound and get dns backend pid
+       #
        if [ "${restart_rc}" = "0" ]; then
                while [ "${cnt}" -le "${adb_dnstimeout}" ]; do
                        if "${adb_lookupcmd}" "${adb_lookupdomain}." >/dev/null 2>&1; then
@@ -678,9 +727,21 @@ f_dnsup() {
                        fi
                fi
        fi
-       adb_dnspid="$("${adb_ubuscmd}" -S call service list 2>/dev/null | "${adb_jsoncmd}" -l1 -e "@[\"${adb_dns}\"].instances.*.pid")"
+       adb_dnspid="$("${adb_ubuscmd}" -S call service list 2>>"${adb_errorlog}" | "${adb_jsoncmd}" -l1 -e "@[\"${adb_dns}\"].instances.*.pid")"
 
-       f_log "debug" "f_dnsup  ::: dns: ${adb_dns}, cache_cmd: ${adb_dnscachecmd:-"-"}, lookup_domain: ${adb_lookupdomain:-"-"}, restart_rc: ${restart_rc:-"-"}, dns_flush: ${adb_dnsflush}, dns_timeout: ${adb_dnstimeout}, dns_pid: ${adb_dnspid}, dns_cnt: ${cnt}, rc: ${out_rc}"
+       # remove external dns bridge
+       #
+       if [ "${adb_nftbridge}" = "1" ] && "${adb_nftcmd}" list chain inet adblock dns-bridge >/dev/null 2>&1; then
+               "${adb_nftcmd}" flush chain inet adblock dns-bridge 2>>"${adb_errorlog}"
+               nft_rc="${?}"
+               if [ "${nft_rc}" = "0" ]; then
+                       f_log "info" "external DNS bridge removed"
+               else
+                       f_log "err" "failed to remove external DNS bridge"
+               fi
+       fi
+
+       f_log "debug" "f_dnsup  ::: dns: ${adb_dns}, cache_cmd: ${adb_dnscachecmd:-"-"}, lookup_domain: ${adb_lookupdomain:-"-"}, restart_rc: ${restart_rc:-"-"}, dns_flush: ${adb_dnsflush}, dns_timeout: ${adb_dnstimeout}, dns_pid: ${adb_dnspid}, dns_cnt: ${cnt}, nft_rc: ${nft_rc:-"-"}, rc: ${out_rc}"
        return "${out_rc}"
 }
 
@@ -721,7 +782,9 @@ f_nftadd() {
 
        # only proceed if at least one feature is enabled
        #
-       if [ "${adb_nftallow}" = "0" ] && [ "${adb_nftblock}" = "0" ] && [ "${adb_nftremote}" = "0" ] && [ "${adb_nftforce}" = "0" ]; then
+       if [ "${adb_nftallow}" = "0" ] && [ "${adb_nftblock}" = "0" ] \
+               && [ "${adb_nftremote}" = "0" ] && [ "${adb_nftforce}" = "0" ] \
+               && [ "${adb_nftbridging}" = "0" ]; then
                return
        fi
 
@@ -733,17 +796,20 @@ f_nftadd() {
                        printf "%s\n" "delete table inet adblock"
                fi
                printf "%s\n" "add table inet adblock"
+
                # allow Set
                #
                if [ "${adb_nftallow}" = "1" ] && [ -n "${adb_nftmacallow}" ]; then
                        printf "%s\n" "add set inet adblock mac_allow { type ether_addr; flags interval; auto-merge; elements = { ${adb_nftmacallow// /, } }; }"
                fi
+
                # remote allow Set with timeout, for MACs that should be temporary allowed to bypass dns blocking
                #
                if [ "${adb_nftremote}" = "1" ] && [ -n "${adb_nftmacremote}" ]; then
                        printf "%s\n" "add set inet adblock mac_remote { type ether_addr; flags timeout; timeout ${adb_nftremotetimeout}m; }"
                fi
-               # block Set
+
+               # adblock pre-routing chain for allow/block rules
                #
                if [ "${adb_nftblock}" = "1" ] && [ -n "${adb_nftmacblock}" ]; then
                        printf "%s\n" "add set inet adblock mac_block { type ether_addr; flags interval; auto-merge; elements = { ${adb_nftmacblock// /, } }; }"
@@ -751,6 +817,10 @@ f_nftadd() {
                printf "%s\n" "add chain inet adblock pre-routing { type nat hook prerouting priority -150; policy accept; }"
                printf "%s\n" "add chain inet adblock _reject"
 
+               # dns-bridge base chain
+               #
+               printf "%s\n" "add chain inet adblock dns-bridge { type nat hook prerouting priority -160; policy accept; }"
+
                # reject chain rules
                #
                printf "%s\n" "add rule inet adblock _reject meta l4proto tcp counter reject with tcp reset"
@@ -767,6 +837,7 @@ f_nftadd() {
                                [ -n "${adb_allowdnsv4}" ] && printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" meta nfproto ipv4 meta l4proto { udp, tcp } th dport 53 counter dnat to ${adb_allowdnsv4}:53"
                                [ -n "${adb_allowdnsv6}" ] && printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" meta nfproto ipv6 meta l4proto { udp, tcp } th dport 53 counter dnat to [${adb_allowdnsv6}]:53"
                        done
+                       f_log "info" "adblock-related nft allow rules prepared for external DNS ${adb_allowdnsv4:-"-"} / ${adb_allowdnsv6:-"-"}"
                fi
 
                # external remote allow rules
@@ -774,6 +845,7 @@ f_nftadd() {
                if [ "${adb_nftremote}" = "1" ]; then
                        [ -n "${adb_remotednsv4}" ] && printf "%s\n" "add rule inet adblock pre-routing meta nfproto ipv4 ether saddr @mac_remote meta l4proto { udp, tcp } th dport 53 counter dnat to ${adb_remotednsv4}:53"
                        [ -n "${adb_remotednsv6}" ] && printf "%s\n" "add rule inet adblock pre-routing meta nfproto ipv6 ether saddr @mac_remote meta l4proto { udp, tcp } th dport 53 counter dnat to [${adb_remotednsv6}]:53"
+                       f_log "info" "adblock-related nft remote allow rules prepared for external DNS ${adb_remotednsv4:-"-"} / ${adb_remotednsv6:-"-"} with timeout of ${adb_nftremotetimeout} minutes"
                fi
 
                # external block rules
@@ -787,22 +859,25 @@ f_nftadd() {
                                [ -n "${adb_blockdnsv4}" ] && printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" meta nfproto ipv4 meta l4proto { udp, tcp } th dport 53 counter dnat to ${adb_blockdnsv4}:53"
                                [ -n "${adb_blockdnsv6}" ] && printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" meta nfproto ipv6 meta l4proto { udp, tcp } th dport 53 counter dnat to [${adb_blockdnsv6}]:53"
                        done
+                       f_log "info" "adblock-related nft block rules prepared for external DNS ${adb_blockdnsv4:-"-"} / ${adb_blockdnsv6:-"-"}"
                fi
 
                # local dns enforcement
                #
                if [ "${adb_nftforce}" = "1" ]; then
+
                        # device/vlan exceptions
                        #
                        for device in ${adb_nftdevallow} ${adb_nftdevblock}; do
                                case " ${devices} " in
                                        *" ${device} "*)
                                                ;;
-                                       *)      devices="${devices} ${device}"
+                                       *)      [ -n "${devices}" ] && devices="${devices} ${device}" || devices="${device}"
                                                printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" return"
                                                ;;
                                esac
                        done
+
                        # mac exceptions
                        #
                        for device in ${adb_nftdevforce}; do
@@ -812,6 +887,7 @@ f_nftadd() {
                                if [ "${adb_nftblock}" = "1" ] && [ -n "${adb_nftmacblock}" ]; then
                                        printf "%s\n" "add rule inet adblock pre-routing iifname \"${device}\" ether saddr @mac_block return"
                                fi
+
                                # dns enforce rules
                                #
                                for port in ${adb_nftportforce}; do
@@ -822,12 +898,13 @@ f_nftadd() {
                                        fi
                                done
                        done
+                       f_log "info" "adblock-related nft local DNS enforcement rules prepared for devices: ${adb_nftdevforce// /, } and ports: ${adb_nftportforce// /, }"
                fi
        } >"${file}"
        if "${adb_nftcmd}" -f "${file}" >/dev/null 2>&1; then
-               f_log "info" "adblock-related nft rules added"
+               f_log "info" "adblock-related nft rules loaded"
        else
-               f_log "err" "failed to add adblock-related nft rules"
+               f_log "err" "failed to load adblock-related nft rules"
        fi
 }
 
@@ -873,7 +950,7 @@ f_list() {
                                                                "${adb_sortcmd}" ${adb_srtopts} -u >"${file_name}"
                                                        out_rc="${?}"
                                                else
-                                                       "${adb_sortcmd}" ${adb_srtopts} -u "${adb_tmpdir}/tmp.deduplicate.${src_name}" 2>/dev/null >"${file_name}"
+                                                       "${adb_sortcmd}" ${adb_srtopts} -u "${adb_tmpdir}/tmp.deduplicate.${src_name}" 2>>"${adb_errorlog}" >"${file_name}"
                                                        out_rc="${?}"
                                                fi
                                        fi
@@ -907,7 +984,7 @@ f_list() {
                                        if [ -s "${adb_backupdir}/safesearch.${src_name}.gz" ]; then
                                                "${adb_zcatcmd}" "${adb_backupdir}/safesearch.${src_name}.gz" >"${adb_tmpdir}/tmp.load.safesearch.${src_name}"
                                        else
-                                               "${adb_fetchcmd}" ${adb_fetchparm} "${adb_tmpdir}/tmp.load.safesearch.${src_name}" "${safe_url}" 2>/dev/null
+                                               "${adb_fetchcmd}" ${adb_fetchparm} "${adb_tmpdir}/tmp.load.safesearch.${src_name}" "${safe_url}" 2>>"${adb_errorlog}"
                                                if [ -s "${adb_tmpdir}/tmp.load.safesearch.${src_name}" ]; then
                                                        "${adb_gzipcmd}" -cf "${adb_tmpdir}/tmp.load.safesearch.${src_name}" >"${adb_backupdir}/safesearch.${src_name}.gz"
                                                fi
@@ -941,7 +1018,7 @@ f_list() {
                        esac
                        if [ -n "${safe_domains}" ] && [ -n "${safe_cname}" ]; then
                                if [ "${use_cname}" = "0" ]; then
-                                       safe_ips="$("${adb_lookupcmd}" "${safe_cname}" 2>/dev/null | "${adb_awkcmd}" '/^Address[ 0-9]*: /{ORS=" ";print $NF}')"
+                                       safe_ips="$("${adb_lookupcmd}" "${safe_cname}" 2>>"${adb_errorlog}" | "${adb_awkcmd}" '/^Address[ 0-9]*: /{ORS=" ";print $NF}')"
                                fi
                                if [ -n "${safe_ips}" ] || [ "${use_cname}" = "1" ]; then
                                        printf "%s\n" ${safe_domains} >"${adb_tmpdir}/tmp.raw.safesearch.${src_name}"
@@ -966,10 +1043,10 @@ f_list() {
                                if [ "${adb_tld}" = "1" ]; then
                                        f_chkdom ${src_rset} < "${src_tmpload}" |
                                                "${adb_awkcmd}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' |
-                                               "${adb_sortcmd}" ${adb_srtopts} -u >"${src_tmpfile}" 2>/dev/null
+                                               "${adb_sortcmd}" ${adb_srtopts} -u >"${src_tmpfile}" 2>>"${adb_errorlog}"
                                else
                                        f_chkdom ${src_rset} < "${src_tmpload}" |
-                                               "${adb_sortcmd}" ${adb_srtopts} -u >"${src_tmpfile}" 2>/dev/null
+                                               "${adb_sortcmd}" ${adb_srtopts} -u >"${src_tmpfile}" 2>>"${adb_errorlog}"
                                fi
                                out_rc="${?}"
                                if [ "${out_rc}" = "0" ] && [ -s "${src_tmpfile}" ]; then
@@ -1017,7 +1094,7 @@ f_list() {
                        fi
                        ;;
                "remove")
-                       rm "${adb_backupdir}/adb_list.${src_name}.gz" 2>/dev/null
+                       rm "${adb_backupdir}/adb_list.${src_name}.gz" 2>>"${adb_errorlog}"
                        out_rc="${?}"
                        adb_feed="${adb_feed/${src_name}/}"
                        ;;
@@ -1034,7 +1111,7 @@ f_list() {
                        if [ "${adb_safesearch}" = "1" ] && [ "${adb_dnssafesearch}" != "0" ]; then
                                files="${files} ! -name safesearch.google.gz"
                        fi
-                       "${adb_findcmd}" "${adb_backupdir}" ${files} -print0 2>/dev/null | xargs -0r rm -f 2>/dev/null
+                       "${adb_findcmd}" "${adb_backupdir}" ${files} -print0 2>>"${adb_errorlog}" | xargs -0r rm -f
 
                        # merge files
                        #
@@ -1043,10 +1120,10 @@ f_list() {
                                : > "${file_name}"
                                out_rc="4"
                        else
-                               "${adb_sortcmd}" ${adb_srtopts} -mu ${files} > "${file_name}"
+                               "${adb_sortcmd}" ${adb_srtopts} -mu ${files} 2>>"${adb_errorlog}" > "${file_name}"
                                out_rc="${?}"
                        fi
-                       rm -f "${adb_tmpfile}".* 2>/dev/null
+                       rm -f "${adb_tmpfile}".*
                        ;;
                "final")
                        src_name=""
@@ -1054,7 +1131,7 @@ f_list() {
                        rm -f "${file_name}"
                        [ -n "${adb_dnsheader}" ] && printf "%b" "${adb_dnsheader}" >>"${file_name}"
                        [ -s "${adb_tmpdir}/tmp.add.allowlist" ] && "${adb_sortcmd}" ${adb_srtopts} -u "${adb_tmpdir}/tmp.add.allowlist" >>"${file_name}"
-                       [ "${adb_safesearch}" = "1" ] && "${adb_catcmd}" "${adb_tmpdir}/tmp.safesearch."* 2>/dev/null >>"${file_name}"
+                       [ "${adb_safesearch}" = "1" ] && "${adb_catcmd}" "${adb_tmpdir}/tmp.safesearch."* 2>>"${adb_errorlog}" >>"${file_name}"
                        if [ "${adb_dnsdeny}" != "0" ]; then
                                eval "${adb_dnsdeny}" "${adb_tmpdir}/${adb_dnsfile}" >>"${file_name}"
                        else
@@ -1195,11 +1272,11 @@ f_query() {
                                suffix="${file##*.}"
                                if [ "${suffix}" = "gz" ]; then
                                        if [ "${adb_tld}" = "1" ]; then
-                                               "${adb_zcatcmd}" "${file}" 2>/dev/null |
+                                               "${adb_zcatcmd}" "${file}" 2>>"${adb_errorlog}" |
                                                        "${adb_awkcmd}" 'BEGIN{FS="."}{for(f=NF;f>1;f--)printf "%s.",$f;print $1}' |
                                                        "${adb_awkcmd}" -v f="${file##*/}" "BEGIN{rc=1};/^($search|.*\\.${search})$/{i++;if(i<=3){printf \"  + %-30s%s\n\",f,\$1;rc=0}else if(i==4){printf \"  + %-30s%s\n\",f,\"[...]\"}};END{exit rc}"
                                        else
-                                               "${adb_zcatcmd}" "${file}" 2>/dev/null |
+                                               "${adb_zcatcmd}" "${file}" 2>>"${adb_errorlog}" |
                                                        "${adb_awkcmd}" -v f="${file##*/}" "BEGIN{rc=1};/^($search|.*\\.${search})$/{i++;if(i<=3){printf \"  + %-30s%s\n\",f,\$1;rc=0}else if(i==4){printf \"  + %-30s%s\n\",f,\"[...]\"}};END{exit rc}"
                                        fi
                                        rc="${?}"
@@ -1225,12 +1302,12 @@ f_query() {
 #
 f_jsnup() {
        local pids object feeds end_time runtime dns dns_ver dns_mem free_mem custom_feed="0" status="${1:-"enabled"}"
-       local duration jail="0" nft_unfiltered="0" nft_filtered="0" nft_remote="0" nft_force="0"
+       local duration jail="0" nft_unfiltered="0" nft_filtered="0" nft_remote="0" nft_bridge="0" nft_force="0"
 
        if [ -n "${adb_dnspid}" ]; then
-               pids="$("${adb_pgrepcmd}" -P "${adb_dnspid}" 2>/dev/null)"
+               pids="$("${adb_pgrepcmd}" -P "${adb_dnspid}" 2>>"${adb_errorlog}")"
                for pid in ${adb_dnspid} ${pids}; do
-                       dns_mem="$((dns_mem + $("${adb_awkcmd}" '/^VmSize/{printf "%s", $2}' "/proc/${pid}/status" 2>/dev/null)))"
+                       dns_mem="$((dns_mem + $("${adb_awkcmd}" '/^VmSize/{printf "%s", $2}' "/proc/${pid}/status" 2>>"${adb_errorlog}")))"
                done
                case "${adb_dns}" in
                        "kresd")
@@ -1247,9 +1324,9 @@ f_jsnup() {
                                ;;
                esac
                dns_ver="$(printf "%s" "${adb_packages}" | "${adb_jsoncmd}" -ql1 -e "@.packages[\"${dns:-"${adb_dns}"}\"]")"
-               dns_mem="$("${adb_awkcmd}" -v mem="${dns_mem}" 'BEGIN{printf "%.2f", mem/1024}' 2>/dev/null)"
+               dns_mem="$("${adb_awkcmd}" -v mem="${dns_mem}" 'BEGIN{printf "%.2f", mem/1024}' 2>>"${adb_errorlog}")"
        fi
-       free_mem="$("${adb_awkcmd}" '/^MemAvailable/{printf "%.2f", $2/1024}' "/proc/meminfo" 2>/dev/null)"
+       free_mem="$("${adb_awkcmd}" '/^MemAvailable/{printf "%.2f", $2/1024}' "/proc/meminfo" 2>>"${adb_errorlog}")"
        adb_cnt="$("${adb_awkcmd}" -v cnt="${adb_cnt}" 'BEGIN{res="";pos=0;for(i=length(cnt);i>0;i--){res=substr(cnt,i,1)res;pos++;if(pos==3&&i>1){res=" "res;pos=0;}}; printf"%s",res}')"
        [ -s "${adb_customfeedfile}" ] && custom_feed="1"
        if [ "${adb_nftforce}" = "1" ] && [ -n "${adb_nftdevforce}" ] && [ -n "${adb_nftportforce}" ]; then
@@ -1269,6 +1346,10 @@ f_jsnup() {
                && { [ -n "${adb_remotednsv4}" ] || [ -n "${adb_remotednsv6}" ]; }; then
                nft_remote="1"
        fi
+       if [ "${adb_nftbridge}" = "1" ] \
+               && { [ -n "${adb_bridgednsv4}" ] || [ -n "${adb_bridgednsv6}" ]; }; then
+               nft_bridge="1"
+       fi
        case "${status}" in
                "enabled")
                        if [ -n "${adb_starttime}" ] && [ "${adb_action}" != "boot" ]; then
@@ -1317,8 +1398,8 @@ f_jsnup() {
        json_close_array
        json_add_string "dns_backend" "${adb_dns:-"-"} (${dns_ver:-"-"}), ${adb_finaldir:-"-"}, ${dns_mem:-"0"} MB"
        json_add_string "run_ifaces" "trigger: ${adb_trigger:-"-"}, report: ${adb_repiface:-"-"}"
-       json_add_string "run_directories" "base: ${adb_basedir}, dns: ${adb_dnsdir}, backup: ${adb_backupdir}, report: ${adb_reportdir}"
-       json_add_string "run_flags" "shift: $(f_char ${adb_dnsshift}), custom feed: $(f_char ${custom_feed}), ext. DNS (std/prot/remote): $(f_char ${nft_unfiltered})/$(f_char ${nft_filtered})/$(f_char ${nft_remote}), force: $(f_char ${nft_force}), flush: $(f_char ${adb_dnsflush}), tld: $(f_char ${adb_tld}), search: $(f_char ${adb_safesearch}), report: $(f_char ${adb_report}), mail: $(f_char ${adb_mail}), jail: $(f_char ${jail})"
+       json_add_string "run_information" "base: ${adb_basedir}, dns: ${adb_dnsdir}, backup: ${adb_backupdir}, report: ${adb_reportdir}, error: ${adb_errorlog}"
+       json_add_string "run_flags" "shift: $(f_char ${adb_dnsshift}), custom feed: $(f_char ${custom_feed}), ext. DNS (std/prot/remote/bridge): $(f_char ${nft_unfiltered})/$(f_char ${nft_filtered})/$(f_char ${nft_remote})/$(f_char ${nft_bridge}), force: $(f_char ${nft_force}), flush: $(f_char ${adb_dnsflush}), tld: $(f_char ${adb_tld}), search: $(f_char ${adb_safesearch}), report: $(f_char ${adb_report}), mail: $(f_char ${adb_mail}), jail: $(f_char ${jail})"
        json_add_string "last_run" "${runtime:-"-"}"
        json_add_string "system_info" "cores: ${adb_cores}, fetch: ${adb_fetchcmd##*/}, ${adb_sysver}"
        json_dump >"${adb_rtfile}"
@@ -1365,7 +1446,7 @@ f_main() {
        #
        if [ "${adb_jail}" = "1" ] && [ "${adb_dnsstop}" != "0" ]; then
                "${adb_mvcmd}" -f "${adb_tmpdir}/${adb_dnsfile}" "${adb_finaldir}/${adb_dnsfile}"
-               chown "${adb_dnsuser}" "${adb_finaldir}/${adb_dnsfile}" 2>/dev/null
+               chown "${adb_dnsuser}" "${adb_finaldir}/${adb_dnsfile}" 2>>"${adb_errorlog}"
                if [ "${adb_dnsshift}" = "1" ] && [ ! -L "${adb_dnsdir}/${adb_dnsfile}" ]; then
                        ln -fs "${adb_finaldir}/${adb_dnsfile}" "${adb_dnsdir}/${adb_dnsfile}"
                elif [ "${adb_dnsshift}" = "0" ] && [ -s "${adb_backupdir}/${adb_dnsfile}" ]; then
@@ -1452,6 +1533,7 @@ f_main() {
                                                continue
                                        fi
                                fi
+
                                # etag handling on reload
                                #
                                if [ -n "${adb_etagparm}" ] && [ "${adb_action}" = "reload" ]; then
@@ -1468,6 +1550,7 @@ f_main() {
                                                fi
                                        fi
                                fi
+
                                # normal download
                                #
                                for suffix in ${src_cat}; do
@@ -1483,6 +1566,7 @@ f_main() {
                else
                        (
                                [ "${src_name}" = "utcapitole" ] && src_cat="${adb_utc_feed}"
+
                                # restore handling on boot, resume or (re-)start
                                #
                                if [ "${adb_action}" = "boot" ] || [ "${adb_action}" = "start" ] || [ "${adb_action}" = "restart" ] || [ "${adb_action}" = "resume" ]; then
@@ -1490,6 +1574,7 @@ f_main() {
                                                continue
                                        fi
                                fi
+
                                # etag handling on reload
                                #
                                if [ -n "${adb_etagparm}" ] && [ "${adb_action}" = "reload" ]; then
@@ -1499,6 +1584,7 @@ f_main() {
                                                fi
                                        fi
                                fi
+
                                # normal download
                                #
                                if [ "${src_name}" = "utcapitole" ]; then
@@ -1507,12 +1593,12 @@ f_main() {
                                                src_rc="${?}"
                                                if [ "${src_rc}" = "0" ] && [ -s "${src_tmparchive}" ]; then
                                                        src_suffix="$(eval printf "%s" \"\$\{adb_src_suffix_${src_name}:-\"domains\"\}\")"
-                                                       src_list="$(tar -tzf "${src_tmparchive}" 2>/dev/null)"
+                                                       src_list="$(tar -tzf "${src_tmparchive}" 2>>"${adb_errorlog}")"
                                                        for src_item in ${src_cat}; do
                                                                src_entries="${src_entries} $(printf "%s" "${src_list}" | "${adb_grepcmd}" -E "${src_item}/${src_suffix}$")"
                                                        done
                                                        if [ -n "${src_entries}" ]; then
-                                                               tar -xOzf "${src_tmparchive}" ${src_entries} 2>/dev/null >"${src_tmpload}"
+                                                               tar -xOzf "${src_tmparchive}" ${src_entries} 2>>"${adb_errorlog}" >"${src_tmpload}"
                                                                src_rc="${?}"
                                                        fi
                                                        : >"${src_tmparchive}"
@@ -1539,7 +1625,7 @@ f_main() {
                printf "%b" "${adb_dnsheader}" >"${adb_finaldir}/${adb_dnsfile}"
                f_log "info" "no merge input, only header written to ${adb_finaldir}/${adb_dnsfile}"
        fi
-       chown "${adb_dnsuser}" "${adb_finaldir}/${adb_dnsfile}" 2>/dev/null
+       chown "${adb_dnsuser}" "${adb_finaldir}/${adb_dnsfile}" 2>>"${adb_errorlog}"
        if f_dnsup; then
                [ "${adb_action}" != "resume" ] && f_jsnup "enabled"
                f_log "info" "blocklist with overall ${adb_cnt} blocked domains loaded successfully (${adb_sysver})"
@@ -1572,7 +1658,7 @@ f_report() {
                [ "${adb_represolve}" = "1" ] && resolve=""
                for file in "${adb_reportdir}/adb_report.pcap"*; do
                        (
-                               "${adb_dumpcmd}" ${resolve} --immediate-mode -tttt -T domain -r "${file}" 2>/dev/null |
+                               "${adb_dumpcmd}" ${resolve} --immediate-mode -tttt -T domain -r "${file}" 2>>"${adb_errorlog}" |
                                "${adb_awkcmd}" -v repiface="${adb_repiface}" '
                                        BEGIN {
                                                pending = 0
@@ -1814,7 +1900,7 @@ f_report() {
                        fi
                        for ip in ${ip_v4} ${ip_v6}; do
                                (
-                                       "${adb_fetchcmd}" ${adb_geoparm} "${adb_geourl}/${ip}" 2>/dev/null |
+                                       "${adb_fetchcmd}" ${adb_geoparm} "${adb_geourl}/${ip}" 2>>"${adb_errorlog}" |
                                                "${adb_awkcmd}" -v feed="homeIP" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}"
                                ) &
                                [ "${cnt}" -gt "${adb_cores}" ] && wait -n
@@ -1832,7 +1918,7 @@ f_report() {
                                                json_get_var domain "domain" >/dev/null 2>&1
                                                if [ "${rc}" = "NX" ] && ! "${adb_grepcmd}" -q "\"${domain}\":" "${map_jsn}"; then
                                                        (
-                                                               "${adb_fetchcmd}" ${adb_geoparm} "${adb_geourl}/${domain}" 2>/dev/null |
+                                                               "${adb_fetchcmd}" ${adb_geoparm} "${adb_geourl}/${domain}" 2>>"${adb_errorlog}" |
                                                                        "${adb_awkcmd}" -v feed="${domain}" '{printf ",{\"%s\": %s}\n",feed,$0}' >>"${map_jsn}"
                                                        ) &
                                                        [ "${cnt}" -gt "${adb_cores}" ] && wait -n
@@ -1896,7 +1982,7 @@ f_report() {
                        fi
                        json_select ".."
                done
-               content="$("${adb_catcmd}" "${report_txt}" 2>/dev/null)"
+               content="$("${adb_catcmd}" "${report_txt}" 2>>"${adb_errorlog}")"
                rm -f "${report_txt}"
        fi
 
@@ -1908,10 +1994,10 @@ f_report() {
                        ;;
                "json")
                        if [ "${adb_map}" = "1" ] && [ -s "${map_jsn}" ]; then
-                               jsn="$("${adb_catcmd}" ${report_jsn} ${map_jsn} 2>/dev/null)"
+                               jsn="$("${adb_catcmd}" ${report_jsn} ${map_jsn} 2>>"${adb_errorlog}")"
                                [ -n "${jsn}" ] && printf "[%s]]\n" "${jsn}"
                        else
-                               jsn="$("${adb_catcmd}" ${report_jsn} 2>/dev/null)"
+                               jsn="$("${adb_catcmd}" ${report_jsn} 2>>"${adb_errorlog}")"
                                [ -n "${jsn}" ] && printf "[%s]\n" "${jsn}"
                        fi
                        ;;
@@ -1983,7 +2069,6 @@ case "${adb_action}" in
        "restart")
                f_temp
                f_jsnup "processing"
-               f_nftremove
                f_rmdns
                f_env
                f_main
git clone https://git.99rst.org/PROJECT