diff --git a/net/banip/Makefile b/net/banip/Makefile index 7da810862..a816ec858 100644 --- a/net/banip/Makefile +++ b/net/banip/Makefile @@ -1,13 +1,14 @@ # -# Copyright (c) 2018-2021 Dirk Brenken (dev@brenken.org) +# banIP - ban incoming and outgoing ip adresses/subnets via sets in nftables +# Copyright (c) 2018-2023 Dirk Brenken (dev@brenken.org) # This is free software, licensed under the GNU General Public License v3. # include $(TOPDIR)/rules.mk PKG_NAME:=banip -PKG_VERSION:=0.7.10 -PKG_RELEASE:=6 +PKG_VERSION:=0.8.0 +PKG_RELEASE:=1 PKG_LICENSE:=GPL-3.0-or-later PKG_MAINTAINER:=Dirk Brenken @@ -16,23 +17,22 @@ include $(INCLUDE_DIR)/package.mk define Package/banip SECTION:=net CATEGORY:=Network - TITLE:=Ban incoming and outgoing ip adresses via ipsets - DEPENDS:=+jshn +jsonfilter +ip +ipset +iptables +ca-bundle @BROKEN + TITLE:=banIP blocks IP addresses via named nftables sets + DEPENDS:=+jshn +jsonfilter +firewall4 +ca-bundle +logd +rpcd +rpcd-mod-rpcsys PKGARCH:=all endef define Package/banip/description -Powerful banIP script to block ip addresses via ipsets. -The script supports many ip blacklist sites plus manual black- and whitelist overrides. +banIP blocks IP addresses via named nftables sets. +banIP supports many IP blocklist feeds and provides a log service to block suspicious IPs in realtime. Please see https://github.com/openwrt/packages/blob/master/net/banip/files/README.md for further information. endef define Package/banip/conffiles /etc/config/banip -/etc/banip/banip.maclist -/etc/banip/banip.blacklist -/etc/banip/banip.whitelist +/etc/banip/banip.allowlist +/etc/banip/banip.blocklist endef define Build/Prepare @@ -46,27 +46,23 @@ endef define Package/banip/install $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) ./files/banip.sh $(1)/usr/bin + $(INSTALL_BIN) ./files/banip-service.sh $(1)/usr/bin $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/banip.init $(1)/etc/init.d/banip + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_CONF) ./files/banip-functions.sh $(1)/usr/lib + $(INSTALL_DIR) $(1)/etc/config $(INSTALL_CONF) ./files/banip.conf $(1)/etc/config/banip $(INSTALL_DIR) $(1)/etc/banip - $(INSTALL_BIN) ./files/banip.dns $(1)/etc/banip - $(INSTALL_BIN) ./files/banip.mail $(1)/etc/banip - $(INSTALL_BIN) ./files/banip.service $(1)/etc/banip - $(INSTALL_CONF) ./files/banip.maclist $(1)/etc/banip - $(INSTALL_CONF) ./files/banip.blacklist $(1)/etc/banip - $(INSTALL_CONF) ./files/banip.whitelist $(1)/etc/banip - $(INSTALL_CONF) ./files/banip.countries $(1)/etc/banip - $(INSTALL_CONF) ./files/banip.sources $(1)/etc/banip - gzip -9n $(1)/etc/banip/banip.sources - - $(INSTALL_DIR) $(1)/etc/hotplug.d/firewall - $(INSTALL_DATA) ./files/banip.hotplug $(1)/etc/hotplug.d/firewall/30-banip + $(INSTALL_CONF) ./files/banip.tpl $(1)/etc/banip + $(INSTALL_CONF) ./files/banip.allowlist $(1)/etc/banip + $(INSTALL_CONF) ./files/banip.blocklist $(1)/etc/banip + $(INSTALL_CONF) ./files/banip.feeds $(1)/etc/banip + gzip -9n $(1)/etc/banip/banip.feeds endef $(eval $(call BuildPackage,banip)) diff --git a/net/banip/files/README.md b/net/banip/files/README.md index 5f7a37c72..e0bf951f9 100644 --- a/net/banip/files/README.md +++ b/net/banip/files/README.md @@ -1,91 +1,103 @@ -# banIP - ban incoming and/or outgoing ip adresses via ipsets +# banIP - ban incoming and outgoing IP addresses/subnets via sets in nftables ## Description -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. +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. Further more banIP scans the log file via logread and bans IP addresses that make too many password failures, e.g. via ssh. ## Main Features -* Support of the following fully pre-configured domain blocklist sources (free for private usage, for commercial use please check their individual licenses) +* banIP supports the following fully pre-configured domain blocklist feeds (free for private usage, for commercial use please check their individual licenses). + **Please note:** the columns "INP" and "FWD" show for which chains the feeds are suitable in common scenarios, e.g. the first entry should be limited to forward chain - see the config options 'ban\_blockforward' and 'ban\_blockinput' below. -| Source | Focus | Information | -| :------------------ | :----------------------------: | :-------------------------------------------------------------------------------- | -| asn | ASN block | [Link](https://asn.ipinfo.app) | -| bogon | Bogon prefixes | [Link](https://team-cymru.com) | -| country | Country blocks | [Link](https://www.ipdeny.com/ipblocks) | -| darklist | blocks suspicious attacker IPs | [Link](https://darklist.de) | -| debl | Fail2ban IP blacklist | [Link](https://www.blocklist.de) | -| doh | Public DoH-Provider | [Link](https://github.com/dibdot/DoH-IP-blocklists) | -| drop | Spamhaus drop compilation | [Link](https://www.spamhaus.org) | -| dshield | Dshield IP blocklist | [Link](https://www.dshield.org) | -| edrop | Spamhaus edrop compilation | [Link](https://www.spamhaus.org) | -| feodo | Feodo Tracker | [Link](https://feodotracker.abuse.ch) | -| firehol1 | Firehol Level 1 compilation | [Link](https://iplists.firehol.org/?ipset=firehol_level1) | -| firehol2 | Firehol Level 2 compilation | [Link](https://iplists.firehol.org/?ipset=firehol_level2) | -| firehol3 | Firehol Level 3 compilation | [Link](https://iplists.firehol.org/?ipset=firehol_level3) | -| firehol4 | Firehol Level 4 compilation | [Link](https://iplists.firehol.org/?ipset=firehol_level4) | -| greensnow | blocks suspicious server IPs | [Link](https://greensnow.co) | -| iblockads | Advertising blocklist | [Link](https://www.iblocklist.com) | -| iblockspy | Malicious spyware blocklist | [Link](https://www.iblocklist.com) | -| myip | Myip Live IP blacklist | [Link](https://myip.ms) | -| nixspam | iX spam protection | [Link](http://www.nixspam.org) | -| proxy | Firehol list of open proxies | [Link](https://iplists.firehol.org/?ipset=proxylists) | -| ssbl | SSL botnet IP blacklist | [Link](https://sslbl.abuse.ch) | -| talos | Cisco Talos IP Blacklist | [Link](https://talosintelligence.com/reputation_center) | -| threat | Emerging Threats | [Link](https://rules.emergingthreats.net) | -| tor | Tor exit nodes | [Link](https://fissionrelays.net/lists) | -| uceprotect1 | Spam protection level 1 | [Link](http://www.uceprotect.net/en/index.php) | -| uceprotect2 | Spam protection level 2 | [Link](http://www.uceprotect.net/en/index.php) | -| voip | VoIP fraud blocklist | [Link](http://www.voipbl.org) | -| yoyo | Ad protection blacklist | [Link](https://pgl.yoyo.org/adservers/) | +| Feed | Focus | INP | FWD | Information | +| :------------------ | :----------------------------: | :-: | :-: | :-------------------------------------------------------------------- | +| adaway | adaway IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| adguard | adguard IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| adguardtrackers | adguardtracker IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| antipopads | antipopads IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| asn | ASN IPs | | x | [Link](https://asn.ipinfo.app) | +| backscatterer | backscatterer IPs | x | x | [Link](https://www.uceprotect.net/en/index.php) | +| bogon | bogon prefixes | x | x | [Link](https://team-cymru.com) | +| country | country blocks | x | | [Link](https://www.ipdeny.com/ipblocks) | +| cinsscore | suspicious attacker IPs | x | x | [Link](https://cinsscore.com/#list) | +| darklist | blocks suspicious attacker IPs | x | x | [Link](https://darklist.de) | +| debl | fail2ban IP blacklist | x | x | [Link](https://www.blocklist.de) | +| doh | public DoH-Provider | | x | [Link](https://github.com/dibdot/DoH-IP-blocklists) | +| drop | spamhaus drop compilation | x | x | [Link](https://www.spamhaus.org) | +| dshield | dshield IP blocklist | x | x | [Link](https://www.dshield.org) | +| edrop | spamhaus edrop compilation | x | x | [Link](https://www.spamhaus.org) | +| feodo | feodo tracker | x | x | [Link](https://feodotracker.abuse.ch) | +| firehol1 | firehol level 1 compilation | x | x | [Link](https://iplists.firehol.org/?ipset=firehol_level1) | +| firehol2 | firehol level 2 compilation | x | x | [Link](https://iplists.firehol.org/?ipset=firehol_level2) | +| firehol3 | firehol level 3 compilation | x | x | [Link](https://iplists.firehol.org/?ipset=firehol_level3) | +| firehol4 | firehol level 4 compilation | x | x | [Link](https://iplists.firehol.org/?ipset=firehol_level4) | +| greensnow | suspicious server IPs | x | x | [Link](https://greensnow.co) | +| iblockads | Advertising IPs | | x | [Link](https://www.iblocklist.com) | +| iblockspy | Malicious spyware IPs | x | x | [Link](https://www.iblocklist.com) | +| myip | real-time IP blocklist | x | x | [Link](https://myip.ms) | +| nixspam | iX spam protection | x | x | [Link](http://www.nixspam.org) | +| oisdnsfw | OISD-nsfw IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| oisdsmall | OISD-small IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| proxy | open proxies | x | | [Link](https://iplists.firehol.org/?ipset=proxylists) | +| ssbl | SSL botnet IPs | x | x | [Link](https://sslbl.abuse.ch) | +| stevenblack | stevenblack IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | +| talos | talos IPs | x | x | [Link](https://talosintelligence.com/reputation_center) | +| threat | emerging threats | x | x | [Link](https://rules.emergingthreats.net) | +| threatview | malicious IPs | x | x | [Link](https://threatview.io) | +| tor | tor exit nodes | x | | [Link](https://github.com/SecOps-Institute/Tor-IP-Addresses) | +| uceprotect1 | spam protection level 1 | x | x | [Link](http://www.uceprotect.net/en/index.php) | +| uceprotect2 | spam protection level 2 | x | x | [Link](http://www.uceprotect.net/en/index.php) | +| uceprotect3 | spam protection level 3 | x | x | [Link](http://www.uceprotect.net/en/index.php) | +| urlhaus | urlhaus IDS IPs | x | x | [Link](https://urlhaus.abuse.ch) | +| urlvir | malware related IPs | x | x | [Link](https://iplists.firehol.org/?ipset=urlvir) | +| webclient | malware related IPs | x | x | [Link](https://iplists.firehol.org/?ipset=firehol_webclient) | +| voip | VoIP fraud blocklist | x | x | [Link](https://voipbl.org) | +| yoyo | yoyo IPs | | x | [Link](https://github.com/dibdot/banIP-IP-blocklists) | * zero-conf like automatic installation & setup, usually no manual changes needed -* automatically selects one of the following supported download utilities: aria2c, curl, uclient-fetch, wget -* fast downloads & list processing as they are handled in parallel as background jobs in a configurable 'Download Queue' +* all sets are handled in a separate nft table/namespace 'banIP' * 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 black- & whitelist (IPv4, IPv6, CIDR notation or domain names) -* auto-add unsuccessful LuCI, nginx or ssh login attempts via 'dropbear'/'sshd' to local blacklist -* auto-add the uplink subnet to local whitelist -* black- and whitelist also accept domain names as input to allow IP filtering based on these names -* supports a 'whitelist only' mode, this option allows to restrict Internet access from/to a small number of secure websites/IPs +* supports nft atomic set loading +* supports blocking by ASN numbers and by iso country codes +* supports local allow- and blocklist (IPv4, IPv6, CIDR notation or domain names) +* auto-add the uplink subnet to the local allowlist * provides a small background log monitor to ban unsuccessful login attempts in real-time -* per source configuration of SRC (incoming) and DST (outgoing) -* integrated IPSet-Lookup -* integrated bgpview-Lookup -* blocklist source parsing by fast & flexible regex rulesets -* minimal status & error logging to syslog, enable debug logging to receive more output -* procd based init system support (start/stop/restart/reload/refresh/status) -* procd network interface trigger support -* automatic blocklist backup & restore, they will be used in case of download errors or during startup +* auto-add unsuccessful LuCI, nginx, Asterisk or ssh login attempts to the local blocklist +* fast feed processing as they are handled in parallel as background jobs +* per feed it can be defined whether the input chain or the forward chain should be blocked (default: both chains) +* automatic blocklist backup & restore, the backups will be used in case of download errors or during startup +* automatically selects one of the following download utilities with ssl support: aria2c, curl, uclient-fetch or wget +* supports a 'allowlist only' mode, this option restricts internet access from/to a small number of secure websites/IPs * provides comprehensive runtime information -* provides a detailed IPSet Report -* provides a powerful query function to quickly find blocked IPs/CIDR in banIP related IPSets -* provides an easily configurable blocklist update scheduler called 'Refresh Timer' -* strong LuCI support -* optional: add new banIP sources on your own +* provides a detailed set report +* provides a set search engine for certain IPs +* feed parsing by fast & flexible regex rulesets +* minimal status & error logging to syslog, enable debug logging to receive more output +* procd based init system support (start/stop/restart/reload/status/report/search) +* procd network interface trigger support +* ability to add new banIP feeds on your own ## Prerequisites -* [OpenWrt](https://openwrt.org), tested with the stable release series (21.02.x) and with the latest rolling snapshot releases. On turris devices it has been successfully tested with TurrisOS 5.2.x - Please note: Ancient OpenWrt releases like 18.06.x or 17.01.x are _not_ supported! - Please note: Devices with less than 128 MByte RAM are _not_ supported! - Please note: If you're updating from former banIP 0.3x please manually remove your config (/etc/config/banip) before you start! -* A download utility with SSL support: 'wget', 'uclient-fetch' with one of the 'libustream-*' ssl libraries, 'aria2c' or 'curl' is required -* A certificate store like 'ca-bundle', as banIP checks the validity of the SSL certificates of all download sites by default -* Optional E-Mail notification support: for E-Mail notifications you need to install and setup the additional 'msmtp' package +* **[OpenWrt](https://openwrt.org)**, latest stable release or a snapshot with nft/firewall 4 support +* a download utility with SSL support: 'wget', 'uclient-fetch' with one of the 'libustream-*' SSL libraries, 'aria2c' or 'curl' is required +* a certificate store like 'ca-bundle', as banIP checks the validity of the SSL certificates of all download sites by default +* for E-Mail notifications you need to install and setup the additional 'msmtp' package + +**Please note the following:** +* Devices with less than 256Mb of RAM are **_not_** supported +* Any previous installation of banIP must be uninstalled, and the /etc/banip folder and the /etc/config/banip configuration file must be deleted (they are recreated when this version is installed) +* There is no LuCI frontend at this time ## Installation & Usage -* Update your local opkg repository (_opkg update_) -* Install 'banip' (_opkg install banip_). The banIP service is disabled by default -* Install the LuCI companion package 'luci-app-banip' (_opkg install luci-app-banip_) -* It's strongly recommended to use the LuCI frontend to easily configure all aspects of banIP, the application is located in LuCI under the 'Services' menu +* update your local opkg repository (_opkg update_) +* install banIP (_opkg install banip_) - the banIP service is disabled by default +* edit the config file '/etc/config/banip' and enable the service (set ban\_enabled to '1'), then add pre-configured feeds via 'ban\_feed' (see the config options below) +* start the service with '/etc/init.d/banip start' and check check everything is working by running '/etc/init.d/banip status' -## banIP CLI -* All important banIP functions are accessible via CLI as well. -

-~# /etc/init.d/banip 
+## banIP CLI interface
+* All important banIP functions are accessible via CLI. A LuCI frontend will be available in due course.
+```
+~# /etc/init.d/banip
 Syntax: /etc/init.d/banip [command]
 
 Available commands:
@@ -96,259 +108,151 @@ Available commands:
 	enable          Enable service autostart
 	disable         Disable service autostart
 	enabled         Check if service is started on boot
-	refresh         Refresh ipsets without new list downloads
-	suspend         Suspend banIP processing
-	resume          Resume banIP processing
-	query           <IP> Query active banIP IPSets for a specific IP address
-	report          [<cli>|<mail>|<gen>|<json>] Print banIP related IPset statistics
-	list            [<add>|<add_asn>|<add_country>|<remove>|<remove_asn>|<remove_country>] <source(s)> List/Edit available sources
-	timer           [<add> <tasks> <hour> [<minute>] [<weekday>]]|[<remove> <line no.>] List/Edit cron update intervals
-	version         Print version information
+	report          [text|json|mail] Print banIP related set statistics
+	search          [|] Check if an element exists in the banIP sets
 	running         Check if service is running
 	status          Service status
 	trace           Start with syscall trace
-
+ info Dump procd service info +``` ## banIP config options -* Usually the auto pre-configured banIP setup works quite well and no manual overrides are needed | Option | Type | Default | Description | | :---------------------- | :----- | :---------------------------- | :------------------------------------------------------------------------------------ | | ban_enabled | option | 0 | enable the banIP service | +| ban_nicelimit | option | 0 | ulimit nice level of the banIP service (range 0-19) | +| ban_filelimit | option | 1024 | ulimit max open/number of files (range 1024-4096) | +| ban_loglimit | option | 100 | the logread monitor scans only the last n lines of the logfile | +| ban_logcount | option | 1 | how many times the IP must appear in the log to be considered as suspicious | +| ban_logterm | list | regex | various regex for logfile parsing (default: dropbear, sshd, luci, nginx, asterisk) | | ban_autodetect | option | 1 | auto-detect wan interfaces, devices and subnets | | ban_debug | option | 0 | enable banIP related debug logging | -| ban_mail_enabled | option | 0 | enable the mail service | -| ban_monitor_enabled | option | 0 | enable the log monitor, e.g. to catch failed ssh/luci logins | -| ban_logsrc_enabled | option | 0 | enable the src-related logchain | -| ban_logdst_enabled | option | 0 | enable the dst-related logchain | -| ban_autoblacklist | option | 1 | add suspicious IPs automatically to the local blacklist | -| ban_autowhitelist | option | 1 | add wan IPs/subnets automatically to the local whitelist | -| ban_whitelistonly | option | 0 | allow to restrict Internet access from/to a small number of secure websites/IPs | -| ban_maxqueue | option | 4 | size of the download queue to handle downloads and processing in parallel | -| ban_reportdir | option | /tmp/banIP-Report | directory where banIP stores the report files | -| ban_backupdir | option | /tmp/banIP-Backup | directory where banIP stores the compressed backup files | -| ban_ifaces | list | - | list option to add logical wan interfaces manually | -| ban_sources | list | - | list option to add banIP sources | -| ban_countries | list | - | list option to add certain countries as an alpha-2 ISO code, e.g. 'de' for germany | -| ban_asns | list | - | list option to add certain ASNs (autonomous system number), e.g. '32934' for facebook | -| ban_chain | option | banIP | name of the root chain used by banIP | -| ban_global_settype | option | src+dst | global settype as default for all sources | -| ban_settype_src | list | - | special SRC settype for a certain sources | -| ban_settype_dst | list | - | special DST settype for a certain sources | -| ban_settype_all | list | - | special SRC+DST settype for a certain sources | -| ban_target_src | option | DROP | default src action (used by log chains as well) | -| ban_target_dst | option | REJECT | default dst action (used by log chains as well) | -| ban_lan_inputchains_4 | list | input_lan_rule | list option to add IPv4 lan input chains | -| ban_lan_inputchains_6 | list | input_lan_rule | list option to add IPv6 lan input chains | -| ban_lan_forwardchains_4 | list | forwarding_lan_rule | list option to add IPv4 lan forward chains | -| ban_lan_forwardchains_6 | list | forwarding_lan_rule | list option to add IPv6 lan forward chains | -| ban_wan_inputchains_4 | list | input_wan_rule | list option to add IPv4 wan input chains | -| ban_wan_inputchains_6 | list | input_wan_rule | list option to add IPv6 wan input chains | -| ban_wan_forwardchains_4 | list | forwarding_wan_rule | list option to add IPv4 wan forward chains | -| ban_wan_forwardchains_6 | list | forwarding_wan_rule | list option to add IPv6 wan forward chains | -| ban_fetchutil | option | -, auto-detected | 'uclient-fetch', 'wget', 'curl' or 'aria2c' | -| ban_fetchparm | option | -, auto-detected | manually override the config options for the selected download utility | -| ban_fetchinsecure | option | 0, disabled | don't check SSL server certificates during download | +| ban_loginput | option | 1 | log drops in the input chain | +| ban_logforward | option | 0 | log rejects in the forward chain | +| ban_autoallowlist | option | 1 | add wan IPs/subnets automatically to the local allowlist | +| ban_autoblocklist | option | 1 | add suspicious attacker IPs automatically to the local blocklist | +| ban_allowlistonly | option | 0 | restrict the internet access from/to a small number of secure websites/IPs | +| ban_reportdir | option | /tmp/banIP-report | directory where banIP stores the report files | +| ban_backupdir | option | /tmp/banIP-backup | directory where banIP stores the compressed backup files | +| ban_protov4 | option | - / autodetect | enable IPv4 support | +| ban_protov6 | option | - / autodetect | enable IPv4 support | +| ban_ifv4 | list | - / autodetect | logical wan IPv4 interfaces, e.g. 'wan' | +| ban_ifv6 | list | - / autodetect | logical wan IPv6 interfaces, e.g. 'wan6' | +| ban_dev | list | - / autodetect | wan device(s), e.g. 'eth2' | +| ban_trigger | list | - | logical startup trigger interface(s), e.g. 'wan' | +| ban_triggerdelay | option | 10 | trigger timeout before banIP processing begins | +| ban_deduplicate | option | 1 | deduplicate IP addresses across all active sets | +| ban_splitsize | option | 0 | split ext. sets after every n lines/members (saves RAM) | +| ban_cores | option | - / autodetect | limit the cpu cores used by banIP (saves RAM) | +| ban_nftexpiry | option | - | expiry time for auto added blocklist members, e.g. '5m', '2h' or '1d' | +| ban_nftpriority | option | -200 | nft banIP table priority (default is the prerouting table priority) | +| ban_feed | list | - | external download feeds, e.g. 'yoyo', 'doh', 'country' or 'talos' (see feed table) | +| ban_asn | list | - | ASNs for the 'asn' feed, e.g.'32934' | +| ban_country | list | - | country iso codes for the 'country' feed, e.g. 'ru' | +| ban_blockinput | list | - | limit a feed to the input chain, e.g. 'country' | +| ban_blockforward | list | - | limit a feed to the forward chain, e.g. 'doh' | +| ban_fetchcmd | option | - / autodetect | 'uclient-fetch', 'wget', 'curl' or 'aria2c' | +| ban_fetchparm | option | - / autodetect | set the config options for the selected download utility | +| ban_fetchinsecure | option | 0 | don't check SSL server certificates during download | | ban_mailreceiver | option | - | receiver address for banIP related notification E-Mails | | ban_mailsender | option | no-reply@banIP | sender address for banIP related notification E-Mails | | ban_mailtopic | option | banIP notification | topic for banIP related notification E-Mails | | ban_mailprofile | option | ban_notify | mail profile used in 'msmtp' for banIP related notification E-Mails | -| ban_srcarc | option | /etc/banip/banip.sources.gz | full path to the compressed source archive file used by banIP | -| ban_localsources | list | maclist, whitelist, blacklist | limit the selection to certain local sources | -| ban_extrasources | list | - | add additional, non-banIP related IPSets e.g. for reporting or queries | -| ban_maclist_timeout | option | - | individual maclist IPSet timeout | -| ban_whitelist_timeout | option | - | individual whitelist IPSet timeout | -| ban_blacklist_timeout | option | - | individual blacklist IPSet timeout | -| ban_logterms | list | dropbear, sshd, luci, nginx | limit the log monitor to certain log terms | -| ban_loglimit | option | 100 | parse only the last stated number of log entries for suspicious events | -| ban_ssh_logcount | option | 3 | number of the failed ssh login repetitions of the same ip in the log before banning | -| ban_luci_logcount | option | 3 | number of the failed luci login repetitions of the same ip in the log before banning | -| ban_nginx_logcount | option | 5 | number of the failed nginx requests of the same ip in the log before banning | - -## Examples -**list/edit banIP sources:** -

-~# /etc/init.d/banip list
-::: Available banIP sources
-:::
-    Name                 Enabled   Focus                               Info URL
-    ---------------------------------------------------------------------------
-  + asn                            ASN blocks                          https://asn.ipinfo.app
-  + bogon                          Bogon prefixes                      https://team-cymru.com
-  + country              x         Country blocks                      https://www.ipdeny.com/ipblocks
-  + darklist             x         Blocks suspicious attacker IPs      https://darklist.de
-  + debl                 x         Fail2ban IP blacklist               https://www.blocklist.de
-  + doh                  x         Public DoH-Provider                 https://github.com/dibdot/DoH-IP-blocklists
-  + drop                 x         Spamhaus drop compilation           https://www.spamhaus.org
-  + dshield              x         Dshield IP blocklist                https://www.dshield.org
-  + edrop                          Spamhaus edrop compilation          https://www.spamhaus.org
-  + feodo                x         Feodo Tracker                       https://feodotracker.abuse.ch
-  + firehol1             x         Firehol Level 1 compilation         https://iplists.firehol.org/?ipset=firehol_level1
-  + firehol2                       Firehol Level 2 compilation         https://iplists.firehol.org/?ipset=firehol_level2
-  + firehol3                       Firehol Level 3 compilation         https://iplists.firehol.org/?ipset=firehol_level3
-  + firehol4                       Firehol Level 4 compilation         https://iplists.firehol.org/?ipset=firehol_level4
-  + greensnow            x         Blocks suspicious server IPs        https://greensnow.co
-  + iblockads                      Advertising blocklist               https://www.iblocklist.com
-  + iblockspy            x         Malicious spyware blocklist         https://www.iblocklist.com
-  + myip                           Myip Live IP blacklist              https://myip.ms
-  + nixspam              x         iX spam protection                  http://www.nixspam.org
-  + proxy                          Firehol list of open proxies        https://iplists.firehol.org/?ipset=proxylists
-  + sslbl                x         SSL botnet IP blacklist             https://sslbl.abuse.ch
-  + talos                x         Cisco Talos IP Blacklist            https://talosintelligence.com/reputation_center
-  + threat               x         Emerging Threats                    https://rules.emergingthreats.net
-  + tor                  x         Tor exit nodes                      https://fissionrelays.net/lists
-  + uceprotect1          x         Spam protection level 1             http://www.uceprotect.net/en/index.php
-  + uceprotect2                    Spam protection level 2             http://www.uceprotect.net/en/index.php
-  + voip                 x         VoIP fraud blocklist                http://www.voipbl.org
-  + yoyo                 x         Ad protection blacklist             https://pgl.yoyo.org/adservers/
-    ---------------------------------------------------------------------------
-  * Configured ASNs: -
-  * Configured Countries: af, bd, br, cn, hk, hu, id, il, in, iq, ir, kp, kr, no, pk, pl, ro, ru, sa, th, tr, ua, gb
-
- -**receive banIP runtime information:** -

