v1.0. Support for nftables and dnsmasq 2.88.

This commit is contained in:
gSpot
2023-02-06 17:27:15 +03:00
parent c1ad1ab10e
commit 5d2c716795
19 changed files with 671 additions and 640 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_VERSION:=0.9.7-0 PKG_VERSION:=1.0-0
LUCI_TITLE:=LuCI support for ruantiblock LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock LUCI_DEPENDS:=+ruantiblock
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
@@ -5,7 +5,18 @@
'require view'; 'require view';
'require view.ruantiblock.tools as tools'; '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({ return view.extend({
pollInterval : L.env.pollinterval,
secToTimeString: function(value) { secToTimeString: function(value) {
let string = ''; let string = '';
if(/^\d+$/.test(value)) { if(/^\d+$/.test(value)) {
@@ -31,11 +42,52 @@ return view.extend({
return string; 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) { makeDnsmasqTable: function(ipDataArray) {
let lines = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`; let lines = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`;
let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' }); let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' });
if(ipDataArray.length > 1) { if(ipDataArray.length > 0) {
lines = []; lines = [];
ipDataArray.forEach((e, i) => { ipDataArray.forEach((e, i) => {
if(e) { if(e) {
@@ -57,18 +109,23 @@ return view.extend({
try { try {
ipTable.insertAdjacentHTML('beforeend', lines); ipTable.insertAdjacentHTML('beforeend', lines);
} catch(err) { } catch(e) {
if(err.name === 'SyntaxError') { if(e.name === 'SyntaxError') {
ui.addNotification(null, 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 => { return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => {
ui.addNotification(null, E('p', _('Unable to execute or read contents') ui.addNotification(null, E('p', _('Unable to execute or read contents')
+ ': %s [ %s ]'.format(e.message, tools.execPath) + ': %s [ %s ]'.format(e.message, tools.execPath)
@@ -81,7 +138,7 @@ return view.extend({
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch(err) {}; } catch(e) {};
if(data.status === 'enabled') { if(data.status === 'enabled') {
let date = document.getElementById('last_blacklist_update.date'); let date = document.getElementById('last_blacklist_update.date');
@@ -111,34 +168,27 @@ return view.extend({
}; };
}; };
if(data.iptables) { let nft_data = this.formatNftJson(data);
for(let [k, v] of Object.entries(data.iptables)) {
if(k === '_dummy') continue;
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) { if(elem) {
elem.textContent = v; elem.textContent = bytes;
}; };
}; };
}; };
if(data.ipset) { if(nft_data.dnsmasq.length > 0) {
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) {
let rdTableWrapper = document.getElementById('rdTableWrapper'); let rdTableWrapper = document.getElementById('rdTableWrapper');
rdTableWrapper.innerHTML = ''; 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 { } else {
if(poll.active()) { if(poll.active()) {
@@ -163,12 +213,12 @@ return view.extend({
try { try {
data = JSON.parse(data); data = JSON.parse(data);
} catch(err) {}; } catch(e) {};
let update_status = null, let update_status = null,
iptables = null, rules = null,
ipset = null, dnsmasq = null,
dnsmasq = null; dnsmasq_u = null;
if(data) { if(data) {
if(data.status === 'enabled') { if(data.status === 'enabled') {
update_status = E('table', { 'class': 'table' }); update_status = E('table', { 'class': 'table' });
@@ -211,8 +261,10 @@ return view.extend({
); );
}; };
if(data.iptables) { let nft_data = this.formatNftJson(data);
let table_iptables = E('table', { 'class': 'table' }, [
if(nft_data.rules) {
let table_rules = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [ E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th left', 'style': 'min-width:33%' }, E('th', { 'class': 'th left', 'style': 'min-width:33%' },
_('Match-set')), _('Match-set')),
@@ -220,76 +272,33 @@ return view.extend({
]), ]),
]); ]);
for(let [k, v] of Object.entries(data.iptables)) { for(let [set, bytes] of nft_data.rules) {
if(k === '_dummy') continue; table_rules.append(
table_iptables.append(
E('tr', { 'class': 'tr' }, [ E('tr', { 'class': 'tr' }, [
E('td', { E('td',{
'class' : 'td left', 'class' : 'td left',
'data-title': _('Match-set'), 'data-title': _('Match-set'),
}, k), }, set + ' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq').replace(/u$/, '-user') + ')'),
E('td', { E('td', {
'class' : 'td left', 'class' : 'td left',
'id' : 'iptables.' + k, 'id' : 'rules.' + set,
'data-title': _('Bytes'), 'data-title': _('Bytes'),
}, v), }, bytes),
]) ])
); );
}; };
iptables = E([ rules = E([
E('h3', {}, _('Iptables rules')), E('h3', {}, _('Nftables rules')),
table_iptables, table_rules,
]); ]);
}; };
if(data.ipset) { if(nft_data.dnsmasq) {
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) {
let rdTableWrapper = E('div', { let rdTableWrapper = E('div', {
'id' : 'rdTableWrapper', 'id' : 'rdTableWrapper',
'style': 'width:100%' 'style': 'width:100%'
}, this.makeDnsmasqTable(data.dnsmasq)); }, this.makeDnsmasqTable(nft_data.dnsmasq));
dnsmasq = E([ dnsmasq = E([
E('h3', {}, _('Dnsmasq')), 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 { } else {
update_status = E('em', {}, _('Status') + ' : ' + _('disabled')); 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-node' }, update_status)
), ),
E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, iptables) E('div', { 'class': 'cbi-section-node' }, rules)
),
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, ipset)
), ),
E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasq) E('div', { 'class': 'cbi-section-node' }, dnsmasq)
), ),
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasq_u)
),
]); ]);
}, },
@@ -284,7 +284,7 @@ return view.extend({
btn_destroy.onclick = L.bind(this.dialogDestroy, this); btn_destroy.onclick = L.bind(this.dialogDestroy, this);
layout_append(btn_destroy, _('Shutdown'), 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, [ this.setAppStatus(status_array, [
status_string, status_string,
@@ -8,11 +8,11 @@
'require view.ruantiblock.tools as tools'; 'require view.ruantiblock.tools as tools';
return view.extend({ 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) { if(empty && array.length === 0) {
elem.depends(key, '_dummy'); elem.depends(key, '_dummy');
} else { } else {
@@ -111,18 +111,17 @@ return view.extend({
s.anonymous = true; s.anonymous = true;
s.addremove = false; s.addremove = false;
/* Main settings tab */ /* Main settings tab */
s.tab('main_settings', _('Main settings')); s.tab('main_settings', _('Main settings'));
// PROXY_MODE // PROXY_MODE
if(this.appStatusCode == 1 || this.appStatusCode == 2) {
o = s.taboption('main_settings', form.ListValue, 'proxy_mode', o = s.taboption('main_settings', form.ListValue, 'proxy_mode',
_('Proxy mode')); _('Proxy mode'));
o.value('1', 'Tor'); o.value('1', 'Tor');
o.value('2', 'VPN'); o.value('2', 'VPN');
o.value('3', _('Transparent proxy')); o.value('3', _('Transparent proxy'));
};
// PROXY_LOCAL_CLIENTS // PROXY_LOCAL_CLIENTS
let proxy_local_clients = s.taboption('main_settings', form.Flag, '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.description = _('Update blacklist after system startup');
o.rmempty = false; o.rmempty = false;
// IPSET_CLEAR_SETS // NFTSET_CLEAR_SETS
o = s.taboption('main_settings', form.Flag, 'ipset_clear_sets', o = s.taboption('main_settings', form.Flag, 'nftset_clear_sets',
_('Clean up ipsets before updating blacklist')); _('Clean up nftsets before updating blacklist'));
o.description = _('Reduces RAM consumption during update'); o.description = _('Reduces RAM consumption during update');
o.rmempty = false; o.rmempty = false;
@@ -160,7 +159,6 @@ return view.extend({
o.datatype = "ip4addr"; 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'));
@@ -223,7 +221,6 @@ return view.extend({
_('Transparent proxy UDP port')); _('Transparent proxy UDP port'));
o.rmempty = false; o.rmempty = false;
o.datatype = "port"; o.datatype = "port";
};
/* Blacklist module tab */ /* Blacklist module tab */
+6 -9
View File
@@ -64,15 +64,15 @@ msgstr "Отмена"
msgid "Changes have been saved." msgid "Changes have been saved."
msgstr "Изменения сохранены." msgstr "Изменения сохранены."
msgid "Clean up ipsets before updating blacklist" msgid "Clean up nftsets before updating blacklist"
msgstr "Очищать ipset'ы перед обновлением блэклиста" msgstr "Очищать nft-сеты перед обновлением блэклиста"
msgid "Command failed" msgid "Command failed"
msgstr "Команда не выполнена" msgstr "Команда не выполнена"
msgid "" msgid ""
"Complete service shutdown, as well as deleting ipsets and blacklist data" "Complete service shutdown, as well as deleting nftsets and blacklist data"
msgstr "Полное выключение службы, а также удаление ipset'ов и данных блэклиста" msgstr "Полное выключение службы, а также удаление nft-сетов и данных блэклиста"
msgid "Contents have been saved." msgid "Contents have been saved."
msgstr "Содержимое сохранено." msgstr "Содержимое сохранено."
@@ -191,11 +191,8 @@ msgstr "Интервал"
msgid "Invalid regular expression" msgid "Invalid regular expression"
msgstr "Неправильное регулярное выражение" msgstr "Неправильное регулярное выражение"
msgid "Ipset" msgid "Nftables rules"
msgstr "Ipset" msgstr "Правила nftables"
msgid "Iptables rules"
msgstr "Правила iptables"
msgid "Last blacklist update" msgid "Last blacklist update"
msgstr "Последнее обновление блэклиста" msgstr "Последнее обновление блэклиста"
@@ -49,14 +49,14 @@ msgstr ""
msgid "Changes have been saved." msgid "Changes have been saved."
msgstr "" msgstr ""
msgid "Clean up ipsets before updating blacklist" msgid "Clean up nftsets before updating blacklist"
msgstr "" msgstr ""
msgid "Command failed" msgid "Command failed"
msgstr "" msgstr ""
msgid "" msgid ""
"Complete service shutdown, as well as deleting ipsets and blacklist data" "Complete service shutdown, as well as deleting nftsets and blacklist data"
msgstr "" msgstr ""
msgid "Contents have been saved." msgid "Contents have been saved."
@@ -171,10 +171,7 @@ msgstr ""
msgid "Invalid regular expression" msgid "Invalid regular expression"
msgstr "" msgstr ""
msgid "Ipset" msgid "Nftables rules"
msgstr ""
msgid "Iptables rules"
msgstr "" msgstr ""
msgid "Last blacklist update" msgid "Last blacklist update"
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-lua PKG_NAME:=ruantiblock-mod-lua
PKG_VERSION:=0.9.7 PKG_VERSION:=1.0
PKG_RELEASE:=0 PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -53,10 +53,11 @@ local Config = Class(nil, {
["BLLIST_GR_EXCLUDED_NETS"] = true, ["BLLIST_GR_EXCLUDED_NETS"] = true,
["BLLIST_MIN_ENTRIES"] = true, ["BLLIST_MIN_ENTRIES"] = true,
["BLLIST_STRIP_WWW"] = true, ["BLLIST_STRIP_WWW"] = true,
["DATA_DIR"] = true, ["NFT_TABLE"] = true,
["IPSET_DNSMASQ"] = true, ["NFT_TABLE_DNSMASQ"] = true,
["IPSET_IP_TMP"] = true, ["NFTSET_CIDR_CFG"] = true,
["IPSET_CIDR_TMP"] = true, ["NFTSET_IP_CFG"] = true,
["NFTSET_DNSMASQ"] = true,
["DNSMASQ_DATA_FILE"] = true, ["DNSMASQ_DATA_FILE"] = true,
["IP_DATA_FILE"] = true, ["IP_DATA_FILE"] = true,
["UPDATE_STATUS_FILE"] = true, ["UPDATE_STATUS_FILE"] = true,
@@ -65,10 +66,10 @@ local Config = Class(nil, {
["ZI_ALL_URL"] = true, ["ZI_ALL_URL"] = true,
["AF_IP_URL"] = true, ["AF_IP_URL"] = true,
["AF_FQDN_URL"] = true, ["AF_FQDN_URL"] = true,
["RA_IP_IPSET_URL"] = true, ["RA_IP_NFTSET_URL"] = true,
["RA_IP_DMASK_URL"] = true, ["RA_IP_DMASK_URL"] = true,
["RA_IP_STAT_URL"] = true, ["RA_IP_STAT_URL"] = true,
["RA_FQDN_IPSET_URL"] = true, ["RA_FQDN_NFTSET_URL"] = true,
["RA_FQDN_DMASK_URL"] = true, ["RA_FQDN_DMASK_URL"] = true,
["RA_FQDN_STAT_URL"] = true, ["RA_FQDN_STAT_URL"] = true,
["RBL_ENCODING"] = true, ["RBL_ENCODING"] = true,
@@ -228,16 +229,16 @@ function BlackListParser:new(t)
instance.records_separator = instance["records_separator"] or self.records_separator instance.records_separator = instance["records_separator"] or self.records_separator
instance.ips_separator = instance["ips_separator"] or self.ips_separator instance.ips_separator = instance["ips_separator"] or self.ips_separator
instance.site_encoding = instance["site_encoding"] or self.site_encoding instance.site_encoding = instance["site_encoding"] or self.site_encoding
instance.ip_records_count = 0
instance.ip_count = 0
instance.ip_subnet_table = {} instance.ip_subnet_table = {}
instance.cidr_count = 0 instance.cidr_count = 0
instance.fqdn_table = {} instance.ip_records_count = 0
instance.ip_count = 0
instance.fqdn_count = 0 instance.fqdn_count = 0
instance.sld_table = {} instance.sld_table = {}
instance.fqdn_records_count = 0 instance.fqdn_records_count = 0
instance.ip_table = {}
instance.cidr_table = {} instance.cidr_table = {}
instance.ip_table = {}
instance.fqdn_table = {}
instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil instance.iconv_handler = iconv and iconv.open(instance.encoding, instance.site_encoding) or nil
return instance return instance
end end
@@ -387,19 +388,34 @@ function BlackListParser:group_cidr_ranges()
end end
function BlackListParser:write_ipset_config() 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 local i = 0
if next(self.ip_table) then
file_handler:write("elements={")
for ipaddr in pairs(self.ip_table) do for ipaddr in pairs(self.ip_table) do
file_handler:write(string.format("add %s %s\n", self.IPSET_IP_TMP, ipaddr)) file_handler:write(string.format("%s,", ipaddr))
i = i + 1 i = i + 1
end end
file_handler:write("};")
end
file_handler:write(
string.format("}\n%s", self.NFTSET_CIDR_CFG)
)
self.ip_records_count = i self.ip_records_count = i
local c = 0 local c = 0
if next(self.cidr_table) then
file_handler:write("elements={")
for cidr in pairs(self.cidr_table) do for cidr in pairs(self.cidr_table) do
file_handler:write(string.format("add %s %s\n", self.IPSET_CIDR_TMP, cidr)) file_handler:write(string.format("%s,", cidr))
c = c + 1 c = c + 1
end end
file_handler:write("};")
end
self.cidr_count = c self.cidr_count = c
file_handler:write("}\n}\n")
file_handler:close() file_handler:close()
end end
@@ -409,7 +425,7 @@ function BlackListParser:write_dnsmasq_config()
if self.BLLIST_ALT_NSLOOKUP then if self.BLLIST_ALT_NSLOOKUP then
file_handler:write(string.format("server=/%s/%s\n", fqdn, self.BLLIST_ALT_DNS_ADDR)) file_handler:write(string.format("server=/%s/%s\n", fqdn, self.BLLIST_ALT_DNS_ADDR))
end 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 end
file_handler:close() file_handler:close()
end end
@@ -465,7 +481,7 @@ end
function BlackListParser:run() function BlackListParser:run()
local return_code = 0 local return_code = 0
if self:get_http_data(self.url) then 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_fqdn_table()
self:optimize_ip_table() self:optimize_ip_table()
if self.BLLIST_SUMMARIZE_IP then if self.BLLIST_SUMMARIZE_IP then
@@ -593,6 +609,7 @@ local Ra = Class(BlackListParser, {
function Ra:download_config(url, file) function Ra:download_config(url, file)
local ret_val = false local ret_val = false
self.current_file_handler = assert(io.open(file, "w"), "Could not open file") 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 if self:get_http_data(url) then
ret_val = true ret_val = true
end end
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-py PKG_NAME:=ruantiblock-mod-py
PKG_VERSION:=0.9.7 PKG_VERSION:=1.0
PKG_RELEASE:=0 PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -37,10 +37,11 @@ class Config:
"BLLIST_GR_EXCLUDED_NETS", "BLLIST_GR_EXCLUDED_NETS",
"BLLIST_MIN_ENTRIES", "BLLIST_MIN_ENTRIES",
"BLLIST_STRIP_WWW", "BLLIST_STRIP_WWW",
"DATA_DIR", "NFT_TABLE",
"IPSET_DNSMASQ", "NFT_TABLE_DNSMASQ",
"IPSET_IP_TMP", "NFTSET_CIDR_CFG",
"IPSET_CIDR_TMP", "NFTSET_IP_CFG",
"NFTSET_DNSMASQ",
"DNSMASQ_DATA_FILE", "DNSMASQ_DATA_FILE",
"IP_DATA_FILE", "IP_DATA_FILE",
"UPDATE_STATUS_FILE", "UPDATE_STATUS_FILE",
@@ -49,10 +50,10 @@ class Config:
"ZI_ALL_URL", "ZI_ALL_URL",
"AF_IP_URL", "AF_IP_URL",
"AF_FQDN_URL", "AF_FQDN_URL",
"RA_IP_IPSET_URL", "RA_IP_NFTSET_URL",
"RA_IP_DMASK_URL", "RA_IP_DMASK_URL",
"RA_IP_STAT_URL", "RA_IP_STAT_URL",
"RA_FQDN_IPSET_URL", "RA_FQDN_NFTSET_URL",
"RA_FQDN_DMASK_URL", "RA_FQDN_DMASK_URL",
"RA_FQDN_STAT_URL", "RA_FQDN_STAT_URL",
"RBL_ENCODING", "RBL_ENCODING",
@@ -131,18 +132,18 @@ class FieldValueError(ParserError):
class BlackListParser(Config): class BlackListParser(Config):
def __init__(self): def __init__(self):
self.ip_pattern = re.compile("(([0-9]{1,3}[.]){3})[0-9]{1,3}") self.ip_pattern = re.compile(r"(([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.cidr_pattern = re.compile(r"([0-9]{1,3}[.]){3}[0-9]{1,3}/[0-9]{1,2}")
self.fqdn_pattern = re.compile( 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) re.U)
self.www_pattern = re.compile("^www[0-9]?[.]") self.www_pattern = re.compile(r"^www[0-9]?[.]")
self.cyr_pattern = re.compile("[а-яё]", re.U) self.cyr_pattern = re.compile(r"[а-яё]", re.U)
self.fqdn_set = {} self.cidr_set = set()
self.sld_dict = {}
self.ip_set = {} self.ip_set = {}
self.ip_subnet_dict = {} self.ip_subnet_dict = {}
self.cidr_set = set() self.fqdn_set = {}
self.sld_dict = {}
self.cidr_count = 0 self.cidr_count = 0
self.ip_count = 0 self.ip_count = 0
self.output_fqdn_count = 0 self.output_fqdn_count = 0
@@ -256,7 +257,7 @@ class BlackListParser(Config):
subnet = self._get_subnet(i) subnet = self._get_subnet(i)
if subnet in self.BLLIST_GR_EXCLUDED_NETS or ( if subnet in self.BLLIST_GR_EXCLUDED_NETS or (
not self.BLLIST_IP_LIMIT 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 self.ip_set[i] = subnet
@@ -496,18 +497,31 @@ class WriteConfigFiles(Config):
def write_ipset_config(self, ip_set, cidr_set): def write_ipset_config(self, ip_set, cidr_set):
with open(self.IP_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler: with open(self.IP_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler:
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: for i in ip_set:
file_handler.write(f"add {self.IPSET_IP_TMP} {i}\n") 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: for i in cidr_set:
file_handler.write(f"add {self.IPSET_CIDR_TMP} {i}\n") file_handler.write(f"{i},")
file_handler.write("};")
file_handler.write("}\n}\n")
def write_dnsmasq_config(self, fqdn_set): def write_dnsmasq_config(self, fqdn_set):
with open(self.DNSMASQ_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler: with open(self.DNSMASQ_DATA_FILE, "wt", buffering=self.write_buffer) as file_handler:
for fqdn in fqdn_set: for fqdn in fqdn_set:
file_handler.write( 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 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): def write_update_status_file(self, ip_count, cidr_count, output_fqdn_count):
with open(self.UPDATE_STATUS_FILE, "wt") as file_handler: with open(self.UPDATE_STATUS_FILE, "wt") as file_handler:
+3 -3
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock PKG_NAME:=ruantiblock
PKG_VERSION:=0.9.7 PKG_VERSION:=1.0
PKG_RELEASE:=0 PKG_RELEASE:=0
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -17,7 +17,7 @@ define Package/$(PKG_NAME)
TITLE:=Ruantiblock TITLE:=Ruantiblock
URL:=https://github.com/gSpotx2f/ruantiblock_openwrt URL:=https://github.com/gSpotx2f/ruantiblock_openwrt
PKGARCH:=all PKGARCH:=all
DEPENDS:=+wget +ipset +kmod-ipt-ipset +dnsmasq-full DEPENDS:=+wget +dnsmasq-full
endef endef
define Package/$(PKG_NAME)/description define Package/$(PKG_NAME)/description
@@ -45,7 +45,7 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/ruantiblock/scripts $(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/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/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_DIR) $(1)/usr/bin
$(INSTALL_BIN) ./files/usr/bin/ruantiblock $(1)/usr/bin/ruantiblock $(INSTALL_BIN) ./files/usr/bin/ruantiblock $(1)/usr/bin/ruantiblock
endef endef
+1 -1
View File
@@ -2,7 +2,7 @@
config main 'config' config main 'config'
option proxy_mode '1' option proxy_mode '1'
option proxy_local_clients '1' option proxy_local_clients '1'
option ipset_clear_sets '1' option nftset_clear_sets '1'
option allowed_hosts_mode '0' option allowed_hosts_mode '0'
option if_vpn 'tun0' option if_vpn 'tun0'
option tor_trans_port '9040' option tor_trans_port '9040'
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh /etc/rc.common #!/bin/sh /etc/rc.common
START=96 START=99
STOP=01 STOP=01
APP_NAME="ruantiblock" APP_NAME="ruantiblock"
@@ -1,7 +1,7 @@
### Настройки ruantiblock ### ### Настройки ruantiblock ###
### Директория данных (генерируемые конфиги dnsmasq, ipset и пр.) ### Директория данных (генерируемые конфиги dnsmasq, nftset и пр.)
DATA_DIR="/tmp/ruantiblock" DATA_DIR="/tmp/ruantiblock"
### Директория модулей ### Директория модулей
MODULES_DIR="/usr/libexec/ruantiblock" MODULES_DIR="/usr/libexec/ruantiblock"
@@ -12,12 +12,12 @@ DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart"
### Директория для html-страницы статуса (не используется в OpenWrt) ### Директория для html-страницы статуса (не используется в OpenWrt)
HTML_DIR="/www" HTML_DIR="/www"
### Режим обработки пакетов в правилах iptables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) ### Режим обработки пакетов в правилах nftables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси)
PROXY_MODE=1 PROXY_MODE=1
### Применять правила проксификации для трафика локальных сервисов роутера (0 - off, 1 - on) ### Применять правила проксификации для трафика локальных сервисов роутера (0 - выкл, 1 - вкл)
PROXY_LOCAL_CLIENTS=1 PROXY_LOCAL_CLIENTS=1
### Удаление записей из основных сетов перед началом заполнения временных сетов при обновлении (для освобождения оперативной памяти перед заполнением сетов) (0 - off, 1 - on) ### Удаление записей сетов перед началом обновления (для освобождения оперативной памяти перед обновлением сетов) (0 - выкл, 1 - вкл)
IPSET_CLEAR_SETS=0 NFTSET_CLEAR_SETS=0
### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке) ### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке)
ALLOWED_HOSTS_MODE=0 ALLOWED_HOSTS_MODE=0
### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15)
@@ -26,7 +26,7 @@ ALLOWED_HOSTS_LIST=""
IF_VPN="tun0" IF_VPN="tun0"
### Порт прозрачного прокси Tor (параметр TransPort в torrc) ### Порт прозрачного прокси Tor (параметр TransPort в torrc)
TOR_TRANS_PORT=9040 TOR_TRANS_PORT=9040
### Отправлять в Tor UDP-трафик (0 - off, 1 - on) ### Отправлять в Tor UDP-трафик (0 - вкл, 1 - выкл)
TOR_ALLOW_UDP=0 TOR_ALLOW_UDP=0
### DNS-сервер для резолвинга в домене .onion (Tor) ### DNS-сервер для резолвинга в домене .onion (Tor)
ONION_DNS_ADDR="127.0.0.1#9053" ONION_DNS_ADDR="127.0.0.1#9053"
@@ -36,9 +36,9 @@ VPN_PKTS_MARK=8
T_PROXY_PORT_TCP=1100 T_PROXY_PORT_TCP=1100
### UDP порт прокси в режиме прозрачного прокси ### UDP порт прокси в режиме прозрачного прокси
T_PROXY_PORT_UDP=1100 T_PROXY_PORT_UDP=1100
### Отправлять в прозрачный прокси UDP-трафик (0 - off, 1 - on) ### Отправлять в прозрачный прокси UDP-трафик (0 - вкл, 1 - выкл)
T_PROXY_ALLOW_UDP=0 T_PROXY_ALLOW_UDP=0
### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - off, 1 - on) ### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл)
### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок
### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8)
### Можно комментировать строки (#) ### Можно комментировать строки (#)
@@ -47,14 +47,22 @@ ADD_USER_ENTRIES=0
USER_ENTRIES_DNS="" USER_ENTRIES_DNS=""
### Файл пользовательских записей ### Файл пользовательских записей
USER_ENTRIES_FILE="/etc/ruantiblock/user_entries" USER_ENTRIES_FILE="/etc/ruantiblock/user_entries"
### Запись событий в syslog (0 - off, 1 - on) ### Запись событий в syslog (0 - выкл, 1 - вкл)
ENABLE_LOGGING=1 ENABLE_LOGGING=1
### Html-страница с инфо о текущем статусе (0 - off, 1 - on) (не используется в OpenWrt) ### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt)
ENABLE_HTML_INFO=0 ENABLE_HTML_INFO=0
### Максимальное кол-во элементов списка ipset ### метка для отбора пакетов в VPN туннель
IPSET_MAXELEM=2000000 VPN_PKTS_MARK=8
### Таймаут для записей в сете $IPSET_DNSMASQ ### Максимальное кол-во элементов списка nftables
IPSET_DNSMASQ_TIMEOUT=3600 #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 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_PRESET=""
### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит ### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит
BLLIST_MIN_ENTRIES=3000 BLLIST_MIN_ENTRIES=3000
### Лимит ip адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества ip-адресов пренадлежащих этой сети (0 - off) ### Лимит ip адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества ip-адресов пренадлежащих этой сети (0 - выкл)
BLLIST_IP_LIMIT=0 BLLIST_IP_LIMIT=0
### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162." ### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162."
BLLIST_GR_EXCLUDED_NETS="" BLLIST_GR_EXCLUDED_NETS=""
@@ -78,29 +86,29 @@ BLLIST_GR_EXCLUDED_NETS=""
BLLIST_SUMMARIZE_IP=0 BLLIST_SUMMARIZE_IP=0
### Группировать идущие подряд подсети /24 в диапазоны CIDR ### Группировать идущие подряд подсети /24 в диапазоны CIDR
BLLIST_SUMMARIZE_CIDR=0 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 BLLIST_IP_FILTER=0
### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) ### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
BLLIST_IP_FILTER_TYPE=0 BLLIST_IP_FILTER_TYPE=0
### Файл с шаблонами ip для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) ### Файл с шаблонами ip для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку)
BLLIST_IP_FILTER_FILE="/etc/ruantiblock/ip_filter" BLLIST_IP_FILTER_FILE="/etc/ruantiblock/ip_filter"
### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - off) ### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - выкл)
BLLIST_SD_LIMIT=16 BLLIST_SD_LIMIT=16
### SLD не подлежащие группировке при оптимизации (через пробел) ### 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" 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}$") ### Не группировать SLD попадающие под выражения (через пробел) ("[.][a-z]{2,3}[.][a-z]{2}$")
BLLIST_GR_EXCLUDED_MASKS="" BLLIST_GR_EXCLUDED_MASKS=""
### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - off, 1 - on) ### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - выкл, 1 - вкл)
BLLIST_FQDN_FILTER=0 BLLIST_FQDN_FILTER=0
### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) ### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
BLLIST_FQDN_FILTER_TYPE=0 BLLIST_FQDN_FILTER_TYPE=0
### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) ### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку)
BLLIST_FQDN_FILTER_FILE="/etc/ruantiblock/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 BLLIST_STRIP_WWW=1
### Преобразование кириллических доменов в punycode (0 - off, 1 - on) ### Преобразование кириллических доменов в punycode (0 - выкл, 1 - вкл)
BLLIST_ENABLE_IDN=0 BLLIST_ENABLE_IDN=0
### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - off, 1 - on) ### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - выкл, 1 - вкл)
BLLIST_ALT_NSLOOKUP=0 BLLIST_ALT_NSLOOKUP=0
### Альтернативный DNS-сервер ### Альтернативный DNS-сервер
BLLIST_ALT_DNS_ADDR="8.8.8.8" 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" #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_IP_URL="https://antifilter.download/list/allyouneed.lst"
AF_FQDN_URL="https://antifilter.download/list/domains.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_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/ip/ruantiblock.dnsmasq" 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/ip/update_status" 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/fqdn/ruantiblock.ip" 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/fqdn/ruantiblock.dnsmasq" 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/fqdn/update_status" RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/update_status"
RBL_ENCODING="" RBL_ENCODING=""
ZI_ENCODING="CP1251" ZI_ENCODING="CP1251"
AF_ENCODING="" AF_ENCODING=""
@@ -1,6 +1,6 @@
AWK_CMD="awk" AWK_CMD="awk"
UCI_SECTION="ruantiblock.config" 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" ' eval `uci show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
BEGIN { BEGIN {
@@ -1,66 +1,36 @@
Info() { Info() {
local _set local _update_status
if CheckStatus; then
printf "{\"status\":\"enabled\",\"last_blacklist_update\":{"
if [ -f "$UPDATE_STATUS_FILE" ]; then if [ -f "$UPDATE_STATUS_FILE" ]; then
$AWK_CMD '{ _update_status=`$AWK_CMD '{
if(NF < 4) if(NF < 4)
print "\"status\":false"; printf "{\"status\":false}";
else else
print "\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\""; printf "{\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}";
}' "$UPDATE_STATUS_FILE" }' "$UPDATE_STATUS_FILE"`
else else
printf "\"status\":false" _update_status="{\"status\":false}"
fi fi
printf "}," NftListBllistChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" '
IptListBllistChain | $AWK_CMD '
BEGIN { BEGIN {
printf "\"iptables\":{" rules_str = "";
} }
{ {
if(NR > 2) rules_str = rules_str $0;
printf "\""(($10 == "!") ? $12 : $11)"\":\""$2"\",";
} }
END { END {
printf "\"_dummy\":false},"; if(NR == 0) {
}' printf "{\"status\": \"disabled\"}";
printf "\"ipset\":{"; exit 1;
for _set in "$IPSET_ALLOWED_HOSTS" "$IPSET_ONION" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" } else {
do printf "{\"status\":\"enabled\",\"last_blacklist_update\":%s,\"rules\":%s", UPDATE_STATUS, rules_str;
$IPSET_CMD list "$_set" -terse | $AWK_CMD -F ": " ' exit 0;
{
if($1 ~ /^Name/) {
printf "\""$2"\":[";
}
else if($1 ~ /^Size in memory/) {
printf "\""$2"\",";
}
else if($1 ~ /^Number of entries/) {
printf "\""$2"\"],";
}; };
}' }'
done if [ $? -eq 0 ]; then
$IPSET_CMD list "$IPSET_DNSMASQ" | $AWK_CMD -F ": " ' printf ",\"dnsmasq\":"
{ $NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ" 2> /dev/null
if($1 ~ /^Name/) { printf ",\"dnsmasq_u\":"
printf "\""$2"\":["; $NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ_USER" 2> /dev/null
} printf "}"
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\"}"
fi fi
} }
@@ -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"
}
@@ -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 $?
}
+216 -195
View File
@@ -15,7 +15,7 @@ export LANGUAGE="en"
CONFIG_DIR="/etc/${NAME}" CONFIG_DIR="/etc/${NAME}"
CONFIG_FILE="${CONFIG_DIR}/${NAME}.conf" CONFIG_FILE="${CONFIG_DIR}/${NAME}.conf"
export DATA_DIR="/var/${NAME}" export DATA_DIR="${CONFIG_DIR}/var"
export MODULES_DIR="/usr/libexec/${NAME}" export MODULES_DIR="/usr/libexec/${NAME}"
### Дополнительный конфиг dnsmasq с FQDN записями блэклиста ### Дополнительный конфиг dnsmasq с FQDN записями блэклиста
export DNSMASQ_DATA_FILE="/var/dnsmasq.d/${NAME}.dnsmasq" export DNSMASQ_DATA_FILE="/var/dnsmasq.d/${NAME}.dnsmasq"
@@ -26,12 +26,12 @@ export HTML_DIR="/www"
########################## Default Settings ############################ ########################## Default Settings ############################
### Режим обработки пакетов в правилах iptables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси) ### Режим обработки пакетов в правилах nftables (1 - Tor, 2 - VPN, 3 - Прозрачный прокси)
export PROXY_MODE=1 export PROXY_MODE=1
### Применять правила проксификации для трафика локальных сервисов роутера (0 - off, 1 - on) ### Применять правила проксификации для трафика локальных сервисов роутера (0 - выкл, 1 - вкл)
export PROXY_LOCAL_CLIENTS=1 export PROXY_LOCAL_CLIENTS=1
### Удаление записей из основных сетов перед началом заполнения временных сетов при обновлении (для освобождения оперативной памяти перед заполнением сетов) (0 - off, 1 - on) ### Удаление записей сетов перед началом обновления (для освобождения оперативной памяти перед обновлением сетов) (0 - выкл, 1 - вкл)
export IPSET_CLEAR_SETS=0 export NFTSET_CLEAR_SETS=0
### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке) ### Режим фильтра хостов которым разрешено обходить блокировки (0 - выкл., 1 - только адреса из списка, 2 - любые адреса кроме присутствующих в списке)
export ALLOWED_HOSTS_MODE=0 export ALLOWED_HOSTS_MODE=0
### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15) ### Список IP адресов хостов для фильтра, через пробел (прим.: 192.168.0.10 192.168.0.15)
@@ -40,7 +40,7 @@ export ALLOWED_HOSTS_LIST=""
export IF_VPN="tun0" export IF_VPN="tun0"
### Порт прозрачного прокси Tor (параметр TransPort в torrc) ### Порт прозрачного прокси Tor (параметр TransPort в torrc)
export TOR_TRANS_PORT=9040 export TOR_TRANS_PORT=9040
### Отправлять в Tor UDP-трафик (0 - off, 1 - on) ### Отправлять в Tor UDP-трафик (0 - выкл, 1 - вкл)
export TOR_ALLOW_UDP=0 export TOR_ALLOW_UDP=0
### DNS-сервер для резолвинга в домене .onion (Tor) ### DNS-сервер для резолвинга в домене .onion (Tor)
export ONION_DNS_ADDR="127.0.0.1#9053" export ONION_DNS_ADDR="127.0.0.1#9053"
@@ -50,9 +50,9 @@ export VPN_PKTS_MARK=8
export T_PROXY_PORT_TCP=1100 export T_PROXY_PORT_TCP=1100
### UDP порт прокси в режиме прозрачного прокси ### UDP порт прокси в режиме прозрачного прокси
export T_PROXY_PORT_UDP=1100 export T_PROXY_PORT_UDP=1100
### Отправлять в прозрачный прокси UDP-трафик (0 - off, 1 - on) ### Отправлять в прозрачный прокси UDP-трафик (0 - выкл, 1 - вкл)
export T_PROXY_ALLOW_UDP=0 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 (одна на строку). Эти записи будут добавлены в список блокировок ### В $DATA_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок
### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8) ### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8)
### Можно комментировать строки (#) ### Можно комментировать строки (#)
@@ -61,14 +61,20 @@ export ADD_USER_ENTRIES=0
export USER_ENTRIES_DNS="" export USER_ENTRIES_DNS=""
### Файл пользовательских записей ### Файл пользовательских записей
export USER_ENTRIES_FILE="${CONFIG_DIR}/user_entries" export USER_ENTRIES_FILE="${CONFIG_DIR}/user_entries"
### Запись событий в syslog (0 - off, 1 - on) ### Запись событий в syslog (0 - выкл, 1 - вкл)
export ENABLE_LOGGING=1 export ENABLE_LOGGING=1
### Html-страница с инфо о текущем статусе (0 - off, 1 - on) (не используется в OpenWrt) ### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt)
export ENABLE_HTML_INFO=0 export ENABLE_HTML_INFO=0
### Максимальное кол-во элементов списка ipset ### Максимальное кол-во элементов списка nftables
export IPSET_MAXELEM=2000000 export NFTSET_MAXELEM_CIDR=65535
### Таймаут для записей в сете $IPSET_DNSMASQ export NFTSET_MAXELEM_IP=1000000
export IPSET_DNSMASQ_TIMEOUT=3600 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 export MODULE_RUN_ATTEMPTS=3
### Таймаут между попытками обновления ### Таймаут между попытками обновления
@@ -84,7 +90,7 @@ export BLLIST_MODULE=""
export BLLIST_PRESET="" export BLLIST_PRESET=""
### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит ### В случае если из источника получено менее указанного кол-ва записей, то обновления списков не происходит
export BLLIST_MIN_ENTRIES=3000 export BLLIST_MIN_ENTRIES=3000
### Лимит IP адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества IP адресов пренадлежащих этой сети (0 - off) ### Лимит IP адресов. При достижении, в конфиг ipset будет добавлена вся подсеть /24 вместо множества IP адресов пренадлежащих этой сети (0 - выкл)
export BLLIST_IP_LIMIT=0 export BLLIST_IP_LIMIT=0
### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162." ### Подсети класса C (/24). IP адреса из этих подсетей не группируются при оптимизации (записи д.б. в виде: 68.183.221. 149.154.162. и пр.). Прим.: "68.183.221. 149.154.162."
export BLLIST_GR_EXCLUDED_NETS="" export BLLIST_GR_EXCLUDED_NETS=""
@@ -92,29 +98,29 @@ export BLLIST_GR_EXCLUDED_NETS=""
export BLLIST_SUMMARIZE_IP=0 export BLLIST_SUMMARIZE_IP=0
### Группировать идущие подряд подсети /24 в диапазоны CIDR ### Группировать идущие подряд подсети /24 в диапазоны CIDR
export BLLIST_SUMMARIZE_CIDR=0 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 export BLLIST_IP_FILTER=0
### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) ### Тип фильтра IP (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
export BLLIST_IP_FILTER_TYPE=0 export BLLIST_IP_FILTER_TYPE=0
### Файл с шаблонами IP для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) ### Файл с шаблонами IP для опции BLLIST_IP_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку)
export BLLIST_IP_FILTER_FILE="${CONFIG_DIR}/ip_filter" export BLLIST_IP_FILTER_FILE="${CONFIG_DIR}/ip_filter"
### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - off) ### Лимит субдоменов для группировки. При достижении, в конфиг dnsmasq будет добавлен весь домен 2-го ур-ня вместо множества субдоменов (0 - выкл)
export BLLIST_SD_LIMIT=16 export BLLIST_SD_LIMIT=16
### SLD не подлежащие группировке при оптимизации (через пробел) ### 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" 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}$") ### Не группировать SLD попадающие под выражения (через пробел) ("[.][a-z]{2,3}[.][a-z]{2}$")
export BLLIST_GR_EXCLUDED_MASKS="" 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 export BLLIST_FQDN_FILTER=0
### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) ### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
export BLLIST_FQDN_FILTER_TYPE=0 export BLLIST_FQDN_FILTER_TYPE=0
### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку) ### Файл с шаблонами FQDN для опции BLLIST_FQDN_FILTER (каждый шаблон в отдельной строке. # в первом символе строки - комментирует строку)
export BLLIST_FQDN_FILTER_FILE="${CONFIG_DIR}/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 export BLLIST_STRIP_WWW=1
### Преобразование кириллических доменов в punycode (0 - off, 1 - on) ### Преобразование кириллических доменов в punycode (0 - выкл, 1 - вкл)
export BLLIST_ENABLE_IDN=0 export BLLIST_ENABLE_IDN=0
### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - off, 1 - on) ### Перенаправлять DNS-запросы на альтернативный DNS-сервер для заблокированных FQDN (0 - выкл, 1 - вкл)
export BLLIST_ALT_NSLOOKUP=0 export BLLIST_ALT_NSLOOKUP=0
### Альтернативный DNS-сервер ### Альтернативный DNS-сервер
export BLLIST_ALT_DNS_ADDR="8.8.8.8" 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 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_IP_URL="https://antifilter.download/list/allyouneed.lst"
export AF_FQDN_URL="https://antifilter.download/list/domains.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_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/ip/ruantiblock.dnsmasq" 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/ip/update_status" 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/fqdn/ruantiblock.ip" 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/fqdn/ruantiblock.dnsmasq" 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/fqdn/update_status" export RA_FQDN_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.0/fqdn/update_status"
export RBL_ENCODING="" export RBL_ENCODING=""
export ZI_ENCODING="CP1251" export ZI_ENCODING="CP1251"
export AF_ENCODING="" export AF_ENCODING=""
@@ -141,18 +147,19 @@ export RA_ENCODING=""
### External config ### External config
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE" [ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
CONFIG_SCRIPT="${CONFIG_DIR}/scripts/config_script" SCRIPTS_DIR="${CONFIG_DIR}/scripts"
START_SCRIPT="${CONFIG_DIR}/scripts/start_script" CONFIG_SCRIPT="${SCRIPTS_DIR}/config_script"
STOP_SCRIPT="${CONFIG_DIR}/scripts/stop_script" START_SCRIPT="${SCRIPTS_DIR}/start_script"
STOP_SCRIPT="${SCRIPTS_DIR}/stop_script"
### Config script ### Config script
[ -f "$CONFIG_SCRIPT" ] && . "$CONFIG_SCRIPT" [ -f "$CONFIG_SCRIPT" ] && . "$CONFIG_SCRIPT"
### Utilities ### Utilities
AWK_CMD="awk" AWK_CMD="awk"
IPSET_CMD=`which ipset` NFT_CMD=`which nft`
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! Ipset doesn't exists" >&2 echo " Error! Nftables doesn't exists" >&2
exit 1 exit 1
fi fi
LOGGER_CMD=`which logger` LOGGER_CMD=`which logger`
@@ -168,24 +175,33 @@ if [ $? -ne 0 ]; then
fi fi
WGET_PARAMS="--no-check-certificate -q -O" WGET_PARAMS="--no-check-certificate -q -O"
export IP_DATA_FILE="${DATA_DIR}/${NAME}.ip" export IP_DATA_FILE="${DATA_DIR}/${NAME}.ip"
export IPSET_ALLOWED_HOSTS="r_allowed_ip" export NFT_TABLE="ip r"
export IPSET_ONION="r_onion" export NFT_TABLE_DNSMASQ="4#ip#r"
export IPSET_CIDR="rc" export NFTSET_ALLOWED_HOSTS="allowed_ip"
export IPSET_CIDR_TMP="${IPSET_CIDR}t" export NFTSET_ONION="onion"
export IPSET_IP="ri" export NFTSET_CIDR="c"
export IPSET_IP_TMP="${IPSET_IP}t" export NFTSET_IP="i"
export IPSET_DNSMASQ="rd" 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" 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" START_PID_FILE="/var/run/${NAME}_start.pid"
TOKEN_FILE="/var/run/${NAME}.token" TOKEN_FILE="/var/run/${NAME}.token"
export HTML_OUTPUT="${HTML_DIR}/${NAME}.html" export HTML_OUTPUT="${HTML_DIR}/${NAME}.html"
IPT_FUNCTIONS="${CONFIG_DIR}/scripts/ipt_functions" NFT_FUNCTIONS="${SCRIPTS_DIR}/nft_functions"
INFO_OUTPUT_FUNCTION="${CONFIG_DIR}/scripts/info_output" INFO_OUTPUT_FUNCTION="${SCRIPTS_DIR}/info_output"
######################### External functions ########################### ######################### External functions ###########################
. "$IPT_FUNCTIONS" . "$NFT_FUNCTIONS"
if [ -f "$INFO_OUTPUT_FUNCTION" ]; then if [ -f "$INFO_OUTPUT_FUNCTION" ]; then
. "$INFO_OUTPUT_FUNCTION" . "$INFO_OUTPUT_FUNCTION"
else else
@@ -196,13 +212,13 @@ fi
Help() { Help() {
cat << EOF 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 start : Start
force-start : Removing the pid-file before running force-start : Removing the pid-file before running
stop : Stop stop : Stop
destroy : Stop + destroy ipsets and clear all data files destroy : Stop + remove nft table and clear all data files
restart : Restart restart : Restart
reload : Renew iptables configuration reload : Renew nftables configuration
update : Update blacklist update : Update blacklist
force-update : Force update blacklist force-update : Force update blacklist
data-files : Create ${IP_DATA_FILE} & ${DNSMASQ_DATA_FILE} (without network functions) data-files : Create ${IP_DATA_FILE} & ${DNSMASQ_DATA_FILE} (without network functions)
@@ -216,10 +232,12 @@ cat << EOF
`basename $0` stop `basename $0` stop
`basename $0` destroy `basename $0` destroy
`basename $0` restart `basename $0` restart
`basename $0` reload
`basename $0` update `basename $0` update
`basename $0` force-update `basename $0` force-update
`basename $0` data-files `basename $0` data-files
`basename $0` status `basename $0` status
`basename $0` raw-status
`basename $0` html-info `basename $0` html-info
EOF EOF
} }
@@ -259,86 +277,68 @@ DnsmasqRestart() {
eval `echo "$DNSMASQ_RESTART_CMD"` eval `echo "$DNSMASQ_RESTART_CMD"`
} }
IsIpsetExists() { FlushNftSets() {
$IPSET_CMD list "$1" -terse &> /dev/null
return $?
}
FlushIpSets() {
local _set local _set
for _set in "$@" for _set in "$@"
do do
IsIpsetExists "$_set" && $IPSET_CMD flush "$_set" $NFT_CMD flush set $NFT_TABLE "$_set" &> /dev/null
done done
} }
DestroyIpsets() { AddNftSets() {
local _set local _hosts
for _set in "$@" $NFT_CMD add set $NFT_TABLE "$NFTSET_CIDR" { type "$NFTSET_CIDR_TYPE"\; size $NFTSET_MAXELEM_CIDR\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
do $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\; }
IsIpsetExists "$_set" && $IPSET_CMD destroy "$_set" $NFT_CMD add set $NFT_TABLE "$NFTSET_IP" { type "$NFTSET_IP_TYPE"\; size $NFTSET_MAXELEM_IP\; policy "$NFTSET_POLICY_IP"\; }
done $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"\; }
FillAllowedHostsSet() { $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"\; }
local _entry $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_IP"\; }
for _entry in $ALLOWED_HOSTS_LIST _hosts=`printf "$ALLOWED_HOSTS_LIST" | $AWK_CMD '{gsub(/[ ]+/, ",", $0); printf $0;}'`
do if [ -n "$_hosts" ]; then
$IPSET_CMD add "$IPSET_ALLOWED_HOSTS" "$_entry" $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_hosts" }
done
}
AddIptRules() {
IptMainAdd
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
IptLocalClientsAdd
fi fi
} }
DelIptRules() { UpdateBllistSets() {
IptLocalClientsDel if [ -f "$IP_DATA_FILE" ]; then
IptMainDel 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() { SetNetConfig() {
local _set $NFT_CMD add table $NFT_TABLE
### Создание списков ipset. Проверка на наличие списка с таким же именем, если нет, то создается новый AddNftSets
for _set in "$IPSET_CIDR_TMP" "$IPSET_CIDR" AddNftRules
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
} }
DropNetConfig() { DropNetConfig() {
DelIptRules DeleteNftRules
FlushIpSets "$IPSET_ALLOWED_HOSTS" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" "$IPSET_ONION" FlushNftSets "$NFTSET_ALLOWED_HOSTS" "$NFTSET_CIDR" "$NFTSET_CIDR_USER" "$NFTSET_IP" "$NFTSET_IP_USER" "$NFTSET_DNSMASQ" "$NFTSET_DNSMASQ_USER" "$NFTSET_ONION"
} }
FillIpsets() { DestroyNetConfig() {
local _set $NFT_CMD flush table $NFT_TABLE &> /dev/null
### Заполнение списков ipset $IPSET_IP и $IPSET_CIDR. Сначала restore загружает во временные списки, а затем swap из временных добавляет в основные $NFT_CMD delete table $NFT_TABLE &> /dev/null
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
} }
ClearDataFiles() { ClearDataFiles() {
@@ -350,19 +350,8 @@ ClearDataFiles() {
} }
CheckStatus() { CheckStatus() {
local _set _ipset_return=0 _return_code=1 NftReturnStatus
if [ "$1" = "ipsets" ]; then return $?
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
} }
PreStartCheck() { PreStartCheck() {
@@ -377,43 +366,64 @@ AddUserEntries() {
if [ -f "$USER_ENTRIES_FILE" -a -s "$USER_ENTRIES_FILE" ]; then if [ -f "$USER_ENTRIES_FILE" -a -s "$USER_ENTRIES_FILE" ]; then
$AWK_CMD 'BEGIN { $AWK_CMD 'BEGIN {
null=""; null="";
while((getline ip_string <ENVIRON["IP_DATA_FILE"]) > 0) { fqdn_array[0]=null;
split(ip_string, ip_string_arr, " "); ip_list="";
ip_data_array[ip_string_arr[3]]=null; cidr_list="";
};
close(ENVIRON["IP_DATA_FILE"]);
while((getline fqdn_string <ENVIRON["DNSMASQ_DATA_FILE"]) > 0) {
split(fqdn_string, fqdn_string_arr, "/");
fqdn_data_array[fqdn_string_arr[2]]=null;
};
close(ENVIRON["DNSMASQ_DATA_FILE"]);
} }
function writeIpsetEntries(val, set) {
printf "add %s %s\n", set, val >> ENVIRON["IP_DATA_FILE"];
};
function writeDNSData(val, dns) { 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"]; 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 "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]*$|#)/) { ($0 !~ /^([\040\011]*$|#)/) {
if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}$/ && !($0 in ip_data_array)) if($0 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}$/) {
writeIpsetEntries($0, ENVIRON["IPSET_IP_TMP"]); ip_list=ip_list $0 ",";
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 ~ /^[0-9]{1,3}([.][0-9]{1,3}){3}[\057][0-9]{1,2}$/) {
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)) cidr_list=cidr_list $0 ",";
writeDNSData($1, $2); }
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" }' "$USER_ENTRIES_FILE"
fi fi
fi fi
} }
ToggleUPIDFile() {
if [ "$1" = "del" ]; then
rm -f "$U_PID_FILE"
else
echo "$$" > "$U_PID_FILE"
fi
}
GetDataFiles() { GetDataFiles() {
local _return_code=1 _attempt=1 _update_string local _return_code=1 _attempt=1 _update_string
PreStartCheck PreStartCheck
echo "$$" > "$UPDATE_PID_FILE"
if [ -n "$BLLIST_PRESET" -a -n "$BLLIST_MODULE" ]; then if [ -n "$BLLIST_PRESET" -a -n "$BLLIST_MODULE" ]; then
while : while :
do do
@@ -445,16 +455,16 @@ GetDataFiles() {
_return_code=0 _return_code=0
else else
_return_code=2 _return_code=2
rm -f "$UPDATE_PID_FILE"
return $_return_code return $_return_code
fi fi
if [ $_return_code -eq 0 ]; then
if [ "$PROXY_MODE" = "2" -o "$PROXY_MODE" = "3" ]; then if [ "$PROXY_MODE" = "2" -o "$PROXY_MODE" = "3" ]; then
printf "\n" >> "$DNSMASQ_DATA_FILE" printf "\n" >> "$DNSMASQ_DATA_FILE"
else else
### Запись для .onion в $DNSMASQ_DATA_FILE ### Запись для .onion в $DNSMASQ_DATA_FILE
printf "server=/onion/%s\nipset=/onion/%s\n" "${ONION_DNS_ADDR}" "${IPSET_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 fi
rm -f "$UPDATE_PID_FILE"
return $_return_code return $_return_code
} }
@@ -464,22 +474,25 @@ MakeToken() {
Update() { Update() {
local _return_code=0 local _return_code=0
if CheckStatus ipsets; then if CheckStatus; then
: :
else else
echo " ${NAME} ${1} - Error! ${NAME} does not running or another error has occurred" >&2 echo " ${NAME} ${1} - Error! ${NAME} does not running or another error has occurred" >&2
return 1 return 1
fi fi
MakeToken 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 echo " ${NAME} ${1} - Error! Another instance of update is already running" >&2
MakeLogRecord "err" "${1} - Error! Another instance of update is already running" MakeLogRecord "err" "${1} - Error! Another instance of update is already running"
_return_code=2 _return_code=2
else else
ToggleUPIDFile add
echo " ${NAME} ${1}..." echo " ${NAME} ${1}..."
MakeLogRecord "notice" "${1}..." MakeLogRecord "notice" "${1}..."
if [ "$IPSET_CLEAR_SETS" = "1" ]; then if [ "$NFTSET_CLEAR_SETS" = "1" ]; then
FlushIpSets "$IPSET_IP" "$IPSET_CIDR" "$IPSET_DNSMASQ" 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 fi
GetDataFiles GetDataFiles
case $? in case $? in
@@ -488,8 +501,8 @@ Update() {
MakeLogRecord "notice" "Blacklist updated" MakeLogRecord "notice" "Blacklist updated"
;; ;;
2) 2)
echo " Blacklist update error!" >&2 echo " Error! Blacklist update error" >&2
MakeLogRecord "err" "Blacklist update error!" MakeLogRecord "err" "Error! Blacklist update error"
_return_code=1 _return_code=1
;; ;;
*) *)
@@ -498,10 +511,13 @@ Update() {
_return_code=1 _return_code=1
;; ;;
esac esac
FlushIpSets "$IPSET_DNSMASQ" FlushNftSets "$NFTSET_DNSMASQ" "$NFTSET_ONION" "$NFTSET_DNSMASQ_USER"
FillIpsets if [ "$ADD_USER_ENTRIES" != "1" ]; then
_return_code=$? FlushNftSets "$NFTSET_CIDR_USER" "$NFTSET_IP_USER"
fi
UpdateBllistSets
DnsmasqRestart DnsmasqRestart
ToggleUPIDFile del
fi fi
MakeToken MakeToken
return $_return_code return $_return_code
@@ -524,10 +540,8 @@ Start() {
MakeLogRecord "info" "${1}..." MakeLogRecord "info" "${1}..."
DropNetConfig &> /dev/null DropNetConfig &> /dev/null
SetNetConfig SetNetConfig
FillAllowedHostsSet
PreStartCheck PreStartCheck
FillIpsets UpdateBllistSets
_return_code=$?
### Start-script ### Start-script
[ -x "$START_SCRIPT" ] && $START_SCRIPT > /dev/null 2>&1 & [ -x "$START_SCRIPT" ] && $START_SCRIPT > /dev/null 2>&1 &
fi fi
@@ -565,48 +579,55 @@ Reload() {
sleep 1 sleep 1
done done
echo " ${NAME} reload..." echo " ${NAME} reload..."
DelIptRules &> /dev/null DeleteNftRules &> /dev/null
AddIptRules &> /dev/null AddNftRules &> /dev/null
MakeToken MakeToken
} }
Status() { Status() {
local _set local _update_status _vpn_error
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 if [ -f "$UPDATE_STATUS_FILE" ]; then
$AWK_CMD '{ _update_status=`$AWK_CMD '{
update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")"; update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")";
printf "\n Last blacklist update: %s\n", update_string; printf "Last blacklist update: %s", update_string;
}' "$UPDATE_STATUS_FILE" }' "$UPDATE_STATUS_FILE"`
else else
printf "\n Last blacklist update: No data\n" _update_status="Last blacklist update: No data"
fi fi
if [ "$PROXY_MODE" = "2" ] && ! IptVpnRouteStatus; then if [ "$PROXY_MODE" = "2" ] && ! NftVpnRouteStatus; then
printf "\n \033[1;31mVPN ROUTING ERROR! (NEED THE RESTART)\033[m\n" _vpn_error="\033[1;31mVPN ROUTING ERROR! (NEED THE RESTART)\033[m"
fi fi
printf "\n \033[4mIptables rules\033[m:\n\n" NftListBllistChain 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v VPN_ERROR="$_vpn_error" '
IptListBllistChain | $AWK_CMD ' BEGIN {
{ rules_str = "";
if(NR > 2) { nftset = "";
printf " Match-set: %s\n Bytes: %s\n\n", $11, $2; 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";
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";
}; };
}
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;
}' }'
done
else
printf "\n \033[1m${NAME} status\033[m: \033[1mDisabled\033[m\n\n"
exit 2
fi
} }
StatusOutput() { StatusOutput() {
@@ -683,10 +704,10 @@ case "$1" in
;; ;;
destroy) destroy)
Stop "$1" &> /dev/null Stop "$1" &> /dev/null
DestroyIpsets "$IPSET_ALLOWED_HOSTS" "$IPSET_CIDR_TMP" "$IPSET_CIDR" "$IPSET_IP_TMP" "$IPSET_IP" "$IPSET_DNSMASQ" "$IPSET_ONION" DestroyNetConfig
ClearDataFiles ClearDataFiles
return_code=$? return_code=$?
rm -f "$UPDATE_PID_FILE" "$START_PID_FILE" ToggleUPIDFile del
DnsmasqRestart DnsmasqRestart
StatusOutput StatusOutput
;; ;;
@@ -696,7 +717,7 @@ case "$1" in
StatusOutput StatusOutput
;; ;;
data-files) 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 echo " ${NAME} - Error! Another instance of update is already running" >&2
exit 2 exit 2
else else
@@ -716,7 +737,7 @@ case "$1" in
if [ -e "$START_PID_FILE" ]; then if [ -e "$START_PID_FILE" ]; then
return_code=3 return_code=3
echo 3 echo 3
elif [ -e "$UPDATE_PID_FILE" ]; then elif [ -e "$U_PID_FILE" ]; then
return_code=4 return_code=4
echo 4 echo 4
else else
@@ -730,7 +751,7 @@ case "$1" in
esac esac
;; ;;
vpn-route-status) vpn-route-status)
IptVpnRouteStatus NftVpnRouteStatus
return_code=$? return_code=$?
echo $return_code echo $return_code
;; ;;