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
PKG_VERSION:=0.9.7-0
PKG_VERSION:=1.0-0
LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock
LUCI_PKGARCH:=all
@@ -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 = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`;
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)
),
]);
},
@@ -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,
@@ -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"), '<code>ipaddress#port</code>');
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"), '<code>ipaddress#port</code>');
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 */
+6 -9
View File
@@ -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 "Последнее обновление блэклиста"
@@ -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"
+1 -1
View File
@@ -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 <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -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
+1 -1
View File
@@ -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 <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -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:
+3 -3
View File
@@ -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 <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -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
+1 -1
View File
@@ -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'
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh /etc/rc.common
START=96
START=99
STOP=01
APP_NAME="ruantiblock"
@@ -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=""
@@ -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 {
@@ -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
}
@@ -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 $?
}
+227 -206
View File
@@ -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 <ENVIRON["IP_DATA_FILE"]) > 0) {
split(ip_string, ip_string_arr, " ");
ip_data_array[ip_string_arr[3]]=null;
};
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"]);
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
;;