diff --git a/luci-app-ruantiblock/Makefile b/luci-app-ruantiblock/Makefile index 056d374..5955996 100644 --- a/luci-app-ruantiblock/Makefile +++ b/luci-app-ruantiblock/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk -PKG_VERSION:=0.9.7-0 +PKG_VERSION:=1.0-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 484a419..4ad8ce8 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 @@ -5,7 +5,18 @@ 'require view'; 'require view.ruantiblock.tools as tools'; +document.head.append(E('style', {'type': 'text/css'}, +` +.log-entries-count { + margin: 0 0 5px 5px; + font-weight: bold; + opacity: 0.7; +} +`)); + return view.extend({ + pollInterval : L.env.pollinterval, + secToTimeString: function(value) { let string = ''; if(/^\d+$/.test(value)) { @@ -31,11 +42,52 @@ return view.extend({ return string; }, + formatNftJson: function(data) { + let output = { 'rules': [] }; + if(data.rules.nftables && data.rules.nftables.length > 1) { + for(let i of data.rules.nftables) { + if(!i.rule) continue; + + let set, bytes; + i.rule.expr.forEach(e => { + if(e.match) { + set = e.match.right.replace('@', ''); + } + else if(e.counter) { + bytes = e.counter.bytes; + }; + }); + output.rules.push([ set, bytes ]); + + }; + + function parseDnsmasqData(set) { + let sArray = []; + if(data[set].nftables && data[set].nftables.length > 1) { + data[set].nftables.forEach(e => { + if(e.set && e.set.elem) { + e.set.elem.forEach(i => { + if(i.elem) { + sArray.push([ i.elem.val, i.elem.expires ]); + }; + }); + }; + }); + }; + return sArray; + }; + + output.dnsmasq = parseDnsmasqData('dnsmasq'); + output.dnsmasq_u = parseDnsmasqData('dnsmasq_u'); + }; + return output; + }, + makeDnsmasqTable: function(ipDataArray) { let lines = `${_('No entries available...')}`; let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' }); - if(ipDataArray.length > 1) { + if(ipDataArray.length > 0) { lines = []; ipDataArray.forEach((e, i) => { if(e) { @@ -57,18 +109,23 @@ return view.extend({ try { ipTable.insertAdjacentHTML('beforeend', lines); - } catch(err) { - if(err.name === 'SyntaxError') { + } catch(e) { + if(e.name === 'SyntaxError') { ui.addNotification(null, - E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error'); + E('p', {}, _('HTML/XML error') + ': ' + e.message), 'error'); }; - throw err; + throw e; }; - return ipTable; + return E([ + E('div', { 'class': 'log-entries-count' }, + `${_('Entries')}: ${ipDataArray.length}` + ), + ipTable, + ]); }, - infoPoll: function() { + pollInfo: function() { return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => { ui.addNotification(null, E('p', _('Unable to execute or read contents') + ': %s [ %s ]'.format(e.message, tools.execPath) @@ -81,7 +138,7 @@ return view.extend({ try { data = JSON.parse(data); - } catch(err) {}; + } catch(e) {}; if(data.status === 'enabled') { let date = document.getElementById('last_blacklist_update.date'); @@ -111,34 +168,27 @@ return view.extend({ }; }; - if(data.iptables) { - for(let [k, v] of Object.entries(data.iptables)) { - if(k === '_dummy') continue; + let nft_data = this.formatNftJson(data); - let elem = document.getElementById('iptables.' + k); + if(nft_data.rules.length > 0) { + for(let [set, bytes] of nft_data.rules) { + let elem = document.getElementById('rules.' + set); if(elem) { - elem.textContent = v; + elem.textContent = bytes; }; }; }; - if(data.ipset) { - for(let [k, v] of Object.entries(data.ipset)) { - if(k === '_dummy') continue; - - let elem0 = document.getElementById('ipset.' + k + '.' + '0'); - let elem1 = document.getElementById('ipset.' + k + '.' + '1'); - if(elem0 && elem1) { - elem0.textContent = v[0]; - elem1.textContent = v[1]; - }; - }; - }; - - if(data.dnsmasq) { + if(nft_data.dnsmasq.length > 0) { let rdTableWrapper = document.getElementById('rdTableWrapper'); rdTableWrapper.innerHTML = ''; - rdTableWrapper.append(this.makeDnsmasqTable(data.dnsmasq)); + rdTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq)); + }; + + if(nft_data.dnsmasq_u.length > 0) { + let rduTableWrapper = document.getElementById('rduTableWrapper'); + rduTableWrapper.innerHTML = ''; + rduTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq_u)); }; } else { if(poll.active()) { @@ -163,12 +213,12 @@ return view.extend({ try { data = JSON.parse(data); - } catch(err) {}; + } catch(e) {}; let update_status = null, - iptables = null, - ipset = null, - dnsmasq = null; + rules = null, + dnsmasq = null, + dnsmasq_u = null; if(data) { if(data.status === 'enabled') { update_status = E('table', { 'class': 'table' }); @@ -211,8 +261,10 @@ return view.extend({ ); }; - if(data.iptables) { - let table_iptables = E('table', { 'class': 'table' }, [ + let nft_data = this.formatNftJson(data); + + if(nft_data.rules) { + let table_rules = E('table', { 'class': 'table' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th left', 'style': 'min-width:33%' }, _('Match-set')), @@ -220,76 +272,33 @@ return view.extend({ ]), ]); - for(let [k, v] of Object.entries(data.iptables)) { - if(k === '_dummy') continue; - - table_iptables.append( + for(let [set, bytes] of nft_data.rules) { + table_rules.append( E('tr', { 'class': 'tr' }, [ - E('td', { + E('td',{ 'class' : 'td left', 'data-title': _('Match-set'), - }, k), + }, set + ' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq').replace(/u$/, '-user') + ')'), E('td', { 'class' : 'td left', - 'id' : 'iptables.' + k, + 'id' : 'rules.' + set, 'data-title': _('Bytes'), - }, v), + }, bytes), ]) ); }; - iptables = E([ - E('h3', {}, _('Iptables rules')), - table_iptables, + rules = E([ + E('h3', {}, _('Nftables rules')), + table_rules, ]); }; - if(data.ipset) { - let table_ipset = E('table', { 'class': 'table' }, - E('tr', { 'class': 'tr table-titles' }, [ - E('th', { 'class': 'th left', 'style': 'min-width:33%' }, - _('Name')), - E('th', { 'class': 'th left' }, - _('Size in memory')), - E('th', { 'class': 'th left' }, - _('Number of entries')), - ]) - ); - - for(let [k, v] of Object.entries(data.ipset)) { - if(k === '_dummy') continue; - - table_ipset.append( - E('tr', { 'class': 'tr' }, [ - E('td', { - 'class': 'td left', - 'data-title': _('Name'), - }, k), - E('td', { - 'class' : 'td left', - 'id' : 'ipset.' + k + '.' + '0', - 'data-title': _('Size in memory'), - }, v[0]), - E('td', { - 'class' : 'td left', - 'id' : 'ipset.' + k + '.' + '1', - 'data-title': _('Number of entries'), - }, v[1]), - ]) - ); - }; - - ipset = E([ - E('h3', {}, _('Ipset')), - table_ipset, - ]); - }; - - if(data.dnsmasq) { + if(nft_data.dnsmasq) { let rdTableWrapper = E('div', { 'id' : 'rdTableWrapper', 'style': 'width:100%' - }, this.makeDnsmasqTable(data.dnsmasq)); + }, this.makeDnsmasqTable(nft_data.dnsmasq)); dnsmasq = E([ E('h3', {}, _('Dnsmasq')), @@ -297,7 +306,19 @@ return view.extend({ ]); }; - poll.add(L.bind(this.infoPoll, this)); + if(nft_data.dnsmasq_u) { + let rduTableWrapper = E('div', { + 'id' : 'rduTableWrapper', + 'style': 'width:100%' + }, this.makeDnsmasqTable(nft_data.dnsmasq_u)); + + dnsmasq_u = E([ + E('h3', {}, _('Dnsmasq') + ' - ' + _('User entries')), + rduTableWrapper, + ]); + }; + + poll.add(L.bind(this.pollInfo, this), this.pollInterval); } else { update_status = E('em', {}, _('Status') + ' : ' + _('disabled')); }; @@ -311,15 +332,14 @@ return view.extend({ E('div', { 'class': 'cbi-section-node' }, update_status) ), E('div', { 'class': 'cbi-section fade-in' }, - E('div', { 'class': 'cbi-section-node' }, iptables) - ), - E('div', { 'class': 'cbi-section fade-in' }, - E('div', { 'class': 'cbi-section-node' }, ipset) + E('div', { 'class': 'cbi-section-node' }, rules) ), E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section-node' }, dnsmasq) ), - + E('div', { 'class': 'cbi-section fade-in' }, + E('div', { 'class': 'cbi-section-node' }, dnsmasq_u) + ), ]); }, diff --git a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/service.js b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/service.js index dd58547..3cf34bb 100644 --- a/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/service.js +++ b/luci-app-ruantiblock/htdocs/luci-static/resources/view/ruantiblock/service.js @@ -284,7 +284,7 @@ return view.extend({ btn_destroy.onclick = L.bind(this.dialogDestroy, this); layout_append(btn_destroy, _('Shutdown'), - _('Complete service shutdown, as well as deleting ipsets and blacklist data')); + _('Complete service shutdown, as well as deleting nftsets and blacklist data')); this.setAppStatus(status_array, [ status_string, 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 fc415d2..39f05db 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 @@ -8,11 +8,11 @@ 'require view.ruantiblock.tools as tools'; return view.extend({ - parsers: {}, + parsers : {}, - appStatusCode : null, + appStatusCode: null, - depends: function(elem, key, array, empty=true) { + depends : function(elem, key, array, empty=true) { if(empty && array.length === 0) { elem.depends(key, '_dummy'); } else { @@ -111,18 +111,17 @@ return view.extend({ s.anonymous = true; s.addremove = false; + /* Main settings tab */ s.tab('main_settings', _('Main settings')); // PROXY_MODE - if(this.appStatusCode == 1 || this.appStatusCode == 2) { - o = s.taboption('main_settings', form.ListValue, 'proxy_mode', - _('Proxy mode')); - o.value('1', 'Tor'); - o.value('2', 'VPN'); - o.value('3', _('Transparent proxy')); - }; + o = s.taboption('main_settings', form.ListValue, 'proxy_mode', + _('Proxy mode')); + o.value('1', 'Tor'); + o.value('2', 'VPN'); + o.value('3', _('Transparent proxy')); // PROXY_LOCAL_CLIENTS let proxy_local_clients = s.taboption('main_settings', form.Flag, 'proxy_local_clients', @@ -140,9 +139,9 @@ return view.extend({ o.description = _('Update blacklist after system startup'); o.rmempty = false; - // IPSET_CLEAR_SETS - o = s.taboption('main_settings', form.Flag, 'ipset_clear_sets', - _('Clean up ipsets before updating blacklist')); + // NFTSET_CLEAR_SETS + o = s.taboption('main_settings', form.Flag, 'nftset_clear_sets', + _('Clean up nftsets before updating blacklist')); o.description = _('Reduces RAM consumption during update'); o.rmempty = false; @@ -160,70 +159,68 @@ return view.extend({ o.datatype = "ip4addr"; - if(this.appStatusCode == 1 || this.appStatusCode == 2) { - /* Tor tab */ + /* Tor tab */ - s.tab('tor_settings', _('Tor mode')); + s.tab('tor_settings', _('Tor mode')); - // TOR_TRANS_PORT - o = s.taboption('tor_settings', form.Value, 'tor_trans_port', - _('Transparent proxy port')); - o.rmempty = false; - o.datatype = "port"; + // TOR_TRANS_PORT + o = s.taboption('tor_settings', form.Value, 'tor_trans_port', + _('Transparent proxy port')); + o.rmempty = false; + o.datatype = "port"; - //TOR_ALLOW_UDP - o = s.taboption('tor_settings', form.Flag, 'tor_allow_udp', - _("Send UDP traffic to Tor")); - o.rmempty = false; + //TOR_ALLOW_UDP + o = s.taboption('tor_settings', form.Flag, 'tor_allow_udp', + _("Send UDP traffic to Tor")); + o.rmempty = false; - // ONION_DNS_ADDR - o = s.taboption('tor_settings', form.Value, 'onion_dns_addr', - _("Optional DNS resolver for '.onion' zone"), 'ipaddress#port'); - o.rmempty = false; - o.validate = this.validateIpPort; + // ONION_DNS_ADDR + o = s.taboption('tor_settings', form.Value, 'onion_dns_addr', + _("Optional DNS resolver for '.onion' zone"), 'ipaddress#port'); + o.rmempty = false; + o.validate = this.validateIpPort; - // Torrc edit dialog - o = s.taboption('tor_settings', form.Button, '_torrc_btn', - _('Tor configuration file')); - o.onclick = () => torrc_edit.show(); - o.inputtitle = _('Edit'); - o.inputstyle = 'edit btn'; + // Torrc edit dialog + o = s.taboption('tor_settings', form.Button, '_torrc_btn', + _('Tor configuration file')); + o.onclick = () => torrc_edit.show(); + o.inputtitle = _('Edit'); + o.inputstyle = 'edit btn'; - /* VPN tab */ + /* VPN tab */ - s.tab('vpn_settings', _('VPN mode')); + s.tab('vpn_settings', _('VPN mode')); - // IF_VPN - o = s.taboption('vpn_settings', widgets.DeviceSelect, 'if_vpn', - _('VPN interface')); - o.multiple = false; - o.noaliases = true; - o.rmempty = false; - o.default = 'tun0'; + // IF_VPN + o = s.taboption('vpn_settings', widgets.DeviceSelect, 'if_vpn', + _('VPN interface')); + o.multiple = false; + o.noaliases = true; + o.rmempty = false; + o.default = 'tun0'; - /* Proxy tab */ + /* Proxy tab */ - s.tab('proxy_settings', _('Transparent proxy mode')); + s.tab('proxy_settings', _('Transparent proxy mode')); - // T_PROXY_PORT_TCP - o = s.taboption('proxy_settings', form.Value, 't_proxy_port_tcp', - _('Transparent proxy TCP port')); - o.rmempty = false; - o.datatype = "port"; + // T_PROXY_PORT_TCP + o = s.taboption('proxy_settings', form.Value, 't_proxy_port_tcp', + _('Transparent proxy TCP port')); + o.rmempty = false; + o.datatype = "port"; - //T_PROXY_ALLOW_UDP - o = s.taboption('proxy_settings', form.Flag, 't_proxy_allow_udp', - _("Send UDP traffic to transparent proxy")); - o.rmempty = false; + //T_PROXY_ALLOW_UDP + o = s.taboption('proxy_settings', form.Flag, 't_proxy_allow_udp', + _("Send UDP traffic to transparent proxy")); + o.rmempty = false; - // T_PROXY_PORT_UDP - o = s.taboption('proxy_settings', form.Value, 't_proxy_port_udp', - _('Transparent proxy UDP port')); - o.rmempty = false; - o.datatype = "port"; - }; + // T_PROXY_PORT_UDP + o = s.taboption('proxy_settings', form.Value, 't_proxy_port_udp', + _('Transparent proxy UDP port')); + o.rmempty = false; + o.datatype = "port"; /* Blacklist module tab */ diff --git a/luci-app-ruantiblock/po/ru/ruantiblock.po b/luci-app-ruantiblock/po/ru/ruantiblock.po index 1b70841..6ff7777 100644 --- a/luci-app-ruantiblock/po/ru/ruantiblock.po +++ b/luci-app-ruantiblock/po/ru/ruantiblock.po @@ -64,15 +64,15 @@ msgstr "Отмена" msgid "Changes have been saved." msgstr "Изменения сохранены." -msgid "Clean up ipsets before updating blacklist" -msgstr "Очищать ipset'ы перед обновлением блэклиста" +msgid "Clean up nftsets before updating blacklist" +msgstr "Очищать nft-сеты перед обновлением блэклиста" msgid "Command failed" msgstr "Команда не выполнена" msgid "" -"Complete service shutdown, as well as deleting ipsets and blacklist data" -msgstr "Полное выключение службы, а также удаление ipset'ов и данных блэклиста" +"Complete service shutdown, as well as deleting nftsets and blacklist data" +msgstr "Полное выключение службы, а также удаление nft-сетов и данных блэклиста" msgid "Contents have been saved." msgstr "Содержимое сохранено." @@ -191,11 +191,8 @@ msgstr "Интервал" msgid "Invalid regular expression" msgstr "Неправильное регулярное выражение" -msgid "Ipset" -msgstr "Ipset" - -msgid "Iptables rules" -msgstr "Правила iptables" +msgid "Nftables rules" +msgstr "Правила nftables" msgid "Last blacklist update" msgstr "Последнее обновление блэклиста" diff --git a/luci-app-ruantiblock/po/templates/ruantiblock.pot b/luci-app-ruantiblock/po/templates/ruantiblock.pot index 2dccd18..5f77d68 100644 --- a/luci-app-ruantiblock/po/templates/ruantiblock.pot +++ b/luci-app-ruantiblock/po/templates/ruantiblock.pot @@ -49,14 +49,14 @@ msgstr "" msgid "Changes have been saved." msgstr "" -msgid "Clean up ipsets before updating blacklist" +msgid "Clean up nftsets before updating blacklist" msgstr "" msgid "Command failed" msgstr "" msgid "" -"Complete service shutdown, as well as deleting ipsets and blacklist data" +"Complete service shutdown, as well as deleting nftsets and blacklist data" msgstr "" msgid "Contents have been saved." @@ -171,10 +171,7 @@ msgstr "" msgid "Invalid regular expression" msgstr "" -msgid "Ipset" -msgstr "" - -msgid "Iptables rules" +msgid "Nftables rules" msgstr "" msgid "Last blacklist update" diff --git a/ruantiblock-mod-lua/Makefile b/ruantiblock-mod-lua/Makefile index 376f96a..9ea52d9 100644 --- a/ruantiblock-mod-lua/Makefile +++ b/ruantiblock-mod-lua/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-lua -PKG_VERSION:=0.9.7 +PKG_VERSION:=1.0 PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot 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 c8b7d4b..5b76e7c 100755 --- a/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua +++ b/ruantiblock-mod-lua/files/usr/libexec/ruantiblock/ruab_parser.lua @@ -53,10 +53,11 @@ local Config = Class(nil, { ["BLLIST_GR_EXCLUDED_NETS"] = true, ["BLLIST_MIN_ENTRIES"] = true, ["BLLIST_STRIP_WWW"] = true, - ["DATA_DIR"] = true, - ["IPSET_DNSMASQ"] = true, - ["IPSET_IP_TMP"] = true, - ["IPSET_CIDR_TMP"] = true, + ["NFT_TABLE"] = true, + ["NFT_TABLE_DNSMASQ"] = true, + ["NFTSET_CIDR_CFG"] = true, + ["NFTSET_IP_CFG"] = true, + ["NFTSET_DNSMASQ"] = true, ["DNSMASQ_DATA_FILE"] = true, ["IP_DATA_FILE"] = true, ["UPDATE_STATUS_FILE"] = true, @@ -65,10 +66,10 @@ local Config = Class(nil, { ["ZI_ALL_URL"] = true, ["AF_IP_URL"] = true, ["AF_FQDN_URL"] = true, - ["RA_IP_IPSET_URL"] = true, + ["RA_IP_NFTSET_URL"] = true, ["RA_IP_DMASK_URL"] = true, ["RA_IP_STAT_URL"] = true, - ["RA_FQDN_IPSET_URL"] = true, + ["RA_FQDN_NFTSET_URL"] = true, ["RA_FQDN_DMASK_URL"] = true, ["RA_FQDN_STAT_URL"] = true, ["RBL_ENCODING"] = true, @@ -228,16 +229,16 @@ function BlackListParser:new(t) instance.records_separator = instance["records_separator"] or self.records_separator instance.ips_separator = instance["ips_separator"] or self.ips_separator instance.site_encoding = instance["site_encoding"] or self.site_encoding - instance.ip_records_count = 0 - instance.ip_count = 0 instance.ip_subnet_table = {} instance.cidr_count = 0 - instance.fqdn_table = {} + instance.ip_records_count = 0 + instance.ip_count = 0 instance.fqdn_count = 0 instance.sld_table = {} instance.fqdn_records_count = 0 - instance.ip_table = {} instance.cidr_table = {} + instance.ip_table = {} + instance.fqdn_table = {} instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil return instance end @@ -387,19 +388,34 @@ function BlackListParser:group_cidr_ranges() end function BlackListParser:write_ipset_config() - local file_handler = assert(io.open(self.IP_DATA_FILE, "w"), "Could not open ipset config") + local file_handler = assert(io.open(self.IP_DATA_FILE, "w"), "Could not open nftset config") + file_handler:write( + string.format("table %s {\n%s", self.NFT_TABLE, self.NFTSET_IP_CFG) + ) local i = 0 - for ipaddr in pairs(self.ip_table) do - file_handler:write(string.format("add %s %s\n", self.IPSET_IP_TMP, ipaddr)) - i = i + 1 + if next(self.ip_table) then + file_handler:write("elements={") + for ipaddr in pairs(self.ip_table) do + file_handler:write(string.format("%s,", ipaddr)) + i = i + 1 + end + file_handler:write("};") end + file_handler:write( + string.format("}\n%s", self.NFTSET_CIDR_CFG) + ) self.ip_records_count = i local c = 0 - for cidr in pairs(self.cidr_table) do - file_handler:write(string.format("add %s %s\n", self.IPSET_CIDR_TMP, cidr)) - c = c + 1 + if next(self.cidr_table) then + file_handler:write("elements={") + for cidr in pairs(self.cidr_table) do + file_handler:write(string.format("%s,", cidr)) + c = c + 1 + end + file_handler:write("};") end self.cidr_count = c + file_handler:write("}\n}\n") file_handler:close() end @@ -409,7 +425,7 @@ function BlackListParser:write_dnsmasq_config() if self.BLLIST_ALT_NSLOOKUP then file_handler:write(string.format("server=/%s/%s\n", fqdn, self.BLLIST_ALT_DNS_ADDR)) end - file_handler:write(string.format("ipset=/%s/%s\n", fqdn, self.IPSET_DNSMASQ)) + file_handler:write(string.format("nftset=/%s/%s#%s\n", fqdn, self.NFT_TABLE_DNSMASQ, self.NFTSET_DNSMASQ)) end file_handler:close() end @@ -465,7 +481,7 @@ end function BlackListParser:run() local return_code = 0 if self:get_http_data(self.url) then - if (self.fqdn_count + self.ip_count + self.cidr_count) >= self.BLLIST_MIN_ENTRIES then + if (self.fqdn_count + self.ip_count + self.cidr_count) > self.BLLIST_MIN_ENTRIES then self:optimize_fqdn_table() self:optimize_ip_table() if self.BLLIST_SUMMARIZE_IP then @@ -593,6 +609,7 @@ 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_handler:setvbuf("no") if self:get_http_data(url) then ret_val = true end diff --git a/ruantiblock-mod-py/Makefile b/ruantiblock-mod-py/Makefile index 338ce48..57ad9ec 100644 --- a/ruantiblock-mod-py/Makefile +++ b/ruantiblock-mod-py/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock-mod-py -PKG_VERSION:=0.9.7 +PKG_VERSION:=1.0 PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot 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 b818762..fc1dc44 100755 --- a/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py +++ b/ruantiblock-mod-py/files/usr/libexec/ruantiblock/ruab_parser.py @@ -37,10 +37,11 @@ class Config: "BLLIST_GR_EXCLUDED_NETS", "BLLIST_MIN_ENTRIES", "BLLIST_STRIP_WWW", - "DATA_DIR", - "IPSET_DNSMASQ", - "IPSET_IP_TMP", - "IPSET_CIDR_TMP", + "NFT_TABLE", + "NFT_TABLE_DNSMASQ", + "NFTSET_CIDR_CFG", + "NFTSET_IP_CFG", + "NFTSET_DNSMASQ", "DNSMASQ_DATA_FILE", "IP_DATA_FILE", "UPDATE_STATUS_FILE", @@ -49,10 +50,10 @@ class Config: "ZI_ALL_URL", "AF_IP_URL", "AF_FQDN_URL", - "RA_IP_IPSET_URL", + "RA_IP_NFTSET_URL", "RA_IP_DMASK_URL", "RA_IP_STAT_URL", - "RA_FQDN_IPSET_URL", + "RA_FQDN_NFTSET_URL", "RA_FQDN_DMASK_URL", "RA_FQDN_STAT_URL", "RBL_ENCODING", @@ -131,18 +132,18 @@ class FieldValueError(ParserError): class BlackListParser(Config): def __init__(self): - self.ip_pattern = re.compile("(([0-9]{1,3}[.]){3})[0-9]{1,3}") - self.cidr_pattern = re.compile("([0-9]{1,3}[.]){3}[0-9]{1,3}/[0-9]{1,2}") + 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( - "([а-яёa-z0-9_.*-]*?)([а-яёa-z0-9_-]+[.][а-яёa-z0-9-]+)", + r"([а-яёa-z0-9_.*-]*?)([а-яёa-z0-9_-]+[.][а-яёa-z0-9-]+)", re.U) - self.www_pattern = re.compile("^www[0-9]?[.]") - self.cyr_pattern = re.compile("[а-яё]", re.U) - self.fqdn_set = {} - self.sld_dict = {} + self.www_pattern = re.compile(r"^www[0-9]?[.]") + self.cyr_pattern = re.compile(r"[а-яё]", re.U) + self.cidr_set = set() self.ip_set = {} self.ip_subnet_dict = {} - self.cidr_set = set() + self.fqdn_set = {} + self.sld_dict = {} self.cidr_count = 0 self.ip_count = 0 self.output_fqdn_count = 0 @@ -256,7 +257,7 @@ class BlackListParser(Config): subnet = self._get_subnet(i) if subnet in self.BLLIST_GR_EXCLUDED_NETS or ( not self.BLLIST_IP_LIMIT or ( - subnet not in self.ip_subnet_dict or self.ip_subnet_dict[subnet] <= self.BLLIST_IP_LIMIT + subnet not in self.ip_subnet_dict or self.ip_subnet_dict[subnet] < self.BLLIST_IP_LIMIT ) ): self.ip_set[i] = subnet @@ -496,18 +497,31 @@ class WriteConfigFiles(Config): def write_ipset_config(self, ip_set, cidr_set): with open(self.IP_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler: - for i in ip_set: - file_handler.write(f"add {self.IPSET_IP_TMP} {i}\n") - for i in cidr_set: - file_handler.write(f"add {self.IPSET_CIDR_TMP} {i}\n") + file_handler.write( + "table {} {{\n{}".format(self.NFT_TABLE, self.NFTSET_IP_CFG) + ) + if len(ip_set) > 0: + file_handler.write("elements={") + for i in ip_set: + file_handler.write(f"{i},") + file_handler.write("};") + file_handler.write( + "}}\n{}".format(self.NFTSET_CIDR_CFG) + ) + if len(cidr_set) > 0: + file_handler.write("elements={") + for i in cidr_set: + file_handler.write(f"{i},") + file_handler.write("};") + file_handler.write("}\n}\n") def write_dnsmasq_config(self, fqdn_set): with open(self.DNSMASQ_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler: for fqdn in fqdn_set: file_handler.write( - f"server=/{fqdn}/{self.BLLIST_ALT_DNS_ADDR}\nipset=/{fqdn}/{self.IPSET_DNSMASQ}\n" + f"server=/{fqdn}/{self.BLLIST_ALT_DNS_ADDR}\nnftset=/{fqdn}/{self.NFT_TABLE_DNSMASQ}#{self.NFTSET_DNSMASQ}\n" if self.BLLIST_ALT_NSLOOKUP else - f"ipset=/{fqdn}/{self.IPSET_DNSMASQ}\n") + f"nftset=/{fqdn}/{self.NFT_TABLE_DNSMASQ}#{self.NFTSET_DNSMASQ}\n") def write_update_status_file(self, ip_count, cidr_count, output_fqdn_count): with open(self.UPDATE_STATUS_FILE, "wt") as file_handler: diff --git a/ruantiblock/Makefile b/ruantiblock/Makefile index df606ae..72e6dce 100644 --- a/ruantiblock/Makefile +++ b/ruantiblock/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=ruantiblock -PKG_VERSION:=0.9.7 +PKG_VERSION:=1.0 PKG_RELEASE:=0 PKG_MAINTAINER:=gSpot @@ -17,7 +17,7 @@ define Package/$(PKG_NAME) TITLE:=Ruantiblock URL:=https://github.com/gSpotx2f/ruantiblock_openwrt PKGARCH:=all - DEPENDS:=+wget +ipset +kmod-ipt-ipset +dnsmasq-full + DEPENDS:=+wget +dnsmasq-full endef define Package/$(PKG_NAME)/description @@ -45,7 +45,7 @@ define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/etc/ruantiblock/scripts $(INSTALL_DATA) ./files/etc/ruantiblock/scripts/config_script $(1)/etc/ruantiblock/scripts/config_script $(INSTALL_DATA) ./files/etc/ruantiblock/scripts/info_output $(1)/etc/ruantiblock/scripts/info_output - $(INSTALL_DATA) ./files/etc/ruantiblock/scripts/ipt_functions $(1)/etc/ruantiblock/scripts/ipt_functions + $(INSTALL_DATA) ./files/etc/ruantiblock/scripts/nft_functions $(1)/etc/ruantiblock/scripts/nft_functions $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) ./files/usr/bin/ruantiblock $(1)/usr/bin/ruantiblock endef diff --git a/ruantiblock/files/etc/config/ruantiblock b/ruantiblock/files/etc/config/ruantiblock index e86c3b2..bc48fb5 100644 --- a/ruantiblock/files/etc/config/ruantiblock +++ b/ruantiblock/files/etc/config/ruantiblock @@ -2,7 +2,7 @@ config main 'config' option proxy_mode '1' option proxy_local_clients '1' - option ipset_clear_sets '1' + option nftset_clear_sets '1' option allowed_hosts_mode '0' option if_vpn 'tun0' option tor_trans_port '9040' diff --git a/ruantiblock/files/etc/init.d/ruantiblock b/ruantiblock/files/etc/init.d/ruantiblock index 7ace15f..e54a79d 100755 --- a/ruantiblock/files/etc/init.d/ruantiblock +++ b/ruantiblock/files/etc/init.d/ruantiblock @@ -1,6 +1,6 @@ #!/bin/sh /etc/rc.common -START=96 +START=99 STOP=01 APP_NAME="ruantiblock" diff --git a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf index 99e865e..6d08463 100644 --- a/ruantiblock/files/etc/ruantiblock/ruantiblock.conf +++ b/ruantiblock/files/etc/ruantiblock/ruantiblock.conf @@ -1,7 +1,7 @@ ### Настройки ruantiblock ### -### Директория данных (генерируемые конфиги dnsmasq, ipset и пр.) +### Директория данных (генерируемые конфиги dnsmasq, nftset и пр.) DATA_DIR="/tmp/ruantiblock" ### Директория модулей MODULES_DIR="/usr/libexec/ruantiblock" @@ -12,12 +12,12 @@ DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart" ### Директория для html-страницы статуса (не используется в OpenWrt) HTML_DIR="/www" -### Режим обработки пакетов в правилах iptables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) +### Режим обработки пакетов в правилах nftables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) PROXY_MODE=1 -### Применять правила проксификации для трафика локальных сервисов роутера (0 - off, 1 - on) +### Применять правила проксификации для трафика локальных сервисов роутера (0 - выкл, 1 - вкл) PROXY_LOCAL_CLIENTS=1 -### Удаление записей из основных сетов перед началом заполнения временных сетов при обновлении (для освобождения оперативной памяти перед заполнением сетов) (0 - off, 1 - on) -IPSET_CLEAR_SETS=0 +### Удаление записей сетов перед началом обновления (для освобождения оперативной памяти перед обновлением сетов) (0 - выкл, 1 - вкл) +NFTSET_CLEAR_SETS=0 ### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке) ALLOWED_HOSTS_MODE=0 ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) @@ -26,7 +26,7 @@ ALLOWED_HOSTS_LIST="" IF_VPN="tun0" ### Порт прозрачного прокси Tor (параметр TransPort в torrc) TOR_TRANS_PORT=9040 -### Отправлять в Tor UDP-трафик (0 - off, 1 - on) +### Отправлять в Tor UDP-трафик (0 - вкл, 1 - выкл) TOR_ALLOW_UDP=0 ### DNS-сервер для резолвинга в домене .onion (Tor) ONION_DNS_ADDR="127.0.0.1#9053" @@ -36,9 +36,9 @@ VPN_PKTS_MARK=8 T_PROXY_PORT_TCP=1100 ### UDP порт прокси в режиме прозрачного прокси T_PROXY_PORT_UDP=1100 -### Отправлять в прозрачный прокси UDP-трафик (0 - off, 1 - on) +### Отправлять в прозрачный прокси UDP-трафик (0 - вкл, 1 - выкл) T_PROXY_ALLOW_UDP=0 -### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - off, 1 - on) +### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл) ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) ### Можно комментировать строки (#) @@ -47,14 +47,22 @@ ADD_USER_ENTRIES=0 USER_ENTRIES_DNS="" ### Файл пользовательских записей USER_ENTRIES_FILE="/etc/ruantiblock/user_entries" -### Запись событий в syslog (0 - off, 1 - on) +### Запись событий в syslog (0 - выкл, 1 - вкл) ENABLE_LOGGING=1 -### Html-страница с инфо о текущем статусе (0 - off, 1 - on) (не используется в OpenWrt) +### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt) ENABLE_HTML_INFO=0 -### Максимальное кол-во элементов списка ipset -IPSET_MAXELEM=2000000 -### Таймаут для записей в сете $IPSET_DNSMASQ -IPSET_DNSMASQ_TIMEOUT=3600 +### метка для отбора пакетов в VPN туннель +VPN_PKTS_MARK=8 +### Максимальное кол-во элементов списка nftables +#NFTSET_MAXELEM_CIDR=65535 +NFTSET_MAXELEM_IP=1000000 +NFTSET_MAXELEM_DNSMASQ=65535 +### Политика отбора элементов в сетах nftables. "performance" - производительность и большее потребление RAM. "memory" - хуже производительность и меньше потребление RAM +NFTSET_POLICY_CIDR="memory" +NFTSET_POLICY_IP="memory" +NFTSET_POLICY_DNSMASQ="performance" +### Таймаут для записей в сете $NFTSET_DNSMASQ +NFTSET_DNSMASQ_TIMEOUT="1h" ### Кол-во попыток обновления блэклиста (в случае неудачи) MODULE_RUN_ATTEMPTS=3 ### Таймаут между попытками обновления @@ -66,11 +74,11 @@ BLLIST_MODULE="" ### Настройки модулей-парсеров ### -### Режим обхода блокировок: ruantiblock-ip, ruantiblock-fqdn, zapret-info-ip, zapret-info-fqdn, rublacklist-ip, rublacklist-fqdn, antifilter-ip +### Режим обхода блокировок: ruantiblock-fqdn, ruantiblock-ip, zapret-info-fqdn, zapret-info-ip, rublacklist-fqdn, rublacklist-ip, antifilter-ip BLLIST_PRESET="" ### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит BLLIST_MIN_ENTRIES=3000 -### Лимит ip адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества ip-адресов пренадлежащих этой сети (0 - off) +### Лимит ip адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества ip-адресов пренадлежащих этой сети (0 - выкл) BLLIST_IP_LIMIT=0 ### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162." BLLIST_GR_EXCLUDED_NETS="" @@ -78,29 +86,29 @@ BLLIST_GR_EXCLUDED_NETS="" BLLIST_SUMMARIZE_IP=0 ### Группировать идущие подряд подсети /24 в диапазоны CIDR BLLIST_SUMMARIZE_CIDR=0 -### Фильтрация записей блэклиста по шаблонам из файла BLLIST_IP_FILTER_FILE. Записи (IP, CIDR) попадающие под шаблоны исключаются из кофига ipset (0 - off, 1 - on) +### Фильтрация записей блэклиста по шаблонам из файла BLLIST_IP_FILTER_FILE. Записи (IP, CIDR) попадающие под шаблоны исключаются из кофига ipset (0 - выкл, 1 - вкл) BLLIST_IP_FILTER=0 ### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) BLLIST_IP_FILTER_TYPE=0 ### Файл с шаблонами ip для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) BLLIST_IP_FILTER_FILE="/etc/ruantiblock/ip_filter" -### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - off) +### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - выкл) BLLIST_SD_LIMIT=16 ### SLD не подлежащие группировке при оптимизации (через пробел) BLLIST_GR_EXCLUDED_SLD="livejournal.com facebook.com vk.com blog.jp msk.ru net.ru org.ru net.ua com.ua org.ua co.uk amazonaws.com" ### Не группировать SLD попадающие под выражения (через пробел) ("[.][a-z]{2,3}[.][a-z]{2}$") BLLIST_GR_EXCLUDED_MASKS="" -### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - off, 1 - on) +### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - выкл, 1 - вкл) BLLIST_FQDN_FILTER=0 ### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) BLLIST_FQDN_FILTER_TYPE=0 ### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) BLLIST_FQDN_FILTER_FILE="/etc/ruantiblock/fqdn_filter" -### Обрезка www[0-9]. в FQDN (0 - off, 1 - on) +### Обрезка www[0-9]. в FQDN (0 - выкл, 1 - вкл) BLLIST_STRIP_WWW=1 -### Преобразование кириллических доменов в punycode (0 - off, 1 - on) +### Преобразование кириллических доменов в punycode (0 - выкл, 1 - вкл) BLLIST_ENABLE_IDN=0 -### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - off, 1 - on) +### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - выкл, 1 - вкл) BLLIST_ALT_NSLOOKUP=0 ### Альтернативный DNS-сервер BLLIST_ALT_DNS_ADDR="8.8.8.8" @@ -112,12 +120,12 @@ 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" -RA_IP_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/ruantiblock.ip" -RA_IP_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/ruantiblock.dnsmasq" -RA_IP_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/update_status" -RA_FQDN_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/ruantiblock.ip" -RA_FQDN_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/ruantiblock.dnsmasq" -RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/update_status" +RA_IP_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/ruantiblock.ip" +RA_IP_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/ruantiblock.dnsmasq" +RA_IP_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/update_status" +RA_FQDN_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/ruantiblock.ip" +RA_FQDN_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/ruantiblock.dnsmasq" +RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/update_status" RBL_ENCODING="" ZI_ENCODING="CP1251" AF_ENCODING="" diff --git a/ruantiblock/files/etc/ruantiblock/scripts/config_script b/ruantiblock/files/etc/ruantiblock/scripts/config_script index 53bff54..77a6dfa 100644 --- a/ruantiblock/files/etc/ruantiblock/scripts/config_script +++ b/ruantiblock/files/etc/ruantiblock/scripts/config_script @@ -1,6 +1,6 @@ AWK_CMD="awk" UCI_SECTION="ruantiblock.config" -UCI_VARS="proxy_mode proxy_local_clients ipset_clear_sets allowed_hosts_mode allowed_hosts_list if_vpn tor_trans_port tor_allow_udp 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 if_vpn tor_trans_port tor_allow_udp 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" eval `uci show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' BEGIN { diff --git a/ruantiblock/files/etc/ruantiblock/scripts/info_output b/ruantiblock/files/etc/ruantiblock/scripts/info_output index b1a5d46..8d55a0f 100644 --- a/ruantiblock/files/etc/ruantiblock/scripts/info_output +++ b/ruantiblock/files/etc/ruantiblock/scripts/info_output @@ -1,66 +1,36 @@ Info() { - local _set - if CheckStatus; then - printf "{\"status\":\"enabled\",\"last_blacklist_update\":{" - if [ -f "$UPDATE_STATUS_FILE" ]; then - $AWK_CMD '{ - if(NF < 4) - print "\"status\":false"; - else - print "\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\""; - }' "$UPDATE_STATUS_FILE" - else - printf "\"status\":false" - fi - printf "}," - IptListBllistChain | $AWK_CMD ' + local _update_status + if [ -f "$UPDATE_STATUS_FILE" ]; then + _update_status=`$AWK_CMD '{ + if(NF < 4) + printf "{\"status\":false}"; + 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" ' BEGIN { - printf "\"iptables\":{" + rules_str = ""; } { - if(NR > 2) - printf "\""(($10 == "!") ? $12 : $11)"\":\""$2"\","; + rules_str = rules_str $0; } END { - printf "\"_dummy\":false},"; + if(NR == 0) { + printf "{\"status\": \"disabled\"}"; + exit 1; + } else { + printf "{\"status\":\"enabled\",\"last_blacklist_update\":%s,\"rules\":%s", UPDATE_STATUS, rules_str; + exit 0; + }; }' - printf "\"ipset\":{"; - for _set in "$IPSET_ALLOWED_HOSTS" "$IPSET_ONION" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" - do - $IPSET_CMD list "$_set" -terse | $AWK_CMD -F ": " ' - { - if($1 ~ /^Name/) { - printf "\""$2"\":["; - } - else if($1 ~ /^Size in memory/) { - printf "\""$2"\","; - } - else if($1 ~ /^Number of entries/) { - printf "\""$2"\"],"; - }; - }' - done - $IPSET_CMD list "$IPSET_DNSMASQ" | $AWK_CMD -F ": " ' - { - if($1 ~ /^Name/) { - printf "\""$2"\":["; - } - else if($1 ~ /^Size in memory/) { - printf "\""$2"\","; - } - else if($1 ~ /^Number of entries/) { - printf "\""$2"\"]},\"dnsmasq\":["; - } - else if($0 ~ /^[0-9]/) { - split($0, a, " "); - printf "[\"" a[1] "\",\"" a[3] "\"],"; - }; - } - END { - printf "false],"; - }' - printf "\"_dummy\":false}" - else - printf "{\"status\": \"disabled\"}" + if [ $? -eq 0 ]; then + printf ",\"dnsmasq\":" + $NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ" 2> /dev/null + printf ",\"dnsmasq_u\":" + $NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ_USER" 2> /dev/null + printf "}" fi } diff --git a/ruantiblock/files/etc/ruantiblock/scripts/ipt_functions b/ruantiblock/files/etc/ruantiblock/scripts/ipt_functions deleted file mode 100644 index 102d4e0..0000000 --- a/ruantiblock/files/etc/ruantiblock/scripts/ipt_functions +++ /dev/null @@ -1,128 +0,0 @@ - -IP_CMD="ip" -IPT_CMD=`which iptables-legacy` -if [ $? -ne 0 ]; then - IPT_CMD=`which iptables` - if [ $? -ne 0 ]; then - echo " Error! Iptables doesn't exists" >&2 - exit 1 - fi -fi - -IPT_ALLOWED_HOSTS_CHAIN="${NAME}_allowed_hosts" -IPT_BLLIST_CHAIN="${NAME}_blacklist" -IPT_ACTION_CHAIN="${NAME}_action" -IPT_FIRST_CHAIN="PREROUTING" -VPN_ROUTE_TABLE_ID=99 - -case "$ALLOWED_HOSTS_MODE" in - "1") - IPT_ALLOWED_HOSTS_RULE="-m set --match-set ${IPSET_ALLOWED_HOSTS} src -j ${IPT_BLLIST_CHAIN}" - ;; - "2") - IPT_ALLOWED_HOSTS_RULE="-m set ! --match-set ${IPSET_ALLOWED_HOSTS} src -j ${IPT_BLLIST_CHAIN}" - ;; - *) - IPT_ALLOWED_HOSTS_RULE="-j ${IPT_BLLIST_CHAIN}" - ;; -esac - -if [ "$PROXY_MODE" = "2" ]; then - IPT_TABLE="mangle" -else - IPT_TABLE="nat" -fi - -IptCmdWrapper() { - local _i=0 _attempts=10 _return_code=1 - while [ $_i -lt $_attempts ] - do - if $*; then - _return_code=$? - break - fi - _i=`expr $_i + 1` - done - return $_return_code -} - -IptVpnRouteAdd() { - VPN_IP=`$IP_CMD addr list dev $IF_VPN 2> /dev/null | $AWK_CMD '/inet/{sub("/[0-9]{1,2}$", "", $2); print $2; exit}'` - if [ -n "$VPN_IP" ]; then - echo 0 > /proc/sys/net/ipv4/conf/$IF_VPN/rp_filter - IptVpnRouteDel 2> /dev/null - $IP_CMD rule add fwmark $VPN_PKTS_MARK table $VPN_ROUTE_TABLE_ID priority 1000 - $IP_CMD route add default via $VPN_IP table $VPN_ROUTE_TABLE_ID - fi -} - -IptVpnRouteDel() { - $IP_CMD route flush table $VPN_ROUTE_TABLE_ID - $IP_CMD rule del table $VPN_ROUTE_TABLE_ID -} - -IptVpnRouteStatus() { - [ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0 - return 1 -} - -IptMainAdd() { - local _set - $IPT_CMD -t "$IPT_TABLE" -N "$IPT_ACTION_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -N "$IPT_BLLIST_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -N "$IPT_ALLOWED_HOSTS_CHAIN" - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ALLOWED_HOSTS_CHAIN" $IPT_ALLOWED_HOSTS_RULE - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -I "$IPT_FIRST_CHAIN" 1 -j "$IPT_ALLOWED_HOSTS_CHAIN" - - if [ "$PROXY_MODE" = "2" ]; then - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -j MARK --set-mark $VPN_PKTS_MARK - IPT_IPSETS="${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}" - elif [ "$PROXY_MODE" = "3" ]; then - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p tcp -j REDIRECT --to-ports ${T_PROXY_PORT_TCP} - if [ "$T_PROXY_ALLOW_UDP" = "1" ]; then - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p udp -j REDIRECT --to-ports ${T_PROXY_PORT_UDP} - fi - IPT_IPSETS="${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}" - else - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p tcp -j REDIRECT --to-ports ${TOR_TRANS_PORT} - if [ "$TOR_ALLOW_UDP" = "1" ]; then - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_ACTION_CHAIN" -p udp -j REDIRECT --to-ports ${TOR_TRANS_PORT} - fi - IPT_IPSETS="${IPSET_ONION} ${IPSET_CIDR} ${IPSET_IP} ${IPSET_DNSMASQ}" - fi - - for _set in $IPT_IPSETS - do - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -A "$IPT_BLLIST_CHAIN" -m set --match-set "$_set" dst -j "$IPT_ACTION_CHAIN" - done - if [ "$PROXY_MODE" = "2" ]; then - IptVpnRouteAdd - fi -} - -IptMainDel() { - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -D "$IPT_FIRST_CHAIN" -j "$IPT_ALLOWED_HOSTS_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -F "$IPT_ALLOWED_HOSTS_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -X "$IPT_ALLOWED_HOSTS_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -F "$IPT_BLLIST_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -X "$IPT_BLLIST_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -F "$IPT_ACTION_CHAIN" - $IPT_CMD -t "$IPT_TABLE" -X "$IPT_ACTION_CHAIN" - if [ "$PROXY_MODE" = "2" ]; then - IptVpnRouteDel 2> /dev/null - fi -} - -IPT_OUTPUT_FIRST_RULE="-j ${IPT_BLLIST_CHAIN}" - -IptLocalClientsAdd() { - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -I OUTPUT 1 $IPT_OUTPUT_FIRST_RULE -} - -IptLocalClientsDel() { - IptCmdWrapper $IPT_CMD -t "$IPT_TABLE" -D OUTPUT $IPT_OUTPUT_FIRST_RULE -} - -IptListBllistChain() { - $IPT_CMD -t "$IPT_TABLE" -v -L "$IPT_BLLIST_CHAIN" -} diff --git a/ruantiblock/files/etc/ruantiblock/scripts/nft_functions b/ruantiblock/files/etc/ruantiblock/scripts/nft_functions new file mode 100644 index 0000000..e3ac59b --- /dev/null +++ b/ruantiblock/files/etc/ruantiblock/scripts/nft_functions @@ -0,0 +1,118 @@ +IP_CMD="ip" +NFT_ALLOWED_HOSTS_CHAIN="allowed_hosts" +NFT_BLLIST_CHAIN="blacklist" +NFT_ACTION_CHAIN="action" +NFT_LOCAL_CLIENTS_CHAIN="local_clients" +VPN_ROUTE_TABLE_ID=99 + +if [ "$PROXY_MODE" = "2" ]; then + MAIN_CHAIN_TYPE="type filter hook prerouting priority -160; policy accept;" + LOCAL_CLIENTS_CHAIN_TYPE="type route hook output priority -160; policy accept;" +else + MAIN_CHAIN_TYPE="type nat hook prerouting priority -110; policy accept;" + LOCAL_CLIENTS_CHAIN_TYPE="type nat hook output priority -110; policy accept;" +fi + +case "$ALLOWED_HOSTS_MODE" in + "1") + IPT_ALLOWED_HOSTS_RULE="ip saddr @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" + ;; + "2") + IPT_ALLOWED_HOSTS_RULE="ip saddr != @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}" + ;; + *) + IPT_ALLOWED_HOSTS_RULE="jump ${NFT_BLLIST_CHAIN}" + ;; +esac + +NftCmdWrapper() { + local _i=0 _attempts=10 _return_code=1 + while [ $_i -lt $_attempts ] + do + if $*; then + _return_code=$? + break + fi + _i=`expr $_i + 1` + done + return $_return_code +} + +IptVpnRouteDel() { + $IP_CMD route flush table $VPN_ROUTE_TABLE_ID + $IP_CMD rule del table $VPN_ROUTE_TABLE_ID +} + +IptVpnRouteAdd() { + VPN_IP=`$IP_CMD addr list dev $IF_VPN 2> /dev/null | $AWK_CMD '/inet/{sub("/[0-9]{1,2}$", "", $2); print $2; exit}'` + if [ -n "$VPN_IP" ]; then + echo 0 > /proc/sys/net/ipv4/conf/$IF_VPN/rp_filter + IptVpnRouteDel 2> /dev/null + $IP_CMD rule add fwmark $VPN_PKTS_MARK table $VPN_ROUTE_TABLE_ID priority 1000 + $IP_CMD route add default via $VPN_IP table $VPN_ROUTE_TABLE_ID + fi +} + +NftVpnRouteStatus() { + [ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0 + return 1 +} + +NftMainAdd() { + local _nft_sets="${NFTSET_CIDR} ${NFTSET_CIDR_USER} ${NFTSET_IP} ${NFTSET_IP_USER} ${NFTSET_DNSMASQ} ${NFTSET_DNSMASQ_USER}" _set + $NFT_CMD add chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" { $LOCAL_CLIENTS_CHAIN_TYPE } + $NFT_CMD add chain $NFT_TABLE "$NFT_ACTION_CHAIN" + $NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN" + $NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { $MAIN_CHAIN_TYPE } + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" $IPT_ALLOWED_HOSTS_RULE + if [ "$PROXY_MODE" = "2" ]; then + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" mark set $VPN_PKTS_MARK + elif [ "$PROXY_MODE" = "3" ]; then + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $T_PROXY_PORT_TCP + if [ "$T_PROXY_ALLOW_UDP" = "1" ]; then + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" udp dport { 0-65535 } redirect to $T_PROXY_PORT_UDP + fi + else + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $TOR_TRANS_PORT + if [ "$TOR_ALLOW_UDP" = "1" ]; then + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" udp dport { 0-65535 } redirect to $TOR_TRANS_PORT + fi + _nft_sets="${NFTSET_ONION} ${_nft_sets}" + fi + for _set in $_nft_sets + do + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${_set}" counter goto "$NFT_ACTION_CHAIN" + done + if [ "$PROXY_MODE" = "2" ]; then + IptVpnRouteAdd + fi +} + +NftMainDelete() { + $NFT_CMD flush chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" + $NFT_CMD delete chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" + $NFT_CMD flush chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" + $NFT_CMD delete chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" + $NFT_CMD flush chain $NFT_TABLE "$NFT_BLLIST_CHAIN" + $NFT_CMD delete chain $NFT_TABLE "$NFT_BLLIST_CHAIN" + $NFT_CMD flush chain $NFT_TABLE "$NFT_ACTION_CHAIN" + $NFT_CMD delete chain $NFT_TABLE "$NFT_ACTION_CHAIN" + IptVpnRouteDel 2> /dev/null +} + +NftLocalClientsAdd() { + NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" jump "$NFT_BLLIST_CHAIN" +} + +NftListBllistChain() { + $NFT_CMD -t list chain $NFT_TABLE "$NFT_BLLIST_CHAIN" +} + +NftListBllistChainJson() { + $NFT_CMD -t -j list chain $NFT_TABLE "$NFT_BLLIST_CHAIN" +} + +NftReturnStatus() { + $NFT_CMD -c add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" continue &> /dev/null + return $? +} diff --git a/ruantiblock/files/usr/bin/ruantiblock b/ruantiblock/files/usr/bin/ruantiblock old mode 100755 new mode 100644 index 629b2d5..e1d9add --- a/ruantiblock/files/usr/bin/ruantiblock +++ b/ruantiblock/files/usr/bin/ruantiblock @@ -15,7 +15,7 @@ export LANGUAGE="en" CONFIG_DIR="/etc/${NAME}" CONFIG_FILE="${CONFIG_DIR}/${NAME}.conf" -export DATA_DIR="/var/${NAME}" +export DATA_DIR="${CONFIG_DIR}/var" export MODULES_DIR="/usr/libexec/${NAME}" ### Дополнительный конфиг dnsmasq с FQDN записями блэклиста export DNSMASQ_DATA_FILE="/var/dnsmasq.d/${NAME}.dnsmasq" @@ -26,12 +26,12 @@ export HTML_DIR="/www" ########################## Default Settings ############################ -### Режим обработки пакетов в правилах iptables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) +### Режим обработки пакетов в правилах nftables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) export PROXY_MODE=1 -### Применять правила проксификации для трафика локальных сервисов роутера (0 - off, 1 - on) +### Применять правила проксификации для трафика локальных сервисов роутера (0 - выкл, 1 - вкл) export PROXY_LOCAL_CLIENTS=1 -### Удаление записей из основных сетов перед началом заполнения временных сетов при обновлении (для освобождения оперативной памяти перед заполнением сетов) (0 - off, 1 - on) -export IPSET_CLEAR_SETS=0 +### Удаление записей сетов перед началом обновления (для освобождения оперативной памяти перед обновлением сетов) (0 - выкл, 1 - вкл) +export NFTSET_CLEAR_SETS=0 ### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке) export ALLOWED_HOSTS_MODE=0 ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) @@ -40,7 +40,7 @@ export ALLOWED_HOSTS_LIST="" export IF_VPN="tun0" ### Порт прозрачного прокси Tor (параметр TransPort в torrc) export TOR_TRANS_PORT=9040 -### Отправлять в Tor UDP-трафик (0 - off, 1 - on) +### Отправлять в Tor UDP-трафик (0 - выкл, 1 - вкл) export TOR_ALLOW_UDP=0 ### DNS-сервер для резолвинга в домене .onion (Tor) export ONION_DNS_ADDR="127.0.0.1#9053" @@ -50,9 +50,9 @@ export VPN_PKTS_MARK=8 export T_PROXY_PORT_TCP=1100 ### UDP порт прокси в режиме прозрачного прокси export T_PROXY_PORT_UDP=1100 -### Отправлять в прозрачный прокси UDP-трафик (0 - off, 1 - on) +### Отправлять в прозрачный прокси UDP-трафик (0 - выкл, 1 - вкл) export T_PROXY_ALLOW_UDP=0 -### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - off, 1 - on) +### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл) ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) ### Можно комментировать строки (#) @@ -61,14 +61,20 @@ export ADD_USER_ENTRIES=0 export USER_ENTRIES_DNS="" ### Файл пользовательских записей export USER_ENTRIES_FILE="${CONFIG_DIR}/user_entries" -### Запись событий в syslog (0 - off, 1 - on) +### Запись событий в syslog (0 - выкл, 1 - вкл) export ENABLE_LOGGING=1 -### Html-страница с инфо о текущем статусе (0 - off, 1 - on) (не используется в OpenWrt) +### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt) export ENABLE_HTML_INFO=0 -### Максимальное кол-во элементов списка ipset -export IPSET_MAXELEM=2000000 -### Таймаут для записей в сете $IPSET_DNSMASQ -export IPSET_DNSMASQ_TIMEOUT=3600 +### Максимальное кол-во элементов списка nftables +export NFTSET_MAXELEM_CIDR=65535 +export NFTSET_MAXELEM_IP=1000000 +export NFTSET_MAXELEM_DNSMASQ=65535 +### Политика отбора элементов в сетах nftables. "performance" - производительность и большее потребление RAM. "memory" - хуже производительность и меньше потребление RAM +export NFTSET_POLICY_CIDR="memory" +export NFTSET_POLICY_IP="memory" +export NFTSET_POLICY_DNSMASQ="performance" +### Таймаут для записей в сете $NFTSET_DNSMASQ +export NFTSET_DNSMASQ_TIMEOUT="1h" ### Кол-во попыток обновления блэклиста (в случае неудачи) export MODULE_RUN_ATTEMPTS=3 ### Таймаут между попытками обновления @@ -84,7 +90,7 @@ export BLLIST_MODULE="" export BLLIST_PRESET="" ### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит export BLLIST_MIN_ENTRIES=3000 -### Лимит IP адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества IP адресов пренадлежащих этой сети (0 - off) +### Лимит IP адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества IP адресов пренадлежащих этой сети (0 - выкл) export BLLIST_IP_LIMIT=0 ### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162." export BLLIST_GR_EXCLUDED_NETS="" @@ -92,29 +98,29 @@ export BLLIST_GR_EXCLUDED_NETS="" export BLLIST_SUMMARIZE_IP=0 ### Группировать идущие подряд подсети /24 в диапазоны CIDR export BLLIST_SUMMARIZE_CIDR=0 -### Фильтрация записей блэклиста по шаблонам из файла BLLIST_IP_FILTER_FILE. Записи (IP, CIDR) попадающие под шаблоны исключаются из кофига ipset (0 - off, 1 - on) +### Фильтрация записей блэклиста по шаблонам из файла BLLIST_IP_FILTER_FILE. Записи (IP, CIDR) попадающие под шаблоны исключаются из кофига ipset (0 - выкл, 1 - вкл) export BLLIST_IP_FILTER=0 ### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) export BLLIST_IP_FILTER_TYPE=0 ### Файл с шаблонами IP для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) export BLLIST_IP_FILTER_FILE="${CONFIG_DIR}/ip_filter" -### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - off) +### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - выкл) export BLLIST_SD_LIMIT=16 ### SLD не подлежащие группировке при оптимизации (через пробел) export BLLIST_GR_EXCLUDED_SLD="livejournal.com facebook.com vk.com blog.jp msk.ru net.ru org.ru net.ua com.ua org.ua co.uk amazonaws.com" ### Не группировать SLD попадающие под выражения (через пробел) ("[.][a-z]{2,3}[.][a-z]{2}$") export BLLIST_GR_EXCLUDED_MASKS="" -### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - off, 1 - on) +### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - выкл, 1 - вкл) export BLLIST_FQDN_FILTER=0 ### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) export BLLIST_FQDN_FILTER_TYPE=0 ### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) export BLLIST_FQDN_FILTER_FILE="${CONFIG_DIR}/fqdn_filter" -### Обрезка www[0-9]. в FQDN (0 - off, 1 - on) +### Обрезка www[0-9]. в FQDN (0 - выкл, 1 - вкл) export BLLIST_STRIP_WWW=1 -### Преобразование кириллических доменов в punycode (0 - off, 1 - on) +### Преобразование кириллических доменов в punycode (0 - выкл, 1 - вкл) export BLLIST_ENABLE_IDN=0 -### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - off, 1 - on) +### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - выкл, 1 - вкл) export BLLIST_ALT_NSLOOKUP=0 ### Альтернативный DNS-сервер export BLLIST_ALT_DNS_ADDR="8.8.8.8" @@ -125,12 +131,12 @@ export RBL_IP_URL="https://reestr.rublacklist.net/api/v3/ips/" export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" export AF_IP_URL="https://antifilter.download/list/allyouneed.lst" export AF_FQDN_URL="https://antifilter.download/list/domains.lst" -export RA_IP_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/ruantiblock.ip" -export RA_IP_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/ruantiblock.dnsmasq" -export RA_IP_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/ip/update_status" -export RA_FQDN_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/ruantiblock.ip" -export RA_FQDN_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/ruantiblock.dnsmasq" -export RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist/fqdn/update_status" +export RA_IP_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/ruantiblock.ip" +export RA_IP_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/ruantiblock.dnsmasq" +export RA_IP_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/ip/update_status" +export RA_FQDN_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/ruantiblock.ip" +export RA_FQDN_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/ruantiblock.dnsmasq" +export RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/update_status" export RBL_ENCODING="" export ZI_ENCODING="CP1251" export AF_ENCODING="" @@ -141,18 +147,19 @@ export RA_ENCODING="" ### External config [ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE" -CONFIG_SCRIPT="${CONFIG_DIR}/scripts/config_script" -START_SCRIPT="${CONFIG_DIR}/scripts/start_script" -STOP_SCRIPT="${CONFIG_DIR}/scripts/stop_script" +SCRIPTS_DIR="${CONFIG_DIR}/scripts" +CONFIG_SCRIPT="${SCRIPTS_DIR}/config_script" +START_SCRIPT="${SCRIPTS_DIR}/start_script" +STOP_SCRIPT="${SCRIPTS_DIR}/stop_script" ### Config script [ -f "$CONFIG_SCRIPT" ] && . "$CONFIG_SCRIPT" ### Utilities AWK_CMD="awk" -IPSET_CMD=`which ipset` +NFT_CMD=`which nft` if [ $? -ne 0 ]; then - echo " Error! Ipset doesn't exists" >&2 + echo " Error! Nftables doesn't exists" >&2 exit 1 fi LOGGER_CMD=`which logger` @@ -168,24 +175,33 @@ if [ $? -ne 0 ]; then fi WGET_PARAMS="--no-check-certificate -q -O" export IP_DATA_FILE="${DATA_DIR}/${NAME}.ip" -export IPSET_ALLOWED_HOSTS="r_allowed_ip" -export IPSET_ONION="r_onion" -export IPSET_CIDR="rc" -export IPSET_CIDR_TMP="${IPSET_CIDR}t" -export IPSET_IP="ri" -export IPSET_IP_TMP="${IPSET_IP}t" -export IPSET_DNSMASQ="rd" +export NFT_TABLE="ip r" +export NFT_TABLE_DNSMASQ="4#ip#r" +export NFTSET_ALLOWED_HOSTS="allowed_ip" +export NFTSET_ONION="onion" +export NFTSET_CIDR="c" +export NFTSET_IP="i" +export NFTSET_DNSMASQ="d" +export NFTSET_CIDR_USER="cu" +export NFTSET_IP_USER="iu" +export NFTSET_DNSMASQ_USER="du" +export NFTSET_ALLOWED_HOSTS_TYPE="ipv4_addr" +export NFTSET_CIDR_TYPE="ipv4_addr" +export NFTSET_IP_TYPE="ipv4_addr" +export NFTSET_DNSMASQ_TYPE="ipv4_addr" +export NFTSET_CIDR_CFG="set ${NFTSET_CIDR} {type ${NFTSET_CIDR_TYPE};size ${NFTSET_MAXELEM_CIDR};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" +export NFTSET_IP_CFG="set ${NFTSET_IP} {type ${NFTSET_IP_TYPE};size ${NFTSET_MAXELEM_IP};policy ${NFTSET_POLICY_IP};" export UPDATE_STATUS_FILE="${DATA_DIR}/update_status" -UPDATE_PID_FILE="/var/run/${NAME}_update.pid" +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" -IPT_FUNCTIONS="${CONFIG_DIR}/scripts/ipt_functions" -INFO_OUTPUT_FUNCTION="${CONFIG_DIR}/scripts/info_output" +NFT_FUNCTIONS="${SCRIPTS_DIR}/nft_functions" +INFO_OUTPUT_FUNCTION="${SCRIPTS_DIR}/info_output" ######################### External functions ########################### -. "$IPT_FUNCTIONS" +. "$NFT_FUNCTIONS" if [ -f "$INFO_OUTPUT_FUNCTION" ]; then . "$INFO_OUTPUT_FUNCTION" else @@ -196,13 +212,13 @@ fi Help() { cat << EOF - Usage: `basename $0` start|force-start|stop|destroy|restart|update|force-update|data-files|status|raw-status|html-info|help + Usage: `basename $0` start|force-start|stop|destroy|restart|reload|update|force-update|data-files|status|raw-status|html-info|help start : Start force-start : Removing the pid-file before running stop : Stop - destroy : Stop + destroy ipsets and clear all data files + destroy : Stop + remove nft table and clear all data files restart : Restart - reload : Renew iptables configuration + reload : Renew nftables configuration update : Update blacklist force-update : Force update blacklist data-files : Create ${IP_DATA_FILE} & ${DNSMASQ_DATA_FILE} (without network functions) @@ -216,10 +232,12 @@ cat << EOF `basename $0` stop `basename $0` destroy `basename $0` restart + `basename $0` reload `basename $0` update `basename $0` force-update `basename $0` data-files `basename $0` status + `basename $0` raw-status `basename $0` html-info EOF } @@ -259,86 +277,68 @@ DnsmasqRestart() { eval `echo "$DNSMASQ_RESTART_CMD"` } -IsIpsetExists() { - $IPSET_CMD list "$1" -terse &> /dev/null - return $? -} - -FlushIpSets() { +FlushNftSets() { local _set for _set in "$@" do - IsIpsetExists "$_set" && $IPSET_CMD flush "$_set" + $NFT_CMD flush set $NFT_TABLE "$_set" &> /dev/null done } -DestroyIpsets() { - local _set - for _set in "$@" - do - IsIpsetExists "$_set" && $IPSET_CMD destroy "$_set" - done -} - -FillAllowedHostsSet() { - local _entry - for _entry in $ALLOWED_HOSTS_LIST - do - $IPSET_CMD add "$IPSET_ALLOWED_HOSTS" "$_entry" - done -} - -AddIptRules() { - IptMainAdd - if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then - IptLocalClientsAdd +AddNftSets() { + local _hosts + $NFT_CMD add set $NFT_TABLE "$NFTSET_CIDR" { type "$NFTSET_CIDR_TYPE"\; size $NFTSET_MAXELEM_CIDR\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_CIDR_USER" { type "$NFTSET_CIDR_TYPE"\; size $NFTSET_MAXELEM_CIDR\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_IP" { type "$NFTSET_IP_TYPE"\; size $NFTSET_MAXELEM_IP\; policy "$NFTSET_POLICY_IP"\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_IP_USER" { type "$NFTSET_IP_TYPE"\; size $NFTSET_MAXELEM_IP\; policy "$NFTSET_POLICY_IP"\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_DNSMASQ" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_DNSMASQ_USER" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_ONION" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } + $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_IP"\; } + _hosts=`printf "$ALLOWED_HOSTS_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'` + if [ -n "$_hosts" ]; then + $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_hosts" } fi } -DelIptRules() { - IptLocalClientsDel - IptMainDel +UpdateBllistSets() { + if [ -f "$IP_DATA_FILE" ]; then + echo " Updating nft sets..." + $NFT_CMD -f "$IP_DATA_FILE" + if [ $? -eq 0 ]; then + echo " Ok" + else + echo " Error! Nft set wasn't updated" >&2 + MakeLogRecord "err" "Error! Nft set wasn't updated" + fi + fi +} + +AddNftRules() { + NftMainAdd + if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then + NftLocalClientsAdd + fi +} + +DeleteNftRules() { + NftMainDelete } SetNetConfig() { - local _set - ### Создание списков ipset. Проверка на наличие списка с таким же именем, если нет, то создается новый - for _set in "$IPSET_CIDR_TMP" "$IPSET_CIDR" - do - IsIpsetExists "$_set" || $IPSET_CMD create "$_set" hash:net maxelem $IPSET_MAXELEM - done - for _set in "$IPSET_ALLOWED_HOSTS" "$IPSET_IP_TMP" "$IPSET_IP" - do - IsIpsetExists "$_set" || $IPSET_CMD create "$_set" hash:ip maxelem $IPSET_MAXELEM - done - for _set in "$IPSET_DNSMASQ" "$IPSET_ONION" - do - IsIpsetExists "$_set" || $IPSET_CMD create "$_set" hash:ip maxelem $IPSET_MAXELEM timeout $IPSET_DNSMASQ_TIMEOUT - done - AddIptRules + $NFT_CMD add table $NFT_TABLE + AddNftSets + AddNftRules } DropNetConfig() { - DelIptRules - FlushIpSets "$IPSET_ALLOWED_HOSTS" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" "$IPSET_ONION" + DeleteNftRules + FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_CIDR" "$NFTSET_CIDR_USER" "$NFTSET_IP" "$NFTSET_IP_USER" "$NFTSET_DNSMASQ" "$NFTSET_DNSMASQ_USER" "$NFTSET_ONION" } -FillIpsets() { - local _set - ### Заполнение списков ipset $IPSET_IP и $IPSET_CIDR. Сначала restore загружает во временные списки, а затем swap из временных добавляет в основные - if [ -f "$IP_DATA_FILE" ]; then - echo " Filling ipsets..." - FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP" - IsIpsetExists "$IPSET_IP_TMP" && IsIpsetExists "$IPSET_CIDR_TMP" && IsIpsetExists "$IPSET_IP" && IsIpsetExists "$IPSET_CIDR" &&\ - cat "$IP_DATA_FILE" | $IPSET_CMD restore && { $IPSET_CMD swap "$IPSET_IP_TMP" "$IPSET_IP"; $IPSET_CMD swap "$IPSET_CIDR_TMP" "$IPSET_CIDR"; } - if [ $? -eq 0 ]; then - echo " Ok" - FlushIpSets "$IPSET_IP_TMP" "$IPSET_CIDR_TMP" - else - echo " Error! Ipset wasn't updated" >&2 - MakeLogRecord "err" "Error! Ipset wasn't updated" - fi - fi +DestroyNetConfig() { + $NFT_CMD flush table $NFT_TABLE &> /dev/null + $NFT_CMD delete table $NFT_TABLE &> /dev/null } ClearDataFiles() { @@ -350,19 +350,8 @@ ClearDataFiles() { } CheckStatus() { - local _set _ipset_return=0 _return_code=1 - if [ "$1" = "ipsets" ]; then - for _set in "$IPSET_ALLOWED_HOSTS" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" "$IPSET_ONION" - do - IsIpsetExists "$_set" - _ipset_return=$? - [ $_ipset_return -ne 0 ] && break - done - fi - if IptListBllistChain &> /dev/null && [ $_ipset_return -eq 0 ]; then - _return_code=0 - fi - return $_return_code + NftReturnStatus + return $? } PreStartCheck() { @@ -377,43 +366,64 @@ AddUserEntries() { if [ -f "$USER_ENTRIES_FILE" -a -s "$USER_ENTRIES_FILE" ]; then $AWK_CMD 'BEGIN { null=""; - while((getline ip_string 0) { - split(ip_string, ip_string_arr, " "); - ip_data_array[ip_string_arr[3]]=null; - }; - close(ENVIRON["IP_DATA_FILE"]); - while((getline fqdn_string 0) { - split(fqdn_string, fqdn_string_arr, "/"); - fqdn_data_array[fqdn_string_arr[2]]=null; - }; - close(ENVIRON["DNSMASQ_DATA_FILE"]); + fqdn_array[0]=null; + ip_list=""; + cidr_list=""; } - function writeIpsetEntries(val, set) { - printf "add %s %s\n", set, val >> ENVIRON["IP_DATA_FILE"]; - }; function writeDNSData(val, dns) { - if(length(dns) == 0 && length(ENVIRON["USER_ENTRIES_DNS"]) > 0) + if(length(dns) == 0 && length(ENVIRON["USER_ENTRIES_DNS"]) > 0) { dns=ENVIRON["USER_ENTRIES_DNS"]; - if(length(dns) > 0) + }; + if(length(dns) > 0) { printf "server=/%s/%s\n", val, dns >> ENVIRON["DNSMASQ_DATA_FILE"]; - printf "ipset=/%s/%s\n", val, ENVIRON["IPSET_DNSMASQ"] >> ENVIRON["DNSMASQ_DATA_FILE"]; + }; + printf "nftset=/%s/%s#%s\n", val, ENVIRON["NFT_TABLE_DNSMASQ"], ENVIRON["NFTSET_DNSMASQ_USER"] >> 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}$/ && !($0 in ip_data_array)) - writeIpsetEntries($0, ENVIRON["IPSET_IP_TMP"]); - else if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}[\057][0-9]{1,2}$/ && !($0 in ip_data_array)) - writeIpsetEntries($0, ENVIRON["IPSET_CIDR_TMP"]); - 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})?)?$/ && !($1 in fqdn_data_array)) - writeDNSData($1, $2); + if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}$/) { + ip_list=ip_list $0 ","; + } + else if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}[\057][0-9]{1,2}$/) { + cidr_list=cidr_list $0 ","; + } + 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 {\nset %s {type %s;size %s;flags interval;auto-merge;", ENVIRON["NFT_TABLE"], ENVIRON["NFTSET_CIDR_USER"], ENVIRON["NFTSET_CIDR_TYPE"], ENVIRON["NFTSET_MAXELEM_CIDR"] >> ENVIRON["IP_DATA_FILE"]; + if(length(cidr_list) > 0) { + printf "elements={%s};", cidr_list >> ENVIRON["IP_DATA_FILE"]; + }; + printf "}\nset %s {type %s;size %s;", ENVIRON["NFTSET_IP_USER"], ENVIRON["NFTSET_IP_TYPE"], ENVIRON["NFTSET_MAXELEM_IP"] >> ENVIRON["IP_DATA_FILE"]; + if(length(ip_list) > 0) { + printf "elements={%s};", ip_list >> ENVIRON["IP_DATA_FILE"]; + }; + printf "}\n}\n" >> ENVIRON["IP_DATA_FILE"]; + writeFqdnEntries(); }' "$USER_ENTRIES_FILE" fi fi } +ToggleUPIDFile() { + if [ "$1" = "del" ]; then + rm -f "$U_PID_FILE" + else + echo "$$" > "$U_PID_FILE" + fi +} + GetDataFiles() { local _return_code=1 _attempt=1 _update_string PreStartCheck - echo "$$" > "$UPDATE_PID_FILE" if [ -n "$BLLIST_PRESET" -a -n "$BLLIST_MODULE" ]; then while : do @@ -445,16 +455,16 @@ GetDataFiles() { _return_code=0 else _return_code=2 - rm -f "$UPDATE_PID_FILE" return $_return_code fi - if [ "$PROXY_MODE" = "2" -o "$PROXY_MODE" = "3" ]; then - printf "\n" >> "$DNSMASQ_DATA_FILE" - else - ### Запись для .onion в $DNSMASQ_DATA_FILE - printf "server=/onion/%s\nipset=/onion/%s\n" "${ONION_DNS_ADDR}" "${IPSET_ONION}" >> "$DNSMASQ_DATA_FILE" + if [ $_return_code -eq 0 ]; then + if [ "$PROXY_MODE" = "2" -o "$PROXY_MODE" = "3" ]; then + printf "\n" >> "$DNSMASQ_DATA_FILE" + else + ### Запись для .onion в $DNSMASQ_DATA_FILE + printf "server=/onion/%s\nnftset=/onion/%s#%s\n" "$ONION_DNS_ADDR" "$NFT_TABLE_DNSMASQ" "$NFTSET_ONION" >> "$DNSMASQ_DATA_FILE" + fi fi - rm -f "$UPDATE_PID_FILE" return $_return_code } @@ -464,22 +474,25 @@ MakeToken() { Update() { local _return_code=0 - if CheckStatus ipsets; then + if CheckStatus; then : else echo " ${NAME} ${1} - Error! ${NAME} does not running or another error has occurred" >&2 return 1 fi MakeToken - if [ -e "$UPDATE_PID_FILE" ] && [ "$1" != "force-update" ]; then + if [ -e "$U_PID_FILE" ] && [ "$1" != "force-update" ]; then echo " ${NAME} ${1} - Error! Another instance of update is already running" >&2 MakeLogRecord "err" "${1} - Error! Another instance of update is already running" _return_code=2 else + ToggleUPIDFile add echo " ${NAME} ${1}..." MakeLogRecord "notice" "${1}..." - if [ "$IPSET_CLEAR_SETS" = "1" ]; then - FlushIpSets "$IPSET_IP" "$IPSET_CIDR" "$IPSET_DNSMASQ" + if [ "$NFTSET_CLEAR_SETS" = "1" ]; then + FlushNftSets "$NFTSET_CIDR" "$NFTSET_CIDR_USER" "$NFTSET_IP" "$NFTSET_IP_USER" "$NFTSET_DNSMASQ" "$NFTSET_DNSMASQ_USER" + elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then + FlushNftSets "$NFTSET_IP" "$NFTSET_CIDR" fi GetDataFiles case $? in @@ -488,8 +501,8 @@ Update() { MakeLogRecord "notice" "Blacklist updated" ;; 2) - echo " Blacklist update error!" >&2 - MakeLogRecord "err" "Blacklist update error!" + echo " Error! Blacklist update error" >&2 + MakeLogRecord "err" "Error! Blacklist update error" _return_code=1 ;; *) @@ -498,10 +511,13 @@ Update() { _return_code=1 ;; esac - FlushIpSets "$IPSET_DNSMASQ" - FillIpsets - _return_code=$? + FlushNftSets "$NFTSET_DNSMASQ" "$NFTSET_ONION" "$NFTSET_DNSMASQ_USER" + if [ "$ADD_USER_ENTRIES" != "1" ]; then + FlushNftSets "$NFTSET_CIDR_USER" "$NFTSET_IP_USER" + fi + UpdateBllistSets DnsmasqRestart + ToggleUPIDFile del fi MakeToken return $_return_code @@ -524,10 +540,8 @@ Start() { MakeLogRecord "info" "${1}..." DropNetConfig &> /dev/null SetNetConfig - FillAllowedHostsSet PreStartCheck - FillIpsets - _return_code=$? + UpdateBllistSets ### Start-script [ -x "$START_SCRIPT" ] && $START_SCRIPT > /dev/null 2>&1 & fi @@ -565,48 +579,55 @@ Reload() { sleep 1 done echo " ${NAME} reload..." - DelIptRules &> /dev/null - AddIptRules &> /dev/null + DeleteNftRules &> /dev/null + AddNftRules &> /dev/null MakeToken } Status() { - local _set - if CheckStatus; then - printf "\n \033[1m${NAME} status\033[m: \033[1;32mEnabled\033[m\n\n PROXY_MODE: ${PROXY_MODE}\n PROXY_LOCAL_CLIENTS: ${PROXY_LOCAL_CLIENTS}\n BLLIST_PRESET: ${BLLIST_PRESET}\n BLLIST_MODULE: ${BLLIST_MODULE}\n" - if [ -f "$UPDATE_STATUS_FILE" ]; then - $AWK_CMD '{ - update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")"; - printf "\n Last blacklist update: %s\n", update_string; - }' "$UPDATE_STATUS_FILE" - else - printf "\n Last blacklist update: No data\n" - fi - if [ "$PROXY_MODE" = "2" ] && ! IptVpnRouteStatus; then - printf "\n \033[1;31mVPN ROUTING ERROR! (NEED THE RESTART)\033[m\n" - fi - printf "\n \033[4mIptables rules\033[m:\n\n" - IptListBllistChain | $AWK_CMD ' - { - if(NR > 2) { - printf " Match-set: %s\n Bytes: %s\n\n", $11, $2; - }; - }' - printf " \033[4mIp sets\033[m:\n\n" - for _set in "$IPSET_ALLOWED_HOSTS" "$IPSET_ONION" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" - do - $IPSET_CMD list "$_set" -terse | $AWK_CMD -F ":" ' - { - if($1 ~ /^(Name|Size in memory|Number of entries)/) { - printf " %s: %s\n", $1, $2; - if($1 ~ /^Number of entries/) printf "\n"; - }; - }' - done + local _update_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")"; + printf "Last blacklist update: %s", update_string; + }' "$UPDATE_STATUS_FILE"` else - printf "\n \033[1m${NAME} status\033[m: \033[1mDisabled\033[m\n\n" - exit 2 + _update_status="Last blacklist update: No data" 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" ' + BEGIN { + rules_str = ""; + nftset = ""; + bytes = ""; + } + /@/ { + if(match($0, /@[^ ]+/) != 0) { + nftset = substr($0, RSTART+1, RLENGTH-1); + if(match($0, /bytes [^ ]+/) != 0) { + bytes = substr($0, RSTART+6, RLENGTH-6); + }; + rules_str = rules_str " Match-set: " nftset "\n Bytes: " bytes "\n\n"; + }; + } + END { + if(NR == 0) { + 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(VPN_ERROR) > 0) { + printf "\n "VPN_ERROR"\n"; + }; + + printf "\n \033[4mNftables rules\033[m:\n\n"; + printf rules_str; + }' } StatusOutput() { @@ -651,7 +672,7 @@ case "$BLLIST_PRESET" in export BLLIST_MODE="fqdn" BLLIST_MODULE="DownloadRuabBlacklist $BLLIST_MODE" ;; - *) + *) export BLLIST_SOURCE="" export BLLIST_MODE="" ;; @@ -683,10 +704,10 @@ case "$1" in ;; destroy) Stop "$1" &> /dev/null - DestroyIpsets "$IPSET_ALLOWED_HOSTS" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" "$IPSET_ONION" + DestroyNetConfig ClearDataFiles return_code=$? - rm -f "$UPDATE_PID_FILE" "$START_PID_FILE" + ToggleUPIDFile del DnsmasqRestart StatusOutput ;; @@ -696,7 +717,7 @@ case "$1" in StatusOutput ;; data-files) - if [ -e "$UPDATE_PID_FILE" ] && [ "$1" != "force-update" ]; then + if [ -e "$U_PID_FILE" ] && [ "$1" != "force-update" ]; then echo " ${NAME} - Error! Another instance of update is already running" >&2 exit 2 else @@ -716,7 +737,7 @@ case "$1" in if [ -e "$START_PID_FILE" ]; then return_code=3 echo 3 - elif [ -e "$UPDATE_PID_FILE" ]; then + elif [ -e "$U_PID_FILE" ]; then return_code=4 echo 4 else @@ -730,7 +751,7 @@ case "$1" in esac ;; vpn-route-status) - IptVpnRouteStatus + NftVpnRouteStatus return_code=$? echo $return_code ;;