-~# /etc/init.d/banip status
-::: banIP runtime information
-  + status          : enabled
-  + version         : 0.7.7
-  + ipset_info      : 2 IPSets with 30 IPs/Prefixes
-  + active_sources  : whitelist
-  + active_devs     : wlan0
-  + active_ifaces   : trm_wwan, trm_wwan6
-  + active_logterms : dropbear, sshd, luci, nginx
-  + active_subnets  : xxx.xxx.xxx.xxx/24, xxxx:xxxx:xxxx:xx::xxx/128
-  + run_infos       : settype: src+dst, backup_dir: /tmp/banIP-Backup, report_dir: /tmp/banIP-Report
-  + run_flags       : protocols (4/6): ✔/✔, log (src/dst): ✔/✘, monitor: ✔, mail: ✘, whitelist only: ✔
-  + last_run        : restart, 0m 3s, 122/30/14, 21.04.2021 20:14:36
-  + system          : TP-Link RE650 v1, OpenWrt SNAPSHOT r16574-f7e00d81bc
-
- -**black-/whitelist handling:** -banIP supports a local black & whitelist (IPv4, IPv6, CIDR notation or domain names), located by default in /etc/banip/banip.whitelist and /etc/banip/banip.blacklist. -Unsuccessful LuCI logins, suspicious nginx request or ssh login attempts via 'dropbear'/'sshd' could be tracked and automatically added to the local blacklist (see the 'ban_autoblacklist' option). Furthermore the uplink subnet could be automatically added to local whitelist (see 'ban_autowhitelist' option). The list behaviour could be further tweaked with different timeout and counter options (see the config options section above). -Last but not least, both lists also accept domain names as input to allow IP filtering based on these names. The corresponding IPs (IPv4 & IPv6) will be resolved in a detached background process and added to the IPsets. The detached name lookup takes place only during 'restart' or 'reload' action, 'start' and 'refresh' actions are using an auto-generated backup instead. - -**whitelist-only mode:** -banIP supports a "whitelist only" mode. This option allows to restrict 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 whitelist are blocked. Please note: suspend/resume does not work in this mode. - -**Manually override the download options:** -By default banIP uses the following pre-configured download options: -* aria2c: --timeout=20 --allow-overwrite=true --auto-file-renaming=false --log-level=warn --dir=/ -o -* curl: --connect-timeout 20 --silent --show-error --location -o -* uclient-fetch: --timeout=20 -O -* wget: --no-cache --no-cookies --max-redirect=0 --timeout=20 -O +| ban_resolver | option | - | external resolver used for DNS lookups | +| ban_feedarchive | option | /etc/banip/banip.feeds.gz | full path to the compressed feed archive file used by banIP | -To override the default set 'ban_fetchparm' manually to your needs. - -**generate an IPSet report:** -

+## Examples
+**banIP report information**  
+```
 ~# /etc/init.d/banip report
 :::
-::: report on all banIP related IPSets
+::: banIP Set Statistics
 :::
-  + Report timestamp           ::: 04.02.2021 06:24:41
-  + Number of all IPSets       ::: 24
-  + Number of all entries      ::: 302448
-  + Number of IP entries       ::: 224748
-  + Number of CIDR entries     ::: 77700
-  + Number of MAC entries      ::: 0
-  + Number of accessed entries ::: 36
+    Timestamp: 2023-02-08 22:12:40
+    ------------------------------
+    auto-added to allowlist: 1
+    auto-added to blocklist: 0
+
+    Set                  | Set Elements  | Chain Input   | Chain Forward | Input Packets | Forward Packets
+    ---------------------+---------------+---------------+---------------+---------------+----------------
+    allowlistvMAC        | 0             | n/a           | OK            | n/a           | 0             
+    allowlistv4          | 1             | OK            | OK            | 0             | 0             
+    allowlistv6          | 0             | OK            | OK            | 0             | 0             
+    blocklistvMAC        | 0             | n/a           | OK            | n/a           | 0             
+    blocklistv4          | 0             | OK            | OK            | 0             | 0             
+    blocklistv6          | 0             | OK            | OK            | 0             | 0             
+    dohv4                | 542           | n/a           | OK            | n/a           | 22            
+    adguardv4            | 23007         | n/a           | OK            | n/a           | 18            
+    yoyov4               | 1936          | n/a           | OK            | n/a           | 1             
+    oisdbasicv4          | 26000         | n/a           | OK            | n/a           | 325           
+    ---------------------+---------------+---------------+---------------+---------------+----------------
+    10                   | 51486         | 4             | 10            | 0             | 366
+```
+
+**banIP runtime information**  
+```
+~# etc/init.d/banip status
+::: banIP runtime information
+  + status            : active
+  + version           : 0.8.0
+  + element_count     : 51486
+  + active_feeds      : allowlistvMAC, allowlistv4, allowlistv6, blocklistvMAC, blocklistv4, blocklistv6, dohv4, adguardv4
+                        , yoyov4, oisdbasicv4
+  + active_devices    : eth2
+  + active_interfaces : wan
+  + active_subnets    : 192.168.98.107/24
+  + run_info          : base_dir: /tmp, backup_dir: /tmp/banIP-backup, report_dir: /tmp/banIP-report, feed_archive: /etc/b
+                        anip/banip.feeds.gz
+  + run_flags         : protocol (4/6): ✔/✘, log (inp/fwd): ✔/✘, deduplicate: ✔, split: ✘, allowed only: ✘
+  + last_run          : action: start, duration: 0m 15s, date: 2023-02-08 22:12:46
+  + system_info       : cores: 2, memory: 3614, device: PC Engines apu1, OpenWrt SNAPSHOT r21997-b5193291bd
+```
+
+**banIP search information**  
+```
+~# /etc/init.d/banip search 221.228.105.173
 :::
-::: IPSet details
+::: banIP Search
 :::
-    Name                 Type        Count      Cnt_IP    Cnt_CIDR  Cnt_MAC   Cnt_ACC   Entry details (Entry/Count)
-    --------------------------------------------------------------------------------------------------------------------
-    whitelist_4          src+dst     1          0         1         0         1
-                                                                                        xxx.xxxx.xxx.xxxx/24     85
-    --------------------------------------------------------------------------------------------------------------------
-    whitelist_6          src+dst     2          0         2         0         1
-                                                                                        xxxx:xxxx:xxxx::/64      29
-    --------------------------------------------------------------------------------------------------------------------
-    blacklist_4          src+dst     513        513       0         0         2
-                                                                                        192.35.168.16            3
-                                                                                        80.82.65.74              1
-    --------------------------------------------------------------------------------------------------------------------
-    blacklist_6          src+dst     1          1         0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    country_4            src         52150      0         52150     0         23
-                                                                                        124.5.0.0/16             1
-                                                                                        95.188.0.0/14            1
-                                                                                        121.16.0.0/12            1
-                                                                                        46.161.0.0/18            1
-                                                                                        42.56.0.0/14             1
-                                                                                        113.64.0.0/10            1
-                                                                                        113.252.0.0/14           1
-                                                                                        5.201.128.0/17           1
-                                                                                        125.64.0.0/11            1
-                                                                                        90.188.0.0/15            1
-                                                                                        60.0.0.0/11              1
-                                                                                        78.160.0.0/11            1
-                                                                                        1.80.0.0/12              1
-                                                                                        183.184.0.0/13           1
-                                                                                        175.24.0.0/14            1
-                                                                                        119.176.0.0/12           1
-                                                                                        59.88.0.0/13             1
-                                                                                        103.78.12.0/22           1
-                                                                                        123.128.0.0/13           1
-                                                                                        116.224.0.0/12           1
-                                                                                        42.224.0.0/12            1
-                                                                                        82.80.0.0/15             1
-                                                                                        14.32.0.0/11             1
-    --------------------------------------------------------------------------------------------------------------------
-    country_6            src         20099      0         20099     0         0
-    --------------------------------------------------------------------------------------------------------------------
-    debl_4               src+dst     29389      29389     0         0         1
-                                                                                        5.182.210.16             4
-    --------------------------------------------------------------------------------------------------------------------
-    debl_6               src+dst     64         64        0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    doh_4                src+dst     168        168       0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    doh_6                src+dst     122        122       0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    drop_4               src+dst     965        0         965       0         0
-    --------------------------------------------------------------------------------------------------------------------
-    drop_6               src+dst     36         0         36        0         0
-    --------------------------------------------------------------------------------------------------------------------
-    dshield_4            src+dst     20         0         20        0         1
-                                                                                        89.248.165.0/24          1
-    --------------------------------------------------------------------------------------------------------------------
-    feodo_4              src+dst     325        325       0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    firehol1_4           src+dst     2763       403       2360      0         0
-    --------------------------------------------------------------------------------------------------------------------
-    iblockspy_4          src+dst     3650       2832      818       0         0
-    --------------------------------------------------------------------------------------------------------------------
-    nixspam_4            src+dst     9577       9577      0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    sslbl_4              src+dst     104        104       0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    threat_4             src+dst     1300       315       985       0         0
-    --------------------------------------------------------------------------------------------------------------------
-    tor_4                src+dst     1437       1437      0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    tor_6                src+dst     478        478       0         0         0
-    --------------------------------------------------------------------------------------------------------------------
-    uceprotect1_4        src+dst     156249     156249    0         0         6
-                                                                                        192.241.220.137          1
-                                                                                        128.14.137.178           1
-                                                                                        61.219.11.153            1
-                                                                                        138.34.32.33             1
-                                                                                        107.174.133.130          2
-                                                                                        180.232.99.46            1
-    --------------------------------------------------------------------------------------------------------------------
-    voip_4               src+dst     12563      12299     264       0         0
-    --------------------------------------------------------------------------------------------------------------------
-    yoyo_4               src+dst     10472      10472     0         0         1
-                                                                                        204.79.197.200           2
-    --------------------------------------------------------------------------------------------------------------------
-
- -**Enable E-Mail notification via 'msmtp':** -To use the email notification you have to install & configure the package 'msmtp'. + Looking for IP 221.228.105.173 on 2023-02-08 22:12:48 + --- + IP found in set oisdbasicv4 +``` + +**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. +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). +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. + +**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. + +**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. + +**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: + + * point 'ban_reportdir' and 'ban_backupdir' to an external usb drive + * set 'ban_cores' to '1' (only useful on a multicore system) to force sequential feed processing + * set 'ban_splitsize' e.g. to '1000' to split the load of an external set after every 1000 lines/members + +**tweak the download options** +By default banIP uses the following pre-configured download options: +``` + * aria2c: --timeout=20 --allow-overwrite=true --auto-file-renaming=false --log-level=warn --dir=/ -o + * curl: --connect-timeout 20 --silent --show-error --location -o + * uclient-fetch: --timeout=20 -O + * wget: --no-cache --no-cookies --max-redirect=0 --timeout=20 -O +``` +To override the default set 'ban_fetchparm' manually to your needs. + +**send E-Mail notifications via 'msmtp'** +To use the email notification you must install & configure the package 'msmtp'. Modify the file '/etc/msmtprc', e.g.: -

+```
 [...]
 defaults
 auth            on
@@ -360,39 +264,37 @@ syslog          LOG_MAIL
 account         ban_notify
 host            smtp.gmail.com
 port            587
-from            <address>@gmail.com
-user            <gmail-user>
-password        <password>
-
-Finally enable E-Mail support and add a valid E-Mail receiver address in LuCI. - -**Edit, add new banIP sources:** -The banIP blocklist sources are stored in an external, compressed JSON file '/etc/banip/banip.sources.gz'. -This file is directly parsed in LuCI and accessible via CLI, just call _/etc/init.d/banip list_. +from
@gmail.com +user +password +``` +Finally add a valid E-Mail receiver address. -To add new or edit existing sources extract the compressed JSON file _gunzip /etc/banip/banip.sources.gz_. +**add new banIP feeds** +The banIP blocklist feeds are stored in an external, compressed JSON file '/etc/banip/banip.feeds.gz'. +To add a new or edit an existing feed extract the compressed JSON file _gunzip /etc/banip/banip.feeds.gz_. A valid JSON source object contains the following required information, e.g.: -

