banip: release 0.8.3-1

* add the new init command 'lookup', to lookup the IPs of domain names in the local lists and update them
* significant acceleration of the domain lookup function
* multiple small fixes and improvements
* readme update
* luci update (separate commit)

Signed-off-by: Dirk Brenken <dev@brenken.org>
This commit is contained in:
Dirk Brenken 2023-04-06 19:37:28 +02:00
parent 04d5fa8dfc
commit c07fae25e7
No known key found for this signature in database
GPG key ID: 9D71CD547BFAE684
6 changed files with 96 additions and 67 deletions

View file

@ -7,8 +7,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=banip PKG_NAME:=banip
PKG_VERSION:=0.8.2 PKG_VERSION:=0.8.3
PKG_RELEASE:=6 PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0-or-later PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org> PKG_MAINTAINER:=Dirk Brenken <dev@brenken.org>

View file

@ -75,7 +75,7 @@ IP address blocking is commonly used to protect against brute force attacks, pre
* Provides a set search engine for certain IPs * Provides a set search engine for certain IPs
* Feed parsing by fast & flexible regex rulesets * Feed parsing by fast & flexible regex rulesets
* Minimal status & error logging to syslog, enable debug logging to receive more output * 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/survey) * Procd based init system support (start/stop/restart/reload/status/report/search/survey/lookup)
* Procd network interface trigger support * Procd network interface trigger support
* Ability to add new banIP feeds on your own * Ability to add new banIP feeds on your own
@ -114,6 +114,7 @@ Available commands:
report [text|json|mail] Print banIP related set statistics report [text|json|mail] Print banIP related set statistics
search [<IPv4 address>|<IPv6 address>] Check if an element exists in a banIP set search [<IPv4 address>|<IPv6 address>] Check if an element exists in a banIP set
survey [<set name>] List all elements of a given banIP set survey [<set name>] List all elements of a given banIP set
lookup Lookup the IPs of domain names in the local lists and update them
running Check if service is running running Check if service is running
status Service status status Service status
trace Start with syscall trace trace Start with syscall trace
@ -226,18 +227,16 @@ Available commands:
~# /etc/init.d/banip status ~# /etc/init.d/banip status
::: banIP runtime information ::: banIP runtime information
+ status : active (nft: ✔, monitor: ✔) + status : active (nft: ✔, monitor: ✔)
+ version : 0.8.2-2 + version : 0.8.3-1
+ element_count : 211397 + element_count : 281161
+ active_feeds : allowlistvMAC, allowlistv4, allowlistv6, adawayv4, adawayv6, adguardv4, adguardtrackersv4, adguardv6, adguardtrackersv + active_feeds : allowlistvMAC, allowlistv6, allowlistv4, adawayv4, adguardtrackersv4, adawayv6, adguardv6, adguardv4, adguardtrackersv6, antipopadsv6, antipopadsv4, cinsscorev4, deblv4, countryv6, countryv4, deblv6, dohv4, dohv6, iblockadsv4, firehol1v4, oisdbigv4, yoyov6, threatviewv4, yoyov4, oisdbigv6, blocklistvMAC, blocklistv4, blocklistv6
6, antipopadsv4, antipopadsv6, cinsscorev4, countryv6, countryv4, deblv4, deblv6, dohv4, dohv6, firehol1v4, oisdsmallv + active_devices : br-wan ::: wan, wan6
6, oisdsmallv4, stevenblackv6, stevenblackv4, webclientv4, blocklistvMAC, blocklistv4, blocklistv6 + active_subnets : 91.64.169.252/24, 2a02:710c:0:60:958b:3bd0:9e14:abb/128
+ active_devices : eth2 ::: wan, wan6
+ active_subnets : 91.64.148.211/24, 2b02:710c:0:80:e442:4b0c:637d:1d33/128
+ nft_info : priority: -200, policy: memory, loglevel: warn, expiry: - + nft_info : priority: -200, policy: memory, loglevel: warn, expiry: -
+ run_info : base: /mnt/data/banIP, backup: /mnt/data/banIP/backup, report: /mnt/data/banIP/report, feed: /etc/banip/banip.feeds + run_info : base: /mnt/data/banIP, backup: /mnt/data/banIP/backup, report: /mnt/data/banIP/report, feed: /etc/banip/banip.feeds
+ run_flags : auto: ✔, proto (4/6): ✔/✔, log (wan-inp/wan-fwd/lan-fwd): ✔/✔/✔, dedup: ✔, split: ✘, allowed only: ✘ + run_flags : auto: ✔, proto (4/6): ✔/✔, log (wan-inp/wan-fwd/lan-fwd): ✔/✔/✔, dedup: ✔, split: ✘, allowed only: ✘
+ last_run : action: restart, duration: 0m 55s, date: 2023-03-10 19:33:08 + last_run : action: reload, duration: 1m 0s, date: 2023-04-06 12:34:10
+ system_info : cores: 2, memory: 1830, device: Turris Omnia, OpenWrt SNAPSHOT r22248-bf055fcdca + system_info : cores: 4, memory: 1822, device: Bananapi BPI-R3, OpenWrt SNAPSHOT r22498-75f7e2d10b
``` ```
**banIP search information** **banIP search information**
@ -288,15 +287,22 @@ list ban_logterm 'SecurityEvent=\"InvalidAccountID\".*RemoteAddress='
**allow-/blocklist handling** **allow-/blocklist handling**
banIP supports local allow and block lists (IPv4, IPv6, CIDR notation or domain names), located in /etc/banip/banip.allowlist and /etc/banip/banip.blocklist. banIP supports local allow and block lists (IPv4, IPv6, CIDR notation or domain names), located in /etc/banip/banip.allowlist and /etc/banip/banip.blocklist.
Unsuccessful login attempts or suspicious requests will be tracked and added to the local blocklist (see the 'ban\_autoblocklist' option). The blocklist behaviour can be further tweaked with the 'ban\_nftexpiry' option. Unsuccessful login attempts or suspicious requests will be tracked and added to the local blocklist (see the 'ban\_autoblocklist' option). The blocklist behaviour can be further tweaked with the 'ban\_nftexpiry' option.
Furthermore the uplink subnet will be added to local allowlist (see 'ban\_autowallowlist' option). Furthermore the uplink subnet will be added to local allowlist (see 'ban\_autoallowlist' option).
Both lists also accept domain names as input to allow IP filtering based on these names. The corresponding IPs (IPv4 & IPv6) will be extracted in a detached background process and added to the sets. Both lists also accept domain names as input to allow IP filtering based on these names. The corresponding IPs (IPv4 & IPv6) will be extracted and added to the sets. You can also start the domain lookup separately via /etc/init.d/banip lookup at any time.
**allowlist-only mode** **allowlist-only mode**
banIP supports an "allowlist only" mode. This option restricts the internet access from/to a small number of secure websites/IPs, and block access from/to the rest of the internet. All IPs and Domains which are _not_ listed in the allowlist are blocked. banIP supports an "allowlist only" mode. This option restricts the internet access from/to a small number of secure websites/IPs, and block access from/to the rest of the internet. All IPs and Domains which are _not_ listed in the allowlist are blocked.
**redirect Asterisk security logs to lodg/logread** **redirect Asterisk security logs to lodg/logread**
banIP only supports logfile scanning via logread, so to monitor attacks on Asterisk, its security log must be available via logread. To do this, edit '/etc/asterisk/logger.conf' and add the line 'syslog.local0 = security', then run 'asterisk -rx reload logger' to update the running Asterisk configuration. banIP only supports logfile scanning via logread, so to monitor attacks on Asterisk, its security log must be available via logread. To do this, edit '/etc/asterisk/logger.conf' and add the line 'syslog.local0 = security', then run 'asterisk -rx reload logger' to update the running Asterisk configuration.
**send status E-Mails and update the banIP lists via cron job**
For a regular, automatic status mailing and update of the used lists on a daily basis set up a cron job, e.g.
```
55 03 * * * /etc/init.d/banip report mail
00 04 * * * /etc/init.d/banip reload
```
**tweaks for low memory systems** **tweaks for low memory systems**
nftables supports the atomic loading of rules/sets/members, which is cool but unfortunately is also very memory intensive. To reduce the memory pressure on low memory systems (i.e. those with 256-512Mb RAM), you should optimize your configuration with the following options: nftables supports the atomic loading of rules/sets/members, which is cool but unfortunately is also very memory intensive. To reduce the memory pressure on low memory systems (i.e. those with 256-512Mb RAM), you should optimize your configuration with the following options:

View file

@ -78,6 +78,7 @@ ban_debug="0"
f_system() { f_system() {
local cpu core local cpu core
[ -z "${ban_dev}" ] && ban_cores="$(uci_get banip global ban_cores)"
ban_memory="$("${ban_awkcmd}" '/^MemAvailable/{printf "%s",int($2/1000)}' "/proc/meminfo" 2>/dev/null)" ban_memory="$("${ban_awkcmd}" '/^MemAvailable/{printf "%s",int($2/1000)}' "/proc/meminfo" 2>/dev/null)"
ban_ver="$(${ban_ubuscmd} -S call rpc-sys packagelist '{ "all": true }' 2>/dev/null | jsonfilter -ql1 -e '@.packages.banip')" ban_ver="$(${ban_ubuscmd} -S call rpc-sys packagelist '{ "all": true }' 2>/dev/null | jsonfilter -ql1 -e '@.packages.banip')"
ban_sysver="$(${ban_ubuscmd} -S call system board 2>/dev/null | jsonfilter -ql1 -e '@.model' -e '@.release.description' | ban_sysver="$(${ban_ubuscmd} -S call system board 2>/dev/null | jsonfilter -ql1 -e '@.model' -e '@.release.description' |
@ -426,7 +427,7 @@ f_getsub() {
f_getelements() { f_getelements() {
local file="${1}" local file="${1}"
[ -s "${file}" ] && printf "%s" "elements={ $(cat "${file}") };" [ -s "${file}" ] && printf "%s" "elements={ $(cat "${file}" 2>/dev/null) };"
} }
# build initial nft file with base table, chains and rules # build initial nft file with base table, chains and rules
@ -975,8 +976,6 @@ f_getstatus() {
done done
json_select ".." json_select ".."
fi fi
value="$(printf "%s" "${value}" |
awk '{NR=1;max=118;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{printf"%-24s%s\n","",substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')"
printf " + %-17s : %s\n" "${key}" "${value:-"-"}" printf " + %-17s : %s\n" "${key}" "${value:-"-"}"
done done
else else
@ -987,7 +986,7 @@ f_getstatus() {
# domain lookup # domain lookup
# #
f_lookup() { f_lookup() {
local cnt list domain lookup ip start_time end_time duration cnt_domain="0" cnt_ip="0" feed="${1}" local cnt list domain lookup ip elementsv4 elementsv6 start_time end_time duration cnt_domain="0" cnt_ip="0" feed="${1}"
start_time="$(date "+%s")" start_time="$(date "+%s")"
if [ "${feed}" = "allowlist" ]; then if [ "${feed}" = "allowlist" ]; then
@ -1004,32 +1003,36 @@ f_lookup() {
else else
if { [ "${feed}" = "allowlist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_allowlist}"; } || if { [ "${feed}" = "allowlist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_allowlist}"; } ||
{ [ "${feed}" = "blocklist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_blocklist}"; }; then { [ "${feed}" = "blocklist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_blocklist}"; }; then
cnt_ip="$((cnt_ip + 1))"
if [ "${ip##*:}" = "${ip}" ]; then if [ "${ip##*:}" = "${ip}" ]; then
if ! "${ban_nftcmd}" add element inet banIP "${feed}v4" "{ ${ip} }" >/dev/null 2>&1; then elementsv4="${elementsv4} ${ip},"
f_log "info" "failed to add IP '${ip}' (${domain}) to ${feed}v4 set"
continue
fi
else else
if ! "${ban_nftcmd}" add element inet banIP "${feed}v6" "{ ${ip} }" >/dev/null 2>&1; then elementsv6="${elementsv6} ${ip},"
f_log "info" "failed to add IP '${ip}' (${domain}) to ${feed}v6 set"
continue
fi
fi fi
if [ "${feed}" = "allowlist" ] && [ "${ban_autoallowlist}" = "1" ]; then if [ "${feed}" = "allowlist" ] && [ "${ban_autoallowlist}" = "1" ]; then
printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_allowlist}" printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_allowlist}"
elif [ "${feed}" = "blocklist" ] && [ "${ban_autoblocklist}" = "1" ]; then elif [ "${feed}" = "blocklist" ] && [ "${ban_autoblocklist}" = "1" ]; then
printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_blocklist}" printf "%-42s%s\n" "${ip}" "# '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_blocklist}"
fi fi
cnt_ip="$((cnt_ip + 1))"
fi fi
fi fi
done done
cnt_domain="$((cnt_domain + 1))" cnt_domain="$((cnt_domain + 1))"
done done
if [ -n "${elementsv4}" ]; then
if ! "${ban_nftcmd}" add element inet banIP "${feed}v4" "{ ${elementsv4} }" >/dev/null 2>&1; then
f_log "info" "failed to add lookup file to ${feed}v4 set"
fi
fi
if [ -n "${elementsv6}" ]; then
if ! "${ban_nftcmd}" add element inet banIP "${feed}v6" "{ ${elementsv6} }" >/dev/null 2>&1; then
f_log "info" "failed to add lookup file to ${feed}v6 set"
fi
fi
end_time="$(date "+%s")" end_time="$(date "+%s")"
duration="$(((end_time - start_time) / 60))m $(((end_time - start_time) % 60))s" duration="$(((end_time - start_time) / 60))m $(((end_time - start_time) % 60))s"
f_log "debug" "f_lookup ::: name: ${feed}, cnt_domain: ${cnt_domain}, cnt_ip: ${cnt_ip}, duration: ${duration}" f_log "info" "Lookup summary for the local ${feed}: Domains processed: ${cnt_domain}, IPs added: ${cnt_ip}, Duration: ${duration}"
} }
# table statistics # table statistics
@ -1198,7 +1201,7 @@ f_report() {
# set search # set search
# #
f_search() { f_search() {
local table_sets ip proto run_search search="${1}" local set table_sets ip proto run_search hold cnt search="${1}"
if [ -n "${search}" ]; then if [ -n "${search}" ]; then
ip="$(printf "%s" "${search}" | "${ban_awkcmd}" 'BEGIN{RS="(([0-9]{1,3}\\.){3}[0-9]{1,3})+"}{printf "%s",RT}')" ip="$(printf "%s" "${search}" | "${ban_awkcmd}" 'BEGIN{RS="(([0-9]{1,3}\\.){3}[0-9]{1,3})+"}{printf "%s",RT}')"
@ -1215,14 +1218,15 @@ f_search() {
return return
fi fi
printf "%s\n%s\n%s\n" ":::" "::: banIP Search" ":::" printf "%s\n%s\n%s\n" ":::" "::: banIP Search" ":::"
printf "%s\n" " Looking for IP '${ip}' on $(date "+%Y-%m-%d %H:%M:%S")" printf " %s\n" "Looking for IP '${ip}' on $(date "+%Y-%m-%d %H:%M:%S")"
printf "%s\n" " ---" printf " %s\n" "---"
cnt="1" cnt="1"
run_search="/var/run/banIP.search" run_search="/var/run/banIP.search"
for set in ${table_sets}; do for set in ${table_sets}; do
[ -f "${run_search}" ] && break
( (
if "${ban_nftcmd}" get element inet banIP "${set}" "{ ${ip} }" >/dev/null 2>&1; then if "${ban_nftcmd}" get element inet banIP "${set}" "{ ${ip} }" >/dev/null 2>&1; then
printf "%s\n" " IP found in Set '${set}'" printf " %s\n" "IP found in Set '${set}'"
: >"${run_search}" : >"${run_search}"
fi fi
) & ) &
@ -1231,11 +1235,8 @@ f_search() {
cnt="$((cnt + 1))" cnt="$((cnt + 1))"
done done
wait wait
if [ ! -f "${run_search}" ]; then [ ! -f "${run_search}" ] && printf " %s\n" "IP not found"
printf "%s\n" " IP not found" rm -f "${run_search}"
else
rm -f "${run_search}"
fi
} }
# set survey # set survey
@ -1243,16 +1244,15 @@ f_search() {
f_survey() { f_survey() {
local set_elements set="${1}" local set_elements set="${1}"
[ -n "${set}" ] && set_elements="$("${ban_nftcmd}" -j list set inet banIP "${set}" 2>/dev/null | jsonfilter -qe '@.nftables[*].set.elem[*]')" if [ -z "${set}" ]; then
if [ -z "${set}" ] || [ -z "${set_elements}" ]; then
printf "%s\n%s\n%s\n" ":::" "::: no valid survey input" ":::" printf "%s\n%s\n%s\n" ":::" "::: no valid survey input" ":::"
return return
fi fi
[ -n "${set}" ] && set_elements="$("${ban_nftcmd}" -j list set inet banIP "${set}" 2>/dev/null | jsonfilter -qe '@.nftables[*].set.elem[*]')"
printf "%s\n%s\n%s\n" ":::" "::: banIP Survey" ":::" printf "%s\n%s\n%s\n" ":::" "::: banIP Survey" ":::"
printf "%s\n" " List the elements of Set '${set}' on $(date "+%Y-%m-%d %H:%M:%S")" printf " %s\n" "List the elements of Set '${set}' on $(date "+%Y-%m-%d %H:%M:%S")"
printf "%s\n" " ---" printf " %s\n" "---"
printf "%s\n" "${set_elements}" [ -n "${set_elements}" ] && printf "%s\n" "${set_elements}" || printf " %s\n" "empty set"
} }
# send status mails # send status mails

View file

@ -124,21 +124,25 @@ for feed in allowlist ${ban_feed} blocklist; do
fi fi
done done
wait wait
# start background domain lookup
#
f_log "info" "start detached banIP domain lookup"
(f_lookup "allowlist") &
hold="$((cnt % ban_cores))"
[ "${hold}" = "0" ] && wait
(f_lookup "blocklist") &
# end processing
#
f_rmset f_rmset
f_rmdir "${ban_tmpdir}" f_rmdir "${ban_tmpdir}"
f_genstatus "active" f_genstatus "active"
f_log "info" "finished banIP download processes" f_log "info" "finished banIP download processes"
# start domain lookup
#
f_log "info" "start banIP domain lookup"
cnt="1"
for list in allowlist blocklist; do
(f_lookup "${list}") &
hold="$((cnt % ban_cores))"
[ "${hold}" = "0" ] && wait
cnt="$((cnt + 1))"
done
wait
# end processing
#
if [ "${ban_mailnotification}" = "1" ] && [ -n "${ban_mailreceiver}" ] && [ -x "${ban_mailcmd}" ]; then if [ "${ban_mailnotification}" = "1" ] && [ -n "${ban_mailreceiver}" ] && [ -x "${ban_mailcmd}" ]; then
( (
sleep ${ban_triggerdelay} sleep ${ban_triggerdelay}

View file

@ -12,6 +12,7 @@ USE_PROCD=1
extra_command "report" "[text|json|mail] Print banIP related set statistics" extra_command "report" "[text|json|mail] Print banIP related set statistics"
extra_command "search" "[<IPv4 address>|<IPv6 address>] Check if an element exists in a banIP set" extra_command "search" "[<IPv4 address>|<IPv6 address>] Check if an element exists in a banIP set"
extra_command "survey" "[<set name>] List all elements of a given banIP set" extra_command "survey" "[<set name>] List all elements of a given banIP set"
extra_command "lookup" "Lookup the IPs of domain names in the local lists and update them"
ban_init="/etc/init.d/banip" ban_init="/etc/init.d/banip"
ban_service="/usr/bin/banip-service.sh" ban_service="/usr/bin/banip-service.sh"
@ -20,10 +21,10 @@ ban_pidfile="/var/run/banip.pid"
ban_lock="/var/run/banip.lock" ban_lock="/var/run/banip.lock"
[ "${action}" = "boot" ] && /etc/init.d/banip running && exit 0 [ "${action}" = "boot" ] && /etc/init.d/banip running && exit 0
[ "${action}" = "stop" ] && ! /etc/init.d/banip running && exit 0 { [ "${action}" = "stop" ] || [ "${action}" = "lookup" ]; } && ! /etc/init.d/banip running && exit 0
[ ! -r "${ban_funlib}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "stop" ] || [ "${action}" = "report" ] || [ "${action}" = "search" ] || [ "${action}" = "survey" ] || [ "${action}" = "status" ]; } && exit 1 [ ! -r "${ban_funlib}" ] && [ "${action}" != "boot" ] && exit 1
[ -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && exit 1 [ -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "lookup" ]; } && exit 1
[ ! -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && mkdir -p "${ban_lock}" [ ! -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "lookup" ]; } && mkdir -p "${ban_lock}"
boot() { boot() {
: >"${ban_pidfile}" : >"${ban_pidfile}"
@ -61,7 +62,7 @@ stop_service() {
"${ban_nftcmd}" delete table inet banIP >/dev/null 2>&1 "${ban_nftcmd}" delete table inet banIP >/dev/null 2>&1
f_genstatus "stopped" f_genstatus "stopped"
f_rmpid f_rmpid
rm -rf "${ban_lock}" [ "${action}" = "stop" ] && rm -rf "${ban_lock}"
} }
restart() { restart() {
@ -74,10 +75,8 @@ status() {
} }
status_service() { status_service() {
local actual="${1}"
[ -z "$(command -v "f_system")" ] && . "${ban_funlib}" [ -z "$(command -v "f_system")" ] && . "${ban_funlib}"
[ -n "${actual}" ] && f_actual || f_getstatus f_getstatus
} }
report() { report() {
@ -95,6 +94,20 @@ survey() {
f_survey "${1}" f_survey "${1}"
} }
lookup() {
local list hold cnt="1"
[ -z "$(command -v "f_system")" ] && . "${ban_funlib}"
for list in allowlist blocklist; do
(f_lookup "${list}") &
hold="$((cnt % ban_cores))"
[ "${hold}" = "0" ] && wait
cnt="$((cnt + 1))"
done
wait
rm -rf "${ban_lock}"
}
service_triggers() { service_triggers() {
local iface trigger trigger_action delay local iface trigger trigger_action delay

View file

@ -6,7 +6,7 @@
# #
local banip_info report_info log_info system_info mail_text local banip_info report_info log_info system_info mail_text
banip_info="$(/etc/init.d/banip status 2>/dev/null)" banip_info="$(/etc/init.d/banip status 2>/dev/null | awk '{NR=1;max=140;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{print substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')"
report_info="$(cat ${ban_reportdir}/ban_report.txt 2>/dev/null)" report_info="$(cat ${ban_reportdir}/ban_report.txt 2>/dev/null)"
log_info="$("${ban_logreadcmd}" -l 100 -e "banIP/" 2>/dev/null | awk '{NR=1;max=140;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{print substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')" log_info="$("${ban_logreadcmd}" -l 100 -e "banIP/" 2>/dev/null | awk '{NR=1;max=140;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{print substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')"
system_info="$( system_info="$(
@ -14,11 +14,17 @@ system_info="$(
ubus call system board | awk 'BEGIN{FS="[{}\"]"}{if($2=="kernel"||$2=="hostname"||$2=="system"||$2=="model"||$2=="description")printf " + %-12s: %s\n",$2,$4}' ubus call system board | awk 'BEGIN{FS="[{}\"]"}{if($2=="kernel"||$2=="hostname"||$2=="system"||$2=="model"||$2=="description")printf " + %-12s: %s\n",$2,$4}'
)" )"
# mail body # content header
# #
mail_text="$(printf "%s\n" "<html><body><pre style='display:block;font-family:monospace;font-size:1rem;padding:20;background-color:#f3eee5;white-space:pre'>")" mail_text="$(printf "%s\n" "<html><body><pre style='display:block;font-family:monospace;font-size:1rem;padding:20;background-color:#f3eee5;white-space:pre'>")"
# content body
#
mail_text="$(printf "%s\n" "${mail_text}\n<strong>++\n++ System Information ++\n++</strong>\n${system_info:-"-"}")" mail_text="$(printf "%s\n" "${mail_text}\n<strong>++\n++ System Information ++\n++</strong>\n${system_info:-"-"}")"
mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ banIP Status ++\n++</strong>\n${banip_info:-"-"}")" mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ banIP Status ++\n++</strong>\n${banip_info:-"-"}")"
mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ banIP Report ++\n++</strong>\n${report_info:-"-"}")" [ -n "${report_info}" ] && mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ banIP Report ++\n++</strong>\n${report_info}")"
mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ Logfile Information ++\n++</strong>\n${log_info}")" [ -n "${log_info}" ] && mail_text="$(printf "%s\n" "${mail_text}\n\n<strong>++\n++ Logfile Information ++\n++</strong>\n${log_info}")"
# content footer
#
mail_text="$(printf "%s\n" "${mail_text}</pre></body></html>")" mail_text="$(printf "%s\n" "${mail_text}</pre></body></html>")"