diff --git a/autoinstall/current/autoinstall.sh b/autoinstall/current/autoinstall.sh index 2e12362..08acec9 100755 --- a/autoinstall/current/autoinstall.sh +++ b/autoinstall/current/autoinstall.sh @@ -9,9 +9,9 @@ LUA_MODULE=0 LUCI_APP=1 OWRT_VERSION="current" -RUAB_VERSION="1.4-3" -RUAB_MOD_LUA_VERSION="1.4-3" -RUAB_LUCI_APP_VERSION="1.4-2" +RUAB_VERSION="1.5-0" +RUAB_MOD_LUA_VERSION="1.5-0" +RUAB_LUCI_APP_VERSION="1.5-0" BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master" PKG_DIR="/tmp" diff --git a/autoinstall/current/uninstall.sh b/autoinstall/current/uninstall.sh index 310dd71..2f06f2c 100755 --- a/autoinstall/current/uninstall.sh +++ b/autoinstall/current/uninstall.sh @@ -12,6 +12,7 @@ HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock" CRONTAB_FILE="/etc/crontabs/root" DATA_DIR="/tmp/ruantiblock" DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq" +DNSMASQ_DATA_FILE_TMP="${DNSMASQ_DATA_FILE}.tmp" DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq" SCRIPTS_DIR="/usr/share/ruantiblock" MODULES_DIR="/usr/libexec/ruantiblock" diff --git a/luci-app-ruantiblock/Makefile b/luci-app-ruantiblock/Makefile index eb9a31d..b7260ab 100644 --- a/luci-app-ruantiblock/Makefile +++ b/luci-app-ruantiblock/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=1.4-2 +PKG_VERSION:=1.5-0 LUCI_TITLE:=LuCI support for ruantiblock LUCI_DEPENDS:=+ruantiblock LUCI_PKGARCH:=all diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js index 63e96fc..105ca1d 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/info.js @@ -219,6 +219,7 @@ return view.extend({ } catch(e) {}; let update_status = null, + user_entries = null, rules = null, dnsmasq = null, dnsmasqBypass = null; @@ -265,6 +266,21 @@ return view.extend({ ); }; + if(data.user_entries && data.user_entries.length > 0) { + user_entries = E('table', { 'class': 'table' }); + for(let i of data.user_entries) { + user_entries.append( + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td left', 'style': 'min-width:33%' }, + i.id), + E('td', { 'class': 'td left', + 'id' : 'user_entries_' + i }, + `CIDR: ${i.cidr}, IP: ${i.ip}, FQDN: ${i.fqdn}`), + ]) + ); + }; + }; + let nft_data = this.formatNftJson(data); if(nft_data.rules) { @@ -346,8 +362,17 @@ return view.extend({ ), ]; + if(user_entries) { + layout.splice(3, 0, + E('div', { 'class': 'cbi-section fade-in' }, [ + E('h3', {}, _('User entries')), + E('div', { 'class': 'cbi-section-node' }, user_entries), + ]) + ); + } + if(dnsmasqBypass) { - layout.splice(4, 0, + layout.splice(5, 0, E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section-node' }, dnsmasqBypass) ) @@ -355,7 +380,7 @@ return view.extend({ }; if(dnsmasq) { - layout.splice(5, 0, + layout.splice(6, 0, E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section-node' }, dnsmasq) ) diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js index ac50c90..a496585 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/settings.js @@ -25,6 +25,11 @@ return view.extend({ + ` ${_('One of the following:')}\n - ${_('valid IP address')}\n - ${_('valid address#port')}\n`; }, + validateUrl: function(section, value) { + return (/^$|^https?:\/\/[\w.-]+(:[0-9]{2,5})?[\w\/~.&?+=-]*$/.test(value)) ? true : _('Expecting:') + + ` ${_('valid URL')}\n`; + }, + load: function() { return Promise.all([ L.resolveDefault(fs.exec(tools.execPath, [ 'raw-status' ]), 1), @@ -287,6 +292,13 @@ return view.extend({ o.default = 0; o.depends({ bllist_preset: '', '!reverse': true }); + // ENABLE_TMP_DOWNLOADS + o = s.taboption('blacklist_tab', form.Flag, 'enable_tmp_downloads', + _('Safe blacklist update'), + _('If update fails, the old blacklist configuration will be retained. Temporary files are used, when updating the blacklist (increases memory consumption).')); + o.rmempty = false; + o.default = 0; + // ADD_USER_ENTRIES o = s.taboption('blacklist_tab', form.Flag, 'add_user_entries', _('Enable user entries'), _('Add user entries to the blacklist when updating')); @@ -301,6 +313,11 @@ return view.extend({ o.inputtitle = _('Edit'); o.inputstyle = 'edit btn'; + // USER_ENTRIES_REMOTE + o = s.taboption('blacklist_tab', form.DynamicList, 'user_entries_remote', + _('URLs of remote user entries file')); + o.validate = this.validateUrl; + // USER_ENTRIES_DNS o = s.taboption('blacklist_tab', form.Value, 'user_entries_dns', _("DNS server that is used for the user's FQDN entries"), 'ipaddress[#port]'); diff --git a/luci-app-ruantiblock/po/ru/ruantiblock.po b/luci-app-ruantiblock/po/ru/ruantiblock.po index 0ba2a1c..9ac81e0 100644 --- a/luci-app-ruantiblock/po/ru/ruantiblock.po +++ b/luci-app-ruantiblock/po/ru/ruantiblock.po @@ -381,6 +381,9 @@ msgstr "Ruantiblock" msgid "Run at startup" msgstr "Запуск при старте системы" +msgid "Safe blacklist update" +msgstr "Безопасное обновление блэклиста" + msgid "Save" msgstr "Сохранить" @@ -426,6 +429,13 @@ msgstr "Суммировать '/24' подсети" msgid "Summarize IP ranges" msgstr "Суммировать IP диапазоны" +msgid "" +"If update fails, the old blacklist configuration will be retained. " +"Temporary files are used, when updating the blacklist (increases memory consumption)." +msgstr "" +"Если обновление завершилось с ошибками, будет сохранена старая конфигурация блэклиста. " +"При обновлении используются временные файлы (увеличивается потребление памяти)." + msgid "" "The number of IP addresses in the subnet, upon reaching which the entire " "'/24' subnet is added to the list" @@ -521,6 +531,9 @@ msgstr "Обновлять блэклист после запуска систе msgid "Updating" msgstr "Обновление" +msgid "URLs of remote user entries file" +msgstr "URL удалённых файлов записей пользователя" + msgid "Use optional DNS resolver" msgstr "Использовать альтернативный DNS резолвер" @@ -577,3 +590,6 @@ msgstr "верный IP-адрес" msgid "valid address#port" msgstr "верный IP-адрес#порт" + +msgid "valid URL" +msgstr "верный URL" diff --git a/luci-app-ruantiblock/po/templates/ruantiblock.pot b/luci-app-ruantiblock/po/templates/ruantiblock.pot index 5c0d885..299559d 100644 --- a/luci-app-ruantiblock/po/templates/ruantiblock.pot +++ b/luci-app-ruantiblock/po/templates/ruantiblock.pot @@ -353,6 +353,9 @@ msgstr "" msgid "Run at startup" msgstr "" +msgid "Safe blacklist update" +msgstr "" + msgid "Save" msgstr "" @@ -396,6 +399,11 @@ msgstr "" msgid "Summarize IP ranges" msgstr "" +msgid "" +"If update fails, the old blacklist configuration will be retained. " +"Temporary files are used, when updating the blacklist (increases memory consumption)." +msgstr "" + msgid "" "The number of IP addresses in the subnet, upon reaching which the entire " "'/24' subnet is added to the list" @@ -486,6 +494,9 @@ msgstr "" msgid "Updating" msgstr "" +msgid "URLs of remote user entries file" +"" + msgid "Use optional DNS resolver" msgstr "" msgid "User entries" @@ -541,3 +552,6 @@ msgstr "" msgid "valid address#port" msgstr "" + +msgid "valid URL" +msgstr "" diff --git a/ruantiblock-mod-lua/Makefile b/ruantiblock-mod-lua/Makefile index 60d61eb..f6e40e4 100644 --- a/ruantiblock-mod-lua/Makefile +++ b/ruantiblock-mod-lua/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-lua -PKG_VERSION:=1.4 -PKG_RELEASE:=3 +PKG_VERSION:=1.5 +PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk diff --git a/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua b/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua index 74ae9b8..a7e2f52 100755 --- a/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua +++ b/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua @@ -97,6 +97,7 @@ local Config = Class(nil, { http_send_headers = { ["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0", }, + connect_timeout = nil, }) Config.wget_user_agent = (Config.http_send_headers["User-Agent"]) and ' -U "' .. Config.http_send_headers["User-Agent"] .. '"' or '' @@ -263,6 +264,7 @@ function BlackListParser:new(t) instance.fqdn_table = {} instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil instance.buff = "" + instance.http_codes = {} return instance end @@ -382,9 +384,19 @@ function BlackListParser:get_http_data(url) local ret_val, ret_code, ret_headers local http_module = url:match("^https") and https or http if http_module then - local http_sink = ltn12.sink.chain(self:chunk_buffer(), self:parser_func()) - ret_val, ret_code, ret_headers = http_module.request{url = url, sink = http_sink, headers = self.http_send_headers} - if not ret_val or ret_code ~= 200 then + if self.connect_timeout ~= nil then + http_module.TIMEOUT = self.connect_timeout + end + ret_val, ret_code, ret_headers = http_module.request{url = url, method="HEAD", headers = self.http_send_headers} + if ret_val and ret_code == 200 then + local http_sink = ltn12.sink.chain(self:chunk_buffer(), self:parser_func()) + ret_val, ret_code, ret_headers = http_module.request{url = url, sink = http_sink, headers = self.http_send_headers} + self.http_codes[ret_code] = true + if not ret_val or ret_code ~= 200 then + ret_val = nil + print(string.format("Connection error! (%s) URL: %s", ret_code, url)) + end + else ret_val = nil print(string.format("Connection error! (%s) URL: %s", ret_code, url)) end @@ -419,9 +431,16 @@ function BlackListParser:run() return_code = 2 end else - return_code = 1 + return_code = 2 + end + for i in pairs(self.http_codes) do + if i ~= 200 then + return_code = 2 + break + end end self.buff = "" + self.http_codes = {} return return_code end @@ -961,11 +980,16 @@ local Ra = Class(BlackListParser, { function Ra:download_config(url, file) local ret_val = false - self.current_file_handler = assert(io.open(file, "w"), "Could not open file") + self.current_file = file + self.current_file_handler = nil if self:download_files(url) then ret_val = true end - self.current_file_handler:close() + if self.current_file_handler then + self.current_file_handler:close() + end + self.current_file_handler = nil + self.current_file = nil return ret_val end @@ -978,7 +1002,12 @@ end function Ra:parser_func() return function(chunk) if chunk and chunk ~= "" then - self.current_file_handler:write(chunk) + if not self.current_file_handler and self.current_file then + self.current_file_handler = assert(io.open(self.current_file, "w"), "Could not open file") + end + if self.current_file_handler then + self.current_file_handler:write(chunk) + end end return true end @@ -993,6 +1022,13 @@ function Ra:run() end end end + for i in pairs(self.http_codes) do + if i ~= 200 then + return_code = 2 + break + end + end + self.http_codes = {} return return_code end diff --git a/ruantiblock-mod-py/Makefile b/ruantiblock-mod-py/Makefile index d83b7f1..527eefe 100644 --- a/ruantiblock-mod-py/Makefile +++ b/ruantiblock-mod-py/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-py -PKG_VERSION:=1.4 -PKG_RELEASE:=3 +PKG_VERSION:=1.5 +PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk diff --git a/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py b/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py index 2336b5a..e7e412a 100755 --- a/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py +++ b/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py @@ -158,8 +158,7 @@ class BlackListParser(Config): self.ip_pattern = re.compile(r"(([0-9]{1,3}[.]){3})[0-9]{1,3}") self.cidr_pattern = re.compile(r"([0-9]{1,3}[.]){3}[0-9]{1,3}/[0-9]{1,2}") self.fqdn_pattern = re.compile( - r"([а-яёa-z0-9_.*-]*?)([а-яёa-z0-9_-]+[.][а-яёa-z0-9-]+)", - re.U) + r"([а-яёa-z0-9_.*-]*?)([а-яёa-z0-9_-]+[.][а-яёa-z0-9-]+)", re.U) self.www_pattern = re.compile(r"^www[0-9]?[.]") self.cyr_pattern = re.compile(r"[а-яё]", re.U) self.cidr_set = set() @@ -183,6 +182,7 @@ class BlackListParser(Config): self.default_site_encoding = "utf-8" self.site_encoding = self.default_site_encoding self.rest = bytes() + self.http_codes = set() @staticmethod def _compile_filter_patterns(filters_seq): @@ -233,6 +233,7 @@ class BlackListParser(Config): timeout=self.connect_timeout ) as conn_params: conn_object, http_code, _ = conn_params + self.http_codes.add(http_code) if http_code == 200: while True: chunk = conn_object.read(self.data_chunk) @@ -350,7 +351,12 @@ class BlackListParser(Config): ret_value = 0 else: ret_value = 2 + for i in self.http_codes: + if i != 200: + ret_value = 2 + break self.rest = bytes() + self.http_codes = set() return ret_value @@ -722,23 +728,34 @@ class RaFQDN(BlackListParser): self.url_ipset = self.RA_FQDN_IPSET_URL self.url_dnsmasq = self.RA_FQDN_DMASK_URL self.url_stat = self.RA_FQDN_STAT_URL - self.current_file_handler = None - - def parser_func(self): - for chunk in self._download_data(self.url[0]): - if chunk: - self.current_file_handler.write(chunk) def download_config(self, url, cfg_file): self.url = url - with open(cfg_file, "wb", buffering=-1) as self.current_file_handler: - self.parser_func() + file_handler = None + for chunk in self._download_data(self.url[0]): + if chunk: + if not file_handler: + try: + file_handler = open(cfg_file, "wb", buffering=-1) + except Exception: + break + if file_handler: + file_handler.write(chunk) + if file_handler: + file_handler.close() + file_handler = None def run(self): + ret_value = 0 self.download_config(self.url_ipset, self.IP_DATA_FILE) self.download_config(self.url_dnsmasq, self.DNSMASQ_DATA_FILE) self.download_config(self.url_stat, self.UPDATE_STATUS_FILE) - return 0 + for i in self.http_codes: + if i != 200: + ret_value = 2 + break + self.http_codes = set() + return ret_value class RaIp(RaFQDN): diff --git a/ruantiblock/Makefile b/ruantiblock/Makefile index e1c03b5..ca661dc 100644 --- a/ruantiblock/Makefile +++ b/ruantiblock/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock -PKG_VERSION:=1.4 -PKG_RELEASE:=3 +PKG_VERSION:=1.5 +PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot include $(INCLUDE_DIR)/package.mk @@ -78,9 +78,10 @@ FILE_INIT_SCRIPT="/etc/init.d/ruantiblock" FILE_MAIN_SCRIPT="/usr/bin/ruantiblock" CRONTAB_FILE="/etc/crontabs/root" DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq" +DNSMASQ_DATA_FILE_TMP="${DNSMASQ_DATA_FILE}.tmp" DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq" -rm -f $$DNSMASQ_DATA_FILE $$DNSMASQ_DATA_FILE_BYPASS +rm -f $$DNSMASQ_DATA_FILE $$DNSMASQ_DATA_FILE_TMP $$DNSMASQ_DATA_FILE_BYPASS test -e "$$FILE_MAIN_SCRIPT" && $$FILE_MAIN_SCRIPT destroy test -e "$$FILE_INIT_SCRIPT" && $$FILE_INIT_SCRIPT disable diff --git a/ruantiblock/files/etc/config/ruantiblock b/ruantiblock/files/etc/config/ruantiblock index 3085042..c5def4d 100644 --- a/ruantiblock/files/etc/config/ruantiblock +++ b/ruantiblock/files/etc/config/ruantiblock @@ -2,11 +2,11 @@ config main 'config' option proxy_mode '1' option proxy_local_clients '1' + option enable_logging '1' + option update_at_startup '1' option nftset_clear_sets '1' option allowed_hosts_mode '0' - option bypass_mode '0' option enable_fproxy '0' - option enable_bllist_proxy '0' option if_vpn 'tun0' option vpn_route_check '0' option tor_trans_port '9040' @@ -14,8 +14,10 @@ config main 'config' option t_proxy_port_tcp '1100' option t_proxy_port_udp '1100' option t_proxy_allow_udp '0' + option bypass_mode '0' + option enable_bllist_proxy '0' + option enable_tmp_downloads '0' option add_user_entries '0' - option enable_logging '1' option bllist_min_entries '3000' option bllist_ip_limit '0' option bllist_summarize_ip '1' @@ -43,4 +45,3 @@ config main 'config' option bllist_enable_idn '0' option bllist_alt_nslookup '0' option bllist_alt_dns_addr '8.8.8.8' - option update_at_startup '1' diff --git a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf index 9666b52..7164f7b 100644 --- a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf +++ b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf @@ -80,6 +80,12 @@ ADD_USER_ENTRIES=0 USER_ENTRIES_DNS="" ### Файл пользовательских записей USER_ENTRIES_FILE="/etc/ruantiblock/user_entries" +### URL удаленных файлов записей пользователя, через пробел (прим.: http://server.lan/files/user_entries_1 http://server.lan/files/user_entries_2) +USER_ENTRIES_REMOTE="" +### Кол-во попыток скачивания удаленного файла записей пользователя (в случае неудачи) +USER_ENTRIES_REMOTE_DOWNLOAD_ATTEMPTS=3 +### Таймаут между попытками скачивания +USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT=60 ### Режим списка записей, исключаемых из обхода блокировок (0 - выкл, 1 - вкл) BYPASS_MODE=0 ### DNS-сервер для исключаемых записей (пустая строка - без DNS-сервера). Можно с портом: 8.8.8.8#53. Если в записи указан свой DNS-сервер - он имеет приоритет @@ -92,10 +98,12 @@ ENABLE_FPROXY=0 FPROXY_LIST="" ### Список приватных сетей для режима полного прокси, через пробел FPROXY_PRIVATE_NETS="192.168.0.0/16 172.16.0.0/12 10.0.0.0/8" +### Режим безопасного обновления блэклиста. Скачивание во временный файл и затем замена основного. Увеличивает потребление памяти (0 - выкл, 1 - вкл) +ENABLE_TMP_DOWNLOADS=0 ### Скачивать блэклисты через прокси ENABLE_BLLIST_PROXY=0 ### Список хостов источников блэклиста -BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com antifilter.download" +BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com app.assembla.com antifilter.download" ### Кол-во попыток обновления блэклиста (в случае неудачи) MODULE_RUN_ATTEMPTS=3 ### Таймаут между попытками обновления @@ -150,8 +158,8 @@ BLLIST_ALT_DNS_ADDR="8.8.8.8" RBL_ALL_URL="https://reestr.rublacklist.net/api/v3/snapshot/" RBL_IP_URL="https://reestr.rublacklist.net/api/v3/ips/" RBL_DPI_URL="https://reestr.rublacklist.net/api/v3/dpi/" -ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" -#ZI_ALL_URL="https://app.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw" +#ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" +ZI_ALL_URL="https://app.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw" AF_IP_URL="https://antifilter.download/list/allyouneed.lst" AF_FQDN_URL="https://antifilter.download/list/domains.lst" FZ_URL="https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.00 https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.01 https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.02" diff --git a/ruantiblock/files/usr/bin/ruantiblock b/ruantiblock/files/usr/bin/ruantiblock index 76f8df6..fc233aa 100755 --- a/ruantiblock/files/usr/bin/ruantiblock +++ b/ruantiblock/files/usr/bin/ruantiblock @@ -97,6 +97,12 @@ export ADD_USER_ENTRIES=0 export USER_ENTRIES_DNS="" ### Файл пользовательских записей export USER_ENTRIES_FILE="${CONFIG_DIR}/user_entries" +### URL удаленных файлов записей пользователя, через пробел (прим.: http://server.lan/files/user_entries_1 http://server.lan/files/user_entries_2) +export USER_ENTRIES_REMOTE="" +### Кол-во попыток скачивания удаленного файла записей пользователя (в случае неудачи) +export USER_ENTRIES_REMOTE_DOWNLOAD_ATTEMPTS=3 +### Таймаут между попытками скачивания +export USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT=60 ### Режим списка IP адресов исключаемых из обхода блокировок (0 - выкл, 1 - вкл) export BYPASS_MODE=0 ### DNS-сервер для исключаемых записей (пустая строка - без DNS-сервера). Можно с портом: 8.8.8.8#53. Если в записи указан свой DNS-сервер - он имеет приоритет @@ -109,10 +115,12 @@ export ENABLE_FPROXY=0 export FPROXY_LIST="" ### Список приватных сетей для режима полного прокси, через пробел export FPROXY_PRIVATE_NETS="192.168.0.0/16 172.16.0.0/12 10.0.0.0/8" +### Режим безопасного обновления блэклиста. Скачивание во временный файл и затем замена основного. Увеличивает потребление памяти (0 - выкл, 1 - вкл) +export ENABLE_TMP_DOWNLOADS=0 ### Скачивать блэклисты через прокси export ENABLE_BLLIST_PROXY=0 ### Список хостов источников блэклиста -export BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com antifilter.download" +export BLLIST_HOSTS="reestr.rublacklist.net raw.githubusercontent.com app.assembla.com antifilter.download" ### Кол-во попыток обновления блэклиста (в случае неудачи) export MODULE_RUN_ATTEMPTS=3 ### Таймаут между попытками обновления @@ -167,7 +175,8 @@ export BLLIST_ALT_DNS_ADDR="8.8.8.8" export RBL_ALL_URL="https://reestr.rublacklist.net/api/v3/snapshot/" export RBL_IP_URL="https://reestr.rublacklist.net/api/v3/ips/" export RBL_DPI_URL="https://reestr.rublacklist.net/api/v3/dpi/" -export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" +#export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" +export ZI_ALL_URL="https://app.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw" export AF_IP_URL="https://antifilter.download/list/allyouneed.lst" export AF_FQDN_URL="https://antifilter.download/list/domains.lst" export FZ_URL="https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.00 https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.01 https://raw.githubusercontent.com/fz139/vigruzki/main/dump.xml.02" @@ -251,12 +260,17 @@ export NFTSET_CIDR_CFG="set ${NFTSET_CIDR} {type ${NFTSET_CIDR_TYPE};size ${NFTS export NFTSET_IP_CFG="set ${NFTSET_IP} {type ${NFTSET_IP_TYPE};size ${NFTSET_MAXELEM_IP};policy ${NFTSET_POLICY_IP};flags dynamic;" export NFTSET_BYPASS_IP_CFG="set ${NFTSET_BYPASS_IP} {type ${NFTSET_BYPASS_IP_TYPE};size ${NFTSET_MAXELEM_BYPASS_IP};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" export UPDATE_STATUS_FILE="${DATA_DIR}/update_status" +export USER_ENTRIES_STATUS_FILE="${DATA_DIR}/user_entries_status" U_PID_FILE="/var/run/${NAME}_update.pid" START_PID_FILE="/var/run/${NAME}_start.pid" TOKEN_FILE="/var/run/${NAME}.token" export HTML_OUTPUT="${HTML_DIR}/${NAME}.html" NFT_FUNCTIONS="${SCRIPTS_DIR}/nft_functions" INFO_OUTPUT_FUNCTION="${SCRIPTS_DIR}/info_output" +export IP_DATA_FILE_TMP="${IP_DATA_FILE}.tmp" +export DNSMASQ_DATA_FILE_TMP="${DNSMASQ_DATA_FILE}.tmp" +export UPDATE_STATUS_FILE_TMP="${UPDATE_STATUS_FILE}.tmp" +export USER_ENTRIES_STATUS_FILE_TMP="${USER_ENTRIES_STATUS_FILE}.tmp" ######################### External functions ########################### @@ -310,26 +324,73 @@ MakeLogRecord() { Download() { $WGET_CMD $WGET_PARAMS "$1" "$2" if [ $? -ne 0 ]; then - echo "Blacklist downloading failed! Connection error (${2})" >&2 - MakeLogRecord "err" "Blacklist downloading failed! Connection error (${2})" + echo " Downloading failed! Connection error (${2})" >&2 + MakeLogRecord "err" "Downloading failed! Connection error (${2})" return 1 fi } DownloadRuabBlacklist() { + local _ip_data_file _dnsmasq_data_file _update_status_file _return_code=0 + if [ "$ENABLE_TMP_DOWNLOADS" = "1" ]; then + _ip_data_file="$IP_DATA_FILE_TMP" + _dnsmasq_data_file="$DNSMASQ_DATA_FILE_TMP" + _update_status_file="$UPDATE_STATUS_FILE_TMP" + rm -f "$_ip_data_file" "$_dnsmasq_data_file" "$_update_status_file" + else + _ip_data_file="$IP_DATA_FILE" + _dnsmasq_data_file="$DNSMASQ_DATA_FILE" + _update_status_file="$UPDATE_STATUS_FILE" + fi case "$1" in "ip") - Download "$IP_DATA_FILE" "$RA_IP_IPSET_URL" && Download "$DNSMASQ_DATA_FILE" "$RA_IP_DMASK_URL" && Download "$UPDATE_STATUS_FILE" "$RA_IP_STAT_URL" + Download "$_ip_data_file" "$RA_IP_IPSET_URL" + if [ $? -ne 0 ]; then + _return_code=1 + else + Download "$_dnsmasq_data_file" "$RA_IP_DMASK_URL" + if [ $? -ne 0 ]; then + _return_code=1 + else + Download "$_update_status_file" "$RA_IP_STAT_URL" + if [ $? -ne 0 ]; then + _return_code=1 + fi + fi + fi ;; "fqdn") - Download "$DNSMASQ_DATA_FILE" "$RA_FQDN_DMASK_URL" && Download "$IP_DATA_FILE" "$RA_FQDN_IPSET_URL" && Download "$UPDATE_STATUS_FILE" "$RA_FQDN_STAT_URL" + Download "$_dnsmasq_data_file" "$RA_FQDN_DMASK_URL" + if [ $? -ne 0 ]; then + _return_code=1 + else + Download "$_ip_data_file" "$RA_FQDN_IPSET_URL" + if [ $? -ne 0 ]; then + _return_code=1 + else + Download "$_update_status_file" "$RA_FQDN_STAT_URL" + if [ $? -ne 0 ]; then + _return_code=1 + fi + fi + fi ;; *) - echo "Blacklist configuration error (${1})" >&2 + echo " Blacklist configuration error (${1})" >&2 MakeLogRecord "err" "Blacklist configuration error (${1})" exit 1 ;; esac + if [ "$ENABLE_TMP_DOWNLOADS" = "1" ]; then + if [ $_return_code -eq 0 ]; then + mv -f "$_ip_data_file" "$IP_DATA_FILE" + mv -f "$_dnsmasq_data_file" "$DNSMASQ_DATA_FILE" + mv -f "$_update_status_file" "$UPDATE_STATUS_FILE" + else + rm -f "$_ip_data_file" "$_dnsmasq_data_file" "$_update_status_file" + fi + fi + return $_return_code } RestartDnsmasq() { @@ -437,6 +498,7 @@ ClearDataFiles() { printf "" > "$DNSMASQ_DATA_FILE_BYPASS" printf "" > "$IP_DATA_FILE" printf "0 0 0" > "$UPDATE_STATUS_FILE" + printf "" > "$USER_ENTRIES_STATUS_FILE" fi } @@ -453,69 +515,156 @@ PreStartCheck() { [ -e "$DNSMASQ_DATA_FILE_BYPASS" ] || printf "" > "$DNSMASQ_DATA_FILE_BYPASS" } +ParseUserEntries() { + $AWK_CMD -v IP_DATA_FILE="$1" -v DNSMASQ_DATA_FILE="$2" -v USER_ENTRIES_STATUS_FILE="$3" -v ID="$4" 'BEGIN { + null = ""; + ip_array[0] = null; + cidr_array[0] = null; + fqdn_array[0] = null; + } + function writeIpList(array, _str) { + _str = ""; + for(i in array) { + _str = _str i ","; + }; + return _str; + }; + function writeDNSData(val, dns) { + if(length(dns) == 0 && length(ENVIRON["USER_ENTRIES_DNS"]) > 0) { + dns = ENVIRON["USER_ENTRIES_DNS"]; + }; + if(length(dns) > 0) { + printf "server=/%s/%s\n", val, dns >> DNSMASQ_DATA_FILE; + }; + printf "nftset=/%s/%s#%s\n", val, ENVIRON["NFT_TABLE_DNSMASQ"], ENVIRON["NFTSET_DNSMASQ"] >> DNSMASQ_DATA_FILE; + }; + function writeFqdnEntries() { + delete fqdn_array[0]; + for(i in fqdn_array) { + split(fqdn_array[i], a, " "); + writeDNSData(a[1], a[2]); + }; + }; + ($0 !~ /^([\040\011]*$|#)/) { + if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}$/) { + ip_array[$0] = null; + } + else if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}[\057][0-9]{1,2}$/) { + cidr_array[$0] = null; + } + else if($0 ~ /^[a-z0-9.\052-]+[.]([a-z]{2,}|xn--[a-z0-9]+)([ ][0-9]{1,3}([.][0-9]{1,3}){3}([#][0-9]{2,5})?)?$/) { + fqdn_array[length(fqdn_array)] = $1 " " $2; + }; + } + END { + ret_code = 0; + if($0 ~ /[0-9]+/) { + ret_code = $0; + }; + delete cidr_array[0]; + delete ip_array[0]; + if(ret_code == 0 && (length(cidr_array) > 0 || length(ip_array) > 0)) { + printf "table %s {\n%s", ENVIRON["NFT_TABLE"], ENVIRON["NFTSET_CIDR_CFG"] >> IP_DATA_FILE; + if(length(cidr_array) > 0) { + printf "elements={%s};", writeIpList(cidr_array) >> IP_DATA_FILE; + }; + printf "}\n%s", ENVIRON["NFTSET_IP_CFG"] >> IP_DATA_FILE; + + if(length(ip_array) > 0) { + printf "elements={%s};", writeIpList(ip_array) >> IP_DATA_FILE; + }; + printf "}\n}\n" >> IP_DATA_FILE; + }; + writeFqdnEntries(); + if(ret_code == 0) { + printf "%s %s %s %s\n", length(cidr_array), length(ip_array), length(fqdn_array), ID >> USER_ENTRIES_STATUS_FILE; + }; + exit ret_code; + }' - +} + AddUserEntries() { + local _url _return_code=0 _attempt=1 _ip_data_file _dnsmasq_data_file _user_entries_status_file _str _update_string if [ "$ADD_USER_ENTRIES" = "1" ]; then - if [ -f "$USER_ENTRIES_FILE" ]; then - $AWK_CMD 'BEGIN { - null = ""; - ip_array[0] = null; - cidr_array[0] = null; - fqdn_array[0] = null; - } - function writeIpList(array, _str) { - _str = ""; - for(i in array) { - _str = _str i ","; - }; - return _str; - }; - function writeDNSData(val, dns) { - if(length(dns) == 0 && length(ENVIRON["USER_ENTRIES_DNS"]) > 0) { - dns = ENVIRON["USER_ENTRIES_DNS"]; - }; - if(length(dns) > 0) { - printf "server=/%s/%s\n", val, dns >> ENVIRON["DNSMASQ_DATA_FILE"]; - }; - printf "nftset=/%s/%s#%s\n", val, ENVIRON["NFT_TABLE_DNSMASQ"], ENVIRON["NFTSET_DNSMASQ"] >> ENVIRON["DNSMASQ_DATA_FILE"]; - }; - function writeFqdnEntries() { - delete fqdn_array[0]; - for(i in fqdn_array) { - split(fqdn_array[i], a, " "); - writeDNSData(a[1], a[2]); - }; - }; - ($0 !~ /^([\040\011]*$|#)/) { - if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}$/) { - ip_array[$0] = null; - } - else if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}[\057][0-9]{1,2}$/) { - cidr_array[$0] = null; - } - else if($0 ~ /^[a-z0-9.\052-]+[.]([a-z]{2,}|xn--[a-z0-9]+)([ ][0-9]{1,3}([.][0-9]{1,3}){3}([#][0-9]{2,5})?)?$/) { - fqdn_array[length(fqdn_array)] = $1 " " $2; - }; - } - END { - printf "table %s {\n%s", ENVIRON["NFT_TABLE"], ENVIRON["NFTSET_CIDR_CFG"] >> ENVIRON["IP_DATA_FILE"]; - delete cidr_array[0]; - if(length(cidr_array) > 0) { - printf "elements={%s};", writeIpList(cidr_array) >> ENVIRON["IP_DATA_FILE"]; - }; - printf "}\n%s", ENVIRON["NFTSET_IP_CFG"] >> ENVIRON["IP_DATA_FILE"]; - delete ip_array[0]; - if(length(ip_array) > 0) { - printf "elements={%s};", writeIpList(ip_array) >> ENVIRON["IP_DATA_FILE"]; - }; - printf "}\n}\n" >> ENVIRON["IP_DATA_FILE"]; - writeFqdnEntries(); - }' "$USER_ENTRIES_FILE" + if [ "$ENABLE_TMP_DOWNLOADS" = "1" ]; then + _ip_data_file="$IP_DATA_FILE_TMP" + _dnsmasq_data_file="$DNSMASQ_DATA_FILE_TMP" + _user_entries_status_file="$USER_ENTRIES_STATUS_FILE_TMP" + rm -f "$_ip_data_file" "$_dnsmasq_data_file" "$_user_entries_status_file" + else + _ip_data_file="$IP_DATA_FILE" + _dnsmasq_data_file="$DNSMASQ_DATA_FILE" + _user_entries_status_file="$USER_ENTRIES_STATUS_FILE" fi + if [ "$1" = "flush" ]; then + if [ "$ENABLE_TMP_DOWNLOADS" != "1" ]; then + ClearDataFiles + fi + printf "flush set %s %s\nflush set %s %s\n" "$NFT_TABLE" "$NFTSET_CIDR" "$NFT_TABLE" "$NFTSET_IP" >> "$_ip_data_file" + else + printf "" > "$USER_ENTRIES_STATUS_FILE" + fi + if [ -f "$USER_ENTRIES_FILE" ]; then + { cat "$USER_ENTRIES_FILE"; echo 0; } | ParseUserEntries "$_ip_data_file" "$_dnsmasq_data_file" "$_user_entries_status_file" "local" + fi + if [ -n "$USER_ENTRIES_REMOTE" ]; then + for _url in $USER_ENTRIES_REMOTE + do + _attempt=1 + while : + do + if [ "$ENABLE_BLLIST_PROXY" = "1" ]; then + UpdateBllistProxySet + fi + { Download - "$_url"; echo $?; } | ParseUserEntries "$_ip_data_file" "$_dnsmasq_data_file" "$_user_entries_status_file" "$_url" + if [ $? -eq 0 ]; then + break + else + _return_code=1 + ### STDOUT + echo " User entries download attempt ${_attempt}: failed [${_url}]" >&2 + MakeLogRecord "err" "User entries download attempt ${_attempt}: failed [${_url}]" + _attempt=$(($_attempt + 1)) + [ $_attempt -gt $USER_ENTRIES_REMOTE_DOWNLOAD_ATTEMPTS ] && break + sleep $USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT + fi + done + done + if [ "$ENABLE_BLLIST_PROXY" = "1" ]; then + FlushNftSets "$NFTSET_BLLIST_PROXY" + fi + fi + if [ "$ENABLE_TMP_DOWNLOADS" = "1" ]; then + if [ $_return_code -eq 0 ]; then + if [ "$1" = "flush" ]; then + ClearDataFiles + fi + cat "$_ip_data_file" >> "$IP_DATA_FILE" + cat "$_dnsmasq_data_file" >> "$DNSMASQ_DATA_FILE" + mv -f "$_user_entries_status_file" "$USER_ENTRIES_STATUS_FILE" + fi + rm -f "$_ip_data_file" "$_dnsmasq_data_file" "$_user_entries_status_file" + fi + while read _str + do + _update_string=`printf "$_str" | $AWK_CMD '{ + if(NF == 4) { + printf "User entries (%s): CIDR: %s, IP: %s, FQDN: %s", $4, $1, $2, $3; + }; + }'` + if [ -n "$_update_string" ]; then + ### STDOUT + echo " ${_update_string}" + MakeLogRecord "notice" "${_update_string}" + fi + done < "$USER_ENTRIES_STATUS_FILE" + else + printf "" > "$USER_ENTRIES_STATUS_FILE" fi } AddBypassEntries() { - printf "" > "$DNSMASQ_DATA_FILE_BYPASS" + [ -d "$DATA_DIR" ] && printf "" > "$DNSMASQ_DATA_FILE_BYPASS" FlushNftSets "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" if [ "$BYPASS_MODE" = "1" ]; then if [ -f "$BYPASS_ENTRIES_FILE" ]; then @@ -599,8 +748,6 @@ GetDataFiles() { FlushNftSets "$NFTSET_BLLIST_PROXY" fi if [ $_return_code -eq 0 ]; then - AddUserEntries - AddBypassEntries _update_string=`$AWK_CMD '{ printf "Received entries: %s\n", (NF < 3) ? "No data" : "CIDR: "$1", IP: "$2", FQDN: "$3; exit; @@ -609,11 +756,12 @@ GetDataFiles() { echo " ${_update_string}" MakeLogRecord "notice" "${_update_string}" printf " `date +%d.%m.%Y-%H:%M`\n" >> "$UPDATE_STATUS_FILE" + AddUserEntries + AddBypassEntries fi elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then - ClearDataFiles ADD_USER_ENTRIES=1 - AddUserEntries + AddUserEntries flush AddBypassEntries _return_code=0 else @@ -654,8 +802,6 @@ Update() { MakeLogRecord "notice" "${1}..." if [ "$NFTSET_CLEAR_SETS" = "1" ]; then FlushNftSets "$NFTSET_CIDR" "$NFTSET_IP" "$NFTSET_DNSMASQ" - elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then - FlushNftSets "$NFTSET_IP" "$NFTSET_CIDR" fi GetDataFiles case $? in @@ -753,7 +899,7 @@ Reload() { } Status() { - local _update_status _vpn_error + local _update_status _user_entries_status _vpn_error if [ -f "$UPDATE_STATUS_FILE" ]; then _update_status=`$AWK_CMD '{ update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")"; @@ -762,10 +908,19 @@ Status() { else _update_status="Last blacklist update: No data" fi + + if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then + _user_entries_status=`$AWK_CMD '{ + if(NF == 4) { + printf " User entries (%s): CIDR: %s | IP: %s | FQDN: %s\n", $4, $1, $2, $3; + }; + }' "$USER_ENTRIES_STATUS_FILE"` + fi + if [ "$PROXY_MODE" = "2" ] && ! NftVpnRouteStatus; then _vpn_error="\033[1;31mVPN ROUTING ERROR! (NEED THE RESTART)\033[m" fi - NftListBllistChain 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v VPN_ERROR="$_vpn_error" ' + NftListBllistChain 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v USER_ENTRIES_STATUS="$_user_entries_status" -v VPN_ERROR="$_vpn_error" ' BEGIN { rules_str = ""; nftset = ""; @@ -785,14 +940,14 @@ Status() { printf "\n \033[1m" ENVIRON["NAME"] " status\033[m: \033[1mDisabled\033[m\n\n"; exit 2; }; - printf "\n \033[1m" ENVIRON["NAME"] " status\033[m: \033[1;32mEnabled\033[m\n\n PROXY_MODE: " ENVIRON["PROXY_MODE"] "\n PROXY_LOCAL_CLIENTS: " ENVIRON["PROXY_LOCAL_CLIENTS"] "\n BLLIST_PRESET: " ENVIRON["BLLIST_PRESET"] "\n BLLIST_MODULE: " ENVIRON["BLLIST_MODULE"] "\n"; printf "\n "UPDATE_STATUS"\n"; - + if(length(USER_ENTRIES_STATUS) > 0) { + printf "\n"USER_ENTRIES_STATUS"\n"; + }; if(length(VPN_ERROR) > 0) { printf "\n "VPN_ERROR"\n"; }; - printf "\n \033[4mNftables rules\033[m:\n\n"; printf rules_str; }' @@ -809,7 +964,7 @@ StatusOutput() { ### Blacklist source and mode case "$BLLIST_PRESET" in zapret-info-ip) - ### Источник для обновления списка блокировок (zapret-info, rublacklist, antifilter, ruantiblock) + ### Источник для обновления списка блокировок (zapret-info, rublacklist, antifilter, fz, ruantiblock) export BLLIST_SOURCE="zapret-info" ### Режим обхода блокировок: ip, fqdn export BLLIST_MODE="ip" diff --git a/ruantiblock/files/usr/share/ruantiblock/config_script b/ruantiblock/files/usr/share/ruantiblock/config_script index 99a05f8..c023ad4 100644 --- a/ruantiblock/files/usr/share/ruantiblock/config_script +++ b/ruantiblock/files/usr/share/ruantiblock/config_script @@ -1,5 +1,6 @@ + UCI_SECTION="ruantiblock.config" -UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup" +UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns user_entries_remote enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_gr_excluded_nets bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_gr_excluded_sld bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup enable_tmp_downloads" UCI_CMD=`which uci` if [ $? -ne 0 ]; then echo " Error! UCI doesn't exists" >&2 diff --git a/ruantiblock/files/usr/share/ruantiblock/info_output b/ruantiblock/files/usr/share/ruantiblock/info_output index 5bfe4b8..45321d8 100644 --- a/ruantiblock/files/usr/share/ruantiblock/info_output +++ b/ruantiblock/files/usr/share/ruantiblock/info_output @@ -2,15 +2,38 @@ Info() { local _update_status if [ -f "$UPDATE_STATUS_FILE" ]; then _update_status=`$AWK_CMD '{ - if(NF < 4) + if(NF < 4) { printf "{\"status\":false}"; - else + } else { printf "{\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}"; + }; }' "$UPDATE_STATUS_FILE"` else _update_status="{\"status\":false}" fi - NftListBllistChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" ' + if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then + _user_entries_status=`$AWK_CMD ' + BEGIN { + items = 0; + printf "["; + } + { + if(NF == 4) { + gsub("/", "\134\134/", $4); + if(items >= 1) { + printf ","; + }; + printf "{\"id\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}"; + items++; + }; + } + END { + printf "]"; + }' "$USER_ENTRIES_STATUS_FILE"` + else + _user_entries_status="[]" + fi + NftListBllistChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v USER_ENTRIES_STATUS="$_user_entries_status" ' BEGIN { rules_str = ""; } @@ -22,7 +45,7 @@ Info() { printf "{\"status\": \"disabled\"}"; exit 1; } else { - printf "{\"status\":\"enabled\",\"last_blacklist_update\":%s,\"rules\":%s", UPDATE_STATUS, rules_str; + printf "{\"status\":\"enabled\",\"last_blacklist_update\":%s,\"user_entries\":%s,\"rules\":%s", UPDATE_STATUS, USER_ENTRIES_STATUS, rules_str; exit 0; }; }'