+```
 	[...]
 	"tor": {
-		"url_4": "https://lists.fissionrelays.net/tor/exits-ipv4.txt",
-		"url_6": "https://lists.fissionrelays.net/tor/exits-ipv6.txt",
-		"rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add tor_4 \"$1}",
-		"rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add tor_6 \"$1}",
-		"focus": "Tor exit nodes",
-		"descurl": "https://fissionrelays.net/lists"
+		"url_4": "https://raw.githubusercontent.com/SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst",
+		"url_6": "https://raw.githubusercontent.com/SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst",
+		"rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}",
+		"rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}",
+		"focus": "tor exit nodes",
+		"descurl": "https://github.com/SecOps-Institute/Tor-IP-Addresses"
 	},
 	[...]
-
-Add an unique object name, make the required changes to 'url_4', 'rule_4' (and/or 'url_6', 'rule_6'), 'focus' and 'descurl' and finally compress the changed JSON file _gzip /etc/banip/banip.sources.gz_ to use the new source object in banIP. -Please note: if you're going to add new sources on your own, please make a copy of the default file and work with that copy further on, cause the default will be overwritten with every banIP update. To reference your copy set the option 'ban\_srcarc' which points by default to '/etc/banip/banip.sources.gz' - +``` +Add an unique object name, make the required changes and compress the changed JSON file finally with _gzip /etc/banip/banip.feeds_ to use the new feed file in banIP. +**Please note:** if you're going to add new feeds, **always** work with a copy of the default file; this file is always overwritten with every banIP update. To reference your own file set the option 'ban\_feedarchive' accordingly + ## Support -Please join the banIP discussion in this [forum thread](https://forum.openwrt.org/t/banip-support-thread/16985) or contact me by mail +Please join the banIP discussion in this [forum thread](https://forum.openwrt.org/t/banip-support-thread/16985) or contact me by mail ## Removal * stop all banIP related services with _/etc/init.d/banip stop_ * optional: remove the banip package (_opkg remove banip_) Have fun! -Dirk +Dirk diff --git a/net/banip/files/banip-functions.sh b/net/banip/files/banip-functions.sh new file mode 100644 index 000000000..532b3b183 --- /dev/null +++ b/net/banip/files/banip-functions.sh @@ -0,0 +1,1159 @@ +# banIP shared function library/include +# Copyright (c) 2018-2023 Dirk Brenken (dev@brenken.org) +# This is free software, licensed under the GNU General Public License v3. + +# (s)hellcheck exceptions +# shellcheck disable=all + +# set initial defaults +# +export LC_ALL=C +export PATH="/usr/sbin:/usr/bin:/sbin:/bin" + +ban_basedir="/tmp" +ban_backupdir="${ban_basedir}/banIP-backup" +ban_reportdir="${ban_basedir}/banIP-report" +ban_feedarchive="/etc/banip/banip.feeds.gz" +ban_pidfile="/var/run/banip.pid" +ban_lock="/var/run/banip.lock" +ban_blocklist="/etc/banip/banip.blocklist" +ban_allowlist="/etc/banip/banip.allowlist" +ban_fetchcmd="" +ban_logreadcmd="$(command -v logread)" +ban_logcmd="$(command -v logger)" +ban_ubuscmd="$(command -v ubus)" +ban_nftcmd="$(command -v nft)" +ban_fw4cmd="$(command -v fw4)" +ban_awkcmd="$(command -v awk)" +ban_grepcmd="$(command -v grep)" +ban_lookupcmd="$(command -v nslookup)" +ban_mailcmd="$(command -v msmtp)" +ban_mailsender="no-reply@banIP" +ban_mailreceiver="" +ban_mailtopic="banIP notification" +ban_mailprofile="ban_notify" +ban_mailtemplate="/etc/banip/banip.tpl" +ban_nftpriority="-200" +ban_nftexpiry="" +ban_loglevel="warn" +ban_loglimit="100" +ban_logcount="1" +ban_logterm="" +ban_country="" +ban_asn="" +ban_loginput="0" +ban_logforward="0" +ban_allowlistonly="0" +ban_autoallowlist="1" +ban_autoblocklist="1" +ban_deduplicate="1" +ban_splitsize="0" +ban_autodetect="" +ban_feed="" +ban_blockinput="" +ban_blockforward="" +ban_protov4="0" +ban_protov6="0" +ban_ifv4="" +ban_ifv6="" +ban_dev="" +ban_sub="" +ban_fetchinsecure="" +ban_cores="" +ban_memory="" +ban_trigger="" +ban_triggerdelay="10" +ban_resolver="" +ban_enabled="0" +ban_debug="0" + +# gather system information +# +f_system() { + local cpu core + + ban_memory="$("${ban_awkcmd}" '/^MemAvailable/{printf "%s",int($2/1000)}' "/proc/meminfo" 2>/dev/null)" + ban_ver="$(${ban_ubuscmd} -S call rpc-sys packagelist 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_awkcmd}" 'BEGIN{RS="";FS="\n"}{printf "%s, %s",$1,$2}')" + if [ -z "${ban_cores}" ]; then + cpu="$("${ban_grepcmd}" -c '^processor' /proc/cpuinfo 2>/dev/null)" + core="$("${ban_grepcmd}" -cm1 '^core id' /proc/cpuinfo 2>/dev/null)" + [ "${cpu}" = "0" ] && cpu="1" + [ "${core}" = "0" ] && core="1" + ban_cores="$((cpu * core))" + fi + + f_log "debug" "f_system ::: system: ${ban_sysver:-"n/a"}, version: ${ban_ver:-"n/a"}, memory: ${ban_memory:-"0"}, cpu_cores: ${ban_cores}" +} + +# create directories +# +f_mkdir() { + local dir="${1}" + + if [ ! -d "${dir}" ]; then + rm -f "${dir}" + mkdir -p "${dir}" + f_log "debug" "f_mkdir ::: created directory: ${dir}" + fi +} + +# create files +# +f_mkfile() { + local file="${1}" + + if [ ! -f "${file}" ]; then + : >"${file}" + f_log "debug" "f_mkfile ::: created file: ${file}" + fi +} + +# create temporary files and directories +# +f_tmp() { + f_mkdir "${ban_basedir}" + ban_tmpdir="$(mktemp -p "${ban_basedir}" -d)" + ban_tmpfile="$(mktemp -p "${ban_tmpdir}" -tu)" + + f_log "debug" "f_tmp ::: base_dir: ${ban_basedir:-"-"}, tmp_dir: ${ban_tmpdir:-"-"}" +} + +# remove directories +# +f_rmdir() { + local dir="${1}" + + if [ -d "${dir}" ]; then + rm -rf "${dir}" + f_log "debug" "f_rmdir ::: deleted directory: ${dir}" + fi +} + +# convert chars +# +f_char() { + local char="${1}" + + [ "${char}" = "1" ] && printf "%s" "✔" || printf "%s" "✘" +} + +# trim strings +# +f_trim() { + local string="${1}" + + string="${string#"${string%%[![:space:]]*}"}" + string="${string%"${string##*[![:space:]]}"}" + printf "%s" "${string}" +} + +# write log messages +# +f_log() { + local class="${1}" log_msg="${2}" + + if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${ban_debug}" = "1" ]; }; then + if [ -x "${ban_logcmd}" ]; then + "${ban_logcmd}" -p "${class}" -t "banIP-${ban_ver}[${$}]" "${log_msg}" + else + printf "%s %s %s\n" "${class}" "banIP-${ban_ver}[${$}]" "${log_msg}" + fi + fi + if [ "${class}" = "err" ]; then + f_genstatus "error" + f_rmdir "${ban_tmpdir}" + rm -rf "${ban_lock}" + exit 1 + fi +} + +# load config +# +f_conf() { + unset ban_dev ban_ifv4 ban_ifv6 ban_feed ban_blockinput ban_blockforward ban_logterm ban_country ban_asn + config_cb() { + option_cb() { + local option="${1}" + local value="${2}" + eval "${option}=\"${value}\"" + } + list_cb() { + local option="${1}" + local value="${2}" + case "${option}" in + "ban_dev") + eval "${option}=\"$(printf "%s" "${ban_dev}")${value} \"" + ;; + "ban_ifv4") + eval "${option}=\"$(printf "%s" "${ban_ifv4}")${value} \"" + ;; + "ban_ifv6") + eval "${option}=\"$(printf "%s" "${ban_ifv6}")${value} \"" + ;; + "ban_feed") + eval "${option}=\"$(printf "%s" "${ban_feed}")${value} \"" + ;; + "ban_blockinput") + eval "${option}=\"$(printf "%s" "${ban_blockinput}")${value} \"" + ;; + "ban_blockforward") + eval "${option}=\"$(printf "%s" "${ban_blockforward}")${value} \"" + ;; + "ban_logterm") + eval "${option}=\"$(printf "%s" "${ban_logterm}")${value}\\|\"" + ;; + "ban_country") + eval "${option}=\"$(printf "%s" "${ban_country}")${value} \"" + ;; + "ban_asn") + eval "${option}=\"$(printf "%s" "${ban_asn}")${value} \"" + ;; + esac + } + } + config_load banip + + [ "${ban_action}" = "boot" ] && [ -z "${ban_trigger}" ] && sleep ${ban_triggerdelay} +} + +# prepare fetch utility +# +f_fetch() { + local ut utils packages insecure + + if [ -z "${ban_fetchcmd}" ] || [ ! -x "${ban_fetchcmd}" ]; then + packages="$(${ban_ubuscmd} -S call rpc-sys packagelist 2>/dev/null)" + [ -z "${packages}" ] && f_log "err" "local opkg package repository is not available, please set the download utility 'ban_fetchcmd' manually" + utils="aria2c curl wget uclient-fetch" + for ut in ${utils}; do + if { [ "${ut}" = "uclient-fetch" ] && printf "%s" "${packages}" | "${ban_grepcmd}" -q '"libustream-'; } || + { [ "${ut}" = "wget" ] && printf "%s" "${packages}" | "${ban_grepcmd}" -q '"wget-ssl'; } || + [ "${ut}" = "curl" ] || [ "${ut}" = "aria2c" ]; then + ban_fetchcmd="$(command -v "${ut}")" + if [ -x "${ban_fetchcmd}" ]; then + uci_set banip global ban_fetchcmd "${ban_fetchcmd##*/}" + uci_commit "banip" + break + fi + fi + done + fi + [ ! -x "${ban_fetchcmd}" ] && f_log "err" "download utility with SSL support not found" + case "${ban_fetchcmd##*/}" in + "aria2c") + [ "${ban_fetchinsecure}" = "1" ] && insecure="--check-certificate=false" + ban_fetchparm="${ban_fetchparm:-"${insecure} --timeout=20 --allow-overwrite=true --auto-file-renaming=false --log-level=warn --dir=/ -o"}" + ;; + "curl") + [ "${ban_fetchinsecure}" = "1" ] && insecure="--insecure" + ban_fetchparm="${ban_fetchparm:-"${insecure} --connect-timeout 20 --fail --silent --show-error --location -o"}" + ;; + "uclient-fetch") + [ "${ban_fetchinsecure}" = "1" ] && insecure="--no-check-certificate" + ban_fetchparm="${ban_fetchparm:-"${insecure} --timeout=20 -O"}" + ;; + "wget") + [ "${ban_fetchinsecure}" = "1" ] && insecure="--no-check-certificate" + ban_fetchparm="${ban_fetchparm:-"${insecure} --no-cache --no-cookies --max-redirect=0 --timeout=20 -O"}" + ;; + esac + + f_log "debug" "f_fetch ::: fetch_cmd: ${ban_fetchcmd:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}" +} + +# remove logservice +# +f_rmpid() { + local ppid pid pids + + ppid="$(cat "${ban_pidfile}" 2>/dev/null)" + [ -n "${ppid}" ] && pids="$(pgrep -P "${ppid}" 2>/dev/null)" || return 0 + for pid in ${pids}; do + kill -INT "${pid}" >/dev/null 2>&1 + done + : >"${ban_pidfile}" +} + +# get wan interfaces +# +f_getif() { + local iface + + "${ban_ubuscmd}" -t 5 wait_for network.device network.interface 2>/dev/null + if [ "${ban_autodetect}" = "1" ]; then + if [ -z "${ban_ifv4}" ]; then + network_find_wan iface + if [ -n "${iface}" ] && ! printf "%s" "${ban_ifv4}" | "${ban_grepcmd}" -q "${iface}"; then + ban_protov4="1" + ban_ifv4="${ban_ifv4}${iface} " + uci_set banip global ban_protov4 "1" + uci_add_list banip global ban_ifv4 "${iface}" + fi + fi + if [ -z "${ban_ifv6}" ]; then + network_find_wan6 iface + if [ -n "${iface}" ] && ! printf "%s" "${ban_ifv6}" | "${ban_grepcmd}" -q "${iface}"; then + ban_protov6="1" + ban_ifv6="${ban_ifv6}${iface} " + uci_set banip global ban_protov6 "1" + uci_add_list banip global ban_ifv6 "${iface}" + fi + fi + ban_ifv4="${ban_ifv4%%?}" + ban_ifv6="${ban_ifv6%%?}" + [ -n "$(uci -q changes "banip")" ] && uci_commit "banip" + fi + [ -z "${ban_ifv4}" ] && [ -z "${ban_ifv6}" ] && f_log "err" "wan interfaces not found, please check your configuration" + + f_log "debug" "f_getif ::: auto_detect: ${ban_autodetect}, interfaces (4/6): ${ban_ifv4}/${ban_ifv6}, protocols (4/6): ${ban_protov4}/${ban_protov6}" +} + +# get wan devices +# +f_getdev() { + local dev iface + + if [ "${ban_autodetect}" = "1" ] && [ -z "${ban_dev}" ]; then + for iface in ${ban_ifv4} ${ban_ifv6}; do + network_get_device dev "${iface}" + if [ -n "${dev}" ] && ! printf "%s" "${ban_dev}" | "${ban_grepcmd}" -q "${dev}"; then + ban_dev="${ban_dev}${dev} " + uci_add_list banip global ban_dev "${dev}" + else + network_get_physdev dev "${iface}" + if [ -n "${dev}" ] && ! printf "%s" "${ban_dev}" | "${ban_grepcmd}" -q "${dev}"; then + ban_dev="${ban_dev}${dev} " + uci_add_list banip global ban_dev "${dev}" + fi + fi + done + ban_dev="${ban_dev%%?}" + [ -n "$(uci -q changes "banip")" ] && uci_commit "banip" + fi + [ -z "${ban_dev}" ] && f_log "err" "wan devices not found, please check your configuration" + + f_log "debug" "f_getdev ::: auto_detect: ${ban_autodetect}, devices: ${ban_dev}" +} + +# get local subnets +# +f_getsub() { + local sub iface ip + + for iface in ${ban_ifv4} ${ban_ifv6}; do + network_get_subnet sub "${iface}" + if [ -n "${sub}" ] && ! printf "%s" "${ban_sub}" | "${ban_grepcmd}" -q "${sub}"; then + ban_sub="${ban_sub} ${sub}" + fi + network_get_subnet6 sub "${iface}" + if [ -n "${sub}" ] && ! printf "%s" "${ban_sub}" | "${ban_grepcmd}" -q "${sub}"; then + ban_sub="${ban_sub} ${sub}" + fi + done + if [ "${ban_autoallowlist}" = "1" ]; then + for ip in ${ban_sub}; do + if ! "${ban_grepcmd}" -q "${ip}" "${ban_allowlist}"; then + printf "%-42s%s\n" "${ip}" "added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_allowlist}" + f_log "info" "add subnet '${ip}' to local allowlist" + fi + done + fi + [ -z "${ban_sub}" ] && f_log "err" "wan subnet(s) not found, please check your configuration" + + f_log "debug" "f_getsub ::: auto_allowlist: ${ban_autoallowlist}, subnet(s): ${ban_sub:-"-"}" +} + +# get set elements +# +f_getelements() { + local file="${1}" + + [ -s "${file}" ] && printf "%s" "elements={ $(cat "${file}") };" +} + +# build initial nft file with base table, chains and rules +# +f_nftinit() { + local feed_log feed_rc file="${1}" + + { + # nft header (tables and chains) + # + printf "%s\n\n" "#!/usr/sbin/nft -f" + if "${ban_nftcmd}" -t list table inet banIP >/dev/null 2>&1; then + printf "%s\n" "delete table inet banIP" + fi + printf "%s\n" "add table inet banIP" + printf "%s\n" "add chain inet banIP wan-input { type filter hook input priority ${ban_nftpriority}; policy accept; }" + printf "%s\n" "add chain inet banIP lan-forward { type filter hook forward priority ${ban_nftpriority}; policy accept; }" + + # default input rules + # + printf "%s\n" "add rule inet banIP wan-input ct state established,related counter accept" + printf "%s\n" "add rule inet banIP wan-input iifname != { ${ban_dev// /, } } counter accept" + printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv4 icmp type { echo-request } limit rate 1000/second counter accept" + printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { echo-request } limit rate 1000/second counter accept" + printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-advert, nd-neighbor-solicit, nd-router-advert} limit rate 1000/second ip6 hoplimit 1 counter accept" + printf "%s\n" "add rule inet banIP wan-input meta nfproto ipv6 icmpv6 type { nd-neighbor-advert, nd-neighbor-solicit, nd-router-advert} limit rate 1000/second ip6 hoplimit 255 counter accept" + + # default forward rules + # + printf "%s\n" "add rule inet banIP lan-forward ct state established,related counter accept" + printf "%s\n" "add rule inet banIP lan-forward oifname != { ${ban_dev// /, } } counter accept" + } >"${file}" + + # load initial banIP table within nft (atomic load) + # + feed_log="$("${ban_nftcmd}" -f "${file}" 2>&1)" + feed_rc="${?}" + + f_log "debug" "f_nftinit ::: devices: ${ban_dev}, priority: ${ban_nftpriority}, rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}" + return ${feed_rc} +} + +f_down() { + local nft_loginput nft_logforward start_ts end_ts tmp_raw tmp_load tmp_file split_file input_handles forward_handles handle + local cnt_set cnt_dl restore_rc feed_direction feed_rc feed_log feed="${1}" proto="${2}" feed_url="${3}" feed_rule="${4}" feed_flag="${5}" + + start_ts="$(date +%s)" + feed="${feed}v${proto}" + tmp_load="${ban_tmpfile}.${feed}.load" + tmp_raw="${ban_tmpfile}.${feed}.raw" + tmp_split="${ban_tmpfile}.${feed}.split" + tmp_file="${ban_tmpfile}.${feed}.file" + tmp_flush="${ban_tmpfile}.${feed}.flush" + tmp_nft="${ban_tmpfile}.${feed}.nft" + + [ "${ban_loginput}" = "1" ] && nft_loginput="limit rate 2/second log level ${ban_loglevel} prefix \"banIP_drp/${feed}: \"" + [ "${ban_logforward}" = "1" ] && nft_logforward="limit rate 2/second log level ${ban_loglevel} prefix \"banIP_rej/${feed}: \"" + + # set source block direction + # + if printf "%s" "${ban_blockinput}" | "${ban_grepcmd}" -q "${feed%v*}"; then + feed_direction="input" + elif printf "%s" "${ban_blockforward}" | "${ban_grepcmd}" -q "${feed%v*}"; then + feed_direction="forward" + fi + + # chain/rule maintenance + # + if [ "${ban_action}" = "reload" ] && "${ban_nftcmd}" -t list set inet banIP "${feed}" >/dev/null 2>&1; then + input_handles="$("${ban_nftcmd}" -t --handle --numeric list chain inet banIP wan-input 2>/dev/null)" + forward_handles="$("${ban_nftcmd}" -t --handle --numeric list chain inet banIP lan-forward 2>/dev/null)" + { + printf "%s\n" "flush set inet banIP ${feed}" + handle="$(printf "%s\n" "${input_handles}" | "${ban_awkcmd}" "/@${feed} /{print \$NF}")" + [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-input handle ${handle}" + handle="$(printf "%s\n" "${forward_handles}" | "${ban_awkcmd}" "/@${feed} /{print \$NF}")" + [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP lan-forward handle ${handle}" + } >"${tmp_flush}" + fi + + # restore local backups during init + # + if { [ "${ban_action}" != "reload" ] || [ "${feed_url}" = "local" ]; } && [ "${feed%v*}" != "allowlist" ] && [ "${feed%v*}" != "blocklist" ]; then + f_restore "${feed}" "${feed_url}" "${tmp_load}" + restore_rc="${?}" + feed_rc="${restore_rc}" + fi + + # handle local lists + # + if [ "${feed%v*}" = "allowlist" ]; then + { + printf "%s\n\n" "#!/usr/sbin/nft -f" + [ -s "${tmp_flush}" ] && cat "${tmp_flush}" + if [ "${proto}" = "MAC" ]; then + "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}([[:space:]]|$)/{printf "%s, ",tolower($1)}' "${ban_allowlist}" >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ether_addr; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ether saddr @${feed} counter accept" + fi + elif [ "${proto}" = "4" ]; then + "${ban_awkcmd}" '/^(([0-9]{1,3}\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{printf "%s, ",$1}' "${ban_allowlist}" >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "forward" ]; then + if [ "${ban_allowlistonly}" = "1" ]; then + printf "%s\n" "add rule inet banIP wan-input ip saddr != @${feed} ${nft_loginput} counter drop" + else + printf "%s\n" "add rule inet banIP wan-input ip saddr @${feed} counter accept" + fi + fi + if [ "${feed_direction}" != "input" ]; then + if [ "${ban_allowlistonly}" = "1" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip daddr != @${feed} ${nft_logforward} counter reject with icmp type admin-prohibited" + else + printf "%s\n" "add rule inet banIP lan-forward ip daddr @${feed} counter accept" + fi + fi + elif [ "${proto}" = "6" ]; then + "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}([[:space:]]|$)/{printf "%s\n",$1}' "${ban_allowlist}" | + "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{printf "%s, ",tolower($1)}' >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "forward" ]; then + if [ "${ban_allowlistonly}" = "1" ]; then + printf "%s\n" "add rule inet banIP wan-input ip6 saddr != @${feed} ${nft_loginput} counter drop" + else + printf "%s\n" "add rule inet banIP wan-input ip6 saddr @${feed} counter accept" + fi + fi + if [ "${feed_direction}" != "input" ]; then + if [ "${ban_allowlistonly}" = "1" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip6 daddr != @${feed} ${nft_logforward} counter reject with icmpv6 type admin-prohibited" + else + printf "%s\n" "add rule inet banIP lan-forward ip6 daddr @${feed} counter accept" + fi + fi + fi + } >"${tmp_nft}" + feed_rc="${?}" + elif [ "${feed%v*}" = "blocklist" ]; then + { + printf "%s\n\n" "#!/usr/sbin/nft -f" + [ -s "${tmp_flush}" ] && cat "${tmp_flush}" + if [ "${proto}" = "MAC" ]; then + "${ban_awkcmd}" '/^([0-9A-f]{2}:){5}[0-9A-f]{2}([[:space:]]|$)/{printf "%s, ",tolower($1)}' "${ban_blocklist}" >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ether_addr; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ether saddr @${feed} ${nft_logforward} counter reject" + fi + elif [ "${proto}" = "4" ]; then + if [ "${ban_deduplicate}" = "1" ]; then + "${ban_awkcmd}" '/^(([0-9]{1,3}\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{printf "%s,\n",$1}' "${ban_blocklist}" >"${tmp_raw}" + "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null >"${tmp_split}" + "${ban_awkcmd}" 'BEGIN{FS="[ ,]"}NR==FNR{member[$1];next}!($1 in member)' "${ban_tmpfile}.deduplicate" "${ban_blocklist}" 2>/dev/null >"${tmp_raw}" + cat "${tmp_raw}" 2>/dev/null >"${ban_blocklist}" + else + "${ban_awkcmd}" '/^(([0-9]{1,3}\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{printf "%s,\n",$1}' "${ban_blocklist}" >"${tmp_split}" + fi + "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval, timeout; auto-merge; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "forward" ]; then + printf "%s\n" "add rule inet banIP wan-input ip saddr @${feed} ${nft_loginput} counter drop" + fi + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip daddr @${feed} ${nft_logforward} counter reject with icmp type admin-prohibited" + fi + elif [ "${proto}" = "6" ]; then + if [ "${ban_deduplicate}" = "1" ]; then + "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}([[:space:]]|$)/{printf "%s\n",$1}' "${ban_blocklist}" | + "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{printf "%s,\n",tolower($1)}' >"${tmp_raw}" + "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null >"${tmp_split}" + "${ban_awkcmd}" 'BEGIN{FS="[ ,]"}NR==FNR{member[$1];next}!($1 in member)' "${ban_tmpfile}.deduplicate" "${ban_blocklist}" 2>/dev/null >"${tmp_raw}" + cat "${tmp_raw}" 2>/dev/null >"${ban_blocklist}" + else + "${ban_awkcmd}" '!/^([0-9A-f]{2}:){5}[0-9A-f]{2}([[:space:]]|$)/{printf "%s\n",$1}' "${ban_blocklist}" | + "${ban_awkcmd}" '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{printf "%s,\n",tolower($1)}' >"${tmp_split}" + fi + "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}" + printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval, timeout; auto-merge; policy memory; $(f_getelements "${tmp_file}") }" + if [ "${feed_direction}" != "forward" ]; then + printf "%s\n" "add rule inet banIP wan-input ip6 saddr @${feed} ${nft_loginput} counter drop" + fi + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip6 daddr @${feed} ${nft_logforward} counter reject with icmpv6 type admin-prohibited" + fi + fi + } >"${tmp_nft}" + feed_rc="${?}" + # handle external downloads + # + elif [ "${restore_rc}" != "0" ] && [ "${feed_url}" != "local" ]; then + # handle country downloads + # + if [ "${feed%v*}" = "country" ]; then + for country in ${ban_country}; do + feed_log="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}${country}-aggregated.zone" 2>&1)" + feed_rc="${?}" + [ "${feed_rc}" = "0" ] && cat "${tmp_raw}" 2>/dev/null >>"${tmp_load}" + done + rm -f "${tmp_raw}" + + # handle asn downloads + # + elif [ "${feed%v*}" = "asn" ]; then + for asn in ${ban_asn}; do + feed_log="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}AS${asn}" 2>&1)" + feed_rc="${?}" + [ "${feed_rc}" = "0" ] && cat "${tmp_raw}" 2>/dev/null >>"${tmp_load}" + done + rm -f "${tmp_raw}" + + # handle compressed downloads + # + elif [ -n "${feed_flag}" ]; then + case "${feed_flag}" in + "gz") + feed_log="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_raw}" "${feed_url}" 2>&1)" + feed_rc="${?}" + if [ "${feed_rc}" = "0" ]; then + zcat "${tmp_raw}" 2>/dev/null >"${tmp_load}" + feed_rc="${?}" + fi + rm -f "${tmp_raw}" + ;; + esac + + # handle normal downloads + # + else + feed_log="$("${ban_fetchcmd}" ${ban_fetchparm} "${tmp_load}" "${feed_url}" 2>&1)" + feed_rc="${?}" + fi + fi + + # backup/restore + # + if [ "${restore_rc}" != "0" ] && [ "${feed_rc}" = "0" ] && [ "${feed_url}" != "local" ] && [ ! -s "${tmp_nft}" ]; then + f_backup "${feed}" "${tmp_load}" + feed_rc="${?}" + elif [ -z "${restore_rc}" ] && [ "${feed_rc}" != "0" ] && [ "${feed_url}" != "local" ] && [ ! -s "${tmp_nft}" ]; then + f_restore "${feed}" "${feed_url}" "${tmp_load}" "${feed_rc}" + feed_rc="${?}" + fi + + # build nft file with set and rules for regular downloads + # + if [ "${feed_rc}" = "0" ] && [ ! -s "${tmp_nft}" ]; then + # deduplicate sets + # + if [ "${ban_deduplicate}" = "1" ] && [ "${feed_url}" != "local" ]; then + "${ban_awkcmd}" "${feed_rule}" "${tmp_load}" 2>/dev/null >"${tmp_raw}" + "${ban_awkcmd}" 'NR==FNR{member[$0];next}!($0 in member)' "${ban_tmpfile}.deduplicate" "${tmp_raw}" 2>/dev/null | tee -a "${ban_tmpfile}.deduplicate" >"${tmp_split}" + else + "${ban_awkcmd}" "${feed_rule}" "${tmp_load}" 2>/dev/null >"${tmp_split}" + fi + feed_rc="${?}" + # split sets + # + if [ "${feed_rc}" = "0" ]; then + if [ -n "${ban_splitsize//[![:digit]]/}" ] && [ "${ban_splitsize//[![:digit]]/}" -gt "0" ]; then + if ! "${ban_awkcmd}" "NR%${ban_splitsize//[![:digit]]/}==1{file=\"${tmp_file}.\"++i;}{ORS=\" \";print > file}" "${tmp_split}" 2>/dev/null; then + rm -f "${tmp_file}".* + f_log "info" "failed to split ${feed} set to size '${ban_splitsize//[![:digit]]/}'" + fi + else + "${ban_awkcmd}" '{ORS=" ";print}' "${tmp_split}" 2>/dev/null >"${tmp_file}.1" + fi + feed_rc="${?}" + fi + rm -f "${tmp_raw}" "${tmp_load}" + if [ "${feed_rc}" = "0" ] && [ "${proto}" = "4" ]; then + { + # nft header (IPv4 set) + # + printf "%s\n\n" "#!/usr/sbin/nft -f" + [ -s "${tmp_flush}" ] && cat "${tmp_flush}" + printf "%s\n" "add set inet banIP ${feed} { type ipv4_addr; flags interval; auto-merge; policy memory; $(f_getelements "${tmp_file}.1") }" + + # input and forward rules + # + if [ "${feed_direction}" != "forward" ]; then + printf "%s\n" "add rule inet banIP wan-input ip saddr @${feed} ${nft_loginput} counter drop" + fi + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip daddr @${feed} ${nft_logforward} counter reject with icmp type admin-prohibited" + fi + } >"${tmp_nft}" + elif [ "${feed_rc}" = "0" ] && [ "${proto}" = "6" ]; then + { + # nft header (IPv6 set) + # + printf "%s\n\n" "#!/usr/sbin/nft -f" + [ -s "${tmp_flush}" ] && cat "${tmp_flush}" + printf "%s\n" "add set inet banIP ${feed} { type ipv6_addr; flags interval; auto-merge; policy memory; $(f_getelements "${tmp_file}.1") }" + + # input and forward rules + # + if [ "${feed_direction}" != "forward" ]; then + printf "%s\n" "add rule inet banIP wan-input ip6 saddr @${feed} ${nft_loginput} counter drop" + fi + if [ "${feed_direction}" != "input" ]; then + printf "%s\n" "add rule inet banIP lan-forward ip6 daddr @${feed} ${nft_logforward} counter reject with icmpv6 type admin-prohibited" + fi + } >"${tmp_nft}" + fi + fi + + # load generated nft file in banIP table + # + if [ "${feed_rc}" = "0" ]; then + cnt_dl="$("${ban_awkcmd}" 'END{printf "%d",NR}' "${tmp_split}" 2>/dev/null)" + if [ "${cnt_dl:-"0"}" -gt "0" ] || [ "${feed_url}" = "local" ] || [ "${feed%v*}" = "allowlist" ] || [ "${feed%v*}" = "blocklist" ]; then + feed_log="$("${ban_nftcmd}" -f "${tmp_nft}" 2>&1)" + feed_rc="${?}" + # load additional split files + # + if [ "${feed_rc}" = "0" ]; then + for split_file in "${tmp_file}".*; do + [ ! -f "${split_file}" ] && break + if [ "${split_file##*.}" = "1" ]; then + rm -f "${split_file}" + continue + fi + if ! "${ban_nftcmd}" add element inet banIP "${feed}" "{ $(cat "${split_file}") }" >/dev/null 2>&1; then + f_log "info" "failed to add split file '${split_file##*.}' to ${feed} set" + fi + rm -f "${split_file}" + done + cnt_set="$("${ban_nftcmd}" -j list set inet banIP "${feed}" 2>/dev/null | jsonfilter -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)" + fi + else + f_log "info" "empty feed ${feed} will be skipped" + fi + fi + rm -f "${tmp_split}" "${tmp_nft}" + end_ts="$(date +%s)" + + f_log "debug" "f_down ::: name: ${feed}, cnt_dl: ${cnt_dl:-"-"}, cnt_set: ${cnt_set:-"-"}, split_size: ${ban_splitsize:-"-"}, time: $((end_ts - start_ts)), rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}" +} + +# backup feeds +# +f_backup() { + local backup_rc feed="${1}" feed_file="${2}" + + gzip -cf "${feed_file}" >"${ban_backupdir}/banIP.${feed}.gz" + backup_rc="${?}" + + f_log "debug" "f_backup ::: name: ${feed}, source: ${feed_file##*/}, target: banIP.${feed}.gz, rc: ${backup_rc}" + return ${backup_rc} +} + +# restore feeds +# +f_restore() { + local tmp_feed restore_rc="1" feed="${1}" feed_url="${2}" feed_file="${3}" feed_rc="${4:-"0"}" + + [ "${feed_rc}" != "0" ] && restore_rc="${feed_rc}" + [ "${feed_url}" = "local" ] && tmp_feed="${feed%v*}v4" || tmp_feed="${feed}" + if [ -f "${ban_backupdir}/banIP.${tmp_feed}.gz" ]; then + zcat "${ban_backupdir}/banIP.${tmp_feed}.gz" 2>/dev/null >"${feed_file}" + restore_rc="${?}" + fi + + f_log "debug" "f_restore ::: name: ${feed}, source: banIP.${tmp_feed}.gz, target: ${feed_file##*/}, in_rc: ${feed_rc}, rc: ${restore_rc}" + return ${restore_rc} +} + +# remove disabled feeds +# +f_rmset() { + local tmp_del table_sets input_handles forward_handles handle sets feed feed_log feed_rc + + tmp_del="${ban_tmpfile}.final.delete" + table_sets="$("${ban_nftcmd}" -t list table inet banIP 2>/dev/null | "${ban_awkcmd}" '/^[[:space:]]+set [[:alnum:]]+ /{printf "%s ",$2}' 2>/dev/null)" + input_handles="$("${ban_nftcmd}" -t --handle --numeric list chain inet banIP wan-input 2>/dev/null)" + forward_handles="$("${ban_nftcmd}" -t --handle --numeric list chain inet banIP lan-forward 2>/dev/null)" + { + printf "%s\n\n" "#!/usr/sbin/nft -f" + for feed in ${table_sets}; do + if ! printf "%s" "allowlist blocklist ${ban_feed}" | "${ban_grepcmd}" -q "${feed%v*}"; then + sets="${sets}${feed}/" + rm -f "${ban_backupdir}/banIP.${feed}.gz" + printf "%s\n" "flush set inet banIP ${feed}" + handle="$(printf "%s\n" "${input_handles}" | "${ban_awkcmd}" "/@${feed} /{print \$NF}" 2>/dev/null)" + [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP wan-input handle ${handle}" + handle="$(printf "%s\n" "${forward_handles}" | "${ban_awkcmd}" "/@${feed} /{print \$NF}" 2>/dev/null)" + [ -n "${handle}" ] && printf "%s\n" "delete rule inet banIP lan-forward handle ${handle}" + printf "%s\n\n" "delete set inet banIP ${feed}" + fi + done + } >"${tmp_del}" + + if [ -n "${sets}" ]; then + feed_log="$("${ban_nftcmd}" -f "${tmp_del}" 2>&1)" + feed_rc="${?}" + fi + rm -f "${tmp_del}" + + f_log "debug" "f_rmset ::: sets: ${sets:-"-"}, tmp: ${tmp_del}, rc: ${feed_rc:-"-"}, log: ${feed_log:-"-"}" +} + +# generate status information +# +f_genstatus() { + local object duration nft_table nft_feeds cnt_elements="0" split="0" status="${1}" + + [ -z "${ban_dev}" ] && f_conf + if [ "${status}" = "active" ]; then + if [ -n "${ban_starttime}" ]; then + ban_endtime="$(date "+%s")" + duration="$(((ban_endtime - ban_starttime) / 60))m $(((ban_endtime - ban_starttime) % 60))s" + fi + nft_table="$("${ban_nftcmd}" -t list table inet banIP 2>/dev/null)" + nft_feeds="$(f_trim "$(printf "%s\n" "${nft_table}" | "${ban_awkcmd}" '/^[[:space:]]+set [[:alnum:]]+ /{printf "%s ",$2}')")" + for object in ${nft_feeds}; do + cnt_elements="$((cnt_elements + $("${ban_nftcmd}" -j list set inet banIP "${object}" 2>/dev/null | jsonfilter -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)))" + done + runtime="action: ${ban_action:-"-"}, duration: ${duration:-"-"}, date: $(date "+%Y-%m-%d %H:%M:%S")" + fi + f_system + [ ${ban_splitsize:-"0"} -gt "0" ] && split="1" + + : >"${ban_basedir}/ban_runtime.json" + json_init + json_load_file "${ban_basedir}/ban_runtime.json" >/dev/null 2>&1 + json_add_string "status" "${status}" + json_add_string "version" "${ban_ver}" + json_add_string "element_count" "${cnt_elements}" + json_add_array "active_feeds" + if [ "${status}" != "active" ]; then + json_add_object + json_add_string "feed" "-" + json_close_object + else + for object in ${nft_feeds}; do + json_add_object + json_add_string "feed" "${object}" + json_close_object + done + fi + json_close_array + json_add_array "active_devices" + if [ "${status}" != "active" ]; then + json_add_object + json_add_string "device" "-" + json_close_object + else + for object in ${ban_dev}; do + json_add_object + json_add_string "device" "${object}" + json_close_object + done + fi + json_close_array + json_add_array "active_interfaces" + if [ "${status}" != "active" ]; then + json_add_object + json_add_string "interface" "-" + json_close_object + else + for object in ${ban_ifv4} ${ban_ifv6}; do + json_add_object + json_add_string "interface" "${object}" + json_close_object + done + fi + json_close_array + json_add_array "active_subnets" + if [ "${status}" != "active" ]; then + json_add_object + json_add_string "subnet" "-" + json_close_object + else + for object in ${ban_sub}; do + json_add_object + json_add_string "subnet" "${object}" + json_close_object + done + fi + json_close_array + json_add_string "run_info" "base_dir: ${ban_basedir}, backup_dir: ${ban_backupdir}, report_dir: ${ban_reportdir}, feed_archive: ${ban_feedarchive}" + json_add_string "run_flags" "protocol (4/6): $(f_char ${ban_protov4})/$(f_char ${ban_protov6}), log (inp/fwd): $(f_char ${ban_loginput})/$(f_char ${ban_logforward}), deduplicate: $(f_char ${ban_deduplicate}), split: $(f_char ${split}), allowed only: $(f_char ${ban_allowlistonly})" + json_add_string "last_run" "${runtime:-"-"}" + json_add_string "system_info" "cores: ${ban_cores}, memory: ${ban_memory}, device: ${ban_sysver}" + json_dump >"${ban_basedir}/ban_runtime.json" +} + +# get status information +# +f_getstatus() { + local key keylist type value index_value + + [ -z "${ban_dev}" ] && f_conf + json_load_file "${ban_basedir}/ban_runtime.json" >/dev/null 2>&1 + if json_get_keys keylist; then + printf "%s\n" "::: banIP runtime information" + for key in ${keylist}; do + json_get_var value "${key}" >/dev/null 2>&1 + if [ "${key%_*}" = "active" ]; then + json_select "${key}" >/dev/null 2>&1 + index=1 + while json_get_type type "${index}" && [ "${type}" = "object" ]; do + json_get_values index_value "${index}" >/dev/null 2>&1 + if [ "${index}" = "1" ]; then + value="${index_value}" + else + value="${value}, ${index_value}" + fi + index=$((index + 1)) + done + json_select ".." + fi + value="$( + printf "%s" "${value}" | + awk '{NR=1;max=98;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:-"-"}" + done + else + printf "%s\n" "::: no banIP runtime information available" + fi +} + +# domain lookup +# +f_lookup() { + local cnt list domain lookup ip start_time end_time duration cnt_domain="0" cnt_ip="0" feed="${1}" + + start_time="$(date "+%s")" + if [ "${feed}" = "allowlist" ]; then + list="$("${ban_awkcmd}" '/^([[:alnum:]_-]{1,63}\.)+[[:alpha:]]+([[:space:]]|$)/{printf "%s ",tolower($1)}' "${ban_allowlist}" 2>/dev/null)" + elif [ "${feed}" = "blocklist" ]; then + list="$("${ban_awkcmd}" '/^([[:alnum:]_-]{1,63}\.)+[[:alpha:]]+([[:space:]]|$)/{printf "%s ",tolower($1)}' "${ban_blocklist}" 2>/dev/null)" + fi + + for domain in ${list}; do + lookup="$("${ban_lookupcmd}" "${domain}" ${ban_resolver} 2>/dev/null | "${ban_awkcmd}" '/^Address[ 0-9]*: /{if(!seen[$NF]++)printf "%s ",$NF}' 2>/dev/null)" + for ip in ${lookup}; do + if [ "${ip%%.*}" = "0" ] || [ -z "${ip%%::*}" ]; then + continue + else + if { [ "${feed}" = "allowlist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_allowlist}"; } || + { [ "${feed}" = "blocklist" ] && ! "${ban_grepcmd}" -q "^${ip}" "${ban_blocklist}"; }; then + cnt_ip="$((cnt_ip + 1))" + if [ "${ip##*:}" = "${ip}" ]; then + if ! "${ban_nftcmd}" add element inet banIP "${feed}v4" "{ ${ip} }" >/dev/null 2>&1; then + f_log "info" "failed to add IP '${ip}' (${domain}) to ${feed}v4 set" + continue + fi + else + if ! "${ban_nftcmd}" add element inet banIP "${feed}v6" "{ ${ip} }" >/dev/null 2>&1; then + f_log "info" "failed to add IP '${ip}' (${domain}) to ${feed}v6 set" + continue + fi + fi + if [ "${feed}" = "allowlist" ] && [ "${ban_autoallowlist}" = "1" ]; then + printf "%-42s%s\n" "${ip}" "# ip of '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_allowlist}" + elif [ "${feed}" = "blocklist" ] && [ "${ban_autoblocklist}" = "1" ]; then + printf "%-42s%s\n" "${ip}" "# ip of '${domain}' added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_blocklist}" + fi + fi + fi + done + cnt_domain="$((cnt_domain + 1))" + done + end_time="$(date "+%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}" +} + +# banIP table statistics +# +f_report() { + local report_jsn report_txt set nft_raw nft_sets set_cnt set_input set_forward set_cntinput set_cntforward output="${1}" + local detail set_details jsnval timestamp autoadd_allow autoadd_block sum_sets sum_setinput sum_setforward sum_setelements sum_cntinput sum_cntforward + + [ -z "${ban_dev}" ] && f_conf + f_mkdir "${ban_reportdir}" + report_jsn="${ban_reportdir}/ban_report.jsn" + report_txt="${ban_reportdir}/ban_report.txt" + + # json output preparation + # + nft_raw="$("${ban_nftcmd}" -tj list table inet banIP 2>/dev/null)" + nft_sets="$(printf "%s" "${nft_raw}" | jsonfilter -qe '@.nftables[*].set.name')" + sum_sets="0" + sum_setinput="0" + sum_setforward="0" + sum_setelements="0" + sum_cntinput="0" + sum_cntforward="0" + timestamp="$(date "+%Y-%m-%d %H:%M:%S")" + : >"${report_jsn}" + { + printf "%s\n" "{" + printf "\t%s\n" '"sets": {' + for set in ${nft_sets}; do + set_cnt="$("${ban_nftcmd}" -j list set inet banIP "${set}" 2>/dev/null | jsonfilter -qe '@.nftables[*].set.elem[*]' | wc -l 2>/dev/null)" + sum_setelements="$((sum_setelements + set_cnt))" + set_cntinput="$(printf "%s" "${nft_raw}" | jsonfilter -qe "@.nftables[@.rule.chain=\"wan-input\"][@.expr[*].match.right=\"@${set}\"].expr[*].counter.packets")" + set_cntforward="$(printf "%s" "${nft_raw}" | jsonfilter -qe "@.nftables[@.rule.chain=\"lan-forward\"][@.expr[*].match.right=\"@${set}\"].expr[*].counter.packets")" + if [ -n "${set_cntinput}" ]; then + set_input="OK" + sum_setinput="$((sum_setinput + 1))" + sum_cntinput="$((sum_cntinput + set_cntinput))" + else + set_input="n/a" + set_cntinput="n/a" + fi + if [ -n "${set_cntforward}" ]; then + set_forward="OK" + sum_setforward="$((sum_setforward + 1))" + sum_cntforward="$((sum_cntforward + set_cntforward))" + else + set_forward="n/a" + set_cntforward="n/a" + fi + [ "${sum_sets}" -gt "0" ] && printf "%s\n" "," + printf "\t\t%s\n" "\"${set}\": {" + printf "\t\t\t%s\n" "\"cnt_elements\": \"${set_cnt}\"," + printf "\t\t\t%s\n" "\"input\": \"${set_input}\"," + printf "\t\t\t%s\n" "\"forward\": \"${set_forward}\"," + printf "\t\t\t%s\n" "\"cnt_input\": \"${set_cntinput}\"," + printf "\t\t\t%s\n" "\"cnt_forward\": \"${set_cntforward}\"" + printf "\t\t%s" "}" + sum_sets="$((sum_sets + 1))" + done + printf "\n\t%s\n" "}," + printf "\t%s\n" "\"timestamp\": \"${timestamp}\"," + printf "\t%s\n" "\"autoadd_allow\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_allowlist}")\"," + printf "\t%s\n" "\"autoadd_block\": \"$("${ban_grepcmd}" -c "added on ${timestamp% *}" "${ban_blocklist}")\"," + printf "\t%s\n" "\"sum_sets\": \"${sum_sets}\"," + printf "\t%s\n" "\"sum_setinput\": \"${sum_setinput}\"," + printf "\t%s\n" "\"sum_setforward\": \"${sum_setforward}\"," + printf "\t%s\n" "\"sum_setelements\": \"${sum_setelements}\"," + printf "\t%s\n" "\"sum_cntinput\": \"${sum_cntinput}\"," + printf "\t%s\n" "\"sum_cntforward\": \"${sum_cntforward}\"" + printf "%s\n" "}" + } >>"${report_jsn}" + + # text output preparation + # + if [ "${output}" != "json" ] && [ -s "${report_jsn}" ]; then + : >"${report_txt}" + json_init + if json_load_file "${report_jsn}" >/dev/null 2>&1; then + json_get_var timestamp "timestamp" >/dev/null 2>&1 + json_get_var autoadd_allow "autoadd_allow" >/dev/null 2>&1 + json_get_var autoadd_block "autoadd_block" >/dev/null 2>&1 + json_get_var sum_sets "sum_sets" >/dev/null 2>&1 + json_get_var sum_setinput "sum_setinput" >/dev/null 2>&1 + json_get_var sum_setforward "sum_setforward" >/dev/null 2>&1 + json_get_var sum_setelements "sum_setelements" >/dev/null 2>&1 + json_get_var sum_cntinput "sum_cntinput" >/dev/null 2>&1 + json_get_var sum_cntforward "sum_cntforward" >/dev/null 2>&1 + { + printf "%s\n%s\n%s\n" ":::" "::: banIP Set Statistics" ":::" + printf "%s\n" " Timestamp: ${timestamp}" + printf "%s\n" " ------------------------------" + printf "%s\n" " auto-added to allowlist: ${autoadd_allow}" + printf "%s\n\n" " auto-added to blocklist: ${autoadd_block}" + json_select "sets" >/dev/null 2>&1 + json_get_keys nft_sets >/dev/null 2>&1 + if [ -n "${nft_sets}" ]; then + printf "%-25s%-16s%-16s%-16s%-16s%s\n" " Set" "| Set Elements" "| Chain Input" "| Chain Forward" "| Input Packets" "| Forward Packets" + printf "%s\n" " ---------------------+---------------+---------------+---------------+---------------+----------------" + for set in ${nft_sets}; do + printf " %-21s" "${set}" + json_select "${set}" + json_get_keys set_details + for detail in ${set_details}; do + json_get_var jsnval "${detail}" >/dev/null 2>&1 + printf "%-16s" "| ${jsnval}" + done + printf "\n" + json_select ".." + done + printf "%s\n" " ---------------------+---------------+---------------+---------------+---------------+----------------" + printf "%-25s%-16s%-16s%-16s%-16s%s\n" " ${sum_sets}" "| ${sum_setelements}" "| ${sum_setinput}" "| ${sum_setforward}" "| ${sum_cntinput}" "| ${sum_cntforward}" + fi + } >>"${report_txt}" + fi + fi + + # output channel (text|json|mail) + # + case "${output}" in + "text") + [ -s "${report_txt}" ] && cat "${report_txt}" + ;; + "json") + [ -s "${report_jsn}" ] && cat "${report_jsn}" + ;; + "mail") + [ -x "${ban_mailcmd}" ] && f_mail + ;; + esac +} + +# banIP set search +# +f_search() { + local nft_sets ip proto run_search search="${1}" + + f_system + run_search="/var/run/banIP.search" + + if [ -n "${search}" ]; then + ip="$(printf "%s" "${search}" | "${ban_awkcmd}" 'BEGIN{RS="(([0-9]{1,3}\\.){3}[0-9]{1,3})+"}{printf "%s",RT}')" + [ -n "${ip}" ] && proto="v4" + if [ -z "${proto}" ]; then + ip="$(printf "%s" "${search}" | "${ban_awkcmd}" 'BEGIN{RS="([A-Fa-f0-9]{1,4}::?){3,7}[A-Fa-f0-9]{1,4}"}{printf "%s",RT}')" + [ -n "${ip}" ] && proto="v6" + fi + if [ -n "${proto}" ]; then + nft_sets="$("${ban_nftcmd}" -tj list table inet banIP 2>/dev/null | jsonfilter -qe "@.nftables[@.set.type=\"ip${proto}_addr\"].set.name")" + else + printf "%s\n%s\n%s\n" ":::" "::: no valid search input (single IPv4/IPv6 address)" ":::" + return + fi + else + printf "%s\n%s\n%s\n" ":::" "::: no valid search input (single IPv4/IPv6 address)" ":::" + return + fi + 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" " ---" + cnt=1 + for set in ${nft_sets}; do + ( + if "${ban_nftcmd}" get element inet banIP "${set}" "{ ${ip} }" >/dev/null 2>&1; then + printf "%s\n" " IP found in set ${set}" + : >"${run_search}" + fi + ) & + hold="$((cnt % ban_cores))" + [ "${hold}" = "0" ] && wait + cnt="$((cnt + 1))" + done + wait + [ ! -f "${run_search}" ] && printf "%s\n" " IP not found" + rm -f "${run_search}" +} + +# send status mails +# +f_mail() { + local msmtp_debug + + # load mail template + # + [ ! -r "${ban_mailtemplate}" ] && f_log "err" "the mail template is missing" + . "${ban_mailtemplate}" + + [ -z "${ban_mailreceiver}" ] && f_log "err" "the option 'ban_mailreceiver' is missing" + [ -z "${mail_text}" ] && f_log "err" "the 'mail_text' is empty" + [ "${ban_debug}" = "1" ] && msmtp_debug="--debug" + + # send mail + # + ban_mailhead="From: ${ban_mailsender}\nTo: ${ban_mailreceiver}\nSubject: ${ban_mailtopic}\nReply-to: ${ban_mailsender}\nMime-Version: 1.0\nContent-Type: text/html;charset=utf-8\nContent-Disposition: inline\n\n" + if printf "%b" "${ban_mailhead}${mail_text}" | "${ban_mailcmd}" --timeout=10 ${msmtp_debug} -a "${ban_mailprofile}" "${ban_mailreceiver}" >/dev/null 2>&1; then + f_log "info" "status mail was sent successfully" + else + f_log "info" "failed to send status mail (${?})" + fi + + f_log "debug" "f_mail ::: template: ${ban_mailtemplate}, profile: ${ban_mailprofile}, receiver: ${ban_mailreceiver}, rc: ${?}" +} + +# check banIP availability and initial sourcing +# +if [ "${ban_action}" != "stop" ]; then + if [ -r "/lib/functions.sh" ] && [ -r "/lib/functions/network.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]; then + . "/lib/functions.sh" + . "/lib/functions/network.sh" + . "/usr/share/libubox/jshn.sh" + else + f_log "err" "system libraries not found" + fi + [ ! -d "/etc/banip" ] && f_log "err" "banIP config directory not found, please re-install the package" + [ ! -r "/etc/config/banip" ] && f_log "err" "banIP config not found, please re-install the package" + [ ! -r "/etc/banip/banip.feeds.gz" ] || ! zcat "$(uci_get banip global ban_feedarchive "/etc/banip/banip.feeds.gz")" >"$(uci_get banip global ban_basedir "/tmp")/ban_feeds.json" && f_log "err" "banIP feed archive not found, please re-install the package" + [ "$(uci_get banip global ban_enabled)" = "0" ] && f_log "err" "banIP is currently disabled, please set the config option 'ban_enabled' to '1' to use this service" +fi diff --git a/net/banip/files/banip-service.sh b/net/banip/files/banip-service.sh new file mode 100755 index 000000000..29a0436c9 --- /dev/null +++ b/net/banip/files/banip-service.sh @@ -0,0 +1,193 @@ +#!/bin/sh +# banIP main service script - ban incoming and outgoing ip adresses/subnets via sets in nftables +# Copyright (c) 2018-2023 Dirk Brenken (dev@brenken.org) +# This is free software, licensed under the GNU General Public License v3. + +# (s)hellcheck exceptions +# shellcheck disable=all + +ban_action="${1}" +ban_starttime="$(date "+%s")" +ban_funlib="/usr/lib/banip-functions.sh" +[ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + +# load config and set banIP environment +# +f_conf +f_log "info" "start banIP processing (${ban_action})" +f_genstatus "processing" +f_tmp +f_fetch +f_getif +f_getdev +f_getsub +f_mkdir "${ban_backupdir}" +f_mkfile "${ban_blocklist}" +f_mkfile "${ban_allowlist}" + +# firewall check +# +if [ "${ban_action}" != "reload" ]; then + if [ -x "${ban_fw4cmd}" ]; then + cnt=0 + while [ "${cnt}" -lt "10" ] && ! /etc/init.d/firewall status | grep -q "^active"; do + cnt="$((cnt + 1))" + sleep 1 + done + if ! /etc/init.d/firewall status | grep -q "^active"; then + f_log "err" "nft based firewall/fw4 not functional" + fi + else + f_log "err" "nft based firewall/fw4 not found" + fi +fi + +# init nft namespace +# +if [ "${ban_action}" != "reload" ] || ! "${ban_nftcmd}" -t list table inet banIP >/dev/null 2>&1; then + if f_nftinit "${ban_tmpfile}".init.nft; then + f_log "info" "nft namespace initialized" + else + f_log "err" "nft namespace can't be initialized" + fi +fi + +# handle downloads +# +f_log "info" "start banIP download processes" +if [ "${ban_allowlistonly}" = "1" ]; then + ban_feed="" +else + json_init + if ! json_load_file "${ban_basedir}/ban_feeds.json" >/dev/null 2>&1; then + f_log "err" "banIP feed file can't be loaded" + fi + [ "${ban_deduplicate}" = "1" ] && printf "\n" >"${ban_tmpfile}.deduplicate" +fi + +cnt="1" +for feed in allowlist ${ban_feed} blocklist; do + # local feeds + # + if [ "${feed}" = "allowlist" ] || [ "${feed}" = "blocklist" ]; then + for proto in MAC 4 6; do + [ "${feed}" = "blocklist" ] && wait + (f_down "${feed}" "${proto}") & + [ "${feed}" = "blocklist" ] || { [ "${feed}" = "allowlist" ] && [ "${proto}" = "MAC" ]; } && wait + hold="$((cnt % ban_cores))" + [ "${hold}" = "0" ] && wait + cnt="$((cnt + 1))" + done + wait + continue + fi + + # read external feed information + # + if ! json_select "${feed}" >/dev/null 2>&1; then + continue + fi + json_objects="url_4 rule_4 url_6 rule_6 flag" + for object in ${json_objects}; do + eval json_get_var feed_"${object}" '${object}' >/dev/null 2>&1 + done + json_select .. + # handle IPv4/IPv6 feeds with the same/single download URL + # + if [ "${feed_url_4}" = "${feed_url_6}" ]; then + if [ "${ban_protov4}" = "1" ] && [ -n "${feed_url_4}" ] && [ -n "${feed_rule_4}" ]; then + (f_down "${feed}" "4" "${feed_url_4}" "${feed_rule_4}" "${feed_flag}") & + feed_url_6="local" + wait + fi + if [ "${ban_protov6}" = "1" ] && [ -n "${feed_url_6}" ] && [ -n "${feed_rule_6}" ]; then + (f_down "${feed}" "6" "${feed_url_6}" "${feed_rule_6}" "${feed_flag}") & + hold="$((cnt % ban_cores))" + [ "${hold}" = "0" ] && wait + cnt="$((cnt + 1))" + fi + continue + fi + # handle IPv4/IPv6 feeds with separated download URLs + # + if [ "${ban_protov4}" = "1" ] && [ -n "${feed_url_4}" ] && [ -n "${feed_rule_4}" ]; then + (f_down "${feed}" "4" "${feed_url_4}" "${feed_rule_4}" "${feed_flag}") & + hold="$((cnt % ban_cores))" + [ "${hold}" = "0" ] && wait + cnt="$((cnt + 1))" + fi + if [ "${ban_protov6}" = "1" ] && [ -n "${feed_url_6}" ] && [ -n "${feed_rule_6}" ]; then + (f_down "${feed}" "6" "${feed_url_6}" "${feed_rule_6}" "${feed_flag}") & + hold="$((cnt % ban_cores))" + [ "${hold}" = "0" ] && wait + cnt="$((cnt + 1))" + fi +done +wait + +# start domain lookup +# +f_log "info" "start detached banIP domain lookup" +(f_lookup "allowlist") & +hold="$((cnt % ban_cores))" +[ "${hold}" = "0" ] && wait +(f_lookup "blocklist") & + +# tidy up +# +f_rmset +f_rmdir "${ban_tmpdir}" +f_genstatus "active" +f_log "info" "finished banIP download processes" +rm -rf "${ban_lock}" + +# start log service +# +if [ -x "${ban_logreadcmd}" ] && [ -n "${ban_logterm%%??}" ]; then + f_log "info" "start detached banIP log service" + + nft_expiry="$(printf "%s" "${ban_nftexpiry}" | grep -oE "([0-9]+[h|m|s]$)")" + [ -n "${nft_expiry}" ] && nft_expiry="timeout ${nft_expiry}" + + # read log continuously with given logterms + # + "${ban_logreadcmd}" -fe "${ban_logterm%%??}" 2>/dev/null | + while read -r line; do + # IPv4 log parsing + # + ip="$(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="(([0-9]{1,3}\\.){3}[0-9]{1,3})+"}{if(!seen[RT]++)printf "%s ",RT}')" + ip="$(f_trim "${ip}")" + ip="${ip##* }" + [ -n "${ip}" ] && proto="v4" + if [ -z "${proto}" ]; then + # IPv6 log parsing + # + ip="$(printf "%s" "${line}" | "${ban_awkcmd}" 'BEGIN{RS="([A-Fa-f0-9]{1,4}::?){3,7}[A-Fa-f0-9]{1,4}"}{if(!seen[RT]++)printf "%s ",RT}')" + ip="$(f_trim "${ip}")" + ip="${ip##* }" + [ -n "${ip}" ] && proto="v6" + fi + if [ -n "${proto}" ] && ! "${ban_nftcmd}" get element inet banIP blocklist"${proto}" "{ ${ip} }" >/dev/null 2>&1; then + f_log "info" "suspicious IP found '${ip}'" + log_raw="$("${ban_logreadcmd}" -l "${ban_loglimit}" 2>/dev/null)" + log_count="$(printf "%s\n" "${log_raw}" | grep -c "found '${ip}'")" + if [ "${log_count}" -ge "${ban_logcount}" ]; then + if "${ban_nftcmd}" add element inet banIP "blocklist${proto}" "{ ${ip} ${nft_expiry} }" >/dev/null 2>&1; then + f_log "info" "added IP '${ip}' (${nft_expiry:-"-"}) to blocklist${proto} set" + if [ "${ban_autoblocklist}" = "1" ] && ! grep -q "^${ip}" "${ban_blocklist}"; then + printf "%-42s%s\n" "${ip}" "# added on $(date "+%Y-%m-%d %H:%M:%S")" >>"${ban_blocklist}" + f_log "info" "added IP '${ip}' to local blocklist" + fi + fi + fi + fi + done + +# start no-op service loop +# +else + f_log "info" "start detached no-op banIP service (logterms are missing)" + while :; do + sleep 1 + done +fi diff --git a/net/banip/files/banip.blacklist b/net/banip/files/banip.allowlist similarity index 100% rename from net/banip/files/banip.blacklist rename to net/banip/files/banip.allowlist diff --git a/net/banip/files/banip.maclist b/net/banip/files/banip.blocklist similarity index 100% rename from net/banip/files/banip.maclist rename to net/banip/files/banip.blocklist diff --git a/net/banip/files/banip.conf b/net/banip/files/banip.conf index faae50538..ce0a9cac1 100644 --- a/net/banip/files/banip.conf +++ b/net/banip/files/banip.conf @@ -1,16 +1,9 @@ config banip 'global' option ban_enabled '0' option ban_debug '0' - option ban_mail_enabled '0' - option ban_monitor_enabled '0' - option ban_logsrc_enabled '0' - option ban_logdst_enabled '0' option ban_autodetect '1' - option ban_autoblacklist '1' - option ban_autowhitelist '1' - option ban_nice '0' - option ban_maxqueue '4' - option ban_global_settype 'src+dst' - option ban_target_src 'DROP' - option ban_target_dst 'REJECT' - option ban_loglimit '100' + list ban_logterm 'Exit before auth from' + list ban_logterm 'luci: failed login' + list ban_logterm 'error: maximum authentication attempts exceeded' + list ban_logterm 'sshd.*Connection closed by.*\[preauth\]' + list ban_logterm 'SecurityEvent=\"ChallengeResponseFailed\".*RemoteAddress=' diff --git a/net/banip/files/banip.dns b/net/banip/files/banip.dns deleted file mode 100755 index ab3365056..000000000 --- a/net/banip/files/banip.dns +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh -# helper script to resolve domains for adding to banIP-related IPSets -# Copyright (c) 2020-2021 Dirk Brenken (dev@brenken.org) -# This is free software, licensed under the GNU General Public License v3. - -# (s)hellcheck exceptions -# shellcheck disable=1091,3040 - -export LC_ALL=C -export PATH="/usr/sbin:/usr/bin:/sbin:/bin" -set -o pipefail - -. "/lib/functions.sh" - -ban_src_name="${1}" -ban_src_file="${2}" -ban_tmpbase="$(uci_get banip global ban_tmpbase "/tmp")" -ban_backupdir="$(uci_get banip global ban_backupdir "${ban_tmpbase}/banIP-Backup")" -ban_proto4_enabled="$(uci_get banip global ban_proto4_enabled "0")" -ban_proto6_enabled="$(uci_get banip global ban_proto6_enabled "0")" -ban_ipset_cmd="$(command -v ipset)" -ban_lookup_cmd="$(command -v nslookup)" -ban_logger_cmd="$(command -v logger)" -ban_cnt_err="0" -ban_message="" - -rm -f "${ban_backupdir}/banIP.${ban_src_name}_addon_4" "${ban_backupdir}/banIP.${ban_src_name}_addon_6" -while read -r domain; do - result="$( - "${ban_lookup_cmd}" "${domain}" 2>/dev/null - printf "%s" "${?}" - )" - if [ "$(printf "%s" "${result}" | tail -1)" = "0" ]; then - ips="$(printf "%s" "${result}" | awk '/^Address[ 0-9]*: /{ORS=" ";print $NF}')" - for ip in ${ips}; do - for proto in "4" "6"; do - if { [ "${proto}" = "4" ] && [ "${ban_proto4_enabled}" = "1" ] && [ -n "$("${ban_ipset_cmd}" -q -n list "${ban_src_name}_${proto}")" ] && - [ -n "$(printf "%s" "${ip}" | awk '/^(([0-9]{1,3}\.){3}[0-9]{1,3}(\/[0-9]{1,2})?)([[:space:]]|$)/{print $1}')" ]; } || - { [ "${proto}" = "6" ] && [ "${ban_proto6_enabled}" = "1" ] && [ -n "$("${ban_ipset_cmd}" -q -n list "${ban_src_name}_${proto}")" ] && - [ -n "$(printf "%s" "${ip}" | awk '/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print $1}')" ]; }; then - printf "%s\n" "add ${ban_src_name}_${proto} ${ip}" >>"${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" - fi - done - done - [ -n "${ips}" ] && "${ban_logger_cmd}" -p "debug" -t "banIP-resolve [${$}]" "added IPs of '${domain}' to ${ban_src_name} (${ips})" 2>/dev/null - else - ban_cnt_err=$((ban_cnt_err + 1)) - fi -done <"${ban_src_file}" - -for proto in "4" "6"; do - if { { [ "${proto}" = "4" ] && [ "${ban_proto4_enabled}" = "1" ]; } || { [ "${proto}" = "6" ] && [ "${ban_proto6_enabled}" = "1" ]; }; } && - [ ! -s "${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" ] && [ -s "${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}.gz" ]; then - gzip -df "${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}.gz" 2>/dev/null - "${ban_ipset_cmd}" -q -! restore <"${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" - ban_message="backup used" - elif [ -n "$("${ban_ipset_cmd}" -q -n list "${ban_src_name}_${proto}")" ] && [ -s "${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" ]; then - "${ban_ipset_cmd}" -q -! restore <"${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" - ban_message="${ban_cnt_err} lookup errors" - fi - gzip -f "${ban_backupdir}/banIP.${ban_src_name}_addon_${proto}" 2>/dev/null -done -"${ban_logger_cmd}" -p "info" -t "banIP-resolve [${$}]" "${ban_src_name} domain import has been finished (${ban_message:-"-"})" 2>/dev/null -rm -f "${ban_src_file}" diff --git a/net/banip/files/banip.feeds b/net/banip/files/banip.feeds new file mode 100644 index 000000000..8add8ebe9 --- /dev/null +++ b/net/banip/files/banip.feeds @@ -0,0 +1,295 @@ +{ + "adaway": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adaway-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adaway-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "adaway IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "adguard": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adguard-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adguard-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "adguard IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "adguardtrackers": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adguardtrackers-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/adguardtrackers-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "adguardtracker IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "antipopads": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/antipopads-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/antipopads-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "antipopads IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "asn": { + "url_4": "https://asn.ipinfo.app/api/text/list/", + "url_6": "https://asn.ipinfo.app/api/text/list/", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}", + "focus": "ASN IPs", + "descurl": "https://asn.ipinfo.app" + }, + "backscatterer": { + "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/ips.backscatterer.org.gz", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "backscatterer IPs", + "descurl": "https://www.uceprotect.net/en/index.php", + "flag": "gz" + }, + "bogon": { + "url_4": "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt", + "url_6": "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}", + "focus": "bogon prefixes", + "descurl": "https://team-cymru.com" + }, + "cinsscore": { + "url_4": "https://cinsscore.com/list/ci-badguys.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "suspicious attacker IPs", + "descurl": "https://cinsscore.com/#list" + }, + "country": { + "url_4": "https://www.ipdeny.com/ipblocks/data/aggregated/", + "url_6": "https://www.ipdeny.com/ipv6/ipaddresses/aggregated/", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}", + "focus": "country blocks", + "descurl": "http://www.ipdeny.com/ipblocks" + }, + "darklist": { + "url_4": "https://darklist.de/raw.php", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "suspicious attacker IPs", + "descurl": "https://darklist.de" + }, + "debl": { + "url_4": "https://www.blocklist.de/downloads/export-ips_all.txt", + "url_6": "https://www.blocklist.de/downloads/export-ips_all.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}", + "focus": "fail2ban IP blacklist", + "descurl": "https://www.blocklist.de" + }, + "doh": { + "url_4": "https://raw.githubusercontent.com/dibdot/DoH-IP-blocklists/master/doh-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/DoH-IP-blocklists/master/doh-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "public DoH-Provider", + "descurl": "https://github.com/dibdot/DoH-IP-blocklists" + }, + "drop": { + "url_4": "https://www.spamhaus.org/drop/drop.txt", + "url_6": "https://www.spamhaus.org/drop/dropv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "spamhaus drop compilation", + "descurl": "https://www.spamhaus.org" + }, + "dshield": { + "url_4": "https://feeds.dshield.org/block.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s/%s,\\n\",$1,$3}", + "focus": "dshield IP blocklist", + "descurl": "https://www.dshield.org" + }, + "edrop": { + "url_4": "https://www.spamhaus.org/drop/edrop.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "spamhaus edrop compilation", + "descurl": "https://www.spamhaus.org" + }, + "feodo": { + "url_4": "https://feodotracker.abuse.ch/downloads/ipblocklist.txt", + "rule_4": "BEGIN{RS=\"\\r\\n\"}/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "feodo tracker", + "descurl": "https://feodotracker.abuse.ch" + }, + "firehol1": { + "url_4": "https://iplists.firehol.org/files/firehol_level1.netset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "firehol level 1 compilation", + "descurl": "https://iplists.firehol.org/?ipset=firehol_level1" + }, + "firehol2": { + "url_4": "https://iplists.firehol.org/files/firehol_level2.netset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "firehol level 2 compilation", + "descurl": "https://iplists.firehol.org/?ipset=firehol_level2" + }, + "firehol3": { + "url_4": "https://iplists.firehol.org/files/firehol_level3.netset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "firehol level 3 compilation", + "descurl": "https://iplists.firehol.org/?ipset=firehol_level3" + }, + "firehol4": { + "url_4": "https://iplists.firehol.org/files/firehol_level4.netset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{if(!seen[$1]++)printf \"%s,\\n\",$1}", + "focus": "firehol level 4 compilation", + "descurl": "https://iplists.firehol.org/?ipset=firehol_level4" + }, + "greensnow": { + "url_4": "https://blocklist.greensnow.co/greensnow.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "suspicious server IPs", + "descurl": "https://greensnow.co" + }, + "iblockads": { + "url_4": "https://list.iblocklist.com/?list=dgxtneitpuvgqqcpfulq&fileformat=cidr&archiveformat=gz", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "advertising IPs", + "descurl": "https://www.iblocklist.com", + "flag": "gz", + "login": true + }, + "iblockspy": { + "url_4": "https://list.iblocklist.com/?list=llvtlsjyoyiczbkjsxpf&fileformat=cidr&archiveformat=gz", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "malicious spyware IPs", + "descurl": "https://www.iblocklist.com", + "flag": "gz", + "login": true + }, + "myip": { + "url_4": "https://myip.ms/files/blacklist/general/latest_blacklist.txt", + "url_6": "https://myip.ms/files/blacklist/general/latest_blacklist.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "real-time IP blocklist", + "descurl": "https://myip.ms" + }, + "nixspam": { + "url_4": "https://www.nixspam.net/download/nixspam-ip.dump.gz", + "rule_4": "/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$2}", + "focus": "iX spam protection", + "descurl": "https://www.nixspam.net", + "flag": "gz" + }, + "oisdnsfw": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/oisdnsfw-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/oisdnsfw-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "OISD-nsfw IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "oisdsmall": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/oisdsmall-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/oisdsmall-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "OISD-small IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "proxy": { + "url_4": "https://iplists.firehol.org/files/proxylists.ipset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "open proxies", + "descurl": "https://iplists.firehol.org/?ipset=proxylists" + }, + "sslbl": { + "url_4": "https://sslbl.abuse.ch/blacklist/sslipblacklist.csv", + "rule_4": "BEGIN{FS=\",\"}/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)/{printf \"%s,\\n\",$2}", + "focus": "SSL botnet IPs", + "descurl": "https://sslbl.abuse.ch" + }, + "stevenblack": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/stevenblack-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/stevenblack-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "stevenblack IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + }, + "talos": { + "url_4": "https://www.talosintelligence.com/documents/ip-blacklist", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "talos IPs", + "descurl": "https://talosintelligence.com/reputation_center" + }, + "threat": { + "url_4": "https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "emerging threats", + "descurl": "https://rules.emergingthreats.net" + }, + "threatview": { + "url_4": "https://threatview.io/Downloads/IP-High-Confidence-Feed.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "malicious IPs", + "descurl": "https://threatview.io" + }, + "tor": { + "url_4": "https://raw.githubusercontent.com/SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst", + "url_6": "https://raw.githubusercontent.com/SecOps-Institute/Tor-IP-Addresses/master/tor-exit-nodes.lst", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)$/{printf \"%s,\\n\",$1}", + "focus": "tor exit nodes", + "descurl": "https://github.com/SecOps-Institute/Tor-IP-Addresses" + }, + "uceprotect1": { + "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-1.uceprotect.net.gz", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "spam protection level 1", + "descurl": "http://www.uceprotect.net/en/index.php", + "flag": "gz" + }, + "uceprotect2": { + "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-2.uceprotect.net.gz", + "rule_4": "BEGIN{IGNORECASE=1}/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]NET)/{printf \"%s,\\n\",$1}", + "focus": "spam protection level 2", + "descurl": "http://www.uceprotect.net/en/index.php", + "flag": "gz" + }, + "uceprotect3": { + "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-3.uceprotect.net.gz", + "rule_4": "BEGIN{IGNORECASE=1}/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]YOUR)/{printf \"%s,\\n\",$1}", + "focus": "spam protection level 3", + "descurl": "http://www.uceprotect.net/en/index.php", + "flag": "gz" + }, + "urlhaus": { + "url_4": "https://urlhaus.abuse.ch/downloads/ids/", + "rule_4": "match($0,/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]))/){printf \"%s,\\n\",substr($0,RSTART,RLENGTH)}", + "focus": "urlhaus IDS IPs", + "descurl": "https://urlhaus.abuse.ch" + }, + "urlvir": { + "url_4": "https://iplists.firehol.org/files/urlvir.ipset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "malware related IPs", + "descurl": "https://iplists.firehol.org/?ipset=urlvir" + }, + "voip": { + "url_4": "https://voipbl.org/update/", + "rule_4": "BEGIN{RS=\"(([0-9]{1,3}\\\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)\"}{if(RT)printf \"%s,\\n\",RT}", + "focus": "VoIP fraud blocklist", + "descurl": "https://voipbl.org" + }, + "webclient": { + "url_4": "https://iplists.firehol.org/files/firehol_webclient.netset", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{printf \"%s,\\n\",$1}", + "focus": "malware related IPs", + "descurl": "https://iplists.firehol.org/?ipset=firehol_webclient" + }, + "yoyo": { + "url_4": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/yoyo-ipv4.txt", + "url_6": "https://raw.githubusercontent.com/dibdot/banIP-IP-blocklists/main/yoyo-ipv6.txt", + "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)[[:space:]]/{printf \"%s,\\n\",$1}", + "focus": "yoyo IPs", + "descurl": "https://github.com/dibdot/banIP-IP-blocklists" + } +} diff --git a/net/banip/files/banip.hotplug b/net/banip/files/banip.hotplug deleted file mode 100644 index 436a3a63c..000000000 --- a/net/banip/files/banip.hotplug +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# firewall hotplug script for banIP -# Copyright (c) 2019-2021 Dirk Brenken (dev@brenken.org) -# This is free software, licensed under the GNU General Public License v3. - -if /etc/init.d/banip enabled && [ "${ACTION}" = "add" ] && [ -n "${INTERFACE}" ]; then - if [ ! -s "/var/run/banip.pid" ] && uci_get banip global ban_ifaces | grep -q "${INTERFACE}"; then - /etc/init.d/banip refresh - fi -fi diff --git a/net/banip/files/banip.init b/net/banip/files/banip.init index 08405e608..ab126f230 100755 --- a/net/banip/files/banip.init +++ b/net/banip/files/banip.init @@ -1,202 +1,69 @@ #!/bin/sh /etc/rc.common -# Copyright (c) 2018-2021 Dirk Brenken (dev@brenken.org) +# banIP init script - ban incoming and outgoing ip adresses/subnets via sets in nftables +# Copyright (c) 2018-2023 Dirk Brenken (dev@brenken.org) # This is free software, licensed under the GNU General Public License v3. # (s)hellcheck exceptions -# shellcheck disable=1091,2034,3043,3057,3060 +# shellcheck disable=all START=30 USE_PROCD=1 -if type extra_command >/dev/null 2>&1; then - extra_command "refresh" "Refresh ipsets without new list downloads" - extra_command "suspend" "Suspend banIP processing" - extra_command "resume" "Resume banIP processing" - extra_command "query" " Query active banIP IPSets for a specific IP address" - extra_command "report" "[|||] Print banIP related IPset statistics" - extra_command "list" "[|||||] List/Edit available sources" - extra_command "timer" "[ [] []]|[ ] List/Edit cron update intervals" -else - EXTRA_COMMANDS="status refresh suspend resume query report list timer version" - EXTRA_HELP=" status Service status - refresh Refresh ipsets without new list downloads - suspend Suspend banIP processing - resume Resume banIP processing - query Query active banIP IPSets for a specific IP address - report [|||] Print banIP related IPset statistics - list [|||||] List/Edit available sources - timer [ [] []]|[ ] List/Edit cron update intervals" -fi +extra_command "report" "[text|json|mail] Print banIP related set statistics" +extra_command "search" "[|] Check if an element exists in the banIP sets" ban_init="/etc/init.d/banip" -ban_script="/usr/bin/banip.sh" +ban_service="/usr/bin/banip-service.sh" +ban_funlib="/usr/lib/banip-functions.sh" ban_pidfile="/var/run/banip.pid" +ban_lock="/var/run/banip.lock" -if [ -s "${ban_pidfile}" ] && { [ "${action}" = "start" ] || [ "${action}" = "stop" ] || - [ "${action}" = "restart" ] || [ "${action}" = "reload" ] || [ "${action}" = "refresh" ] || - [ "${action}" = "suspend" ] || [ "${action}" = "resume" ] || [ "${action}" = "query" ] || - { [ "${action}" = "list" ] && [ -n "${1}" ]; } || { [ "${action}" = "report" ] && [ "${1}" != "json" ]; }; }; then - exit 0 -fi +[ ! -r "${ban_funlib}" ] && exit 1 +[ "${action}" = "stop" ] && ! /etc/init.d/banip running && exit 0 +[ -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && exit 1 +[ ! -d "${ban_lock}" ] && { [ "${action}" = "start" ] || [ "${action}" = "restart" ] || [ "${action}" = "reload" ]; } && mkdir -p "${ban_lock}" boot() { : >"${ban_pidfile}" - rc_procd start_service + rc_procd start_service "boot" } start_service() { if "${ban_init}" enabled; then - if [ "${action}" = "boot" ]; then - return 0 - fi - procd_open_instance "banip" - procd_set_param command "${ban_script}" "${@}" + [ "${action}" = "boot" ] && [ -n "$(uci_get banip global ban_trigger)" ] && return 0 + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_rmpid + procd_open_instance "banip-service" + procd_set_param command "${ban_service}" "${@:-"${action}"}" procd_set_param pidfile "${ban_pidfile}" - procd_set_param nice "$(uci_get banip global ban_nice "0")" + procd_set_param nice "$(uci_get banip global ban_nicelimit "0")" + procd_set_param limits nofile="$(uci_get banip global ban_filelimit "1024")" procd_set_param stdout 1 procd_set_param stderr 1 procd_close_instance + else + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_log "err" "banIP service autostart is currently disabled, please enable the service autostart with '/etc/init.d/banip enable'" + rm -rf "${ban_lock}" fi } -version() { - rc_procd "${ban_script}" version -} - -refresh() { - rc_procd start_service refresh -} - reload_service() { - rc_procd start_service reload + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_rmpid + rc_procd start_service "reload" } stop_service() { - rc_procd "${ban_script}" stop + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + "${ban_nftcmd}" delete table inet banIP >/dev/null 2>&1 + f_genstatus "stopped" + f_rmpid } restart() { - rc_procd start_service restart -} - -suspend() { - rc_procd start_service suspend -} - -resume() { - rc_procd start_service resume -} - -query() { - rc_procd "${ban_script}" query "${1}" -} - -list() { - local src_archive src_file src_enabled key name enabled focus descurl url_4 rule_4 url_6 rule_6 action="${1}" - - if [ "${action%_*}" = "add" ] || [ "${action%_*}" = "remove" ]; then - shift - for name in "${@}"; do - case "${action}" in - "add") - if ! uci_get banip global ban_sources | grep -q "${name}"; then - uci_add_list banip global ban_sources "${name}" - printf "%s\n" "::: banIP source '${name}' added to config" - fi - ;; - "remove") - if uci_get banip global ban_sources | grep -q "${name}"; then - uci_remove_list banip global ban_sources "${name}" - printf "%s\n" "::: banIP source '${name}' removed from config" - fi - ;; - "add_asn") - if ! uci_get banip global ban_asns | grep -q "${name}"; then - uci_add_list banip global ban_asns "${name}" - printf "%s\n" "::: banIP asn '${name}' added to config" - fi - ;; - "remove_asn") - if uci_get banip global ban_asns | grep -q "${name}"; then - uci_remove_list banip global ban_asns "${name}" - printf "%s\n" "::: banIP asn '${name}' removed from config" - fi - ;; - "add_country") - if ! uci_get banip global ban_countries | grep -q "${name}"; then - uci_add_list banip global ban_countries "${name}" - printf "%s\n" "::: banIP country '${name}' added to config" - fi - ;; - "remove_country") - if uci_get banip global ban_countries | grep -q "${name}"; then - uci_remove_list banip global ban_countries "${name}" - printf "%s\n" "::: banIP country '${name}' removed from config" - fi - ;; - esac - done - if [ -n "$(uci -q changes banip)" ]; then - uci_commit banip - "${ban_init}" start - fi - else - src_archive="$(uci_get banip global ban_srcarc "/etc/banip/banip.sources.gz")" - src_file="$(uci_get banip global ban_srcfile "/tmp/ban_sources.json")" - src_enabled="$(uci -q show banip.global.ban_sources)" - if [ -r "${src_archive}" ]; then - zcat "${src_archive}" >"${src_file}" - else - printf "%s\n" "::: banIP source archive '${src_archive}' not found" - fi - if [ -r "${src_file}" ]; then - src_enabled="${src_enabled#*=}" - src_enabled="${src_enabled//\'/}" - printf "%s\n" "::: Available banIP sources" - printf "%s\n" ":::" - printf "%-25s%-10s%-36s%s\n" " Name" "Enabled" "Focus" "Info URL" - printf "%s\n" " ---------------------------------------------------------------------------" - json_load_file "${src_file}" - json_get_keys keylist - for key in ${keylist}; do - json_select "${key}" - json_get_var focus "focus" - json_get_var descurl "descurl" - json_get_var url_4 "url_4" - json_get_var rule_4 "rule_4" - json_get_var url_6 "url_6" - json_get_var rule_6 "rule_6" - if { [ -n "${url_4}" ] && [ -n "${rule_4}" ]; } || { [ -n "${url_6}" ] && [ -n "${rule_6}" ]; }; then - if printf "%s" "${src_enabled}" | grep -q "${key}"; then - enabled="x" - else - enabled=" " - fi - src_enabled="${src_enabled/${key}/}" - printf " + %-21s%-10s%-36s%s\n" "${key:0:20}" "${enabled}" "${focus:0:35}" "${descurl:0:50}" - else - src_enabled="${src_enabled} ${key}" - fi - json_select .. - done - asn_list="$(uci_get banip global ban_asns "-")" - country_list="$(uci_get banip global ban_countries "-")" - printf "%s\n" " ---------------------------------------------------------------------------" - printf " * %s\n" "Configured ASNs: ${asn_list// /, }" - printf " * %s\n" "Configured Countries: ${country_list// /, }" - - if [ -n "${src_enabled// /}" ]; then - printf "%s\n" " ---------------------------------------------------------------------------" - printf "%s\n" " Sources without valid configuration" - printf "%s\n" " ---------------------------------------------------------------------------" - for key in ${src_enabled}; do - printf " - %s\n" "${key:0:20}" - done - fi - else - printf "%s\n" "::: banIP source file '${src_file}' not found" - fi - fi + stop_service + rc_procd start_service "restart" } status() { @@ -204,90 +71,29 @@ status() { } status_service() { - local key keylist type value index_value values rtfile - - rtfile="$(uci_get banip global ban_rtfile "/tmp/ban_runtime.json")" - - json_load_file "${rtfile}" >/dev/null 2>&1 - json_get_keys keylist - if [ -n "${keylist}" ]; then - printf "%s\n" "::: banIP runtime information" - for key in ${keylist}; do - json_get_var value "${key}" >/dev/null 2>&1 - if [ "${key%_*}" = "active" ]; then - printf " + %-15s : " "${key}" - json_select "${key}" >/dev/null 2>&1 - values="" - index=1 - while json_get_type type "${index}" && [ "${type}" = "object" ]; do - json_get_values index_value "${index}" >/dev/null 2>&1 - if [ "${index}" = "1" ]; then - values="${index_value}" - else - values="${values}, ${index_value}" - fi - index=$((index + 1)) - done - values="$(printf "%s" "${values}" | awk '{NR=1;max=98;if(length($0)>max+1)while($0){if(NR==1){print substr($0,1,max)}else{printf"%-22s%s\n","",substr($0,1,max)}{$0=substr($0,max+1);NR=NR+1}}else print}')" - printf "%s\n" "${values:-"-"}" - json_select ".." - else - printf " + %-15s : %s\n" "${key}" "${value:-"-"}" - fi - done - else - printf "%s\n" "::: no banIP runtime information available" - fi + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_getstatus } report() { - rc_procd "${ban_script}" report "${1:-"cli"}" + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_report "${1:-"text"}" } -timer() { - local cron_file cron_content cron_lineno action="${1:-"list"}" cron_tasks="${2}" hour="${3}" minute="${4:-0}" weekday="${5:-"*"}" - - cron_file="/etc/crontabs/root" - - if [ -s "${cron_file}" ] && [ "${action}" = "list" ]; then - awk '{print NR "> " $0}' "${cron_file}" - elif [ "${action}" = "add" ]; then - hour="${hour//[[:alpha:]]/}" - minute="${minute//[[:alpha:]]/}" - if [ -n "${cron_tasks}" ] && [ -n "${hour}" ] && [ -n "${minute}" ] && [ -n "${weekday}" ] && - [ "${hour}" -ge 0 ] && [ "${hour}" -le 23 ] && - [ "${minute}" -ge 0 ] && [ "${minute}" -le 59 ]; then - printf "%02d %02d %s\n" "${minute}" "${hour}" "* * ${weekday} ${ban_init} ${cron_tasks}" >>"${cron_file}" - /etc/init.d/cron restart - fi - elif [ -s "${cron_file}" ] && [ "${action}" = "remove" ]; then - cron_tasks="${cron_tasks//[[:alpha:]]/}" - cron_lineno="$(awk 'END{print NR}' "${cron_file}")" - cron_content="$(awk '{print $0}' "${cron_file}")" - if [ "${cron_tasks:-"0"}" -le "${cron_lineno:-"1"}" ] && [ -n "${cron_content}" ]; then - printf "%s\n" "${cron_content}" | awk "NR!~/^${cron_tasks}$/" >"${cron_file}" - /etc/init.d/cron restart - fi - fi +search() { + [ -z "$(command -v "f_system")" ] && . "${ban_funlib}" + f_search "${1}" } service_triggers() { - local iface delay + local iface trigger delay - iface="$(uci_get banip global ban_trigger)" + trigger="$(uci_get banip global ban_trigger)" delay="$(uci_get banip global ban_triggerdelay "5")" PROCD_RELOAD_DELAY=$((delay * 1000)) - if [ -z "${iface}" ]; then - . "/lib/functions/network.sh" - network_find_wan iface - if [ -n "${iface}" ]; then - uci_set banip global ban_trigger "${iface}" - uci_commit "banip" - fi - fi - if [ -n "${iface}" ]; then + for iface in ${trigger}; do procd_add_interface_trigger "interface.*.up" "${iface}" "${ban_init}" "start" - fi + done procd_add_reload_trigger "banip" } diff --git a/net/banip/files/banip.mail b/net/banip/files/banip.mail deleted file mode 100755 index a89b92df3..000000000 --- a/net/banip/files/banip.mail +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh -# send mail script for banIP notifications -# Copyright (c) 2020-2021 Dirk Brenken (dev@brenken.org) -# This is free software, licensed under the GNU General Public License v3. - -# (s)hellcheck exceptions -# shellcheck disable=1091,3040 - -# Please note: you have to setup the package 'msmtp' before using this script - -export LC_ALL=C -export PATH="/usr/sbin:/usr/bin:/sbin:/bin" -set -o pipefail - -. "/lib/functions.sh" -ban_debug="$(uci_get banip global ban_debug "0")" -ban_loglimit="$(uci_get banip global ban_loglimit "100")" -ban_mailsender="$(uci_get banip global ban_mailsender "no-reply@banIP")" -ban_mailreceiver="$(uci_get banip global ban_mailreceiver)" -ban_mailtopic="$(uci_get banip global ban_mailtopic "banIP notification")" -ban_mailprofile="$(uci_get banip global ban_mailprofile "ban_notify")" - -ban_mail="$(command -v msmtp)" -ban_logger="$(command -v logger)" -ban_logread="$(command -v logread)" - -if [ -z "${ban_mailreceiver}" ]; then - f_log "err" "please set the mail receiver with the 'ban_mailreceiver' option" - exit 1 -fi - -if [ "${ban_debug}" = "1" ]; then - msmtp_debug="--debug" -fi - -ban_mailhead="From: ${ban_mailsender}\nTo: ${ban_mailreceiver}\nSubject: ${ban_mailtopic}\nReply-to: ${ban_mailsender}\nMime-Version: 1.0\nContent-Type: text/html;charset=utf-8\nContent-Disposition: inline\n\n" - -# info preparation -# -sys_info="$( - strings /etc/banner 2>/dev/null - ubus call system board | awk 'BEGIN{FS="[{}\"]"}{if($2=="kernel"||$2=="hostname"||$2=="system"||$2=="model"||$2=="description")printf " + %-12s: %s\n",$2,$4}' -)" -ban_info="$(/etc/init.d/banip "status" 2>/dev/null)" -rep_info="${1}" -log_info="$("${ban_logread}" -l "${ban_loglimit}" -e "banIP-" 2>/dev/null | awk '{NR=1;max=120;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}')" - -# mail body -# -ban_mailtext="
"
-ban_mailtext="${ban_mailtext}\n++\n++ System Information ++\n++\n${sys_info}"
-ban_mailtext="${ban_mailtext}\n\n++\n++ banIP Status ++\n++\n${ban_info}"
-if [ -n "${rep_info}" ]; then
-	ban_mailtext="${ban_mailtext}\n\n++\n++ banIP Report ++\n++\n${rep_info}"
-fi
-ban_mailtext="${ban_mailtext}\n\n++\n++ Logfile Information ++\n++\n${log_info}"
-ban_mailtext="${ban_mailtext}
" - -# send mail -# -printf "%b" "${ban_mailhead}${ban_mailtext}" 2>/dev/null | "${ban_mail}" ${msmtp_debug} -a "${ban_mailprofile}" "${ban_mailreceiver}" >/dev/null 2>&1 -"${ban_logger}" -p "info" -t "banIP-mail [${$}]" "mail sent to '${ban_mailreceiver}' with rc '${?}'" 2>/dev/null diff --git a/net/banip/files/banip.service b/net/banip/files/banip.service deleted file mode 100755 index 12e7bda2f..000000000 --- a/net/banip/files/banip.service +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# log service to trace suspicious logins and conditionally refresh banIP -# Copyright (c) 2019-2021 Dirk Brenken (dev@brenken.org) -# This is free software, licensed under the GNU General Public License v3. - -# (s)hellcheck exceptions -# shellcheck disable=3040 - -export LC_ALL=C -export PATH="/usr/sbin:/usr/bin:/sbin:/bin" -set -o pipefail - -ban_search="${1}" -ban_logger_cmd="$(command -v logger)" -ban_logread_cmd="$(command -v logread)" - -if [ -x "${ban_logread_cmd}" ]; then - "${ban_logger_cmd}" -p "info" -t "banIP-service [${$}]" "log/banIP service started" 2>/dev/null - "${ban_logread_cmd}" -f | - { - grep -qE "${ban_search}" && { - /etc/init.d/banip refresh - exit 0 - } - } -else - "${ban_logger_cmd}" -p "err" -t "banIP-service [${$}]" "can't start log/banIP service" 2>/dev/null -fi diff --git a/net/banip/files/banip.sh b/net/banip/files/banip.sh deleted file mode 100755 index 8672ead22..000000000 --- a/net/banip/files/banip.sh +++ /dev/null @@ -1,1595 +0,0 @@ -#!/bin/sh -# banIP - ban incoming and outgoing ip adresses/subnets via ipset -# Copyright (c) 2018-2021 Dirk Brenken (dev@brenken.org) -# This is free software, licensed under the GNU General Public License v3. - -# (s)hellcheck exceptions -# shellcheck disable=1091,2030,2031,2086,2183,3040,3043,3060 - -# set initial defaults -# -export LC_ALL=C -export PATH="/usr/sbin:/usr/bin:/sbin:/bin" -set -o pipefail -ban_ver="0.7.10" -ban_status="" -ban_enabled="0" -ban_mail_enabled="0" -ban_proto4_enabled="0" -ban_proto6_enabled="0" -ban_logsrc_enabled="0" -ban_logdst_enabled="0" -ban_monitor_enabled="0" -ban_autodetect="1" -ban_autoblacklist="1" -ban_autowhitelist="1" -ban_whitelistonly="0" -ban_logterms="" -ban_loglimit="100" -ban_ssh_logcount="3" -ban_luci_logcount="3" -ban_nginx_logcount="5" -ban_mailactions="" -ban_search="" -ban_devs="" -ban_ifaces="" -ban_debug="0" -ban_maxqueue="4" -ban_fetchutil="" -ban_fetchinsecure="0" -ban_ip_cmd="$(command -v ip)" -ban_ipt4_cmd="$(command -v iptables)" -ban_ipt4_savecmd="$(command -v iptables-save)" -ban_ipt4_restorecmd="$(command -v iptables-restore)" -ban_ipt6_cmd="$(command -v ip6tables)" -ban_ipt6_savecmd="$(command -v ip6tables-save)" -ban_ipt6_restorecmd="$(command -v ip6tables-restore)" -ban_ipset_cmd="$(command -v ipset)" -ban_logger_cmd="$(command -v logger)" -ban_logread_cmd="$(command -v logread)" -ban_allsources="" -ban_extrasources="" -ban_sources="" -ban_asns="" -ban_countries="" -ban_settype_src="" -ban_settype_dst="" -ban_settype_all="" -ban_lan_inputchains_4="" -ban_lan_inputchains_6="" -ban_lan_forwardchains_4="" -ban_lan_forwardchains_6="" -ban_wan_inputchains_4="" -ban_wan_inputchains_6="" -ban_wan_forwardchains_4="" -ban_wan_forwardchains_6="" -ban_action="${1:-"start"}" -ban_pidfile="/var/run/banip.pid" -ban_bgpidfile="/var/run/banip_bg.pid" -ban_tmpbase="/tmp" -ban_rtfile="${ban_tmpbase}/ban_runtime.json" -ban_srcfile="${ban_tmpbase}/ban_sources.json" -ban_reportdir="${ban_tmpbase}/banIP-Report" -ban_backupdir="${ban_tmpbase}/banIP-Backup" -ban_srcarc="/etc/banip/banip.sources.gz" -ban_dnsservice="/etc/banip/banip.dns" -ban_mailservice="/etc/banip/banip.mail" -ban_logservice="/etc/banip/banip.service" -ban_maclist="/etc/banip/banip.maclist" -ban_blacklist="/etc/banip/banip.blacklist" -ban_whitelist="/etc/banip/banip.whitelist" -ban_setcnt="0" -ban_cnt="0" - -# load environment -# -f_load() { - ban_sysver="$(ubus -S call system board 2>/dev/null | jsonfilter -q -e '@.model' -e '@.release.description' | - awk 'BEGIN{RS="";FS="\n"}{printf "%s, %s",$1,$2}')" - - f_conf - if [ "${ban_enabled}" = "0" ]; then - f_bgsrv "stop" - f_ipset "destroy" - f_jsnup "disabled" - f_rmbckp - f_rmtmp - f_log "info" "banIP is currently disabled, please set the config option 'ban_enabled' to '1' to use this service" - exit 0 - fi - f_dir "${ban_backupdir}" - f_dir "${ban_reportdir}" -} - -# check/create directories -# -f_dir() { - local dir="${1}" - - if [ -d "${dir}" ]; then - f_log "debug" "directory '${dir}' is used" - else - rm -f "${dir}" - mkdir -p "${dir}" - f_log "debug" "directory '${dir}' created" - fi -} - -# load banIP config -# -f_conf() { - if [ ! -r "/etc/config/banip" ] || [ -z "$(uci -q show banip.global.ban_autodetect)" ]; then - f_log "err" "no valid banIP config found, please re-install the package via opkg with the '--force-reinstall --force-maintainer' options" - fi - - config_cb() { - option_cb() { - local option="${1}" - local value="${2}" - eval "${option}=\"${value}\"" - } - list_cb() { - local option="${1}" - local value="${2}" - if [ "${option}" = "ban_ifaces" ]; then - eval "${option}=\"$(printf "%s" "${ban_ifaces}")${value} \"" - elif [ "${option}" = "ban_sources" ]; then - eval "${option}=\"$(printf "%s" "${ban_sources}")${value} \"" - elif [ "${option}" = "ban_localsources" ]; then - eval "${option}=\"$(printf "%s" "${ban_localsources}")${value} \"" - elif [ "${option}" = "ban_extrasources" ]; then - eval "${option}=\"$(printf "%s" "${ban_extrasources}")${value} \"" - elif [ "${option}" = "ban_settype_src" ]; then - eval "${option}=\"$(printf "%s" "${ban_settype_src}")${value} \"" - elif [ "${option}" = "ban_settype_dst" ]; then - eval "${option}=\"$(printf "%s" "${ban_settype_dst}")${value} \"" - elif [ "${option}" = "ban_settype_all" ]; then - eval "${option}=\"$(printf "%s" "${ban_settype_all}")${value} \"" - elif [ "${option}" = "ban_mailactions" ]; then - eval "${option}=\"$(printf "%s" "${ban_mailactions}")${value} \"" - elif [ "${option}" = "ban_logterms" ]; then - eval "${option}=\"$(printf "%s" "${ban_logterms}")${value} \"" - elif [ "${option}" = "ban_countries" ]; then - eval "${option}=\"$(printf "%s" "${ban_countries}")${value} \"" - elif [ "${option}" = "ban_asns" ]; then - eval "${option}=\"$(printf "%s" "${ban_asns}")${value} \"" - elif [ "${option}" = "ban_lan_inputchains_4" ]; then - eval "${option}=\"$(printf "%s" "${ban_lan_inputchains_4}")${value} \"" - elif [ "${option}" = "ban_lan_inputchains_6" ]; then - eval "${option}=\"$(printf "%s" "${ban_lan_inputchains_6}")${value} \"" - elif [ "${option}" = "ban_lan_forwardchains_4" ]; then - eval "${option}=\"$(printf "%s" "${ban_lan_forwardchains_4}")${value} \"" - elif [ "${option}" = "ban_lan_forwardchains_6" ]; then - eval "${option}=\"$(printf "%s" "${ban_lan_forwardchains_6}")${value} \"" - elif [ "${option}" = "ban_wan_inputchains_4" ]; then - eval "${option}=\"$(printf "%s" "${ban_wan_inputchains_4}")${value} \"" - elif [ "${option}" = "ban_wan_inputchains_6" ]; then - eval "${option}=\"$(printf "%s" "${ban_wan_inputchains_6}")${value} \"" - elif [ "${option}" = "ban_wan_forwardchains_4" ]; then - eval "${option}=\"$(printf "%s" "${ban_wan_forwardchains_4}")${value} \"" - elif [ "${option}" = "ban_wan_forwardchains_6" ]; then - eval "${option}=\"$(printf "%s" "${ban_wan_forwardchains_6}")${value} \"" - fi - } - } - config_load banip - - ban_chain="${ban_chain:-"banIP"}" - ban_global_settype="${ban_global_settype:-"src+dst"}" - ban_target_src="${ban_target_src:-"DROP"}" - ban_target_dst="${ban_target_dst:-"REJECT"}" - ban_lan_inputchains_4="${ban_lan_inputchains_4:-"input_lan_rule"}" - ban_lan_inputchains_6="${ban_lan_inputchains_6:-"input_lan_rule"}" - ban_lan_forwardchains_4="${ban_lan_forwardchains_4:-"forwarding_lan_rule"}" - ban_lan_forwardchains_6="${ban_lan_forwardchains_6:-"forwarding_lan_rule"}" - ban_wan_inputchains_4="${ban_wan_inputchains_4:-"input_wan_rule"}" - ban_wan_inputchains_6="${ban_wan_inputchains_6:-"input_wan_rule"}" - ban_wan_forwardchains_4="${ban_wan_forwardchains_4:-"forwarding_wan_rule"}" - ban_wan_forwardchains_6="${ban_wan_forwardchains_6:-"forwarding_wan_rule"}" - ban_logchain_src="${ban_logchain_src:-"${ban_chain}_log_src"}" - ban_logchain_dst="${ban_logchain_dst:-"${ban_chain}_log_dst"}" - ban_logtarget_src="${ban_target_src}" - ban_logtarget_dst="${ban_target_dst}" - if [ "${ban_logsrc_enabled}" = "1" ]; then - ban_logprefix_src="${ban_logprefix_src:-"[banIP-${ban_ver%-*}, src/${ban_target_src}] "}" - ban_logopts_src="${ban_logopts_src:-"-m limit --limit 2/sec"}" - ban_target_src="${ban_logchain_src}" - fi - if [ "${ban_logdst_enabled}" = "1" ]; then - ban_logprefix_dst="${ban_logprefix_dst:-"[banIP-${ban_ver%-*}, dst/${ban_target_dst}] "}" - ban_logopts_dst="${ban_logopts_dst:-"-m limit --limit 2/sec"}" - ban_target_dst="${ban_logchain_dst}" - fi - ban_localsources="${ban_localsources:-"maclist whitelist blacklist"}" - ban_logterms="${ban_logterms:-"dropbear sshd luci nginx"}" - f_log "debug" "f_conf ::: ifaces: ${ban_ifaces:-"-"}, chain: ${ban_chain}, set_type: ${ban_global_settype}, log_chains (src/dst): ${ban_logchain_src}/${ban_logchain_dst}, targets (src/dst): ${ban_target_src}/${ban_target_dst}, whitelist_only: ${ban_whitelistonly}" - f_log "debug" "f_conf ::: lan_inputs (4/6): ${ban_lan_inputchains_4}/${ban_lan_inputchains_6}, lan_forwards (4/6): ${ban_lan_forwardchains_4}/${ban_lan_forwardchains_6}, wan_inputs (4/6): ${ban_wan_inputchains_4}/${ban_wan_inputchains_6}, wan_forwards (4/6): ${ban_wan_forwardchains_4}/${ban_wan_forwardchains_6}" - f_log "debug" "f_conf ::: local_sources: ${ban_localsources:-"-"}, extra_sources: ${ban_extrasources:-"-"}, log_terms: ${ban_logterms:-"-"}, log_prefixes (src/dst): ${ban_logprefix_src}/${ban_logprefix_dst}, log_options (src/dst): ${ban_logopts_src}/${ban_logopts_dst}" -} - -# check environment -# -f_env() { - local util utils packages iface insecure tmp cnt="0" cnt_max="10" - - ban_starttime="$(date "+%s")" - f_jsnup "running" - f_log "info" "start banIP processing (${ban_action})" - - f_tmp - - if [ "${ban_autodetect}" = "1" ] && [ -z "${ban_ifaces}" ]; then - while [ "${cnt}" -le "${cnt_max}" ]; do - network_find_wan iface - if [ -n "${iface}" ] && ! printf "%s\n" "${ban_ifaces}" | grep -q "${iface}"; then - ban_proto4_enabled="1" - ban_ifaces="${ban_ifaces}${iface} " - uci_set banip global ban_proto4_enabled "1" - uci_add_list banip global ban_ifaces "${iface}" - fi - network_find_wan6 iface - if [ -n "${iface}" ] && ! printf "%s\n" "${ban_ifaces}" | grep -q "${iface}"; then - ban_proto6_enabled="1" - ban_ifaces="${ban_ifaces}${iface} " - uci_set banip global ban_proto6_enabled "1" - uci_add_list banip global ban_ifaces "${iface}" - fi - if [ -z "${ban_ifaces}" ]; then - if [ "${cnt}" -le "${cnt_max}" ]; then - network_flush_cache - cnt=$((cnt + 1)) - sleep 1 - else - break - fi - else - if [ -n "$(uci -q changes "banip")" ]; then - uci_commit "banip" - fi - break - fi - done - fi - - while [ "${cnt}" -le "${cnt_max}" ]; do - for iface in ${ban_ifaces}; do - network_get_device tmp "${iface}" - if [ -n "${tmp}" ] && ! printf "%s\n" "${ban_devs}" | grep -q "${tmp}"; then - ban_devs="${ban_devs} ${tmp}" - else - network_get_physdev tmp "${iface}" - if [ -n "${tmp}" ] && ! printf "%s\n" "${ban_devs}" | grep -q "${tmp}"; then - ban_devs="${ban_devs} ${tmp}" - fi - fi - network_get_subnet tmp "${iface}" - if [ -n "${tmp}" ] && ! printf "%s\n" "${ban_subnets}" | grep -q "${tmp}"; then - ban_subnets="${ban_subnets} ${tmp}" - fi - network_get_subnet6 tmp "${iface}" - if [ -n "${tmp}" ] && ! printf "%s\n" "${ban_subnets}" | grep -q "${tmp}"; then - ban_subnets="${ban_subnets} ${tmp}" - fi - done - if [ -z "${ban_devs}" ] || [ -z "${ban_subnets}" ]; then - if [ "${cnt}" -le "${cnt_max}" ]; then - network_flush_cache - cnt=$((cnt + 1)) - sleep 1 - else - break - fi - else - break - fi - done - ban_ipdevs="$("${ban_ip_cmd}" link show 2>/dev/null | awk 'BEGIN{FS="[@: ]"}/^[0-9:]/{if($3!="lo"){ORS=" ";print $3}}')" - - if [ -z "${ban_ifaces}" ] || [ -z "${ban_devs}" ] || [ -z "${ban_ipdevs}" ]; then - f_log "err" "logical wan interface(s)/device(s) '${ban_ifaces:-"-"}/${ban_devs:-"-"}' not found, please check your configuration" - elif [ -z "${ban_ipdevs}" ]; then - f_log "err" "ip device(s) '${ban_ipdevs:-"-"}' not found, please check your configuration" - fi - - if [ ! -x "${ban_ipset_cmd}" ]; then - f_log "err" "ipset utility '${ban_ipset_cmd:-"-"}' not executable, please install package 'ipset'" - fi - if { [ "${ban_proto4_enabled}" = "1" ] && { [ ! -x "${ban_ipt4_cmd}" ] || [ ! -x "${ban_ipt4_savecmd}" ] || [ ! -x "${ban_ipt4_restorecmd}" ]; }; } || - { [ "${ban_proto6_enabled}" = "1" ] && { [ ! -x "${ban_ipt6_cmd}" ] || [ ! -x "${ban_ipt6_savecmd}" ] || [ ! -x "${ban_ipt6_restorecmd}" ]; }; }; then - f_log "err" "iptables utilities '${ban_ipt4_cmd:-"-"}, ${ban_ipt4_savecmd:-"-"}, ${ban_ipt4_restorecmd:-"-"}/${ban_ipt6_cmd:-"-"}', ${ban_ipt6_savecmd:-"-"}, ${ban_ipt6_restorecmd:-"-"} not executable, please install the relevant iptables packages" - fi - - if [ -z "${ban_fetchutil}" ]; then - while [ -z "${packages}" ] && [ "${cnt}" -le "${cnt_max}" ]; do - packages="$(opkg list-installed 2>/dev/null)" - cnt=$((cnt + 1)) - sleep 1 - done - if [ -z "${packages}" ]; then - f_log "err" "local opkg package repository is not available, please set 'ban_fetchutil' manually" - fi - - utils="aria2c curl wget uclient-fetch" - for util in ${utils}; do - if { [ "${util}" = "uclient-fetch" ] && printf "%s" "${packages}" | grep -q "^libustream-"; } || - { [ "${util}" = "wget" ] && printf "%s" "${packages}" | grep -q "^wget -"; } || - [ "${util}" = "curl" ] || [ "${util}" = "aria2c" ]; then - if [ -x "$(command -v "${util}")" ]; then - ban_fetchutil="${util}" - uci_set banip global ban_fetchutil "${util}" - uci_commit "banip" - break - fi - fi - done - elif [ ! -x "$(command -v "${ban_fetchutil}")" ]; then - unset ban_fetchutil - fi - case "${ban_fetchutil}" in - "aria2c") - if [ "${ban_fetchinsecure}" = "1" ]; then - insecure="--check-certificate=false" - fi - ban_fetchparm="${ban_fetchparm:-"${insecure} --timeout=20 --allow-overwrite=true --auto-file-renaming=false --log-level=warn --dir=/ -o"}" - ;; - "curl") - if [ "${ban_fetchinsecure}" = "1" ]; then - insecure="--insecure" - fi - ban_fetchparm="${ban_fetchparm:-"${insecure} --connect-timeout 20 --silent --show-error --location -o"}" - ;; - "uclient-fetch") - if [ "${ban_fetchinsecure}" = "1" ]; then - insecure="--no-check-certificate" - fi - ban_fetchparm="${ban_fetchparm:-"${insecure} --timeout=20 -O"}" - ;; - "wget") - if [ "${ban_fetchinsecure}" = "1" ]; then - insecure="--no-check-certificate" - fi - ban_fetchparm="${ban_fetchparm:-"${insecure} --no-cache --no-cookies --max-redirect=0 --timeout=20 -O"}" - ;; - esac - if [ -n "${ban_fetchutil}" ] && [ -n "${ban_fetchparm}" ]; then - ban_fetchutil="$(command -v "${ban_fetchutil}")" - else - 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 - - if [ ! -r "${ban_srcfile}" ]; then - if [ -r "${ban_srcarc}" ]; then - zcat "${ban_srcarc}" >"${ban_srcfile}" - else - f_log "err" "banIP source archive not found" - fi - fi - if [ -r "${ban_srcfile}" ]; then - json_init - json_load_file "${ban_srcfile}" - json_get_keys ban_allsources - ban_allsources="${ban_allsources} maclist blacklist whitelist" - else - f_log "err" "banIP source file not found" - fi - f_log "debug" "f_env ::: auto_detect: ${ban_autodetect}, fetch_util: ${ban_fetchutil:-"-"}, fetch_parm: ${ban_fetchparm:-"-"}, src_file: ${ban_srcfile:-"-"}, log_terms: ${ban_logterms}, interfaces: ${ban_ifaces:-"-"}, devices: ${ban_devs:-"-"}, subnets: ${ban_subnets:-"-"}, ip_devices: ${ban_ipdevs:-"-"}, protocols (4/6): ${ban_proto4_enabled}/${ban_proto6_enabled}" -} - -# create temporary files and directories -# -f_tmp() { - f_dir "${ban_tmpbase}" - - ban_tmpdir="$(mktemp -p "${ban_tmpbase}" -d)" - ban_tmpfile="$(mktemp -p "${ban_tmpdir}" -tu)" - - if [ ! -f "${ban_pidfile}" ] || [ ! -s "${ban_pidfile}" ]; then - printf "%s" "${$}" >"${ban_pidfile}" - fi - f_log "debug" "f_tmp ::: tmp_base: ${ban_tmpbase:-"-"}, tmp_dir: ${ban_tmpdir:-"-"}, pid_file: ${ban_pidfile:-"-"}" -} - -# remove temporary files and directories -# -f_rmtmp() { - if [ -d "${ban_tmpdir}" ]; then - rm -rf "${ban_tmpdir}" - fi - rm -f "${ban_srcfile}" - : >"${ban_pidfile}" - f_log "debug" "f_rmtmp ::: tmp_base: ${ban_tmpbase:-"-"}, tmp_dir: ${ban_tmpdir:-"-"}, pid_file: ${ban_pidfile:-"-"}" -} - -# remove backup files -# -f_rmbckp() { - if [ -d "${ban_backupdir}" ]; then - rm -f "${ban_backupdir}/banIP."*".gz" - fi -} - -# status helper function -# -f_char() { - local result input="${1}" - - if [ "${input}" = "1" ]; then - result="✔" - else - result="✘" - fi - printf "%s" "${result}" -} - -# apply iptables rules -# -f_iptrule() { - local rc timeout="-w 5" action="${1}" chain="${2}" rule="${3}" pos="${4}" - - if [ "${ban_proto4_enabled}" = "1" ] && { [ "${src_name}" = "maclist" ] || [ "${src_name##*_}" = "4" ]; }; then - rc="$( - "${ban_ipt4_cmd}" "${timeout}" -C ${chain} ${rule} 2>/dev/null - printf "%u" ${?} - )" - if { [ "${rc}" != "0" ] && { [ "${action}" = "-A" ] || [ "${action}" = "-I" ]; }; } || - { [ "${rc}" = "0" ] && [ "${action}" = "-D" ]; }; then - "${ban_ipt4_cmd}" "${timeout}" "${action}" ${chain} ${pos} ${rule} 2>/dev/null - rc="${?}" - else - rc=0 - fi - fi - if [ "${ban_proto6_enabled}" = "1" ] && { [ "${src_name}" = "maclist" ] || [ "${src_name##*_}" = "6" ]; }; then - rc="$( - "${ban_ipt6_cmd}" "${timeout}" -C ${chain} ${rule} 2>/dev/null - printf "%u" ${?} - )" - if { [ "${rc}" != "0" ] && { [ "${action}" = "-A" ] || [ "${action}" = "-I" ]; }; } || - { [ "${rc}" = "0" ] && [ "${action}" = "-D" ]; }; then - "${ban_ipt6_cmd}" "${timeout}" "${action}" ${chain} ${pos} ${rule} 2>/dev/null - rc="${?}" - else - rc=0 - fi - fi - if [ -n "${rc}" ] && [ "${rc}" != "0" ]; then - : >"${tmp_err}" - f_log "info" "${src_name}: iptables action '${action:-"-"}' failed with '${chain}, ${pos:-"-"}, ${rule:-"-"}'" - fi -} - -# iptables controller -# -f_iptables() { - local ipt_cmd chain chainsets dev pos timeout="-w 5" destroy="${1}" - - if [ "${ban_action}" != "refresh" ] && [ "${ban_action}" != "resume" ]; then - for dev in ${ban_ipdevs}; do - if [ "${src_name}" = "maclist" ]; then - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} src -j RETURN" - elif [ "${src_name%_*}" = "whitelist" ]; then - f_iptrule "-D" "${ban_chain}" "-i ${dev} -m set ! --match-set ${src_name} src -j ${ban_logtarget_src}" - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set ! --match-set ${src_name} dst -j ${ban_logtarget_dst}" - f_iptrule "-D" "${ban_chain}" "-i ${dev} -m set ! --match-set ${src_name} src -j ${ban_logchain_src}" - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set ! --match-set ${src_name} dst -j ${ban_logchain_dst}" - f_iptrule "-D" "${ban_chain}" "-i ${dev} -m set --match-set ${src_name} src -j RETURN" - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} dst -j RETURN" - else - f_iptrule "-D" "${ban_chain}" "-i ${dev} -m set --match-set ${src_name} src -j ${ban_logtarget_src}" - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} dst -j ${ban_logtarget_dst}" - f_iptrule "-D" "${ban_chain}" "-i ${dev} -m set --match-set ${src_name} src -j ${ban_logchain_src}" - f_iptrule "-D" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} dst -j ${ban_logchain_dst}" - fi - done - fi - if [ -z "${destroy}" ] && { [ "${cnt}" -gt "0" ] || [ "${src_name%_*}" = "blacklist" ] || [ "${src_name%_*}" = "whitelist" ]; }; then - if [ "${src_name##*_}" = "4" ]; then - ipt_cmd="${ban_ipt4_cmd}" - if [ ! -f "${ban_tmpfile}.${src_name##*_}.chains" ]; then - : >"${ban_tmpfile}.${src_name##*_}.chains" - chainsets="${ban_lan_inputchains_4} ${ban_wan_inputchains_4} ${ban_lan_forwardchains_4} ${ban_wan_forwardchains_4}" - for chain in ${chainsets}; do - f_iptrule "-I" "${chain}" "-j ${ban_chain}" - done - f_iptrule "-A" "${ban_chain}" "-p udp --dport 67:68 --sport 67:68 -j RETURN" - f_iptrule "-A" "${ban_chain}" "-m conntrack ! --ctstate NEW -j RETURN" - fi - elif [ "${src_name##*_}" = "6" ]; then - ipt_cmd="${ban_ipt6_cmd}" - if [ ! -f "${ban_tmpfile}.${src_name##*_}.chains" ]; then - : >"${ban_tmpfile}.${src_name##*_}.chains" - chainsets="${ban_lan_inputchains_6} ${ban_wan_inputchains_6} ${ban_lan_forwardchains_6} ${ban_wan_forwardchains_6}" - for chain in ${chainsets}; do - f_iptrule "-I" "${chain}" "-j ${ban_chain}" - done - f_iptrule "-A" "${ban_chain}" "-p ipv6-icmp -s fe80::/10 -d fe80::/10 -j RETURN" - f_iptrule "-A" "${ban_chain}" "-p udp -s fc00::/6 --sport 547 -d fc00::/6 --dport 546 -j RETURN" - f_iptrule "-A" "${ban_chain}" "-m conntrack ! --ctstate NEW -j RETURN" - fi - fi - if [ "${src_settype}" != "dst" ]; then - for dev in ${ban_devs}; do - if [ "${src_name}" = "maclist" ]; then - f_iptrule "-I" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} src -j RETURN" "1" - elif [ "${src_name%_*}" = "whitelist" ]; then - pos="$(($("${ipt_cmd}" "${timeout}" -vnL "${ban_chain}" --line-numbers | grep -cF "RETURN") + 1))" - if [ "${ban_whitelistonly}" = "1" ]; then - f_iptrule "-I" "${ban_chain}" "-i ${dev} -m set ! --match-set ${src_name} src -j ${ban_target_src}" "${pos}" - else - f_iptrule "-I" "${ban_chain}" "-i ${dev} -m set --match-set ${src_name} src -j RETURN" "${pos}" - fi - else - f_iptrule "${action:-"-A"}" "${ban_chain}" "-i ${dev} -m set --match-set ${src_name} src -j ${ban_target_src}" - fi - done - fi - if [ "${src_settype}" != "src" ]; then - for dev in ${ban_devs}; do - if [ "${src_name%_*}" = "whitelist" ]; then - pos="$(($("${ipt_cmd}" "${timeout}" -vnL "${ban_chain}" --line-numbers | grep -cF "RETURN") + 1))" - if [ "${ban_whitelistonly}" = "1" ]; then - f_iptrule "-I" "${ban_chain}" "-o ${dev} -m set ! --match-set ${src_name} dst -j ${ban_target_dst}" "${pos}" - else - f_iptrule "-I" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} dst -j RETURN" "${pos}" - fi - elif [ "${src_name}" != "maclist" ]; then - f_iptrule "${action:-"-A"}" "${ban_chain}" "-o ${dev} -m set --match-set ${src_name} dst -j ${ban_target_dst}" - fi - done - fi - else - "${ban_ipset_cmd}" -q destroy "${src_name}" - fi -} - -# ipset controller -# -f_ipset() { - local src src_list action rule ipt_cmd out_rc max="0" cnt="0" cnt_ip="0" cnt_cidr="0" cnt_mac="0" timeout="-w 5" mode="${1}" in_rc="4" - - case "${mode}" in - "backup") - gzip -cf "${tmp_load}" 2>/dev/null >"${ban_backupdir}/banIP.${src_name}.gz" - out_rc="${?}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, out_rc: ${out_rc}" - return "${out_rc}" - ;; - "restore") - if [ -f "${ban_backupdir}/banIP.${src_name}.gz" ]; then - zcat "${ban_backupdir}/banIP.${src_name}.gz" 2>/dev/null >"${tmp_load}" - out_rc="${?}" - else - out_rc="${in_rc}" - fi - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, out_rc: ${out_rc}" - return "${out_rc}" - ;; - "remove") - if [ -f "${ban_backupdir}/banIP.${src_name}.gz" ]; then - rm -f "${ban_backupdir}/banIP.${src_name}.gz" - out_rc="${?}" - else - out_rc="${in_rc}" - fi - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, out_rc: ${out_rc}" - return "${out_rc}" - ;; - "initial") - for proto in "4" "6"; do - if [ "${proto}" = "4" ] && [ "${ban_proto4_enabled}" = "1" ]; then - ipt_cmd="${ban_ipt4_cmd}" - chainsets="${ban_lan_inputchains_4} ${ban_lan_forwardchains_4} ${ban_wan_inputchains_4} ${ban_wan_forwardchains_4}" - elif [ "${proto}" = "6" ] && [ "${ban_proto6_enabled}" = "1" ]; then - ipt_cmd="${ban_ipt6_cmd}" - chainsets="${ban_lan_inputchains_6} ${ban_lan_forwardchains_6} ${ban_wan_inputchains_6} ${ban_wan_forwardchains_6}" - fi - - if { [ "${proto}" = "4" ] && [ "${ban_proto4_enabled}" = "1" ]; } || - { [ "${proto}" = "6" ] && [ "${ban_proto6_enabled}" = "1" ]; }; then - if [ -z "$("${ipt_cmd}" "${timeout}" -nL "${ban_chain}" 2>/dev/null)" ]; then - "${ipt_cmd}" "${timeout}" -N "${ban_chain}" 2>/dev/null - out_rc="${?}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, chain: ${ban_chain:-"-"}, out_rc: ${out_rc}" - else - out_rc=0 - for chain in ${chainsets}; do - f_iptrule "-D" "${chain}" "-j ${ban_chain}" - done - fi - - if [ "${ban_logsrc_enabled}" = "1" ] && [ "${out_rc}" = "0" ] && [ -z "$("${ipt_cmd}" "${timeout}" -nL "${ban_logchain_src}" 2>/dev/null)" ]; then - "${ipt_cmd}" "${timeout}" -N "${ban_logchain_src}" 2>/dev/null - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - "${ipt_cmd}" "${timeout}" -A "${ban_logchain_src}" -j LOG ${ban_logopts_src} --log-prefix "${ban_logprefix_src}" - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - "${ipt_cmd}" "${timeout}" -A "${ban_logchain_src}" -j "${ban_logtarget_src}" - out_rc="${?}" - fi - fi - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, logchain_src: ${ban_logchain_src:-"-"}, out_rc: ${out_rc}" - fi - - if [ "${ban_logdst_enabled}" = "1" ] && [ "${out_rc}" = "0" ] && [ -z "$("${ipt_cmd}" "${timeout}" -nL "${ban_logchain_dst}" 2>/dev/null)" ]; then - "${ipt_cmd}" "${timeout}" -N "${ban_logchain_dst}" 2>/dev/null - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - "${ipt_cmd}" "${timeout}" -A "${ban_logchain_dst}" -j LOG ${ban_logopts_dst} --log-prefix "${ban_logprefix_dst}" - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - "${ipt_cmd}" "${timeout}" -A "${ban_logchain_dst}" -j "${ban_logtarget_dst}" - out_rc="${?}" - fi - fi - f_log "debug" "f_ipset ::: name: initial, mode: ${mode:-"-"}, logchain_dst: ${ban_logchain_dst:-"-"}, out_rc: ${out_rc}" - fi - fi - done - out_rc="${out_rc:-"${in_rc}"}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, out_rc: ${out_rc}" - return "${out_rc}" - ;; - "create") - if [ -z "$("${ban_ipset_cmd}" -q -n list "${src_name}")" ] && - { [ -s "${tmp_file}" ] || [ "${src_name%_*}" = "whitelist" ] || [ "${src_name%_*}" = "blacklist" ]; }; then - max="$(awk 'END{print NR}' "${tmp_file}" 2>/dev/null)" - max=$((max + 262144)) - if [ "${src_name}" = "maclist" ]; then - "${ban_ipset_cmd}" create "${src_name}" hash:mac hashsize 64 maxelem "${max}" counters timeout "${ban_maclist_timeout:-"0"}" - out_rc="${?}" - elif [ "${src_name%_*}" = "whitelist" ]; then - "${ban_ipset_cmd}" create "${src_name}" hash:net hashsize 64 maxelem "${max}" family "${src_ipver}" counters timeout "${ban_whitelist_timeout:-"0"}" - out_rc="${?}" - elif [ "${src_name%_*}" = "blacklist" ]; then - "${ban_ipset_cmd}" create "${src_name}" hash:net hashsize 64 maxelem "${max}" family "${src_ipver}" counters timeout "${ban_blacklist_timeout:-"0"}" - out_rc="${?}" - else - "${ban_ipset_cmd}" create "${src_name}" hash:net hashsize 64 maxelem "${max}" family "${src_ipver}" counters - out_rc="${?}" - fi - elif [ -n "$("${ban_ipset_cmd}" -q -n list "${src_name}")" ]; then - "${ban_ipset_cmd}" -q flush "${src_name}" - out_rc="${?}" - fi - if [ -s "${tmp_file}" ] && [ "${out_rc}" = "0" ]; then - "${ban_ipset_cmd}" -q -! restore <"${tmp_file}" - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - src_list="$("${ban_ipset_cmd}" -q list "${src_name}")" - cnt="$(printf "%s\n" "${src_list}" | awk '/^Number of entries:/{print $4}')" - cnt_mac="$(printf "%s\n" "${src_list}" | grep -cE "^(([0-9A-Z][0-9A-Z]:){5}[0-9A-Z]{2} )")" - cnt_cidr="$(printf "%s\n" "${src_list}" | grep -cE "(/[0-9]{1,3} )")" - cnt_ip=$((cnt - cnt_cidr - cnt_mac)) - printf "%s\n" "${cnt}" >"${tmp_cnt}" - fi - fi - f_iptables - end_ts="$(date +%s)" - out_rc="${out_rc:-"${in_rc}"}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, ipver: ${src_ipver:-"-"}, settype: ${src_settype:-"-"}, count(sum/ip/cidr/mac): ${cnt}/${cnt_ip}/${cnt_cidr}/${cnt_mac}, time: $((end_ts - start_ts)), out_rc: ${out_rc}" - return "${out_rc}" - ;; - "refresh") - if [ -n "$("${ban_ipset_cmd}" -q -n list "${src_name}")" ]; then - out_rc=0 - src_list="$("${ban_ipset_cmd}" -q list "${src_name}")" - cnt="$(printf "%s\n" "${src_list}" | awk '/^Number of entries:/{print $4}')" - cnt_mac="$(printf "%s\n" "${src_list}" | grep -cE "^(([0-9A-Z][0-9A-Z]:){5}[0-9A-Z]{2} )")" - cnt_cidr="$(printf "%s\n" "${src_list}" | grep -cE "(/[0-9]{1,3} )")" - cnt_ip=$((cnt - cnt_cidr - cnt_mac)) - printf "%s\n" "${cnt}" >"${tmp_cnt}" - f_iptables - fi - end_ts="$(date +%s)" - out_rc="${out_rc:-"${in_rc}"}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, count(sum/ip/cidr/mac): ${cnt}/${cnt_ip}/${cnt_cidr}/${cnt_mac}, time: $((end_ts - start_ts)), out_rc: ${out_rc}" - return "${out_rc}" - ;; - "suspend") - for src in ${ban_sources} ${ban_localsources}; do - if [ "${src}" = "maclist" ] && [ -n "$("${ban_ipset_cmd}" -q -n list "${src}")" ]; then - tmp_file="${ban_backupdir}/${src}.file" - "${ban_ipset_cmd}" -q save "${src}" | tail -n +2 >"${tmp_file}" - "${ban_ipset_cmd}" -q flush "${src}" - else - for proto in "4" "6"; do - if [ -n "$("${ban_ipset_cmd}" -q -n list "${src}_${proto}")" ]; then - tmp_file="${ban_backupdir}/${src}_${proto}.file" - "${ban_ipset_cmd}" -q save "${src}_${proto}" | tail -n +2 >"${tmp_file}" - "${ban_ipset_cmd}" -q flush "${src}_${proto}" - fi - done - fi - done - f_log "debug" "f_ipset ::: name: ${src:-"-"}, mode: ${mode:-"-"}" - ;; - "resume") - if [ -f "${ban_backupdir}/${src_name}.file" ]; then - "${ban_ipset_cmd}" -q -! restore <"${ban_backupdir}/${src_name}.file" - out_rc="${?}" - if [ "${out_rc}" = "0" ]; then - rm -f "${ban_backupdir}/${src_name}.file" - src_list="$("${ban_ipset_cmd}" -q list "${src_name}")" - cnt="$(printf "%s\n" "${src_list}" | awk '/^Number of entries:/{print $4}')" - cnt_mac="$(printf "%s\n" "${src_list}" | grep -cE "^(([0-9A-Z][0-9A-Z]:){5}[0-9A-Z]{2} )")" - cnt_cidr="$(printf "%s\n" "${src_list}" | grep -cE "(/[0-9]{1,3} )")" - cnt_ip=$((cnt - cnt_cidr - cnt_mac)) - printf "%s\n" "${cnt}" >"${tmp_cnt}" - fi - f_iptables - fi - end_ts="$(date +%s)" - out_rc="${out_rc:-"${in_rc}"}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, ipver: ${src_ipver:-"-"}, settype: ${src_settype:-"-"}, count(sum/ip/cidr/mac): ${cnt}/${cnt_ip}/${cnt_cidr}/${cnt_mac}, time: $((end_ts - start_ts)), out_rc: ${out_rc}" - return "${out_rc}" - ;; - "flush") - if [ -n "$("${ban_ipset_cmd}" -q -n list "${src_name}")" ]; then - f_iptables "destroy" - out_rc=0 - fi - out_rc="${out_rc:-"${in_rc}"}" - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}, out_rc: ${out_rc}" - return "${out_rc}" - ;; - "destroy") - for chain in ${ban_chain} ${ban_logchain_src} ${ban_logchain_dst}; do - if [ -n "$("${ban_ipt4_cmd}" "${timeout}" -nL "${chain}" 2>/dev/null)" ]; then - "${ban_ipt4_savecmd}" | grep -v -- "-j ${chain}" | "${ban_ipt4_restorecmd}" - "${ban_ipt4_cmd}" "${timeout}" -F "${chain}" 2>/dev/null - "${ban_ipt4_cmd}" "${timeout}" -X "${chain}" 2>/dev/null - fi - if [ -n "$("${ban_ipt6_cmd}" "${timeout}" -nL "${chain}" 2>/dev/null)" ]; then - "${ban_ipt6_savecmd}" | grep -v -- "-j ${chain}" | "${ban_ipt6_restorecmd}" - "${ban_ipt6_cmd}" "${timeout}" -F "${chain}" 2>/dev/null - "${ban_ipt6_cmd}" "${timeout}" -X "${chain}" 2>/dev/null - fi - done - for src in ${ban_sources} maclist blacklist whitelist; do - if [ "${src}" = "maclist" ] && [ -n "$("${ban_ipset_cmd}" -q -n list "${src}")" ]; then - "${ban_ipset_cmd}" -q destroy "${src}" - else - for proto in "4" "6"; do - if [ -n "$("${ban_ipset_cmd}" -q -n list "${src}_${proto}")" ]; then - "${ban_ipset_cmd}" -q destroy "${src}_${proto}" - fi - done - fi - done - f_log "debug" "f_ipset ::: name: ${src_name:-"-"}, mode: ${mode:-"-"}" - ;; - esac -} - -# write to syslog -# -f_log() { - local class="${1}" log_msg="${2}" - - if [ -n "${log_msg}" ] && { [ "${class}" != "debug" ] || [ "${ban_debug}" = "1" ]; }; then - if [ -x "${ban_logger_cmd}" ]; then - "${ban_logger_cmd}" -p "${class}" -t "banIP-${ban_ver%-*}[${$}]" "${log_msg}" - else - printf "%s %s %s\n" "${class}" "banIP-${ban_ver%-*}[${$}]" "${log_msg}" - fi - if [ "${class}" = "err" ]; then - f_jsnup "error" - f_ipset "destroy" - f_rmbckp - f_rmtmp - exit 1 - fi - fi -} - -# kill all relevant background processes -# -f_pidx() { - local pids ppid="${1}" - - pids="$(pgrep -P "${ppid}" 2>/dev/null | awk '{ORS=" ";print $0}')" - kill -HUP "${ppid}" "${pids}" 2>/dev/null - : >"${ban_bgpidfile}" -} - -# start log service to trace failed ssh/luci logins -# -f_bgsrv() { - local bg_pid action="${1}" - - bg_pid="$(cat "${ban_bgpidfile}" 2>/dev/null)" - if [ "${action}" = "start" ] && [ -x "${ban_logservice}" ] && [ "${ban_monitor_enabled}" = "1" ] && [ "${ban_whitelistonly}" = "0" ]; then - if [ -n "${bg_pid}" ]; then - f_pidx "${bg_pid}" - fi - if printf "%s\n" "${ban_logterms}" | grep -q "dropbear"; then - ban_search="Exit before auth from|" - fi - if printf "%s\n" "${ban_logterms}" | grep -q "sshd"; then - ban_search="${ban_search}error: maximum authentication attempts exceeded|sshd.*Connection closed by.*\[preauth\]|" - fi - if printf "%s\n" "${ban_logterms}" | grep -q "luci"; then - ban_search="${ban_search}luci: failed login|" - fi - if printf "%s\n" "${ban_logterms}" | grep -q "nginx"; then - ban_search="${ban_search}nginx(\[[0-9]+\])?:.*\[error\].*open().*client: [[:alnum:].:]+|" - fi - ( - "${ban_logservice}" "${ban_search%?}" & - printf "%s" "${!}" >"${ban_bgpidfile}" - ) - elif { [ "${action}" = "stop" ] || [ "${ban_monitor_enabled}" = "0" ]; } && [ -n "${bg_pid}" ]; then - f_pidx "${bg_pid}" - fi - f_log "debug" "f_bgsrv ::: action: ${action:-"-"}, bg_pid (old/new): ${bg_pid}/$(cat "${ban_bgpidfile}" 2>/dev/null), monitor_enabled: ${ban_monitor_enabled:-"-"}, log_service: ${ban_logservice:-"-"}" -} - -# download controller -# -f_down() { - local src_name="${1}" proto="${2}" src_ipver="${3}" src_url="${4}" src_rule="${5}" src_comp="${6}" - local ip start_ts end_ts src_settype src_log src_rc tmp_load tmp_file tmp_raw tmp_cnt tmp_err - - start_ts="$(date +%s)" - if printf "%s\n" "${ban_settype_src}" | grep -q "${src_name}"; then - src_settype="src" - elif printf "%s\n" "${ban_settype_dst}" | grep -q "${src_name}"; then - src_settype="dst" - elif printf "%s\n" "${ban_settype_all}" | grep -q "${src_name}"; then - src_settype="src+dst" - else - src_settype="${ban_global_settype}" - fi - src_name="${src_name}_${proto}" - tmp_load="${ban_tmpfile}.${src_name}.load" - tmp_file="${ban_tmpfile}.${src_name}.file" - tmp_raw="${tmp_file}.raw" - tmp_cnt="${tmp_file}.cnt" - tmp_err="${tmp_file}.err" - - # 'resume' mode - # - if [ "${ban_action}" = "resume" ]; then - if [ "${src_name%_*}" = "maclist" ]; then - src_name="maclist" - fi - f_ipset "resume" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - return - fi - fi - - # handle local downloads - # - case "${src_name%_*}" in - "blacklist" | "whitelist") - printf "%s\n" "0" >"${tmp_cnt}" - awk "${src_rule}" "${src_url}" >"${tmp_file}" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - f_ipset "create" - if [ ! -f "${tmp_dns}" ] && { { [ "${proto}" = "4" ] && [ "${ban_proto4_enabled}" = "1" ]; } || - { [ "${proto}" = "6" ] && [ "${ban_proto6_enabled}" = "1" ] && [ "${ban_proto4_enabled}" = "0" ]; }; }; then - tmp_dns="${ban_tmpbase}/${src_name%_*}.dns" - src_rule="/^([[:alnum:]_-]{1,63}\\.)+[[:alpha:]]+([[:space:]]|$)/{print tolower(\$1)}" - awk "${src_rule}" "${src_url}" >"${tmp_dns}" - src_rc="${?}" - if [ "${src_rc}" = "0" ] && [ -s "${tmp_dns}" ]; then - ("${ban_dnsservice}" "${src_name%_*}" "${tmp_dns}" &) - else - rm -f "${tmp_dns}" - fi - fi - else - f_log "debug" "f_down ::: name: ${src_name}, url: ${src_url}, rule: ${src_rule}, rc: ${src_rc}" - fi - return - ;; - "maclist") - src_name="${src_name%_*}" - tmp_file="${ban_tmpfile}.${src_name}.file" - tmp_cnt="${tmp_file}.cnt" - tmp_err="${tmp_file}.err" - awk "${src_rule}" "${src_url}" >"${tmp_file}" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - f_ipset "create" - else - f_log "debug" "f_down ::: name: ${src_name}, url: ${src_url}, rule: ${src_rule}, rc: ${src_rc}" - fi - return - ;; - esac - - # 'refresh' mode - # - if [ "${ban_action}" = "refresh" ]; then - f_ipset "refresh" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - return - fi - fi - - # 'start' mode - # - if [ "${ban_action}" = "start" ]; then - f_ipset "restore" - fi - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - awk "${src_rule}" "${tmp_load}" 2>/dev/null >"${tmp_file}" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - f_ipset "create" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - return - fi - fi - fi - - # handle country related downloads - # - if [ "${src_name%_*}" = "country" ]; then - for country in ${ban_countries}; do - src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}${country}-aggregated.zone" 2>&1)" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - cat "${tmp_raw}" 2>/dev/null >>"${tmp_load}" - else - continue - fi - done - - # handle asn related downloads - # - elif [ "${src_name%_*}" = "asn" ]; then - for asn in ${ban_asns}; do - src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}AS${asn}" 2>&1)" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - cat "${tmp_raw}" 2>/dev/null >>"${tmp_load}" - else - continue - fi - done - - # handle compressed downloads - # - elif [ -n "${src_comp}" ]; then - case "${src_comp}" in - "gz") - src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_raw}" "${src_url}" 2>&1)" - src_rc="${?}" - if [ "${src_rc}" -eq 0 ]; then - zcat "${tmp_raw}" 2>/dev/null >"${tmp_load}" - src_rc="${?}" - fi - ;; - esac - - # handle normal downloads - # - else - src_log="$("${ban_fetchutil}" ${ban_fetchparm} "${tmp_load}" "${src_url}" 2>&1)" - src_rc="${?}" - fi - - # download post-processing - # - if [ "${src_rc}" = "0" ]; then - f_ipset "backup" - src_rc="${?}" - elif [ "${ban_action}" != "start" ] && [ "${ban_action}" != "refresh" ]; then - f_ipset "restore" - src_rc="${?}" - fi - if [ "${src_rc}" = "0" ]; then - awk "${src_rule}" "${tmp_load}" 2>/dev/null >"${tmp_file}" - src_rc="${?}" - if [ "${src_rc}" = "0" ]; then - f_ipset "create" - src_rc="${?}" - elif [ "${ban_action}" != "refresh" ]; then - f_ipset "refresh" - src_rc="${?}" - fi - else - src_log="$(printf "%s" "${src_log}" | awk '{ORS=" ";print $0}')" - if [ "${ban_action}" != "refresh" ]; then - f_ipset "refresh" - src_rc="${?}" - fi - f_log "debug" "f_down ::: name: ${src_name}, url: ${src_url}, rule: ${src_rule}, rc: ${src_rc}, log: ${src_log:-"-"}" - fi -} - -# main controller -# -f_main() { - local src_name src_url_4 src_rule_4 src_url_6 src_rule_6 src_comp src_rc src_ts log_raw log_merge log_ips log_count hold err_file cnt_file cnt=0 - - # prepare logfile excerpts - # - if [ "${ban_autoblacklist}" = "1" ] || [ "${ban_monitor_enabled}" = "1" ]; then - log_raw="$(${ban_logread_cmd} -l "${ban_loglimit}")" - if printf "%s\n" "${ban_logterms}" | grep -q "dropbear"; then - log_ips="$(printf "%s\n" "${log_raw}" | grep -E "Exit before auth from" | - awk 'match($0,/<[0-9A-f:\.]+:/){printf "%s\n",substr($0,RSTART+1,RLENGTH-2)}' | awk '!seen[$NF]++' | awk '{ORS=" ";print $NF}')" - for ip in ${log_ips}; do - log_count="$(printf "%s\n" "${log_raw}" | grep -cE "Exit before auth from <${ip}")" - if [ "${log_count}" -ge "${ban_ssh_logcount}" ]; then - log_merge="${log_merge} ${ip}" - fi - done - fi - if printf "%s\n" "${ban_logterms}" | grep -q "sshd"; then - log_ips="$(printf "%s\n" "${log_raw}" | grep -E "error: maximum authentication attempts exceeded|sshd.*Connection closed by.*\[preauth\]" | - awk 'match($0,/[0-9A-f:\.]+ port/){printf "%s\n",substr($0,RSTART,RLENGTH-5)}' | awk '!seen[$NF]++' | awk '{ORS=" ";print $NF}')" - for ip in ${log_ips}; do - log_count="$(printf "%s\n" "${log_raw}" | grep -cE "error: maximum authentication attempts exceeded.*${ip}|sshd.*Connection closed by.*${ip}.*\[preauth\]")" - if [ "${log_count}" -ge "${ban_ssh_logcount}" ]; then - log_merge="${log_merge} ${ip}" - fi - done - fi - if printf "%s\n" "${ban_logterms}" | grep -q "luci"; then - log_ips="$(printf "%s\n" "${log_raw}" | grep -E "luci: failed login on " | - awk 'match($0,/[0-9A-f:\.]+$/){printf "%s\n",substr($0,RSTART,RLENGTH)}' | awk '!seen[$NF]++' | awk '{ORS=" ";print $NF}')" - for ip in ${log_ips}; do - log_count="$(printf "%s\n" "${log_raw}" | grep -cE "luci: failed login on .*from ${ip}")" - if [ "${log_count}" -ge "${ban_luci_logcount}" ]; then - log_merge="${log_merge} ${ip}" - fi - done - fi - if printf "%s\n" "${ban_logterms}" | grep -q "nginx"; then - log_ips="$(printf "%s\n" "${log_raw}" | grep -oE "nginx(\[[0-9]+\])?:.*\[error\].*open\(\).*client: [[:alnum:].:]+" | - awk '!seen[$NF]++' | awk '{ORS=" ";print $NF}')" - for ip in ${log_ips}; do - log_count="$(printf "%s\n" "${log_raw}" | grep -cE "nginx(\[[0-9]+\])?:.*\[error\].*open\(\).*client: ${ip}")" - if [ "${log_count}" -ge "${ban_nginx_logcount}" ]; then - log_merge="${log_merge} ${ip}" - fi - done - fi - fi - - # prepare new black- and whitelist entries - # - if [ "${ban_autowhitelist}" = "1" ] && [ -f "${ban_whitelist}" ]; then - for ip in ${ban_subnets}; do - if ! grep -q "${ip}" "${ban_whitelist}"; then - src_ts="# added on $(date "+%d.%m.%Y %H:%M:%S")" - printf "%-42s%s\n" "${ip}" "${src_ts}" >>"${ban_whitelist}" - f_log "info" "IP address '${ip}' added to whitelist" - fi - done - fi - if [ "${ban_autoblacklist}" = "1" ] && [ -f "${ban_blacklist}" ]; then - for ip in ${log_merge}; do - if ! grep -q "${ip}" "${ban_blacklist}"; then - src_ts="# added on $(date "+%d.%m.%Y %H:%M:%S")" - printf "%-42s%s\n" "${ip}" "${src_ts}" >>"${ban_blacklist}" - f_log "info" "IP address '${ip}' added to blacklist" - fi - done - fi - - # initial ipset/iptables creation - # - if ! f_ipset "initial"; then - f_log "err" "banIP processing failed, fatal error during ipset/iptables creation (${ban_sysver})" - fi - - # load local source files (maclist, blacklist, whitelist) - # - for src_name in ${ban_localsources}; do - if [ "${src_name}" = "maclist" ] && [ -s "${ban_maclist}" ]; then - ( - src_rule_4="/^([0-9A-z][0-9A-z]:){5}[0-9A-z]{2}([[:space:]]|$)/{print \"add ${src_name} \"toupper(\$1)}" - f_down "${src_name}" "mac" "mac" "${ban_maclist}" "${src_rule_4}" - ) & - fi - if [ "${ban_proto4_enabled}" = "1" ]; then - if [ "${src_name}" = "blacklist" ] && [ -s "${ban_blacklist}" ] && [ "${ban_whitelistonly}" = "0" ]; then - ( - src_rule_4="/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add ${src_name}_4 \"\$1}" - f_down "${src_name}" "4" "inet" "${ban_blacklist}" "${src_rule_4}" - ) & - elif [ "${src_name}" = "whitelist" ] && [ -s "${ban_whitelist}" ]; then - ( - src_rule_4="/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add ${src_name}_4 \"\$1}" - f_down "${src_name}" "4" "inet" "${ban_whitelist}" "${src_rule_4}" - ) & - fi - else - ( - src_name="${src_name}_4" - f_ipset "flush" - ) & - fi - if [ "${ban_proto6_enabled}" = "1" ]; then - if [ "${src_name}" = "blacklist" ] && [ -s "${ban_blacklist}" ] && [ "${ban_whitelistonly}" = "0" ]; then - ( - src_rule_6="/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add ${src_name}_6 \"\$1}" - f_down "${src_name}" "6" "inet6" "${ban_blacklist}" "${src_rule_6}" - ) & - elif [ "${src_name}" = "whitelist" ] && [ -s "${ban_whitelist}" ]; then - ( - src_rule_6="/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add ${src_name}_6 \"\$1}" - f_down "${src_name}" "6" "inet6" "${ban_whitelist}" "${src_rule_6}" - ) & - fi - else - ( - src_name="${src_name}_6" - f_ipset "flush" - ) & - fi - done - wait - - # loop over all external sources - # - if [ "${ban_whitelistonly}" = "0" ]; then - for src_name in ${ban_sources}; do - # get source data from JSON file - # - if ! json_select "${src_name}" >/dev/null 2>&1; then - continue - fi - json_objects="url_4 rule_4 url_6 rule_6 comp" - for object in ${json_objects}; do - eval json_get_var src_${object} '${object}' >/dev/null 2>&1 - done - json_select .. - - # handle external IPv4 source downloads in a subshell - # - if [ "${ban_proto4_enabled}" = "1" ] && [ -n "${src_url_4}" ] && [ -n "${src_rule_4}" ]; then - ( - f_down "${src_name}" "4" "inet" "${src_url_4}" "${src_rule_4}" "${src_comp}" - ) & - fi - - # handle external IPv6 source downloads in a subshell - # - if [ "${ban_proto6_enabled}" = "1" ] && [ -n "${src_url_6}" ] && [ -n "${src_rule_6}" ]; then - ( - f_down "${src_name}" "6" "inet6" "${src_url_6}" "${src_rule_6}" "${src_comp}" - ) & - fi - - # control/limit download queues - # - hold=$((cnt % ban_maxqueue)) - if [ "${hold}" = "0" ]; then - wait - fi - cnt=$((cnt + 1)) - done - wait - fi - - # error out - # - for err_file in "${ban_tmpfile}."*".err"; do - if [ -f "${err_file}" ]; then - f_log "err" "banIP processing failed, fatal iptables errors during subshell processing (${ban_sysver})" - fi - done - - # finish processing - # - ban_sources="" - for cnt_file in "${ban_tmpfile}."*".cnt"; do - if [ -f "${cnt_file}" ]; then - read -r cnt <"${cnt_file}" - ban_cnt=$((ban_cnt + cnt)) - ban_setcnt=$((ban_setcnt + 1)) - src_name="$(printf "%s" "${cnt_file}" | grep -Eo "[a-z0-9_]+.file.cnt")" - src_name="${src_name%%.*}" - if ! printf "%s" "${ban_sources}" | grep -q "${src_name%_*}"; then - ban_sources="${ban_sources} ${src_name%_*}" - ban_allsources="${ban_allsources//${src_name%_*}/}" - fi - fi - done - for src_name in ${ban_allsources}; do - if [ "${src_name}" = "maclist" ]; then - f_ipset "flush" - else - for proto in "4" "6"; do - src_name="${src_name%_*}_${proto}" - f_ipset "flush" - if [ "${src_name%_*}" != "blacklist" ] && [ "${src_name%_*}" != "whitelist" ]; then - f_ipset "remove" - fi - done - fi - done - f_log "info" "${ban_setcnt} IPSets with overall ${ban_cnt} IPs/Prefixes loaded successfully (${ban_sysver})" - f_jsnup - f_rmtmp - f_bgsrv "start" -} - -# query ipsets for certain IP -# -f_query() { - local src proto result query_start query_end query_timeout="30" match="0" search="${1}" - - if [ -z "${search}" ]; then - printf "%s\n" "::: missing search term, please submit a single ip or mac address :::" - else - query_start="$(date "+%s")" - printf "%s\n%s\n%s\n" ":::" "::: search '${search}' in banIP related IPSets" ":::" - - for src in ${ban_localsources} ${ban_sources} ${ban_extrasources}; do - if [ "${src}" = "maclist" ] && [ -n "$("${ban_ipset_cmd}" -q -n list "${src}")" ]; then - result="$( - ipset -q test ${src} ${search} >/dev/null 2>&1 - printf "%u" "${?}" - )" - if [ "${result}" = "0" ]; then - match="1" - printf "%s\n" " - found in IPSet '${src}'" - break - fi - else - for proto in "4" "6"; do - if [ -n "$("${ban_ipset_cmd}" -q -n list "${src}_${proto}")" ]; then - result="$( - ipset -q test ${src}_${proto} ${search} >/dev/null 2>&1 - printf "%u" "${?}" - )" - if [ "${result}" = "0" ]; then - match="1" - printf "%s\n" " - found in IPSet '${src}_${proto}'" - fi - fi - done - fi - query_end="$(date "+%s")" - if [ "$((query_end - query_start))" -gt "${query_timeout}" ]; then - printf "%s\n\n" " - [...]" - break - fi - done - if [ "${match}" = "0" ]; then - printf "%s\n\n" " - no match" - fi - fi -} - -# generate statistics -# -f_report() { - local report_json report_txt bg_pid content proto src src_list detaillist type jsnval jsnvals jsnval1 jsnval2 jsnval3 jsnval4 jsnval5 jsnval6 jsnval7 - local cnt cnt_mac cnt_cidr cnt_ip cnt_acc cnt_sum="0" cnt_set_sum="1" cnt_acc_sum="0" cnt_mac_sum="0" cnt_ip_sum="0" cnt_cidr_sum="0" cnt_set_sum="0" action="${1}" - - report_json="${ban_reportdir}/ban_report.json" - report_txt="${ban_reportdir}/ban_mailreport.txt" - - # build json file - # - if [ "${action}" != "json" ] && { "${ban_ipt4_savecmd}" | grep -q " ${ban_chain} " || "${ban_ipt6_savecmd}" | grep -q " ${ban_chain} "; }; then - : >"${report_json}" - printf "%s\n" "{" >>"${report_json}" - printf "%s\n" '"ipsets": {' >>"${report_json}" - for src in ${ban_localsources} ${ban_sources} ${ban_extrasources}; do - if printf "%s" "${ban_extrasources}" | grep -q "${src}"; then - set_type="n/a" - else - if printf "%s\n" "${ban_settype_src}" | grep -q "${src}"; then - set_type="src" - elif printf "%s\n" "${ban_settype_dst}" | grep -q "${src}"; then - set_type="dst" - elif printf "%s\n" "${ban_settype_all}" | grep -q "${src}"; then - set_type="src+dst" - else - set_type="${ban_global_settype}" - fi - fi - if [ "${src}" = "maclist" ]; then - src_list="$("${ban_ipset_cmd}" -q list "${src}")" - if [ -n "${src_list}" ]; then - cnt="$(printf "%s" "${src_list}" | awk '/^Number of entries:/{print $4}')" - cnt_acc="$(printf "%s" "${src_list}" | grep -cE "packets [1-9]+")" - cnt_acc_sum=$((cnt_acc_sum + cnt_acc)) - cnt_mac_sum="${cnt}" - cnt_sum=$((cnt_sum + cnt)) - { - if [ "${cnt_set_sum}" != "0" ]; then - printf "%s\n" "," - fi - printf "\t%s\n" "\"${src}\": {" - printf "\t\t%s\n" "\"type\": \"${set_type}\"," - printf "\t\t%s\n" "\"count\": \"${cnt}\"," - printf "\t\t%s\n" '"count_ip": "0",' - printf "\t\t%s\n" '"count_cidr": "0",' - printf "\t\t%s\n" "\"count_mac\": \"${cnt}\"," - printf "\t\t%s" "\"count_acc\": \"${cnt_acc}\"" - printf ",\n\t\t%s" '"member_acc": [' - printf "%s" "${src_list}" | awk 'match($0,/ packets [1-9]+/){printf "%s %s\n",$1,substr($0,RSTART+9,RLENGTH-9)}' | - awk 'BEGIN{i=0};{i=i+1;if(i==1){printf "{\n\t\t\t\"member\": \"%s\",\n\t\t\t\"packets\": \"%s\"\n\t\t}",$1,$2} - else{printf ",\n\t\t{\n\t\t\t\"member\": \"%s\",\n\t\t\t\"packets\": \"%s\"\n\t\t}",$1,$2}}' - printf "%s\n" "]" - printf "\t%s" "}" - } >>"${report_json}" - cnt_set_sum=$((cnt_set_sum + 1)) - fi - else - for proto in "4" "6"; do - src_list="$("${ban_ipset_cmd}" -q list "${src}_${proto}")" - if [ -n "${src_list}" ]; then - cnt="$(printf "%s\n" "${src_list}" | awk '/^Number of entries:/{print $4}')" - cnt_cidr="$(printf "%s\n" "${src_list}" | grep -cE "/[0-9]{1,3} ")" - cnt_ip=$((cnt - cnt_cidr - cnt_mac)) - cnt_acc="$(printf "%s\n" "${src_list}" | grep -cE "packets [1-9]+")" - cnt_cidr_sum=$((cnt_cidr_sum + cnt_cidr)) - cnt_ip_sum=$((cnt_ip_sum + cnt_ip)) - cnt_acc_sum=$((cnt_acc_sum + cnt_acc)) - cnt_sum=$((cnt_sum + cnt)) - { - if [ "${cnt_set_sum}" != "0" ]; then - printf "%s\n" "," - fi - printf "\t%s\n" "\"${src}_${proto}\": {" - printf "\t\t%s\n" "\"type\": \"${set_type}\"," - printf "\t\t%s\n" "\"count\": \"${cnt}\"," - printf "\t\t%s\n" "\"count_ip\": \"${cnt_ip}\"," - printf "\t\t%s\n" "\"count_cidr\": \"${cnt_cidr}\"," - printf "\t\t%s\n" '"count_mac": "0",' - printf "\t\t%s" "\"count_acc\": \"${cnt_acc}\"" - printf ",\n\t\t%s" '"member_acc": [' - printf "%s" "${src_list}" | awk 'match($0,/ packets [1-9]+/){printf "%s %s\n",$1,substr($0,RSTART+9,RLENGTH-9)}' | - awk 'BEGIN{i=0};{i=i+1;if(i==1){printf "{\n\t\t\t\"member\": \"%s\",\n\t\t\t\"packets\": \"%s\"\n\t\t}",$1,$2} - else{printf ",\n\t\t{\n\t\t\t\"member\": \"%s\",\n\t\t\t\"packets\": \"%s\"\n\t\t}",$1,$2}}' - printf "%s\n" "]" - printf "\t%s" "}" - } >>"${report_json}" - cnt_set_sum=$((cnt_set_sum + 1)) - fi - done - fi - done - { - printf "\n%s" "}" - printf ",\n%s\n" "\"timestamp\": \"$(date "+%d.%m.%Y %H:%M:%S")\"," - printf "%s\n" "\"cnt_set_sum\": \"${cnt_set_sum}\"," - printf "%s\n" "\"cnt_ip_sum\": \"${cnt_ip_sum}\"," - printf "%s\n" "\"cnt_cidr_sum\": \"${cnt_cidr_sum}\"," - printf "%s\n" "\"cnt_mac_sum\": \"${cnt_mac_sum}\"," - printf "%s\n" "\"cnt_sum\": \"${cnt_sum}\"," - printf "%s\n" "\"cnt_acc_sum\": \"${cnt_acc_sum}\"" - printf "%s\n" "}" - } >>"${report_json}" - fi - - # output preparation - # - if [ -s "${report_json}" ] && { [ "${action}" = "cli" ] || [ "${action}" = "mail" ]; }; then - : >"${report_txt}" - json_init - if json_load_file "${report_json}" >/dev/null 2>&1; then - json_get_var jsnval1 "timestamp" >/dev/null 2>&1 - json_get_var jsnval2 "cnt_set_sum" >/dev/null 2>&1 - json_get_var jsnval3 "cnt_sum" >/dev/null 2>&1 - json_get_var jsnval4 "cnt_ip_sum" >/dev/null 2>&1 - json_get_var jsnval5 "cnt_cidr_sum" >/dev/null 2>&1 - json_get_var jsnval6 "cnt_mac_sum" >/dev/null 2>&1 - json_get_var jsnval7 "cnt_acc_sum" >/dev/null 2>&1 - { - printf "%s\n%s\n%s\n" ":::" "::: report on all banIP related IPSets" ":::" - printf " + %s\n" "Report timestamp ::: ${jsnval1:-"-"}" - printf " + %s\n" "Number of all IPSets ::: ${jsnval2:-"0"}" - printf " + %s\n" "Number of all entries ::: ${jsnval3:-"0"}" - printf " + %s\n" "Number of IP entries ::: ${jsnval4:-"0"}" - printf " + %s\n" "Number of CIDR entries ::: ${jsnval5:-"0"}" - printf " + %s\n" "Number of MAC entries ::: ${jsnval6:-"0"}" - printf " + %s\n" "Number of accessed entries ::: ${jsnval7:-"0"}" - } >>"${report_txt}" - - json_select "ipsets" - json_get_keys ipsetlist - if [ -n "${ipsetlist}" ]; then - { - printf "%s\n%s\n%s\n" ":::" "::: IPSet details" ":::" - printf "%-25s%-12s%-11s%-10s%-10s%-10s%-10s%s\n" " Name" "Type" "Count" "Cnt_IP" "Cnt_CIDR" "Cnt_MAC" "Cnt_ACC" "Entry details (Entry/Count)" - printf "%s\n" " --------------------------------------------------------------------------------------------------------------------" - } >>"${report_txt}" - fi - for ipset in ${ipsetlist}; do - set_info="${ipset}" - acc_info="" - json_select "${ipset}" - json_get_keys detaillist - for detail in ${detaillist}; do - if [ "${detail}" != "member_acc" ]; then - json_get_var jsnval "${detail}" >/dev/null 2>&1 - set_info="${set_info} ${jsnval}" - elif [ "${detail}" = "member_acc" ]; then - index=1 - json_select "${detail}" - while json_get_type type "${index}" && [ "${type}" = "object" ]; do - json_get_values jsnvals "${index}" >/dev/null 2>&1 - acc_info="${acc_info} ${jsnvals}" - index=$((index + 1)) - done - json_select ".." - fi - done - { - printf " %-21s%-12s%-11s%-10s%-10s%-10s%s\n" ${set_info} - if [ -n "${acc_info}" ]; then - printf " %-25s%s\n" ${acc_info} - fi - printf "%s\n" " --------------------------------------------------------------------------------------------------------------------" - } >>"${report_txt}" - json_select ".." - done - content="$(cat "${report_txt}" 2>/dev/null)" - rm -f "${report_txt}" - fi - fi - - # report output - # - if [ "${action}" = "cli" ]; then - printf "%s\n" "${content}" - elif [ "${action}" = "json" ]; then - cat "${ban_reportdir}/ban_report.json" - elif [ "${action}" = "mail" ] && [ "${ban_mail_enabled}" = "1" ] && [ -x "${ban_mailservice}" ]; then - ("${ban_mailservice}" "${content}" >/dev/null 2>&1) & - bg_pid="${!}" - fi - f_log "debug" "f_report ::: action: ${action}, report_json: ${report_json}, report_txt: ${report_txt}, bg_pid: ${bg_pid:-"-"}" -} - -# update runtime information -# -f_jsnup() { - local memory entry runtime cnt_info status="${1:-"enabled"}" - - if [ "${status}" = "enabled" ] || [ "${status}" = "error" ]; then - ban_endtime="$(date "+%s")" - cnt_info="${ban_setcnt} IPSets with ${ban_cnt} IPs/Prefixes" - memory="$(awk '/^MemTotal|^MemFree|^MemAvailable/{ORS="/"; print int($2/1000)}' "/proc/meminfo" 2>/dev/null | awk '{print substr($0,1,length($0)-1)}')" - if [ "$(((ban_endtime - ban_starttime) / 60))" -lt "60" ]; then - runtime="${ban_action}, $(((ban_endtime - ban_starttime) / 60))m $(((ban_endtime - ban_starttime) % 60))s, ${memory:-0}, $(date "+%d.%m.%Y %H:%M:%S")" - else - runtime="${ban_action}, n/a, ${memory:-0}, $(date "+%d.%m.%Y %H:%M:%S")" - fi - fi - - : >"${ban_rtfile}" - json_init - json_load_file "${ban_rtfile}" >/dev/null 2>&1 - json_add_string "status" "${status}" - json_add_string "version" "${ban_ver}" - json_add_string "ipset_info" "${cnt_info:-"-"}" - json_add_array "active_sources" - if [ "${status}" = "running" ] || [ "${status}" = "error" ]; then - json_add_object - json_add_string "source" "-" - json_close_object - else - for entry in ${ban_sources}; do - json_add_object - json_add_string "source" "${entry}" - json_close_object - done - fi - json_close_array - json_add_array "active_devs" - for entry in ${ban_devs}; do - json_add_object - json_add_string "dev" "${entry}" - json_close_object - done - json_close_array - json_add_array "active_ifaces" - for entry in ${ban_ifaces}; do - json_add_object - json_add_string "iface" "${entry}" - json_close_object - done - json_close_array - json_add_array "active_logterms" - for entry in ${ban_logterms}; do - json_add_object - json_add_string "term" "${entry}" - json_close_object - done - json_close_array - json_add_array "active_subnets" - for entry in ${ban_subnets}; do - json_add_object - json_add_string "subnet" "${entry}" - json_close_object - done - json_close_array - json_add_string "run_infos" "settype: ${ban_global_settype}, backup_dir: ${ban_backupdir}, report_dir: ${ban_reportdir}" - json_add_string "run_flags" "protocols (4/6): $(f_char ${ban_proto4_enabled})/$(f_char ${ban_proto6_enabled}), log (src/dst): $(f_char ${ban_logsrc_enabled})/$(f_char ${ban_logdst_enabled}), monitor: $(f_char ${ban_monitor_enabled}), mail: $(f_char ${ban_mail_enabled}), whitelist only: $(f_char ${ban_whitelistonly})" - json_add_string "last_run" "${runtime:-"-"}" - json_add_string "system" "${ban_sysver}" - json_dump >"${ban_rtfile}" - - if [ "${ban_mail_enabled}" = "1" ] && [ -x "${ban_mailservice}" ] && { [ "${status}" = "error" ] || - { [ "${status}" = "enabled" ] && { [ -z "${ban_mailactions}" ] || printf "%s\n" "${ban_mailactions}" | grep -q "${ban_action}"; }; }; }; then - ("${ban_mailservice}" "${ban_ver}" >/dev/null 2>&1) & - bg_pid="${!}" - fi - f_log "debug" "f_jsnup ::: status: ${status:-"-"}, action: ${ban_action}, mail_enabled: ${ban_mail_enabled}, mail_actions: ${ban_mailactions}, mail_service: ${ban_mailservice}, mail_pid: ${bg_pid:-"-"}" -} - -# source required system libraries -# -if [ -r "/lib/functions.sh" ] && [ -r "/lib/functions/network.sh" ] && [ -r "/usr/share/libubox/jshn.sh" ]; then - . "/lib/functions.sh" - . "/lib/functions/network.sh" - . "/usr/share/libubox/jshn.sh" -else - f_log "err" "system libraries not found" -fi - -if [ "${ban_action}" = "suspend" ] || [ "${ban_action}" = "resume" ] || - [ "${ban_action}" = "report" ] || [ "${ban_action}" = "query" ]; then - json_init - json_load_file "${ban_rtfile}" >/dev/null 2>&1 - json_get_var ban_status "status" -fi - -# handle different banIP actions -# -f_load -case "${ban_action}" in - "stop") - f_bgsrv "stop" - f_ipset "destroy" - f_jsnup "stopped" - f_rmbckp - ;; - "restart") - f_ipset "destroy" - f_rmbckp - f_env - f_main - ;; - "suspend") - if [ "${ban_status}" = "enabled" ] && [ "${ban_whitelistonly}" = "0" ]; then - f_bgsrv "stop" - f_jsnup "running" - f_ipset "suspend" - f_jsnup "paused" - fi - f_rmtmp - ;; - "resume") - if [ "${ban_status}" = "paused" ] && [ "${ban_whitelistonly}" = "0" ]; then - f_env - f_main - else - f_rmtmp - fi - ;; - "query") - if [ "${ban_status}" = "enabled" ]; then - f_query "${2}" - fi - ;; - "report") - if [ "${ban_status}" = "enabled" ] || [ "${2}" = "json" ]; then - f_report "${2}" - fi - ;; - "start" | "reload" | "refresh") - f_env - f_main - ;; -esac diff --git a/net/banip/files/banip.sources b/net/banip/files/banip.sources deleted file mode 100644 index 5597c06a6..000000000 --- a/net/banip/files/banip.sources +++ /dev/null @@ -1,191 +0,0 @@ -{ - "asn": { - "url_4": "https://asn.ipinfo.app/api/text/list/", - "url_6": "https://asn.ipinfo.app/api/text/list/", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add asn_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add asn_6 \"$1}", - "focus": "ASN blocks", - "descurl": "https://asn.ipinfo.app" - }, - "bogon": { - "url_4": "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt", - "url_6": "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv6.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add bogon_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add bogon_6 \"$1}", - "focus": "Bogon prefixes", - "descurl": "https://team-cymru.com" - }, - "country": { - "url_4": "http://www.ipdeny.com/ipblocks/data/aggregated/", - "url_6": "http://www.ipdeny.com/ipv6/ipaddresses/aggregated/", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add country_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add country_6 \"$1}", - "focus": "Country blocks", - "descurl": "http://www.ipdeny.com/ipblocks" - }, - "darklist": { - "url_4": "https://darklist.de/raw.php", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add darklist_4 \"$1}", - "focus": "Blocks suspicious attacker IPs", - "descurl": "https://darklist.de" - }, - "debl": { - "url_4": "https://www.blocklist.de/downloads/export-ips_all.txt", - "url_6": "https://www.blocklist.de/downloads/export-ips_all.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add debl_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add debl_6 \"$1}", - "focus": "Fail2ban IP blacklist", - "descurl": "https://www.blocklist.de" - }, - "doh": { - "url_4": "https://raw.githubusercontent.com/dibdot/DoH-IP-blocklists/master/doh-ipv4.txt", - "url_6": "https://raw.githubusercontent.com/dibdot/DoH-IP-blocklists/master/doh-ipv6.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add doh_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add doh_6 \"$1}", - "focus": "Public DoH-Provider", - "descurl": "https://github.com/dibdot/DoH-IP-blocklists" - }, - "drop": { - "url_4": "https://www.spamhaus.org/drop/drop.txt", - "url_6": "https://www.spamhaus.org/drop/dropv6.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add drop_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add drop_6 \"$1}", - "focus": "Spamhaus drop compilation", - "descurl": "https://www.spamhaus.org" - }, - "dshield": { - "url_4": "https://feeds.dshield.org/block.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add dshield_4 \"$1 \"/\"$3}", - "focus": "Dshield IP blocklist", - "descurl": "https://www.dshield.org" - }, - "edrop": { - "url_4": "https://www.spamhaus.org/drop/edrop.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add edrop_4 \"$1}", - "focus": "Spamhaus edrop compilation", - "descurl": "https://www.spamhaus.org" - }, - "feodo": { - "url_4": "https://feodotracker.abuse.ch/downloads/ipblocklist.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add feodo_4 \"$1}", - "focus": "Feodo Tracker", - "descurl": "https://feodotracker.abuse.ch" - }, - "firehol1": { - "url_4": "https://iplists.firehol.org/files/firehol_level1.netset", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add firehol1_4 \"$1}", - "focus": "Firehol Level 1 compilation", - "descurl": "https://iplists.firehol.org/?ipset=firehol_level1" - }, - "firehol2": { - "url_4": "https://iplists.firehol.org/files/firehol_level2.netset", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add firehol2_4 \"$1}", - "focus": "Firehol Level 2 compilation", - "descurl": "https://iplists.firehol.org/?ipset=firehol_level2" - }, - "firehol3": { - "url_4": "https://iplists.firehol.org/files/firehol_level3.netset", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add firehol3_4 \"$1}", - "focus": "Firehol Level 3 compilation", - "descurl": "https://iplists.firehol.org/?ipset=firehol_level3" - }, - "firehol4": { - "url_4": "https://iplists.firehol.org/files/firehol_level4.netset", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add firehol4_4 \"$1}", - "focus": "Firehol Level 4 compilation", - "descurl": "https://iplists.firehol.org/?ipset=firehol_level4" - }, - "greensnow": { - "url_4": "https://blocklist.greensnow.co/greensnow.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add greensnow_4 \"$1}", - "focus": "Blocks suspicious server IPs", - "descurl": "https://greensnow.co" - }, - "iblockads": { - "url_4": "https://list.iblocklist.com/?list=dgxtneitpuvgqqcpfulq&fileformat=cidr&archiveformat=gz", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add iblockads_4 \"$1}", - "focus": "Advertising blocklist", - "descurl": "https://www.iblocklist.com", - "comp": "gz" - }, - "iblockspy": { - "url_4": "https://list.iblocklist.com/?list=llvtlsjyoyiczbkjsxpf&fileformat=cidr&archiveformat=gz", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add iblockspy_4 \"$1}", - "focus": "Malicious spyware blocklist", - "descurl": "https://www.iblocklist.com", - "comp": "gz" - }, - "myip": { - "url_4": "https://myip.ms/files/blacklist/general/latest_blacklist.txt", - "url_6": "https://myip.ms/files/blacklist/general/latest_blacklist.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add myip_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add myip_6 \"$1}", - "focus": "Myip Live IP blacklist", - "descurl": "https://myip.ms" - }, - "nixspam": { - "url_4": "http://www.dnsbl.manitu.net/download/nixspam-ip.dump.gz", - "rule_4": "/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add nixspam_4 \"$2}", - "focus": "iX spam protection", - "descurl": "http://www.nixspam.org", - "comp": "gz" - }, - "proxy": { - "url_4": "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/proxylists.ipset", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add proxy_4 \"$1}", - "focus": "Firehol list of open proxies", - "descurl": "https://iplists.firehol.org/?ipset=proxylists" - }, - "sslbl": { - "url_4": "https://sslbl.abuse.ch/blacklist/sslipblacklist.csv", - "rule_4": "BEGIN{FS=\",\"}/(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)/{print \"add sslbl_4 \"$2}", - "focus": "SSL botnet IP blacklist", - "descurl": "https://sslbl.abuse.ch" - }, - "talos": { - "url_4": "https://www.talosintelligence.com/documents/ip-blacklist", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add talos_4 \"$1}", - "focus": "Cisco Talos IP Blacklist", - "descurl": "https://talosintelligence.com/reputation_center" - }, - "threat": { - "url_4": "https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add threat_4 \"$1}", - "focus": "Emerging Threats", - "descurl": "https://rules.emergingthreats.net" - }, - "tor": { - "url_4": "https://lists.fissionrelays.net/tor/exits-ipv4.txt", - "url_6": "https://lists.fissionrelays.net/tor/exits-ipv6.txt", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add tor_4 \"$1}", - "rule_6": "/^(([0-9A-f]{0,4}:){1,7}[0-9A-f]{0,4}:?(\\/(1?[0-2][0-8]|[0-9][0-9]))?)([[:space:]]|$)/{print \"add tor_6 \"$1}", - "focus": "Tor exit nodes", - "descurl": "https://fissionrelays.net/lists" - }, - "uceprotect1": { - "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-1.uceprotect.net.gz", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)$/{print \"add uceprotect1_4 \"$1}", - "focus": "Spam protection level 1", - "descurl": "http://www.uceprotect.net/en/index.php", - "comp": "gz" - }, - "uceprotect2": { - "url_4": "http://wget-mirrors.uceprotect.net/rbldnsd-all/dnsbl-2.uceprotect.net.gz", - "rule_4": "BEGIN{IGNORECASE=1}/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]+NET[[:space:]]+)/{print \"add uceprotect2_4 \"$1}", - "focus": "Spam protection level 2", - "descurl": "http://www.uceprotect.net/en/index.php", - "comp": "gz" - }, - "voip": { - "url_4": "http://www.voipbl.org/update/", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add voip_4 \"$1}", - "focus": "VoIP fraud blocklist", - "descurl": "http://www.voipbl.org" - }, - "yoyo": { - "url_4": "https://pgl.yoyo.org/adservers/iplist.php?ipformat=plain&showintro=0&mimetype=plaintext", - "rule_4": "/^(([0-9]{1,3}\\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])(\\/(1?[0-9]|2?[0-9]|3?[0-2]))?)([[:space:]]|$)/{print \"add yoyo_4 \"$1}", - "focus": "Ad protection blacklist", - "descurl": "https://pgl.yoyo.org/adservers/" - } -} diff --git a/net/banip/files/banip.tpl b/net/banip/files/banip.tpl new file mode 100644 index 000000000..9a614d026 --- /dev/null +++ b/net/banip/files/banip.tpl @@ -0,0 +1,24 @@ +# banIP mail template/include +# Copyright (c) 2020-2023 Dirk Brenken (dev@brenken.org) +# This is free software, licensed under the GNU General Public License v3. + +# info preparation +# +local banip_info report_info log_info system_info mail_text + +banip_info="$(/etc/init.d/banip status 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=120;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="$( + strings /etc/banner 2>/dev/null + 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 +# +mail_text="$(printf "%s\n" "
")"
+mail_text="$(printf "%s\n" "${mail_text}\n++\n++ System Information ++\n++\n${system_info:-"-"}")"
+mail_text="$(printf "%s\n" "${mail_text}\n\n++\n++ banIP Status ++\n++\n${banip_info:-"-"}")"
+mail_text="$(printf "%s\n" "${mail_text}\n\n++\n++ banIP Report ++\n++\n${report_info:-"-"}")"
+mail_text="$(printf "%s\n" "${mail_text}\n\n++\n++ Logfile Information ++\n++\n${log_info}")"
+mail_text="$(printf "%s\n" "${mail_text}
")" diff --git a/net/banip/files/banip.whitelist b/net/banip/files/banip.whitelist deleted file mode 100644 index e69de29bb..000000000