v2.0. Multi proxy for user entries. TProxy support.

This commit is contained in:
gSpot
2024-11-03 02:20:45 +03:00
parent 8184a68fe8
commit 06219e9328
42 changed files with 2185 additions and 764 deletions
@@ -7,11 +7,12 @@ PROXY_MODE=1
BLACKLIST=0
LUA_MODULE=0
LUCI_APP=1
HTTPS_DNS_PROXY=1
OWRT_VERSION="22.03"
RUAB_VERSION="0.9.7-1"
RUAB_MOD_LUA_VERSION="0.9.7-1"
RUAB_LUCI_APP_VERSION="0.9.7-0"
OWRT_VERSION="current"
RUAB_VERSION="2.0.0-r1"
RUAB_MOD_LUA_VERSION="2.0.0-r1"
RUAB_LUCI_APP_VERSION="2.0.0-1"
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master"
PKG_DIR="/tmp"
@@ -27,33 +28,36 @@ URL_MOD_LUA_PKG="${BASE_URL}/${OWRT_VERSION}/ruantiblock-mod-lua_${RUAB_MOD_LUA_
URL_LUCI_APP_PKG="${BASE_URL}/${OWRT_VERSION}/luci-app-ruantiblock_${RUAB_LUCI_APP_VERSION}_all.ipk"
URL_LUCI_APP_RU_PKG="${BASE_URL}/${OWRT_VERSION}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk"
### tor
URL_TORRC="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/0.9/tor/etc/tor/torrc"
URL_TORRC="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master/tor/etc/tor/torrc"
### ruantiblock-mod-lua
URL_LUA_IPTOOL="https://raw.githubusercontent.com/gSpotx2f/iptool-lua/master/5.1/iptool.lua"
URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua"
### Local files
RUAB_CFG_DIR="${PREFIX}/etc/ruantiblock"
CONFIG_DIR="${PREFIX}/etc/ruantiblock"
USER_LISTS_DIR="${CONFIG_DIR}/user_lists"
EXEC_DIR="${PREFIX}/usr/bin"
BACKUP_DIR="${RUAB_CFG_DIR}/autoinstall.bak.`date +%s`"
BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`"
### packages
FILE_RUAB_PKG="${PKG_DIR}/ruantiblock_${RUAB_VERSION}_all.ipk"
FILE_MOD_LUA_PKG="${PKG_DIR}/ruantiblock-mod-lua_${RUAB_MOD_LUA_VERSION}_all.ipk"
FILE_LUCI_APP_PKG="${PKG_DIR}/luci-app-ruantiblock_${RUAB_LUCI_APP_VERSION}_all.ipk"
FILE_LUCI_APP_RU_PKG="${PKG_DIR}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk"
### ruantiblock
FILE_CONFIG="${RUAB_CFG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${RUAB_CFG_DIR}/fqdn_filter"
FILE_IP_FILTER="${RUAB_CFG_DIR}/ip_filter"
FILE_USER_ENTRIES="${RUAB_CFG_DIR}/user_entries"
FILE_CONFIG="${CONFIG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${CONFIG_DIR}/fqdn_filter"
FILE_IP_FILTER="${CONFIG_DIR}/ip_filter"
FILE_USER_ENTRIES="${CONFIG_DIR}/user_entries"
FILE_BYPASS_ENTRIES="${CONFIG_DIR}/bypass_entries"
FILE_GR_EXCLUDED_SLD="${CONFIG_DIR}/gr_excluded_sld"
FILE_GR_EXCLUDED_NETS="${CONFIG_DIR}/gr_excluded_nets"
FILE_UCI_CONFIG="${PREFIX}/etc/config/ruantiblock"
FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
### tor
FILE_TORRC="${PREFIX}/etc/tor/torrc"
### ruantiblock-mod-lua
FILE_LUA_IPTOOL="${PREFIX}/usr/lib/lua/iptool.lua"
#FILE_LUA_IPTOOL="${PREFIX}/usr/lib/lua/iptool.lua"
FILE_LUA_IDN="${PREFIX}/usr/lib/lua/idn.lua"
AWK_CMD="awk"
@@ -121,9 +125,13 @@ BackupFile() {
BackupCurrentConfig() {
local _file
MakeDir "$BACKUP_DIR"
for _file in "$FILE_CONFIG" "$FILE_FQDN_FILTER" "$FILE_IP_FILTER" "$FILE_USER_ENTRIES" "$FILE_UCI_CONFIG" "$FILE_TORRC"
for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"`
do
[ -e "$_file" ] && cp -f "$_file" "${BACKUP_DIR}/`basename ${_file}`"
cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}"
done
for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC"
do
[ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`"
done
}
@@ -136,11 +144,6 @@ AppStop() {
}
AppStart() {
modprobe ip_set > /dev/null
modprobe ip_set_hash_ip > /dev/null
modprobe ip_set_hash_net > /dev/null
modprobe ip_set_list_set > /dev/null
modprobe xt_set > /dev/null
$FILE_INIT_SCRIPT start
}
@@ -174,10 +177,11 @@ InstallPackages() {
InstallBaseConfig() {
_return_code=1
InstallPackages "ipset" "kmod-ipt-ipset" "dnsmasq-full"
InstallPackages "dnsmasq-full" "kmod-nft-tproxy"
RemoveFile "$FILE_RUAB_PKG" > /dev/null
DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null
_return_code=$?
# костыль для остановки сервиса, который запускается автоматически после установки пакета!
AppStop
return $_return_code
}
@@ -219,6 +223,7 @@ InstallTorConfig() {
TorrcSettings
$UCI_CMD set ruantiblock.config.proxy_mode="1"
$UCI_CMD commit ruantiblock
# dnsmasq rebind protection
$UCI_CMD set dhcp.@dnsmasq[0].rebind_domain='onion'
$UCI_CMD commit dhcp
}
@@ -227,7 +232,6 @@ InstallLuaModule() {
InstallPackages "lua" "luasocket" "luasec" "luabitop"
RemoveFile "$FILE_MOD_LUA_PKG" > /dev/null
DlFile "$URL_MOD_LUA_PKG" "$FILE_MOD_LUA_PKG" && $OPKG_CMD install "$FILE_MOD_LUA_PKG"
FileExists "$FILE_LUA_IPTOOL" || DlFile "$URL_LUA_IPTOOL" "$FILE_LUA_IPTOOL"
FileExists "$FILE_LUA_IDN" || DlFile "$URL_LUA_IDN" "$FILE_LUA_IDN"
$UCI_CMD set ruantiblock.config.bllist_module="/usr/libexec/ruantiblock/ruab_parser.lua"
$UCI_CMD commit ruantiblock
@@ -243,6 +247,10 @@ InstallLuciApp() {
/etc/init.d/uhttpd restart
}
InstallHttpsDnsProxy() {
InstallPackages "https-dns-proxy" "luci-app-https-dns-proxy" "luci-i18n-https-dns-proxy-ru"
}
PrintBold() {
printf "\033[1m - ${1}\033[0m\n"
}
@@ -279,7 +287,7 @@ ConfirmProxyMode() {
ConfirmBlacklist() {
local _reply
printf " Select blacklist [ 1: User entries only | 2: RKN blacklist ] (default: 1, quit: q) > "
printf " Select blacklist [ 1: User entries only | 2: Full blacklist ] (default: 1, quit: q) > "
read _reply
case $_reply in
1|"")
@@ -343,6 +351,28 @@ ConfirmLuciApp() {
esac
}
ConfirmHttpsDnsProxy() {
local _reply
printf " Would you like to install the https-dns-proxy? [ y | n ] (default: y, quit: q) > "
read _reply
case $_reply in
y|Y|"")
HTTPS_DNS_PROXY=1
break
;;
n|N)
HTTPS_DNS_PROXY=0
break
;;
q|Q)
printf "Bye...\n"; exit 0
;;
*)
InputError ConfirmHttpsDnsProxy
;;
esac
}
ConfirmProcessing() {
local _reply
printf " Next, the installation will begin... Continue? [ y | n ] (default: y, quit: q) > "
@@ -364,11 +394,13 @@ ConfirmProxyMode
ConfirmBlacklist
#ConfirmLuaModule
ConfirmLuciApp
ConfirmHttpsDnsProxy
ConfirmProcessing
AppStop
PrintBold "Updating packages list..."
UpdatePackagesList
PrintBold "Saving current configuration..."
#BackupCurrentConfig
PrintBold "Installing basic configuration..."
InstallBaseConfig
if [ $? -eq 0 ]; then
@@ -388,7 +420,7 @@ if [ $? -eq 0 ]; then
fi
if [ $BLACKLIST = 2 ]; then
PrintBold "Set RKN blacklist..."
PrintBold "Set full blacklist..."
EnableBlacklist
fi
@@ -402,6 +434,11 @@ if [ $? -eq 0 ]; then
InstallLuciApp
fi
if [ $HTTPS_DNS_PROXY = 1 ]; then
PrintBold "Installing https-dns-proxy..."
InstallHttpsDnsProxy
fi
RunAtStartup
SetCronTask
else
@@ -4,19 +4,27 @@ PREFIX=""
### Local files
RUAB_CFG_DIR="${PREFIX}/etc/ruantiblock"
CONFIG_DIR="${PREFIX}/etc/ruantiblock"
USER_LISTS_DIR="${CONFIG_DIR}/user_lists"
EXEC_DIR="${PREFIX}/usr/bin"
BACKUP_DIR="${RUAB_CFG_DIR}/autoinstall.bak.`date +%s`"
BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`"
HTDOCS_VIEW="${PREFIX}/www/luci-static/resources/view"
HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock"
CRONTAB_FILE="/etc/crontabs/root"
DATA_DIR="/tmp/ruantiblock"
DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/ruantiblock.dnsmasq"
DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq"
DNSMASQ_DATA_FILE_TMP="${DNSMASQ_DATA_FILE}.tmp"
DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq"
SCRIPTS_DIR="/usr/share/ruantiblock"
MODULES_DIR="/usr/libexec/ruantiblock"
### ruantiblock
FILE_CONFIG="${RUAB_CFG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${RUAB_CFG_DIR}/fqdn_filter"
FILE_IP_FILTER="${RUAB_CFG_DIR}/ip_filter"
FILE_USER_ENTRIES="${RUAB_CFG_DIR}/user_entries"
FILE_CONFIG="${CONFIG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${CONFIG_DIR}/fqdn_filter"
FILE_IP_FILTER="${CONFIG_DIR}/ip_filter"
FILE_USER_ENTRIES="${CONFIG_DIR}/user_entries"
FILE_BYPASS_ENTRIES="${CONFIG_DIR}/bypass_entries"
FILE_GR_EXCLUDED_SLD="${CONFIG_DIR}/gr_excluded_sld"
FILE_GR_EXCLUDED_NETS="${CONFIG_DIR}/gr_excluded_nets"
FILE_UCI_CONFIG="${PREFIX}/etc/config/ruantiblock"
FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
@@ -52,9 +60,13 @@ RemoveFile() {
BackupCurrentConfig() {
local _file
MakeDir "$BACKUP_DIR"
for _file in "$FILE_CONFIG" "$FILE_FQDN_FILTER" "$FILE_IP_FILTER" "$FILE_USER_ENTRIES" "$FILE_UCI_CONFIG" "$FILE_TORRC"
for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"`
do
[ -e "$_file" ] && cp -f "$_file" "${BACKUP_DIR}/`basename ${_file}`"
cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}"
done
for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC"
do
[ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`"
done
}
@@ -67,10 +79,12 @@ DisableStartup() {
}
RemoveCronTask() {
$AWK_CMD -v FILE_MAIN_SCRIPT="$FILE_MAIN_SCRIPT" '$0 !~ FILE_MAIN_SCRIPT {
print $0;
}' "$CRONTAB_FILE" > "${CRONTAB_FILE}.tmp" && mv -f "${CRONTAB_FILE}.tmp" "$CRONTAB_FILE"
/etc/init.d/cron restart
if [ -e "$CRONTAB_FILE" ]; then
$AWK_CMD -v FILE_MAIN_SCRIPT="$FILE_MAIN_SCRIPT" '$0 !~ FILE_MAIN_SCRIPT {
print $0;
}' "$CRONTAB_FILE" > "${CRONTAB_FILE}.tmp" && mv -f "${CRONTAB_FILE}.tmp" "$CRONTAB_FILE"
/etc/init.d/cron restart
fi
}
RestoreTorConfig() {
@@ -85,9 +99,25 @@ RestoreTorConfig() {
RemoveAppFiles() {
RestoreTorConfig
$OPKG_CMD remove ruantiblock-mod-py ruantiblock-mod-lua luci-i18n-ruantiblock-ru luci-app-ruantiblock ruantiblock
RemoveFile "$FILE_UCI_CONFIG"
RemoveFile "$FILE_CONFIG"
RemoveFile "$FILE_FQDN_FILTER"
RemoveFile "$FILE_IP_FILTER"
RemoveFile "$FILE_USER_ENTRIES"
RemoveFile "$FILE_BYPASS_ENTRIES"
RemoveFile "$FILE_GR_EXCLUDED_SLD"
RemoveFile "$FILE_GR_EXCLUDED_NETS"
RemoveFile "${FILE_UCI_CONFIG}.opkg"
RemoveFile "${FILE_CONFIG}.opkg"
RemoveFile "${FILE_FQDN_FILTER}.opkg"
RemoveFile "${FILE_IP_FILTER}.opkg"
RemoveFile "${FILE_USER_ENTRIES}.opkg"
RemoveFile "${FILE_BYPASS_ENTRIES}.opkg"
rm -f "$DNSMASQ_DATA_FILE"
rm -f "$DNSMASQ_DATA_FILE_BYPASS"
rm -rf "$DATA_DIR"/*
rmdir "${RUAB_CFG_DIR}/scripts" 2> /dev/null
rm -rf "$USER_LISTS_DIR"
rmdir "$SCRIPTS_DIR" "$MODULES_DIR" 2> /dev/null
rmdir "$HTDOCS_RUAB" 2> /dev/null
rm -f /tmp/luci-modulecache/* /tmp/luci-indexcache*
/etc/init.d/rpcd restart
@@ -117,7 +147,7 @@ ConfirmRemove() {
ConfirmRemove
AppStop
#BackupCurrentConfig
BackupCurrentConfig
DisableStartup
RemoveCronTask
RemoveAppFiles
+3 -1
View File
@@ -4,7 +4,9 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.6.0-r1
PKG_NAME:=luci-app-ruantiblock
PKG_VERSION:=2.0.0
PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock
LUCI_PKGARCH:=all
@@ -10,26 +10,26 @@ return view.extend({
currentCrontabLines: [],
toDD: function(n){
toDD(n){
return String(n).replace(/^(\d)$/, "0$1");
},
cronStatusString: function(s) {
cronStatusString(s) {
return s || _('No Sсhedule');
},
stringifyRuabTasks: function(str_array) {
stringifyRuabTasks(str_array) {
let current_tasks = str_array.filter(s => s.match(this.crontabRegexp));
return current_tasks.join('\n');
},
setCronStatus: function(value) {
setCronStatus(value) {
document.getElementById('cron_status').value = this.cronStatusString(value);
document.getElementById("btn_cron_del").style.visibility = (value) ?
'visible' : 'hidden';
},
writeCronFile: function() {
writeCronFile() {
let btn_cron_add = document.getElementById('btn_cron_add');
let btn_cron_del = document.getElementById('btn_cron_del');
let crontab_string = this.currentCrontabLines.join('\n');
@@ -53,17 +53,17 @@ return view.extend({
});
},
delRuabShedules: function() {
delRuabShedules() {
this.currentCrontabLines = this.currentCrontabLines.filter(
s => s.match(this.crontabRegexp) ? false : true);
},
delCronSchedule: function(ev) {
delCronSchedule(ev) {
this.delRuabShedules();
return this.writeCronFile();
},
setCronSchedule: function(ev) {
setCronSchedule(ev) {
let hour_interval = document.getElementById('cron_hour_interval').value;
let day_interval = document.getElementById('cron_day_interval').value;
let hour = document.getElementById('cron_hour').value;
@@ -88,7 +88,7 @@ return view.extend({
return this.writeCronFile();
},
onchangeHourInterval: function(e) {
onchangeHourInterval(e) {
let value = e.target.value;
let bool = (value != '');
let cron_hour = document.getElementById('cron_hour');
@@ -106,7 +106,7 @@ return view.extend({
};
},
load: function() {
load() {
return fs.lines(tools.crontabFile).catch(e => {
ui.addNotification(null, E('p', _('Unable to read the contents')
+ ': %s [ %s ]'.format(
@@ -115,7 +115,7 @@ return view.extend({
});
},
render: function(content) {
render(content) {
this.currentCrontabLines = content;
let current_task = this.stringifyRuabTasks(content);
@@ -17,7 +17,7 @@ document.head.append(E('style', {'type': 'text/css'},
return view.extend({
pollInterval : L.env.pollinterval,
secToTimeString: function(value) {
secToTimeString(value) {
let string = '';
if(/^\d+$/.test(value)) {
value = Number(value);
@@ -42,50 +42,103 @@ 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 && e.match.left && e.match.left.payload) {
set = e.match.right.replace('@', '');
}
else if(e.counter) {
bytes = e.counter.bytes;
};
});
output.rules.push([ set, bytes ]);
};
formatNftJson(data) {
let output = { 'sink': [] };
if(data.sink.nftables && data.sink.nftables.length > 1) {
let rules = [];
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 ]);
};
});
for(let i of data.sink.nftables) {
if(i.rule) {
let instance = (i.rule.comment === ' ') ? '-main-' : i.rule.comment;
let proto, bytes;
i.rule.expr.forEach(e => {
if(e.match && e.match.left && e.match.left.meta && e.match.left.meta.key && e.match.left.meta.key == "l4proto") {
proto = e.match.right;
}
else if(e.counter) {
bytes = e.counter.bytes;
};
});
rules.push([ instance, proto, bytes ]);
} else {
continue;
};
return sArray;
};
if(data.dnsmasq) {
output.dnsmasq = parseDnsmasqData('dnsmasq');
if(rules.length > 0) {
output.sink = rules;
};
if(data.dnsmasq_bypass) {
output.dnsmasq_bypass = parseDnsmasqData('dnsmasq_bypass');
};
if(data.sink_local && data.sink_local.nftables && data.sink_local.nftables.length > 1) {
output.sink_local = [];
let rules = [];
for(let i of data.sink_local.nftables) {
if(i.rule) {
let instance = (i.rule.comment === ' ') ? '-main-' : i.rule.comment;
let proto, bytes;
i.rule.expr.forEach(e => {
if(e.match && e.match.left && e.match.left.meta && e.match.left.meta.key && e.match.left.meta.key == "l4proto") {
proto = e.match.right;
}
else if(e.counter) {
bytes = e.counter.bytes;
};
});
rules.push([ instance, proto, bytes ]);
} else {
continue;
};
};
if(rules.length > 0) {
output.sink_local = rules;
};
};
function parseDnsmasqData(set) {
let sArray = [];
if(set.nftables && set.nftables.length > 1) {
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;
};
if(data.dnsmasq) {
output.dnsmasq = parseDnsmasqData(data.dnsmasq);
};
if(data.dnsmasq_bypass) {
output.dnsmasq_bypass = parseDnsmasqData(data.dnsmasq_bypass);
};
if(data.dnsmasq_user_instances) {
output.dnsmasq_user_instances = [];
if(data.dnsmasq_user_instances && data.dnsmasq_user_instances.length > 1) {
for(let i of data.dnsmasq_user_instances) {
if(i.nftables) {
let name;
i.nftables.forEach(e => {
if(e.set) {
name = e.set.name;
};
});
output.dnsmasq_user_instances.push([ name, parseDnsmasqData(i) ]);
};
};
};
};
return output;
},
makeDnsmasqTable: function(ipDataArray) {
makeDnsmasqTable(ipDataArray, title) {
let lines = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`;
let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' });
@@ -122,6 +175,7 @@ return view.extend({
};
return E([
E('h3', {}, title),
E('div', { 'class': 'log-entries-count' },
`${_('Entries')}: ${ipDataArray.length}`
),
@@ -129,7 +183,7 @@ return view.extend({
]);
},
pollInfo: function() {
pollInfo() {
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)
@@ -174,11 +228,20 @@ return view.extend({
let nft_data = this.formatNftJson(data);
if(nft_data.rules.length > 0) {
for(let [set, bytes] of nft_data.rules) {
let elem = document.getElementById('rules.' + set);
if(nft_data.sink.length > 0) {
for(let i of nft_data.sink) {
let elem = document.getElementById('sink.' + i[0] + '.' + (i[1] || 'all'));
if(elem) {
elem.textContent = bytes;
elem.textContent = i[2];
};
};
};
if(nft_data.sink_local && nft_data.sink_local.length > 0) {
for(let i of nft_data.sink_local) {
let elem = document.getElementById('sink_local.' + i[0] + '.' + (i[1] || 'all'));
if(elem) {
elem.textContent = i[2];
};
};
};
@@ -186,15 +249,16 @@ return view.extend({
let rdTableWrapper = document.getElementById('rdTableWrapper');
if(rdTableWrapper) {
rdTableWrapper.innerHTML = '';
rdTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq));
rdTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq, _('Dnsmasq')));
};
let rdbTableWrapper = document.getElementById('rdbTableWrapper');
if(rdbTableWrapper) {
rdbTableWrapper.innerHTML = '';
rdbTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq_bypass));
let rdsTableWrapper = document.getElementById('rdsTableWrapper');
if(rdsTableWrapper) {
rdsTableWrapper.innerHTML = '';
for(let i of nft_data.dnsmasq_user_instances) {
rdsTableWrapper.append(this.makeDnsmasqTable(i[1], _('Dnsmasq') + ' ' + i[0]));
};
};
} else {
if(poll.active()) {
poll.stop();
@@ -203,7 +267,7 @@ return view.extend({
});
},
load: function() {
load() {
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)
@@ -211,7 +275,7 @@ return view.extend({
})
},
render: function(data) {
render(data) {
if(!data) {
return;
};
@@ -220,11 +284,12 @@ return view.extend({
data = JSON.parse(data);
} catch(e) {};
let update_status = null,
user_entries = null,
rules = null,
dnsmasq = null,
dnsmasqBypass = null;
let update_status = null,
user_entries = null,
sink = null,
sink_local = null,
dnsmasq = null,
dnsmasqUserInstances = null;
if(data) {
if(data.status === 'enabled') {
@@ -285,39 +350,87 @@ return view.extend({
let nft_data = this.formatNftJson(data);
if(nft_data.rules) {
let table_rules = E('table', { 'class': 'table' }, [
if(nft_data.sink) {
let table = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th left', 'style': 'min-width:33%' },
_('Match-set')),
_('Instance')),
E('th', { 'class': 'th left' }, _('Protocol')),
E('th', { 'class': 'th left' }, _('Bytes')),
]),
]);
for(let i of nft_data.sink) {
let instance = i[0];
let proto = (i[1] === undefined) ? _('all') : i[1];
let bytes = i[2];
for(let [set, bytes] of nft_data.rules) {
if(!set) {
if(!instance) {
continue;
};
table_rules.append(
table.append(
E('tr', { 'class': 'tr' }, [
E('td',{
'class' : 'td left',
'data-title': _('Match-set'),
}, set + ((set.length >= 1) ? (
' (' + set.replace(/^c/, 'CIDR').replace(/^i/, 'IP').replace(/^d/, 'dnsmasq').replace(/^bi/, 'bypass IP').replace(/^bd/, 'bypass dnsmasq').replace(/^fproxy/, 'full proxy') + ')'
) : '')),
E('td', {
'class' : 'td left',
'id' : 'rules.' + set,
'data-title': _('Instance'),
}, instance),
E('td', {
'class' : 'td left',
'data-title': _('Protocol'),
}, proto),
E('td', {
'class' : 'td left',
'id' : 'sink.' + instance + '.' + (i[1] || 'all'),
'data-title': _('Bytes'),
}, bytes),
])
);
};
rules = E([
E('h3', {}, _('Nftables rules')),
table_rules,
};
sink = E([
E('h3', {}, _('Transit traffic')),
table,
]);
};
if(nft_data.sink_local) {
let table = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th left', 'style': 'min-width:33%' },
_('Instance')),
E('th', { 'class': 'th left' }, _('Protocol')),
E('th', { 'class': 'th left' }, _('Bytes')),
]),
]);
for(let i of nft_data.sink_local) {
let instance = i[0];
let proto = (i[1] === undefined) ? _('all') : i[1];
let bytes = i[2];
if(!instance) {
continue;
};
table.append(
E('tr', { 'class': 'tr' }, [
E('td', {
'class' : 'td left',
'data-title': _('Instance'),
}, instance),
E('td', {
'class' : 'td left',
'data-title': _('Protocol'),
}, proto),
E('td', {
'class' : 'td left',
'id' : 'sink_local.' + instance + '.' + (i[1] || 'all'),
'data-title': _('Bytes'),
}, bytes),
])
);
};
sink_local = E([
E('h3', {}, _('Local traffic')),
table,
]);
};
@@ -325,24 +438,28 @@ return view.extend({
let rdTableWrapper = E('div', {
'id' : 'rdTableWrapper',
'style': 'width:100%'
}, this.makeDnsmasqTable(nft_data.dnsmasq));
}, this.makeDnsmasqTable(nft_data.dnsmasq, _('Dnsmasq')));
dnsmasq = E([
E('h3', {}, _('Dnsmasq')),
rdTableWrapper,
]);
};
if(nft_data.dnsmasq_bypass) {
let rdbTableWrapper = E('div', {
'id' : 'rdbTableWrapper',
if(nft_data.dnsmasq_user_instances) {
let rdsTableWrapper = E('div', {
'id' : 'rdsTableWrapper',
'style': 'width:100%'
}, this.makeDnsmasqTable(nft_data.dnsmasq_bypass));
});
dnsmasqBypass = E([
E('h3', {}, _('Dnsmasq bypass')),
rdbTableWrapper,
]);
for(let i of nft_data.dnsmasq_user_instances) {
rdsTableWrapper.append(this.makeDnsmasqTable(i[1], _('Dnsmasq') + ' ' + i[0]));
};
if(nft_data.dnsmasq_user_instances.length > 0) {
dnsmasqUserInstances = E([
rdsTableWrapper,
]);
};
};
poll.add(L.bind(this.pollInfo, this), this.pollInterval);
@@ -360,7 +477,7 @@ return view.extend({
E('div', { 'class': 'cbi-section-node' }, update_status)
),
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, rules)
E('div', { 'class': 'cbi-section-node' }, sink)
),
];
@@ -373,16 +490,24 @@ return view.extend({
);
}
if(dnsmasqBypass) {
if(sink_local) {
layout.splice(5, 0,
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasqBypass)
E('div', { 'class': 'cbi-section-node' }, sink_local)
)
);
};
if(dnsmasqUserInstances) {
layout.splice(6, 0,
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasqUserInstances)
)
);
};
if(dnsmasq) {
layout.splice(6, 0,
layout.splice(7, 0,
E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasq)
)
@@ -1,6 +1,7 @@
'use strict';
'require baseclass';
'require fs';
'require ui';
'require view.ruantiblock.log-widget as widget';
return baseclass.extend({
@@ -1,4 +1,5 @@
'use strict';
'require baseclass';
'require fs';
'require poll';
'require uci';
@@ -15,7 +16,121 @@ const btn_style_warning = 'btn cbi-button-negative important'
return view.extend({
statusTokenValue: null,
disableButtons: function(bool, btn, elems=[]) {
dialogDestroy: baseclass.extend({
__init__(context) {
this.context = context;
},
currentDnsmasqCfgDir: null,
dnsmasqCfgDirsSelect: null,
cancelButton : E('button', {
'id' : 'btn_cancel',
'class': btn_style_neutral,
'click': ui.hideModal,
}, _('Cancel')),
load() {
return L.resolveDefault(fs.list(tools.dnsmasqCfgDirsRoot), null);
},
render(data) {
let section = uci.get(tools.appName, 'config');
this.currentDnsmasqCfgDir = section.dnsmasq_cfg_dir;
let available_cfg_dirs = [];
let dnsmasq_cfg_dirs_arr = data;
if(dnsmasq_cfg_dirs_arr) {
dnsmasq_cfg_dirs_arr.forEach(e => {
let fname = e.name;
if(fname.startsWith('dnsmasq')) {
available_cfg_dirs.push([ fname, tools.dnsmasqCfgDirsRoot + '/' + fname ]);
};
});
};
this.dnsmasqCfgDirsSelect = E('select', {
'id' : 'dnsmasq_cfg_dirs_list',
'class': "cbi-input-select",
}),
available_cfg_dirs.forEach(e => {
this.dnsmasqCfgDirsSelect.append(
E('option', { 'value': e[1] }, e[0]));
});
this.dnsmasqCfgDirsSelect.value = this.currentDnsmasqCfgDir;
ui.showModal(this.title, [
E('h4', _('The service will be disabled and all blacklist data will be deleted. Continue?')),
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' },
_('Dnsmasq config directory')),
E('div', { 'class': 'cbi-value-field' }, [
this.dnsmasqCfgDirsSelect,
E('div', { 'class': 'cbi-value-description' },
_('Change dnsmasq config directory')),
]),
]),
]),
E('div', { 'class': 'right' }, [
this.cancelButton,
' ',
E('button', {
'id' : 'btn_apply',
'class': btn_style_warning,
'click': ui.createHandlerFn(this, this.handleApply),
}, _('Shutdown')),
]),
], 'cbi-modal');
},
handleApply(ev) {
this.cancelButton.disabled = true;
return this.context.appAction('destroy').then(() => {
if(this.dnsmasqCfgDirsSelect.value !== this.currentDnsmasqCfgDir) {
uci.set(tools.appName, 'config', 'dnsmasq_cfg_dir',
this.dnsmasqCfgDirsSelect.value);
uci.save();
uci.apply();
};
}).finally(() => {
this.cancelButton.disabled = false;
ui.hideModal();
});
},
error(e) {
ui.showModal(this.title, [
E('div', { 'class': 'cbi-section' },
E('p', {}, _('An error occurred')
+ ': %s'.format(e.message))
),
E('div', { 'class': 'right' },
E('button', {
'class': btn_style_neutral,
'click': ui.hideModal,
}, _('Dismiss'))
),
]);
},
show() {
ui.showModal(null,
E('p', { 'class': 'spinning' }, _('Loading'))
);
this.load().then(content => {
ui.hideModal();
return this.render(content);
}).catch(e => {
ui.hideModal();
return this.error(e);
})
},
}),
disableButtons(bool, btn, elems=[]) {
let btn_start = elems[1] || document.getElementById("btn_start");
let btn_destroy = elems[4] || document.getElementById("btn_destroy");
let btn_enable = elems[2] || document.getElementById("btn_enable");
@@ -31,7 +146,7 @@ return view.extend({
};
},
getAppStatus: function() {
getAppStatus() {
return Promise.all([
fs.exec(tools.execPath, [ 'raw-status' ]),
fs.exec(tools.execPath, [ 'vpn-route-status' ]),
@@ -46,7 +161,7 @@ return view.extend({
});
},
setAppStatus: function(status_array, elems=[], force_app_code) {
setAppStatus(status_array, elems=[], force_app_code) {
let section = uci.get(tools.appName, 'config');
if(!status_array || typeof(section) !== 'object') {
(elems[0] || document.getElementById("status")).innerHTML = tools.makeStatusString(1);
@@ -59,8 +174,7 @@ return view.extend({
let app_status_code = (force_app_code) ? force_app_code : status_array[0].code;
let vpn_route_status_code = status_array[1].code;
let enabled_flag = status_array[2];
let proxy_local_clients = section.proxy_local_clients;
let proxy_mode = section.proxy_mode;
let dnsmasq_cfg_dir = section.dnsmasq_cfg_dir;
let bllist_preset = section.bllist_preset;
let bllist_module = section.bllist_module;
@@ -122,7 +236,6 @@ return view.extend({
(elems[0] || document.getElementById("status")).innerHTML = tools.makeStatusString(
app_status_code,
proxy_mode,
bllist_preset,
bllist_module,
vpn_route_status_code);
@@ -132,7 +245,7 @@ return view.extend({
};
},
serviceAction: function(action, button) {
serviceAction(action, button) {
if(button) {
let elem = document.getElementById(button);
this.disableButtons(true, elem);
@@ -149,7 +262,7 @@ return view.extend({
});
},
appAction: function(action, button) {
appAction(action, button) {
if(button) {
let elem = document.getElementById(button);
this.disableButtons(true, elem);
@@ -167,13 +280,12 @@ return view.extend({
return this.getAppStatus().then(
(status_array) => {
this.setAppStatus(status_array);
ui.hideModal();
}
);
});
},
statusPoll: function() {
statusPoll() {
return fs.read(tools.tokenFile).then(v => {
v = tools.normalizeValue(v);
if(v != this.statusTokenValue) {
@@ -187,48 +299,21 @@ return view.extend({
});
},
dialogDestroy: function(ev) {
ev.target.blur();
let cancel_button = E('button', {
'class': btn_style_neutral,
'click': ui.hideModal,
}, _('Cancel'));
let shutdown_btn = E('button', {
'class': btn_style_warning,
}, _('Shutdown'));
shutdown_btn.onclick = ui.createHandlerFn(this, () => {
cancel_button.disabled = true;
return this.appAction('destroy');
});
ui.showModal(_('Shutdown'), [
E('div', { 'class': 'cbi-section' }, [
E('p', _('The service will be disabled and all blacklist data will be deleted. Continue?')),
]),
E('div', { 'class': 'right' }, [
shutdown_btn,
' ',
cancel_button,
])
]);
},
load: function() {
load() {
return this.getAppStatus();
},
render: function(status_array) {
render(status_array) {
if(!status_array) {
return;
};
let section = uci.get(tools.appName, 'config');
let proxy_local_clients = (typeof(section) === 'object') ?
section.proxy_local_clients : null;
this.statusTokenValue = (Array.isArray(status_array)) ?
tools.normalizeValue(status_array[4]) : null;
let dialog_destroy = new this.dialogDestroy(this);
let status_string = E('div', {
'id' : 'status',
'name' : 'status',
@@ -281,7 +366,7 @@ return view.extend({
'name' : 'btn_destroy',
'class': btn_style_negative,
}, _('Shutdown'));
btn_destroy.onclick = L.bind(this.dialogDestroy, this);
btn_destroy.onclick = () => dialog_destroy.show();
layout_append(btn_destroy, _('Shutdown'),
_('Complete service shutdown, as well as deleting nftsets and blacklist data'));
@@ -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(elem, key, array, empty=true) {
if(empty && array.length === 0) {
elem.depends(key, '_dummy');
} else {
@@ -20,20 +20,82 @@ return view.extend({
};
},
validateIpPort: function(section, value) {
validateIpPort(section, value) {
return (/^$|^([0-9]{1,3}\.){3}[0-9]{1,3}(#[\d]{2,5})?$/.test(value)) ? true : _('Expecting:')
+ ` ${_('One of the following:')}\n - ${_('valid IP address')}\n - ${_('valid address#port')}\n`;
},
validateUrl: function(section, value) {
validateUrl(section, value) {
return (/^$|^https?:\/\/[\w.-]+(:[0-9]{2,5})?[\w\/~.&?+=-]*$/.test(value)) ? true : _('Expecting:')
+ ` ${_('valid URL')}\n`;
},
load: function() {
CBIBlockFileEdit: form.Value.extend({
__name__ : 'CBI.BlockFileEdit',
__init__(map, section, ctx, id, file, title, description, callback) {
this.map = map;
this.section = section;
this.ctx = ctx;
this.id = id,
this.optional = true;
this.rmempty = true;
this.file = file;
this.title = title;
this.description = description;
this.callback = callback;
this.content = '';
},
cfgvalue(section_id, option) {
return this.content;
},
formvalue(section_id) {
let value = this.content;
let textarea = document.getElementById('widget.file_edit.content.' + this.id);
if(textarea) {
value = textarea.value.trim().replace(/\r\n/g, '\n') + '\n';
};
return value;
},
write(section_id, formvalue) {
return fs.write(this.file, formvalue).then(rc => {
ui.addNotification(null, E('p', _('Contents have been saved.')),
'info');
if(this.callback) {
return this.callback(rc);
};
}).catch(e => {
ui.addNotification(null, E('p', _('Unable to save the contents')
+ ': %s'.format(e.message)));
});
},
load() {
return L.resolveDefault(fs.read(this.file), '').then(c => {
this.content = c;
});
},
renderWidget(section_id, option_index, cfgvalue) {
return E('textarea', {
'id' : 'widget.file_edit.content.' + this.id,
'class' : 'cbi-input-textarea',
'style' : 'width:100% !important;resize:vertical !important',
'rows' : 10,
'wrap' : 'off',
'spellcheck': 'false',
}, cfgvalue);
},
}),
load() {
return Promise.all([
L.resolveDefault(fs.exec(tools.execPath, [ 'raw-status' ]), 1),
L.resolveDefault(fs.list(tools.parsersDir), null),
L.resolveDefault(fs.list(tools.dnsmasqCfgDirsRoot), null),
uci.load(tools.appName),
]).catch(e => {
ui.addNotification(null, E('p', _('Unable to read the contents')
@@ -43,14 +105,14 @@ return view.extend({
});
},
render: function(data) {
render(data) {
if(!data) {
return;
};
this.appStatusCode = data[0].code;
let p_dir_arr = data[1];
let curent_module = uci.get(tools.appName, 'config', 'bllist_module');
let curent_preset = uci.get(tools.appName, 'config', 'bllist_preset');
this.appStatusCode = data[0].code;
let p_dir_arr = data[1];
let curent_module = uci.get(tools.appName, 'config', 'bllist_module');
let curent_preset = uci.get(tools.appName, 'config', 'bllist_preset');
if(p_dir_arr) {
p_dir_arr.forEach(e => {
@@ -129,7 +191,7 @@ return view.extend({
'<br /><code>#comment<br />domain.net<br />anotherdomain.com</code>'
);
let m, s, o;
let m, s, o, ss;
m = new form.Map(tools.appName, _('Ruantiblock') + ' - ' + _('Settings'));
@@ -140,39 +202,32 @@ return view.extend({
/* Main settings tab */
s.tab('main_settings', _('Main settings'));
// PROXY_MODE
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',
_('Apply proxy rules to router application traffic'));
proxy_local_clients.rmempty = false;
s.tab('main_tab', _('Main settings'));
// ENABLE_LOGGING
o = s.taboption('main_settings', form.Flag, 'enable_logging',
o = s.taboption('main_tab', form.Flag, 'enable_logging',
_('Logging events'));
o.rmempty = false;
// update_at_startup
o = s.taboption('main_settings', form.Flag, 'update_at_startup',
o = s.taboption('main_tab', form.Flag, 'update_at_startup',
_('Update at startup'));
o.description = _('Update blacklist after system startup');
o.rmempty = false;
// PROXY_LOCAL_CLIENTS
o = s.taboption('main_tab', form.Flag, 'proxy_local_clients',
_('Apply proxy rules to router application traffic'));
o.rmempty = false;
// NFTSET_CLEAR_SETS
o = s.taboption('main_settings', form.Flag, 'nftset_clear_sets',
o = s.taboption('main_tab', form.Flag, 'nftset_clear_sets',
_('Clean up nftsets before updating blacklist'));
o.description = _('Reduces RAM consumption during update');
o.rmempty = false;
// ALLOWED_HOSTS_MODE
o = s.taboption('main_settings', form.ListValue, 'allowed_hosts_mode',
o = s.taboption('main_tab', form.ListValue, 'allowed_hosts_mode',
_('Host filter'));
o.value('0', _('Disabled'));
o.value('1', _('Only listed hosts'));
@@ -180,40 +235,29 @@ return view.extend({
o.description = _('Restriction of hosts that are allowed to bypass blocking');
// ALLOWED_HOSTS_LIST
o = s.taboption('main_settings', form.DynamicList, 'allowed_hosts_list',
o = s.taboption('main_tab', form.DynamicList, 'allowed_hosts_list',
_('IP addresses for host filter'));
o.datatype = 'ip4addr';
// ENABLE_FPROXY
o = s.taboption('main_settings', form.Flag, 'enable_fproxy',
_('Enable full proxy mode'));
o.description = _('All traffic of the specified hosts passes through the proxy, without a blacklist');
o.rmempty = false;
// FPROXY_LIST
o = s.taboption('main_settings', form.DynamicList, 'fproxy_list',
_('IP addresses for full proxy mode'));
o.datatype = 'ip4addr';
/* Tor tab */
s.tab('tor_settings', _('Tor mode'));
s.tab('tor_tab', _('Tor mode'));
// TOR_TRANS_PORT
o = s.taboption('tor_settings', form.Value, 'tor_trans_port',
o = s.taboption('tor_tab', form.Value, 'tor_trans_port',
_('Transparent proxy port'));
o.rmempty = false;
o.datatype = 'port';
// ONION_DNS_ADDR
o = s.taboption('tor_settings', form.Value, 'onion_dns_addr',
o = s.taboption('tor_tab', 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',
o = s.taboption('tor_tab', form.Button, '_torrc_btn',
_('Tor configuration file'));
o.onclick = () => torrc_edit.show();
o.inputtitle = _('Edit');
@@ -222,10 +266,10 @@ return view.extend({
/* VPN tab */
s.tab('vpn_settings', _('VPN mode'));
s.tab('vpn_tab', _('VPN mode'));
// IF_VPN
o = s.taboption('vpn_settings', widgets.DeviceSelect, 'if_vpn',
o = s.taboption('vpn_tab', widgets.DeviceSelect, 'if_vpn',
_('VPN interface'));
o.multiple = false;
o.noaliases = true;
@@ -233,13 +277,13 @@ return view.extend({
o.default = 'tun0';
// VPN_GW_IP
o = s.taboption('vpn_settings', form.Value, 'vpn_gw_ip',
o = s.taboption('vpn_tab', form.Value, 'vpn_gw_ip',
_('VPN gateway IP address'),
_('If not specified, the VPN interface address is used (or peer address for PPP protocols)'));
o.datatype = 'ip4addr(1)';
// VPN_ROUTE_CHECK
o = s.taboption('vpn_settings', form.ListValue, 'vpn_route_check',
o = s.taboption('vpn_tab', form.ListValue, 'vpn_route_check',
_('Type of adding a VPN rule to the routing table'));
o.value('0', 'hotplug.d');
o.value('1', 'ruab_route_check');
@@ -248,32 +292,46 @@ return view.extend({
_('ruab_route_check - script that regularly checks an entry in the routing table.');
/* Proxy tab */
/* Tproxy tab */
s.tab('proxy_settings', _('Transparent proxy mode'));
s.tab('tproxy_tab', _('Transparent proxy mode'));
// T_PROXY_TYPE
o = s.taboption('tproxy_tab', form.ListValue, 't_proxy_type',
_('Proxy type'));
o.value('0', _('redirect'));
o.value('1', _('tproxy'));
o.description = _('Statement in nftables rules');
// T_PROXY_PORT_TCP
o = s.taboption('proxy_settings', form.Value, 't_proxy_port_tcp',
o = s.taboption('tproxy_tab', 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',
o = s.taboption('tproxy_tab', 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',
o = s.taboption('tproxy_tab', form.Value, 't_proxy_port_udp',
_('Transparent proxy UDP port'));
o.rmempty = false;
o.datatype = 'port';
/* Blacklist module tab */
/* Blacklist tab */
s.tab('blacklist_tab', _('Blacklist settings'));
// PROXY_MODE
o = s.taboption('blacklist_tab', form.ListValue, 'proxy_mode',
_('Proxy mode'));
o.value('1', 'Tor');
o.value('2', 'VPN');
o.value('3', _('Transparent proxy'));
// BLLIST_PRESET
let bllist_preset = s.taboption('blacklist_tab', form.ListValue,
'bllist_preset', _('Blacklist update mode'));
@@ -312,29 +370,16 @@ return view.extend({
o.rmempty = false;
o.default = 0;
// ADD_USER_ENTRIES
o = s.taboption('blacklist_tab', form.Flag, 'add_user_entries',
_('Enable user entries'), _('Add user entries to the blacklist when updating'));
// ENABLE_FPROXY
o = s.taboption('blacklist_tab', form.Flag, 'enable_fproxy',
_('Enable full proxy mode'));
o.description = _('All traffic of the specified hosts passes through the proxy, without a blacklist');
o.rmempty = false;
o.default = 0;
o.depends({ bllist_preset: '', '!reverse': true });
// USER_ENTRIES edit dialog
o = s.taboption('blacklist_tab', form.Button, '_user_entries_btn',
_('User entries'));
o.onclick = () => user_entries_edit.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// USER_ENTRIES_REMOTE
o = s.taboption('blacklist_tab', form.DynamicList, 'user_entries_remote',
_('URLs of remote user entries file'));
o.validate = this.validateUrl;
// USER_ENTRIES_DNS
o = s.taboption('blacklist_tab', form.Value, 'user_entries_dns',
_("DNS server that is used for the user's FQDN entries"), '<code>ipaddress[#port]</code>');
o.validate = this.validateIpPort;
// FPROXY_LIST
o = s.taboption('blacklist_tab', form.DynamicList, 'fproxy_list',
_('IP addresses for full proxy mode'));
o.datatype = 'ip4addr';
// BYPASS_MODE
o = s.taboption('blacklist_tab', form.Flag, 'bypass_mode',
@@ -354,6 +399,7 @@ return view.extend({
_('DNS server that is used for the FQDN entries of exclusion list'), '<code>ipaddress[#port]</code>');
o.validate = this.validateIpPort;
if(availableParsers) {
bllist_preset.description += '<br /> ( * - ' + _('requires installed blacklist module') + ' )';
@@ -398,10 +444,9 @@ return view.extend({
// BLLIST_GR_EXCLUDED_SLD_FILE edit dialog
o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_sld_btn',
_('2nd level domains that are excluded from optimization'));
o.onclick = () => gr_excluded_sld_edit.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
//o.description = _('e.g:') + ' <code>livejournal.com</code>';
o.onclick = () => gr_excluded_sld_edit.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// BLLIST_ENABLE_IDN
o = s.taboption('parser_settings_tab', form.Flag, 'bllist_enable_idn',
@@ -447,10 +492,9 @@ return view.extend({
// BLLIST_GR_EXCLUDED_NETS_FILE edit dialog
o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_nets_btn',
_('IP subnet patterns (/24) that are excluded from optimization'));
o.onclick = () => gr_excluded_nets_edit.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
//o.description = _('e.g:') + ' <code>192.168.1.</code>';
o.onclick = () => gr_excluded_nets_edit.show();
o.inputtitle = _('Edit');
o.inputstyle = 'edit btn';
// BLLIST_SUMMARIZE_IP
o = s.taboption('parser_settings_tab', form.Flag, 'bllist_summarize_ip',
@@ -461,7 +505,180 @@ return view.extend({
o = s.taboption('parser_settings_tab', form.Flag, 'bllist_summarize_cidr',
_("Summarize '/24' networks"));
o.rmempty = false;
};
/* User entries tab */
s.tab('user_entries_tab', _('User entries'));
o = s.taboption('user_entries_tab', form.SectionValue, 'user_instance', form.GridSection,
'user_instance');
ss = o.subsection;
ss.addremove = false;
ss.sortable = false;
ss.nodescriptions = true;
ss.modaltitle = `${_('User entries')} - %s`;
ss.max_cols = 2;
/* User entries main settings tab */
ss.tab('u_main_tab', _('Main settings'));
// U_ENABLED
o = ss.taboption('u_main_tab', form.Flag, 'u_enabled',
_('Enabled'),
);
o.rmempty = false;
o.default = '1';
o.editable = true;
o.modalonly = false;
// description
o = ss.taboption('u_main_tab', form.Value, 'u_description',
_("Description"));
o.datatype = 'maxlength(100)';
o.modalonly = null;
// U_PROXY_MODE
o = ss.taboption('u_main_tab', form.ListValue, 'u_proxy_mode',
_('Proxy mode'));
o.value('1', 'Tor');
o.value('2', 'VPN');
o.value('3', _('Transparent proxy'));
o.default = '2';
o.modalonly = true;
// U_SKIP_MARKED_PACKETS
o = ss.taboption('u_main_tab', form.Flag, 'u_skip_marked_packets',
_('Lowest priority'));
o.description = _('This proxy will receive traffic last, even after the main blacklist');
o.rmempty = false;
o.modalonly = true;
// U_ENABLE_FPROXY
o = ss.taboption('u_main_tab', form.Flag, 'u_enable_fproxy',
_('Enable full proxy mode'));
o.description = _('All traffic of the specified hosts passes through the proxy, without a blacklist');
o.rmempty = false;
o.modalonly = true;
// U_FPROXY_LIST
o = ss.taboption('u_main_tab', form.DynamicList, 'u_fproxy_list',
_('IP addresses for full proxy mode'));
o.datatype = 'ip4addr';
o.modalonly = true;
/* User entries tor tab */
ss.tab('u_tor_tab', _('Tor mode'));
// U_TOR_TRANS_PORT
o = ss.taboption('u_tor_tab', form.Value, 'u_tor_trans_port',
_('Transparent proxy port'));
o.rmempty = false;
o.datatype = 'port';
o.modalonly = true;
// U_ONION_DNS_ADDR
o = ss.taboption('u_tor_tab', form.Value, 'u_onion_dns_addr',
_("Optional DNS resolver for '.onion' zone"), '<code>ipaddress#port</code>');
o.rmempty = false;
o.validate = this.validateIpPort;
o.modalonly = true;
/* User entries VPN tab */
ss.tab('u_vpn_tab', _('VPN mode'));
// U_IF_VPN
o = ss.taboption('u_vpn_tab', widgets.DeviceSelect, 'u_if_vpn',
_('VPN interface'));
o.multiple = false;
o.noaliases = true;
o.rmempty = false;
o.default = 'tun0';
o.modalonly = true;
// U_VPN_GW_IP
o = ss.taboption('u_vpn_tab', form.Value, 'u_vpn_gw_ip',
_('VPN gateway IP address'),
_('If not specified, the VPN interface address is used (or peer address for PPP protocols)'));
o.datatype = 'ip4addr(1)';
o.modalonly = true;
/* User entries tproxy tab */
ss.tab('u_tproxy_tab', _('Transparent proxy mode'));
// U_T_PROXY_TYPE
o = ss.taboption('u_tproxy_tab', form.ListValue, 'u_t_proxy_type',
_('Proxy type'));
o.value('0', _('redirect'));
o.value('1', _('tproxy'));
o.description = _('Statement in nftables rules');
// U_T_PROXY_PORT_TCP
o = ss.taboption('u_tproxy_tab', form.Value, 'u_t_proxy_port_tcp',
_('Transparent proxy TCP port'));
o.rmempty = false;
o.datatype = 'port';
o.modalonly = true;
// U_T_PROXY_ALLOW_UDP
o = ss.taboption('u_tproxy_tab', form.Flag, 'u_t_proxy_allow_udp',
_('Send UDP traffic to transparent proxy'));
o.rmempty = false;
o.modalonly = true;
// U_T_PROXY_PORT_UDP
o = ss.taboption('u_tproxy_tab', form.Value, 'u_t_proxy_port_udp',
_('Transparent proxy UDP port'));
o.rmempty = false;
o.datatype = 'port';
o.modalonly = true;
/* User entries items tab */
ss.tab('u_entries_tab', _('Entries'));
ss.addModalOptions = (s, section_id, ev) => {
// user entries edit dialog
o = s.taboption('u_entries_tab', this.CBIBlockFileEdit, this,
'user-entries',
tools.userListsDir + '/' + s.section,
_('Edit entries'),
_('One entry (IP, CIDR or FQDN) per line. In the FQDN records, you can specify the DNS server for resolving this domain (separated by a space). You can also comment on lines (<code>#</code> is the first character of a line).<br />Examples:') +
'<br /><code>#comment<br />domain.net<br />sub.domain.com 8.8.8.8<br />sub.domain.com 8.8.8.8#53<br />74.125.131.19<br />74.125.0.0/16</code>'
);
// DEBUG
console.log(tools.userListsDir + '/' + s.section);
o.modalonly = true;
// U_ENTRIES_REMOTE
o = s.taboption('u_entries_tab', form.DynamicList, 'u_entries_remote',
_('URLs of remote user entries file'));
o.validate = this.validateUrl;
o.modalonly = true;
// U_ENABLE_ENTRIES_REMOTE_PROXY
o = s.taboption('u_entries_tab', form.Flag, 'u_enable_entries_remote_proxy',
_('Downloading files via proxy'), _('Turn on if files are blocked'));
o.rmempty = false;
o.default = 0;
// U_ENTRIES_DNS
o = s.taboption('u_entries_tab', form.Value, 'u_entries_dns',
_("DNS server that is used for the user's FQDN entries"), '<code>ipaddress[#port]</code>');
o.validate = this.validateIpPort;
o.modalonly = true;
};
let map_promise = m.render();
@@ -469,12 +686,28 @@ return view.extend({
return map_promise;
},
handleSaveApply: function(ev, mode) {
return this.handleSave(ev).then(() => {
handleSave(ev, restart) {
let tasks = [];
document.getElementById('maincontent')
.querySelectorAll('.cbi-map').forEach((map, i, a) => {
let res = DOM.callClassMethod(map, 'save');
if(restart && i == a.length - 1 && this.appStatusCode != 1 && this.appStatusCode != 2) {
res.then(() => {
window.setTimeout(() => {
fs.exec_direct(tools.execPath, [ 'restart' ]).then(
() => console.log(tools.execPath + ' restarted...')
);
}, 1000);
});
};
tasks.push(res);
});
return Promise.all(tasks);
},
handleSaveApply(ev, mode) {
return this.handleSave(ev, true).then(() => {
ui.changes.apply(mode == '0');
if(this.appStatusCode != 1 && this.appStatusCode != 2) {
window.setTimeout(() => fs.exec(tools.execPath, [ 'restart' ]), 3000);
};
});
},
});
@@ -38,8 +38,10 @@ return baseclass.extend({
execPath : '/usr/bin/ruantiblock',
tokenFile : '/var/run/ruantiblock.token',
parsersDir : '/usr/libexec/ruantiblock',
dnsmasqCfgDirsRoot: '/tmp',
torrcFile : '/etc/tor/torrc',
userEntriesFile : '/etc/ruantiblock/user_entries',
userListsDir : '/etc/ruantiblock/user_lists',
bypassEntriesFile : '/etc/ruantiblock/bypass_entries',
fqdnFilterFile : '/etc/ruantiblock/fqdn_filter',
ipFilterFile : '/etc/ruantiblock/ip_filter',
@@ -76,7 +78,7 @@ return baseclass.extend({
expect: { result: false }
}),
getInitStatus: function(name) {
getInitStatus(name) {
return this.callInitStatus(name).then(res => {
if(res) {
return res[name].enabled;
@@ -89,7 +91,7 @@ return baseclass.extend({
});
},
handleServiceAction: function(name, action) {
handleServiceAction(name, action) {
return this.callInitAction(name, action).then(success => {
if(!success) {
throw _('Command failed');
@@ -101,13 +103,12 @@ return baseclass.extend({
});
},
normalizeValue: function(v) {
normalizeValue(v) {
return (v && typeof(v) === 'string') ? v.trim().replace(/\r?\n/g, '') : v;
},
makeStatusString: function(
app_status_code,
proxy_mode,
bllist_preset,
bllist_module,
vpn_route_status_code) {
@@ -152,14 +153,6 @@ return baseclass.extend({
%s %s
</td>
</tr>
<tr class="tr">
<td class="td left">
${_('Proxy mode')}:
</td>
<td class="td left">
%s
</td>
</tr>
<tr class="tr">
<td class="td left">
${_('Blacklist update mode')}:
@@ -172,10 +165,9 @@ return baseclass.extend({
`.format(
spinning,
app_status_label,
(app_status_code != 2 && proxy_mode == 2 && vpn_route_status_code != 0)
(app_status_code != 2 && vpn_route_status_code != 0)
? '<span class="label-status error">'
+ _('VPN routing error! Need restart') + '</span>' : '',
(proxy_mode == 3) ? _('Transparent proxy') : (proxy_mode == 2) ? 'VPN' : 'Tor',
(!bllist_preset || bllist_preset === '') ? _('user entries only') :
(this.blacklistPresets[bllist_preset]) ?
`<span style="cursor:help; border-bottom:1px dotted" data-tooltip="${this.blacklistPresets[bllist_preset][2]}">
@@ -185,7 +177,7 @@ return baseclass.extend({
},
fileEditDialog: baseclass.extend({
__init__: function(file, title, description, callback, file_exists=false) {
__init__(file, title, description, callback, file_exists=false) {
this.file = file;
this.title = title;
this.description = description;
@@ -193,11 +185,11 @@ return baseclass.extend({
this.file_exists = file_exists;
},
load: function() {
load() {
return L.resolveDefault(fs.read(this.file), '');
},
render: function(content) {
render(content) {
ui.showModal(this.title, [
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-section-descr' }, this.description),
@@ -230,7 +222,7 @@ return baseclass.extend({
]);
},
handleSave: function(ev) {
handleSave(ev) {
let textarea = document.getElementById('widget.modal_content');
let value = textarea.value.trim().replace(/\r\n/g, '\n') + '\n';
@@ -249,7 +241,7 @@ return baseclass.extend({
});
},
error: function(e) {
error(e) {
if(!this.file_exists && e instanceof Error && e.name === 'NotFoundError') {
return this.render();
} else {
@@ -268,7 +260,7 @@ return baseclass.extend({
};
},
show: function() {
show() {
ui.showModal(null,
E('p', { 'class': 'spinning' }, _('Loading'))
);
+50 -5
View File
@@ -70,6 +70,9 @@ msgstr "Байты"
msgid "Cancel"
msgstr "Отмена"
msgid "Change dnsmasq config directory"
msgstr "Изменить директорию конфигов dnsmasq"
msgid "Changes have been saved."
msgstr "Изменения сохранены."
@@ -110,12 +113,18 @@ msgstr "День"
msgid "Debug"
msgstr "Отладка"
msgid "Description"
msgstr "Описание"
msgid "Disabled"
msgstr "Отключено"
msgid "Dismiss"
msgstr "Закрыть"
msgid "Dnsmasq config directory"
msgstr "Директория конфигов dnsmasq"
msgid "Download error"
msgstr "Ошибка загрузки"
@@ -125,9 +134,15 @@ msgstr "Скачать журнал"
msgid "Downloading a blacklist via proxy"
msgstr "Скачивать блэклист через прокси"
msgid "Downloading files via proxy"
msgstr "Скачивать файлы через прокси"
msgid "Edit"
msgstr "Изменить"
msgid "Edit entries"
msgstr "Изменить записи"
msgid "Emergency"
msgstr "Чрезвычайная ситуация"
@@ -233,15 +248,15 @@ msgstr "Шаблоны IP подсетей (/24) не подлежащих оп
msgid "Info"
msgstr "Информация"
msgid "Instance"
msgstr "Экземпляр"
msgid "Interval"
msgstr "Интервал"
msgid "Invalid regular expression"
msgstr "Неправильное регулярное выражение"
msgid "Nftables rules"
msgstr "Правила nftables"
msgid "Last blacklist update"
msgstr "Последнее обновление блэклиста"
@@ -257,6 +272,9 @@ msgstr "Список хостов, которые исключаются из о
msgid "Loading"
msgstr "Загрузка"
msgid "Local traffic"
msgstr "Локальный трафик"
msgid "Log"
msgstr "Лог"
@@ -269,6 +287,9 @@ msgstr "Уровни логирования"
msgid "Logread not found"
msgstr "Logread не найден"
msgid "Lowest priority"
msgstr "Самый низкий приоритет"
msgid "Main settings"
msgstr "Основные настройки"
@@ -373,9 +394,15 @@ msgstr "Отбор IP адресов из блэклиста по шаблона
msgid "Pick domains from blacklist by FQDN filter patterns"
msgstr "Отбор доменов из блэклиста по шаблонам фильтра FQDN"
msgid "Protocol"
msgstr "Протокол"
msgid "Proxy mode"
msgstr "Режим прокси"
msgid "Proxy type"
msgstr "Тип прокси"
msgid "Reduces RAM consumption during update"
msgstr "Уменьшает потребление оперативной памяти при обновлении"
@@ -418,8 +445,11 @@ msgstr "Настройки"
msgid "Shutdown"
msgstr "Выключение"
msgid "Size in memory"
msgstr "Размер в памяти"
msgid "Skip marked packets"
msgstr "Пропускать помеченные пакеты"
msgid "Skip packets that have already been marked in previous rules"
msgstr "Пропускать пакеты, которые уже были помечены в предыдущих правилах"
msgid "Sorting entries"
msgstr "Сортировка записей"
@@ -430,6 +460,9 @@ msgstr "Запускается"
msgid "Statistics"
msgstr "Статистика"
msgid "Statement in nftables rules"
msgstr "Действие в правилах nftables"
msgid "Status"
msgstr "Статус"
@@ -469,6 +502,9 @@ msgid ""
msgstr ""
"Служба будет выключена и все данные блэклиста будут удалены. Продолжить?"
msgid "This proxy will receive traffic last, even after the main blacklist"
msgstr "В этот прокси трафик будет попадать в последнюю очередь, даже после основного блэклиста"
msgid "Time"
msgstr "Время"
@@ -487,6 +523,9 @@ msgstr "Конфигурационный файл Tor"
msgid "Tor mode"
msgstr "Режим Tor"
msgid "Transit traffic"
msgstr "Транзитный трафик"
msgid "Transparent proxy"
msgstr "Прозрачный прокси"
@@ -505,6 +544,9 @@ msgstr "UDP порт прозрачного прокси"
msgid "Turn on if blacklist source is blocked"
msgstr "Включите, если источник блэклиста заблокирован"
msgid "Turn on if files are blocked"
msgstr "Включите, если файлы заблокированы"
msgid "Type a search pattern..."
msgstr "Введите шаблон для поиска"
@@ -568,6 +610,9 @@ msgstr "Ошибка маршрутизации VPN! Необходим пере
msgid "Warning"
msgstr "Внимание"
msgid "all"
msgstr "все"
msgid "ascending"
msgstr "по возрастанию"
@@ -55,6 +55,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
msgid "Change dnsmasq config directory"
msgstr ""
msgid "Changes have been saved."
msgstr ""
@@ -95,12 +98,18 @@ msgstr ""
msgid "Debug"
msgstr ""
msgid "Description"
msgstr ""
msgid "Disabled"
msgstr ""
msgid "Dismiss"
msgstr ""
msgid "Dnsmasq config directory"
msgstr ""
msgid "Download error"
msgstr ""
@@ -110,9 +119,15 @@ msgstr ""
msgid "Downloading a blacklist via proxy"
msgstr ""
msgid "Downloading files via proxy"
msgstr ""
msgid "Edit"
msgstr ""
msgid "Edit entries"
msgstr ""
msgid "Emergency"
msgstr ""
msgid "Enable"
@@ -214,15 +229,15 @@ msgstr ""
msgid "Info"
msgstr ""
msgid "Instance"
msgstr ""
msgid "Interval"
msgstr ""
msgid "Invalid regular expression"
msgstr ""
msgid "Nftables rules"
msgstr ""
msgid "Last blacklist update"
msgstr ""
@@ -238,6 +253,9 @@ msgstr ""
msgid "Loading"
msgstr ""
msgid "Local traffic"
msgstr ""
msgid "Log"
msgstr ""
@@ -250,6 +268,9 @@ msgstr ""
msgid "Logread not found"
msgstr ""
msgid "Lowest priority"
msgstr ""
msgid "Main settings"
msgstr ""
@@ -342,9 +363,15 @@ msgstr ""
msgid "Pick domains from blacklist by FQDN filter patterns"
msgstr ""
msgid "Protocol"
msgstr ""
msgid "Proxy mode"
msgstr ""
msgid "Proxy type"
msgstr ""
msgid "Reduces RAM consumption during update"
msgstr ""
@@ -386,9 +413,6 @@ msgstr ""
msgid "Shutdown"
msgstr ""
msgid "Size in memory"
msgstr ""
msgid "Sorting entries"
msgstr ""
@@ -397,6 +421,10 @@ msgstr ""
msgid "Statistics"
msgstr ""
msgid "Statement in nftables rules"
msgstr ""
msgid "Status"
msgstr ""
@@ -429,6 +457,9 @@ msgid ""
"Continue?"
msgstr ""
msgid "This proxy will receive traffic last, even after the main blacklist"
msgstr ""
msgid "Time"
msgstr ""
@@ -447,6 +478,9 @@ msgstr ""
msgid "Tor mode"
msgstr ""
msgid "Transit traffic"
msgstr ""
msgid "Transparent proxy"
msgstr ""
@@ -465,6 +499,9 @@ msgstr ""
msgid "Turn on if blacklist source is blocked"
msgstr ""
msgid "Turn on if files are blocked"
msgstr ""
msgid "Type a search pattern..."
msgstr ""
@@ -509,6 +546,7 @@ msgid "URLs of remote user entries file"
msgid "Use optional DNS resolver"
msgstr ""
msgid "User entries"
msgstr ""
@@ -527,6 +565,9 @@ msgstr ""
msgid "Warning"
msgstr ""
msgid "all"
msgstr "все"
msgid "ascending"
msgstr ""
@@ -7,7 +7,7 @@
"/usr/libexec/ruantiblock": [ "list" ],
"/etc/ruantiblock/fqdn_filter": [ "read" ],
"/etc/ruantiblock/ip_filter": [ "read" ],
"/etc/ruantiblock/user_entries": [ "read" ],
"/etc/ruantiblock/user_lists/*": [ "read" ],
"/etc/ruantiblock/bypass_entries": [ "read" ],
"/etc/ruantiblock/gr_excluded_nets": [ "read" ],
"/etc/ruantiblock/gr_excluded_sld": [ "read" ],
@@ -16,7 +16,8 @@
"/etc/crontabs/root": [ "read" ],
"/usr/bin/ruantiblock*": [ "exec" ],
"/sbin/logread -e ruantiblock:": [ "exec" ],
"/usr/sbin/logread -e ruantiblock:": [ "exec" ]
"/usr/sbin/logread -e ruantiblock:": [ "exec" ],
"/tmp": [ "list" ]
},
"uci": [ "network", "ruantiblock" ],
"ubus": {
@@ -27,7 +28,7 @@
"file": {
"/etc/ruantiblock/fqdn_filter": [ "write" ],
"/etc/ruantiblock/ip_filter": [ "write" ],
"/etc/ruantiblock/user_entries": [ "write" ],
"/etc/ruantiblock/user_lists/*": [ "write" ],
"/etc/ruantiblock/bypass_entries": [ "write" ],
"/etc/ruantiblock/gr_excluded_nets": [ "write" ],
"/etc/ruantiblock/gr_excluded_sld": [ "write" ],
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-lua
PKG_VERSION:=1.6.0
PKG_VERSION:=2.0.0
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -58,9 +58,8 @@ local Config = Class(nil, {
["NFTSET_CIDR"] = true,
["NFTSET_IP"] = true,
["NFTSET_DNSMASQ"] = true,
["NFTSET_CIDR_CFG"] = true,
["NFTSET_IP_CFG"] = true,
["NFTSET_DNSMASQ"] = true,
["NFTSET_CIDR_STRING_MAIN"] = true,
["NFTSET_IP_STRING_MAIN"] = true,
["DNSMASQ_DATA_FILE"] = true,
["IP_DATA_FILE"] = true,
["UPDATE_STATUS_FILE"] = true,
@@ -788,7 +787,7 @@ function WriteConfigFiles:write_ipset_config(ip_table, cidr_table)
file_handler:write(string.format("flush set %s %s\n", self.NFT_TABLE, v))
end
file_handler:write(
string.format("table %s {\n%s", self.NFT_TABLE, self.NFTSET_CIDR_CFG)
string.format("table %s {\n%s", self.NFT_TABLE, self.NFTSET_CIDR_STRING_MAIN)
)
local c = 0
if next(cidr_table) then
@@ -801,7 +800,7 @@ function WriteConfigFiles:write_ipset_config(ip_table, cidr_table)
end
self.cidr_count = c
file_handler:write(
string.format("}\n%s", self.NFTSET_IP_CFG)
string.format("}\n%s", self.NFTSET_IP_STRING_MAIN)
)
local i = 0
if next(ip_table) then
@@ -1076,6 +1075,7 @@ if parser_classes then
for _, i in ipairs(parser_instances) do
ret_list[i:run()] = true
end
local return_sum = 0
for i, _ in pairs(ret_list) do
return_sum = return_sum + i
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-py
PKG_VERSION:=1.6.0
PKG_VERSION:=2.0.0
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -42,9 +42,8 @@ class Config:
"NFTSET_CIDR",
"NFTSET_IP",
"NFTSET_DNSMASQ",
"NFTSET_CIDR_CFG",
"NFTSET_IP_CFG",
"NFTSET_DNSMASQ",
"NFTSET_CIDR_STRING_MAIN",
"NFTSET_IP_STRING_MAIN",
"DNSMASQ_DATA_FILE",
"IP_DATA_FILE",
"UPDATE_STATUS_FILE",
@@ -459,6 +458,7 @@ class Summarize:
@classmethod
def _group_nets(cls, cidr_list, raw_list=None):
def remove_items(start, end):
for ip in range(int(start), int(end) + 1, 256):
raw_list.remove(str(IPv4Address(ip)) + "/24")
@@ -570,7 +570,7 @@ class WriteConfigFiles(Config):
for i in (self.NFTSET_CIDR, self.NFTSET_IP):
file_handler.write("flush set {} {}\n".format(self.NFT_TABLE, i))
file_handler.write(
"table {} {{\n{}".format(self.NFT_TABLE, self.NFTSET_CIDR_CFG)
"table {} {{\n{}".format(self.NFT_TABLE, self.NFTSET_CIDR_STRING_MAIN)
)
if len(cidr_set) > 0:
file_handler.write("elements={")
@@ -578,7 +578,7 @@ class WriteConfigFiles(Config):
file_handler.write(f"{i},")
file_handler.write("};")
file_handler.write(
"}}\n{}".format(self.NFTSET_IP_CFG)
"}}\n{}".format(self.NFTSET_IP_STRING_MAIN)
)
if len(ip_dict) > 0:
file_handler.write("elements={")
+22 -9
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock
PKG_VERSION:=1.6.0
PKG_VERSION:=2.0.0
PKG_RELEASE:=1
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:=+dnsmasq-full
DEPENDS:=+dnsmasq-full +kmod-nft-tproxy
endef
define Package/$(PKG_NAME)/description
@@ -28,10 +28,14 @@ define Package/$(PKG_NAME)/conffiles
/etc/ruantiblock/ruantiblock.conf
/etc/ruantiblock/fqdn_filter
/etc/ruantiblock/ip_filter
/etc/ruantiblock/user_entries
/etc/ruantiblock/bypass_entries
/etc/ruantiblock/gr_excluded_nets
/etc/ruantiblock/gr_excluded_sld
/etc/ruantiblock/user_lists/list1
/etc/ruantiblock/user_lists/list2
/etc/ruantiblock/user_lists/list3
/etc/ruantiblock/user_lists/list4
/etc/ruantiblock/user_lists/list5
endef
define Build/Configure
@@ -51,15 +55,22 @@ define Package/$(PKG_NAME)/install
$(INSTALL_CONF) ./files/etc/ruantiblock/ruantiblock.conf $(1)/etc/ruantiblock/ruantiblock.conf
$(INSTALL_DATA) ./files/etc/ruantiblock/fqdn_filter $(1)/etc/ruantiblock/fqdn_filter
$(INSTALL_DATA) ./files/etc/ruantiblock/ip_filter $(1)/etc/ruantiblock/ip_filter
$(INSTALL_DATA) ./files/etc/ruantiblock/user_entries $(1)/etc/ruantiblock/user_entries
$(INSTALL_DATA) ./files/etc/ruantiblock/bypass_entries $(1)/etc/ruantiblock/bypass_entries
$(INSTALL_DATA) ./files/etc/ruantiblock/gr_excluded_nets $(1)/etc/ruantiblock/gr_excluded_nets
$(INSTALL_DATA) ./files/etc/ruantiblock/gr_excluded_sld $(1)/etc/ruantiblock/gr_excluded_sld
$(INSTALL_DIR) $(1)/etc/ruantiblock/user_lists
$(INSTALL_DATA) ./files/etc/ruantiblock/user_lists/list1 $(1)/etc/ruantiblock/user_lists/list1
$(INSTALL_DATA) ./files/etc/ruantiblock/user_lists/list2 $(1)/etc/ruantiblock/user_lists/list2
$(INSTALL_DATA) ./files/etc/ruantiblock/user_lists/list3 $(1)/etc/ruantiblock/user_lists/list3
$(INSTALL_DATA) ./files/etc/ruantiblock/user_lists/list4 $(1)/etc/ruantiblock/user_lists/list4
$(INSTALL_DATA) ./files/etc/ruantiblock/user_lists/list5 $(1)/etc/ruantiblock/user_lists/list5
$(INSTALL_DIR) $(1)/usr/share/ruantiblock
$(INSTALL_DATA) ./files/usr/share/ruantiblock/blacklist_sources $(1)/usr/share/ruantiblock/blacklist_sources
$(INSTALL_DATA) ./files/usr/share/ruantiblock/config_script $(1)/usr/share/ruantiblock/config_script
$(INSTALL_DATA) ./files/usr/share/ruantiblock/config_script_user_instances $(1)/usr/share/ruantiblock/config_script_user_instances
$(INSTALL_DATA) ./files/usr/share/ruantiblock/info_output $(1)/usr/share/ruantiblock/info_output
$(INSTALL_DATA) ./files/usr/share/ruantiblock/nft_functions $(1)/usr/share/ruantiblock/nft_functions
$(INSTALL_DATA) ./files/usr/share/ruantiblock/blacklist_sources $(1)/usr/share/ruantiblock/blacklist_sources
$(INSTALL_DATA) ./files/usr/share/ruantiblock/user_instances_common $(1)/usr/share/ruantiblock/user_instances_common
$(INSTALL_DIR) $(1)/usr/libexec/ruantiblock
$(INSTALL_BIN) ./files/usr/libexec/ruantiblock/ruab_route_check $(1)/usr/libexec/ruantiblock/ruab_route_check
$(INSTALL_DIR) $(1)/usr/bin
@@ -82,14 +93,16 @@ define Package/$(PKG_NAME)/prerm
FILE_INIT_SCRIPT="/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="/usr/bin/ruantiblock"
CRONTAB_FILE="/etc/crontabs/root"
DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq"
DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq*.d/00-ruantiblock_bypass.dnsmasq"
DNSMASQ_DATA_FILE_USER_INSTANCES="/tmp/dnsmasq*.d/01-ruantiblock_user_instances.dnsmasq"
DNSMASQ_DATA_FILE="/tmp/dnsmasq*.d/02-ruantiblock.dnsmasq"
DNSMASQ_DATA_FILE_BYPASS_TMP="${DNSMASQ_DATA_FILE_BYPASS}.tmp"
DNSMASQ_DATA_FILE_USER_INSTANCES_TMP="${DNSMASQ_DATA_FILE_USER_INSTANCES}.tmp"
DNSMASQ_DATA_FILE_TMP="${DNSMASQ_DATA_FILE}.tmp"
DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq"
rm -f $$DNSMASQ_DATA_FILE $$DNSMASQ_DATA_FILE_TMP $$DNSMASQ_DATA_FILE_BYPASS
test -e "$$FILE_MAIN_SCRIPT" && $$FILE_MAIN_SCRIPT destroy
test -e "$$FILE_INIT_SCRIPT" && $$FILE_INIT_SCRIPT disable
rm -f $$DNSMASQ_DATA_FILE $$DNSMASQ_DATA_FILE_TMP $$DNSMASQ_DATA_FILE_BYPASS $$DNSMASQ_DATA_FILE_BYPASS_TMP $$DNSMASQ_DATA_FILE_USER_INSTANCES $$DNSMASQ_DATA_FILE_USER_INSTANCES_TMP
awk -v FILE_MAIN_SCRIPT="$$FILE_MAIN_SCRIPT" '$$0 !~ FILE_MAIN_SCRIPT {
print $$0;
+76 -1
View File
@@ -11,13 +11,13 @@ config main 'config'
option vpn_route_check '0'
option tor_trans_port '9040'
option onion_dns_addr '127.0.0.1#9053'
option t_proxy_type '0'
option t_proxy_port_tcp '1100'
option t_proxy_port_udp '1100'
option t_proxy_allow_udp '0'
option bypass_mode '0'
option enable_bllist_proxy '0'
option enable_tmp_downloads '0'
option add_user_entries '0'
option bllist_min_entries '3000'
option bllist_ip_limit '0'
option bllist_summarize_ip '1'
@@ -30,3 +30,78 @@ config main 'config'
option bllist_enable_idn '0'
option bllist_alt_nslookup '0'
option bllist_alt_dns_addr '8.8.8.8'
config user_instance 'list1'
option u_enabled '0'
option u_proxy_mode '2'
option u_tor_trans_port '9040'
option u_onion_dns_addr '127.0.0.1#9053'
option u_if_vpn 'tun0'
option u_t_proxy_type '0'
option u_t_proxy_port_tcp '1100'
option u_t_proxy_port_udp '1100'
option u_t_proxy_allow_udp '0'
option u_enable_entries_remote_proxy '0'
option u_entries_dns ''
option u_enable_fproxy '0'
option u_skip_marked_packets '0'
config user_instance 'list2'
option u_enabled '0'
option u_proxy_mode '2'
option u_tor_trans_port '9040'
option u_onion_dns_addr '127.0.0.1#9053'
option u_if_vpn 'tun0'
option u_t_proxy_type '0'
option u_t_proxy_port_tcp '1100'
option u_t_proxy_port_udp '1100'
option u_t_proxy_allow_udp '0'
option u_enable_entries_remote_proxy '0'
option u_entries_dns ''
option u_enable_fproxy '0'
option u_skip_marked_packets '0'
config user_instance 'list3'
option u_enabled '0'
option u_proxy_mode '2'
option u_tor_trans_port '9040'
option u_onion_dns_addr '127.0.0.1#9053'
option u_if_vpn 'tun0'
option u_t_proxy_type '0'
option u_t_proxy_port_tcp '1100'
option u_t_proxy_port_udp '1100'
option u_t_proxy_allow_udp '0'
option u_enable_entries_remote_proxy '0'
option u_entries_dns ''
option u_enable_fproxy '0'
option u_skip_marked_packets '0'
config user_instance 'list4'
option u_enabled '0'
option u_proxy_mode '2'
option u_tor_trans_port '9040'
option u_onion_dns_addr '127.0.0.1#9053'
option u_if_vpn 'tun0'
option u_t_proxy_type '0'
option u_t_proxy_port_tcp '1100'
option u_t_proxy_port_udp '1100'
option u_t_proxy_allow_udp '0'
option u_enable_entries_remote_proxy '0'
option u_entries_dns ''
option u_enable_fproxy '0'
option u_skip_marked_packets '0'
config user_instance 'list5'
option u_enabled '0'
option u_proxy_mode '2'
option u_tor_trans_port '9040'
option u_onion_dns_addr '127.0.0.1#9053'
option u_if_vpn 'tun0'
option u_t_proxy_type '0'
option u_t_proxy_port_tcp '1100'
option u_t_proxy_port_udp '1100'
option u_t_proxy_allow_udp '0'
option u_enable_entries_remote_proxy '0'
option u_entries_dns ''
option u_enable_fproxy '0'
option u_skip_marked_packets '0'
@@ -1,20 +1,64 @@
#!/bin/sh
UCI_CMD=`which uci`
if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2
exit 1
fi
RUAB_CMD="/usr/bin/ruantiblock"
PROXY_MODE=`$UCI_CMD get ruantiblock.config.proxy_mode`
IF_VPN=`$UCI_CMD get ruantiblock.config.if_vpn`
VPN_ROUTE_CHECK=`$UCI_CMD get ruantiblock.config.vpn_route_check`
if [ "$ACTION" = "ifup" ]; then
NAME="ruantiblock"
RUAB_CMD="/usr/bin/ruantiblock"
CONFIG_FILE="/etc/ruantiblock/ruantiblock.conf"
USER_INSTANCES_COMMON="/usr/share/ruantiblock/user_instances_common"
CONFIG_SCRIPT_USER_INSTANCES="/usr/share/ruantiblock/config_script_user_instances"
USER_INSTANCES_DIR="/etc/ruantiblock/user_instances"
USER_INSTANCE_VARS="U_ENABLED U_NAME U_PROXY_MODE U_TOR_TRANS_PORT U_ONION_DNS_ADDR U_IF_VPN U_VPN_GW_IP U_T_PROXY_TYPE U_T_PROXY_PORT_TCP U_T_PROXY_PORT_UDP U_T_PROXY_ALLOW_UDP U_USER_ENTRIES_DNS U_USER_ENTRIES_REMOTE U_ENABLE_ENTRIES_REMOTE_PROXY U_ENABLE_FPROXY U_FPROXY_LIST U_SKIP_MARKED_PACKETS"
USER_INSTANCES_MAX=10
DEBUG=0
IF_VPN_CURRENT=""
[ "$VPN_ROUTE_CHECK" != "0" ] && exit 0
ruab_route_status=`$RUAB_CMD raw-status`
[ $ruab_route_status -eq 1 -o $ruab_route_status -eq 2 ] && exit 0
if [ "$ACTION" = "ifup" ] && [ "$PROXY_MODE" = "2" ] && [ "$DEVICE" = "$IF_VPN" ]; then
if [ `$RUAB_CMD raw-status` -ne 2 ]; then
sleep 5
$RUAB_CMD reload
fi
UCI_CMD=`which uci`
if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2
exit 1
fi
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
VPN_ROUTE_CHECK=`$UCI_CMD get ruantiblock.config.vpn_route_check`
[ "$VPN_ROUTE_CHECK" != "0" ] && exit 0
PROXY_MODE=`$UCI_CMD get ruantiblock.config.proxy_mode`
if [ "$PROXY_MODE" = "2" ]; then
IF_VPN_CURRENT=`$UCI_CMD get ruantiblock.config.if_vpn`
fi
if [ "$DEVICE" != "$IF_VPN_CURRENT" ]; then
. "$USER_INSTANCES_COMMON"
for inst in `GetUserInstances 2`
do
IncludeUserInstanceVars "$inst"
if [ "$DEVICE" = "$U_IF_VPN" ]; then
IF_VPN_CURRENT="$U_IF_VPN"
if [ $DEBUG -ge 1 ]; then
echo " ruantiblock-vpn-iface-script: U_NAME=${U_NAME} U_IF_VPN=${U_IF_VPN}" >&2
logger -p "user.debug" -t "ruantiblock-hotplug-script" "U_NAME=${U_NAME} U_IF_VPN=${U_IF_VPN}"
fi
break
fi
ClearUserInstanceVars
done
fi
if [ "$DEVICE" = "$IF_VPN_CURRENT" ]; then
if [ $DEBUG -ge 1 ]; then
echo " ruantiblock-vpn-iface-script: IF_VPN_CURRENT=${IF_VPN_CURRENT} ACTION=\"${ACTION}\" DEVICE=${DEVICE} INTERFACE=${INTERFACE}" >&2
logger -p "user.debug" -t "ruantiblock-hotplug-script" "IF_VPN_CURRENT=${IF_VPN_CURRENT} ACTION=\"${ACTION}\" DEVICE=${DEVICE} INTERFACE=${INTERFACE}"
fi
sleep 5
$RUAB_CMD reload
fi
fi
+29 -3
View File
@@ -5,14 +5,40 @@ STOP=01
APP_NAME="ruantiblock"
APP_EXEC="/usr/bin/${APP_NAME}"
DNSMASQ_VAR_DIR="/tmp"
config_load $APP_NAME
get_dnsmasq_cfg_dir() {
local _first_instance
if [ -d "${DNSMASQ_VAR_DIR}/dnsmasq.d" ]; then
printf "${DNSMASQ_VAR_DIR}/dnsmasq.d"
return 0
else
_first_instance=`ls -1 "$DNSMASQ_VAR_DIR" | grep -e "^dnsmasq" | head -n 1`
if [ -n "$_first_instance" ]; then
printf "${DNSMASQ_VAR_DIR}/${_first_instance}"
return 0
fi
fi
return 1
}
start() {
local update_at_startup
config_get update_at_startup config update_at_startup
local _update_at_startup _dnsmasq_cfg_dir
config_get _update_at_startup config update_at_startup
config_get _dnsmasq_cfg_dir config dnsmasq_cfg_dir ""
if [ -z "$_dnsmasq_cfg_dir" ]; then
_dnsmasq_cfg_dir=`get_dnsmasq_cfg_dir`
if [ $? -eq 0 -a -n "$_dnsmasq_cfg_dir" ]; then
uci set "${APP_NAME}.config.dnsmasq_cfg_dir"="$_dnsmasq_cfg_dir"
uci commit ruantiblock
else
exit 1
fi
fi
$APP_EXEC start
if [ $? -eq 0 -a "$update_at_startup" = "1" ]; then
if [ $? -eq 0 -a "$_update_at_startup" = "1" ]; then
$APP_EXEC update
else
/etc/init.d/dnsmasq restart
@@ -82,4 +82,3 @@ birds
forex
kraken
zerkalo
#lord
@@ -5,9 +5,10 @@
DATA_DIR="/tmp/ruantiblock"
### Директория модулей
MODULES_DIR="/usr/libexec/ruantiblock"
### Дополнительный конфиг dnsmasq с FQDN записями блэклиста
DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq"
DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq"
### Директория PID-файлов и файлов статуса
RUN_FILES_DIR="/tmp/run"
### Директория доп. конфигов dnsmasq
DNSMASQ_CFG_DIR="/tmp/dnsmasq.d"
### Команда для перезапуска dnsmasq
DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart"
### Директория для html-страницы статуса (не используется в OpenWrt)
@@ -31,26 +32,26 @@ ONION_DNS_ADDR="127.0.0.1#9053"
IF_VPN="tun0"
### IP адрес шлюза для VPN конфигурации. Если не задан, используется адрес VPN интерфейса (или адрес пира для протоколов PPP)
VPN_GW_IP=""
### Метка для отбора пакетов в VPN туннель
VPN_PKTS_MARK=8
### Таблица маршрутизации для отправки пакетов в VPN туннель
VPN_ROUTE_TABLE_ID=99
### Приоритет правила отбора пакетов при маршрутизации в VPN-интерфейс
VPN_RULE_PRIO=1000
### Способ добавления в таблицу маршрутизации правила для отправки пакетов в VPN туннель (0 - hotplug.d, 1 - скрипт ruab_route_check)
VPN_ROUTE_CHECK=0
### Тип прозрачного прокси (0 - redirect, 1 - tproxy)
T_PROXY_TYPE=0
### TCP порт прокси в режиме прозрачного прокси
T_PROXY_PORT_TCP=1100
### UDP порт прокси в режиме прозрачного прокси
T_PROXY_PORT_UDP=1100
### Отправлять в прозрачный прокси UDP-трафик (0 - выкл, 1 - вкл)
T_PROXY_ALLOW_UDP=0
### Начальное значение метки для отбора пакетов в фильтрах
PKTS_MARK_START=8
### Запись событий в syslog (0 - выкл, 1 - вкл)
ENABLE_LOGGING=1
### Вывод дополнительных сообщений в лог (0 - выкл, 1, 2)
DEBUG=0
### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt)
ENABLE_HTML_INFO=0
### Максимальное кол-во элементов списка nftables
#NFTSET_MAXELEM_CIDR=65535
NFTSET_MAXELEM_CIDR=65535
NFTSET_MAXELEM_IP=1000000
NFTSET_MAXELEM_DNSMASQ=65535
NFTSET_MAXELEM_BYPASS_IP=65535
@@ -63,29 +64,14 @@ NFTSET_POLICY_DNSMASQ="performance"
NFTSET_DNSMASQ_TIMEOUT="150m"
### Динамическое обновление таймаута записей в сете $NFTSET_DNSMASQ (0 - выкл, 1 - вкл)
NFTSET_DNSMASQ_TIMEOUT_UPDATE=1
### Приоритет правила отбора пакетов nftables для конфигупации Tor или прозрачного прокси
NFT_PRIO_NAT="dstnat - 10"
### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в конфигупации Tor или прозрачного прокси
NFT_PRIO_NAT_LOCAL="filter - 10"
### Приоритет правила отбора пакетов nftables для VPN-конфигурации
NFT_PRIO_ROUTE="mangle + 10"
### Приоритет правила отбора пакетов nftables для трафика локальных клиентов в VPN-конфигурации
NFT_PRIO_ROUTE_LOCAL="mangle + 10"
### Добавление в список блокировок пользовательских записей из файла $USER_ENTRIES_FILE (0 - выкл, 1 - вкл)
### В $CONFIG_DIR можно создать текстовый файл user_entries с записями IP, CIDR или FQDN (одна на строку). Эти записи будут добавлены в список блокировок
### В записях FQDN можно задать DNS-сервер для разрешения данного домена, через пробел (прим.: domain.com 8.8.8.8)
### Можно комментировать строки (#)
ADD_USER_ENTRIES=0
### DNS-сервер для пользовательских записей (пустая строка - без DNS-сервера). Можно с портом: 8.8.8.8#53. Если в записи указан свой DNS-сервер - он имеет приоритет
USER_ENTRIES_DNS=""
### Файл пользовательских записей
USER_ENTRIES_FILE="/etc/ruantiblock/user_entries"
### URL удаленных файлов записей пользователя, через пробел (прим.: http://server.lan/files/user_entries_1 http://server.lan/files/user_entries_2)
USER_ENTRIES_REMOTE=""
### Кол-во попыток скачивания удаленного файла записей пользователя (в случае неудачи)
USER_ENTRIES_REMOTE_DOWNLOAD_ATTEMPTS=3
### Таймаут между попытками скачивания
USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT=60
### Кол-во экземпляров записей пользователя (не более 50!)
USER_INSTANCES_MAX=5
### Пропускать мимо фильтра пакеты уже помеченные в записях пользователя (0 - выкл, 1 - вкл)
SKIP_MARKED_PACKETS=0
### Режим списка записей, исключаемых из обхода блокировок (0 - выкл, 1 - вкл)
BYPASS_MODE=0
### DNS-сервер для исключаемых записей (пустая строка - без DNS-сервера). Можно с портом: 8.8.8.8#53. Если в записи указан свой DNS-сервер - он имеет приоритет
@@ -143,7 +129,7 @@ BLLIST_SD_LIMIT=16
BLLIST_GR_EXCLUDED_SLD_FILE="/etc/ruantiblock/gr_excluded_sld"
### Файл с масками SLD не подлежащими группировке при оптимизации (одна запись на строку)
BLLIST_GR_EXCLUDED_SLD_MASKS_FILE="/etc/ruantiblock/gr_excluded_sld_mask"
### Фильтрация записей блэклиста по шаблонам из файла ENTRIES_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - выкл, 1 - вкл)
### Фильтрация записей блэклиста по шаблонам из файла BLLIST_FQDN_FILTER_FILE. Записи (FQDN) попадающие под шаблоны исключаются из кофига dnsmasq (0 - выкл, 1 - вкл)
BLLIST_FQDN_FILTER=0
### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
BLLIST_FQDN_FILTER_TYPE=0
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,69 @@
#!/bin/sh
PID_FILE="/var/run/`basename $0`.pid"
APP_EXEC="/usr/bin/ruantiblock"
VpnRouteStatus() {
[ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0
. "$USER_INSTANCES_COMMON"
VPN_IFACES_STATUS=1
CheckIfaceStatus() {
local _iface="$1" _ret_val=0
if [ -z "`$IP_CMD link show dev $_iface up 2> /dev/null`" ]; then
_ret_val=1
if [ $DEBUG -ge 1 ]; then
echo " ruab_route_check.GetVpnRouteStatus: ${_iface} disabled" >&2
logger -p "user.debug" -t "ruantiblock" "ruab_route_check.GetVpnRouteStatus: iface ${_iface} disabled"
fi
fi
return $_ret_val
}
VpnRouteInstanceStatus() {
local _vpn_route_table_id=$1
[ -n "`$IP_CMD route show table $_vpn_route_table_id 2> /dev/null`" ] && return 0
return 1
}
GetVpnRouteStatus() {
local _inst _i=1 _ret_val=0
for _inst in $USER_INSTANCES_VPN_FNAMES
do
IncludeUserInstanceVars "$_inst"
if ! CheckIfaceStatus $U_IF_VPN; then
VPN_IFACES_STATUS=0
fi
if ! VpnRouteInstanceStatus $(($VPN_ROUTE_TABLE_ID_START + $_i)); then
_ret_val=1
break
fi
_i=$(($_i + 1))
ClearUserInstanceVars
done
if [ $_ret_val -eq 0 -a "$PROXY_MODE" = "2" ]; then
if ! CheckIfaceStatus $IF_VPN; then
VPN_IFACES_STATUS=0
fi
if ! VpnRouteInstanceStatus $VPN_ROUTE_TABLE_ID_START; then
_ret_val=1
fi
fi
return $_ret_val
}
Main() {
while [ -e "$PID_FILE" ]
do
if ! VpnRouteStatus; then
if $IP_CMD link show $IF_VPN &> /dev/null; then
VPN_IFACES_STATUS=1
if ! GetVpnRouteStatus; then
if [ "$VPN_IFACES_STATUS" = "1" ]; then
if [ $DEBUG -ge 1 ]; then
echo " ruab_route_check.Main: ${APP_EXEC} reload" >&2
logger -p "user.debug" -t "ruantiblock" "ruab_route_check.Main: ${APP_EXEC} reload"
fi
$APP_EXEC reload
fi
fi
@@ -6,7 +6,6 @@ export RBL_DPI_URL="https://reestr.rublacklist.net/api/v3/dpi/"
export RBL_ENCODING=""
## zapret-info
export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv"
#export ZI_ALL_URL="https://app.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw"
export ZI_ENCODING="CP1251"
## antifilter
export AF_IP_URL="https://antifilter.download/list/allyouneed.lst"
@@ -52,7 +51,6 @@ case "$BLLIST_PRESET" in
export BLLIST_SOURCE="ruantiblock"
export BLLIST_MODE="ip"
BLLIST_MODULE="DownloadNativeBlacklist"
# github
DL_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/ip/ruantiblock.ip"
DL_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/ip/ruantiblock.dnsmasq"
DL_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/ip/update_status"
@@ -61,7 +59,6 @@ case "$BLLIST_PRESET" in
export BLLIST_SOURCE="ruantiblock"
export BLLIST_MODE="fqdn"
BLLIST_MODULE="DownloadNativeBlacklist"
# github
DL_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/fqdn/ruantiblock.ip"
DL_DMASK_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/fqdn/ruantiblock.dnsmasq"
DL_STAT_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/fqdn/update_status"
@@ -1,5 +1,5 @@
UCI_SECTION="ruantiblock.config"
UCI_VARS="proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp add_user_entries user_entries_dns user_entries_remote enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup enable_tmp_downloads"
UCI_VARS="dnsmasq_cfg_dir proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_type t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup enable_tmp_downloads"
UCI_CMD=`which uci`
if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2
@@ -0,0 +1,54 @@
UCI_VARS="u_enabled u_proxy_mode u_tor_trans_port u_onion_dns_addr u_if_vpn u_vpn_gw_ip u_t_proxy_type u_t_proxy_port_tcp u_t_proxy_port_udp u_t_proxy_allow_udp u_entries_dns u_entries_remote u_enable_entries_remote_proxy u_enable_fproxy u_fproxy_list u_skip_marked_packets"
UCI_CMD=`which uci`
if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2
exit 1
fi
AWK_CMD="awk"
ListUserInstances() {
$UCI_CMD export "$NAME" | $AWK_CMD -v TYPE="user_instance" '
BEGIN {
instances="";
}
{
if($0 ~ "config "TYPE) {
gsub(/["\047]/, "", $3);
instances=instances (length(instances) > 0 ? "\n" : "") $3;
};
}
END {
print instances;
}'
}
IncludeUserInstanceVars() {
local _inst="$1"
local _uci_section="${NAME}.${_inst}"
U_NAME="$_inst"
eval `$UCI_CMD show "$_uci_section" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
BEGIN {
split(UCI_VARS, split_array, " ");
for(i in split_array)
vars_array[split_array[i]]="";
}
{
sub(/^.*[.]/, "", $1);
gsub(/["\047]/, "", $2);
if($1 in vars_array) {
print toupper($1) "=\"" $2 "\"";
delete vars_array[$1];
};
}
END {
if(length(vars_array) > 0) {
for(i in vars_array)
print toupper(i) "=\"""\"";
};
}'`
if [ $DEBUG -ge 2 ]; then
echo " user_instances_config_script.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}" >&2
MakeLogRecord "debug" "user_instances_config_script.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}"
fi
}
@@ -1,5 +1,5 @@
Info() {
local _update_status _user_entries_status
local _update_status _user_entries_status _inst
if [ -f "$UPDATE_STATUS_FILE" ]; then
_update_status=`$AWK_CMD '{
if(NF < 4) {
@@ -33,29 +33,30 @@ Info() {
else
_user_entries_status="[]"
fi
NftListBllistChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v USER_ENTRIES_STATUS="$_user_entries_status" '
BEGIN {
rules_str = "";
}
{
rules_str = rules_str $0;
}
NftListSinkChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v USER_ENTRIES_STATUS="$_user_entries_status" '
END {
if(NR == 0) {
printf "{\"status\": \"disabled\"}";
exit 1;
} else {
printf "{\"status\":\"enabled\",\"last_blacklist_update\":%s,\"user_entries\":%s,\"rules\":%s", UPDATE_STATUS, USER_ENTRIES_STATUS, rules_str;
printf "{\"status\": \"enabled\",\"last_blacklist_update\": %s,\"user_entries\" :%s,\"sink\": %s", UPDATE_STATUS, USER_ENTRIES_STATUS, $0;
exit 0;
};
}'
if [ $? -eq 0 ]; then
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
printf ",\"sink_local\":"
NftListSinkLocalChainJson 2> /dev/null
fi
printf ",\"dnsmasq\":"
$NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ" 2> /dev/null
if [ "$BYPASS_MODE" = "1" ]; then
printf ",\"dnsmasq_bypass\":"
$NFT_CMD -j list set $NFT_TABLE "$NFTSET_BYPASS_FQDN" 2> /dev/null
fi
printf ",\"dnsmasq_user_instances\":["
for _inst in $USER_INSTANCES_ALL
do
$NFT_CMD -j list set $NFT_TABLE "${NFTSET_DNSMASQ}-${_inst}" 2> /dev/null
printf ","
done
printf "{\"dummy\": {}}]"
printf "}"
fi
}
@@ -2,35 +2,26 @@ NFT_ALLOWED_HOSTS_CHAIN="allowed_hosts"
NFT_BLLIST_CHAIN="blacklist"
NFT_FPROXY_FILTER="fproxy_filter"
NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN="dnsmasq_timeout_update"
NFT_ACTION_CHAIN="action"
NFT_MARK_CHAIN="mark_chain"
NFT_LOCAL_CLIENTS_CHAIN="local_clients"
if [ "$PROXY_MODE" = "2" ]; then
MAIN_CHAIN_TYPE="type filter hook prerouting priority ${NFT_PRIO_ROUTE}; policy accept;"
LOCAL_CLIENTS_CHAIN_TYPE="type route hook output priority ${NFT_PRIO_ROUTE_LOCAL}; policy accept;"
else
MAIN_CHAIN_TYPE="type nat hook prerouting priority ${NFT_PRIO_NAT}; policy accept;"
LOCAL_CLIENTS_CHAIN_TYPE="type nat hook output priority ${NFT_PRIO_NAT_LOCAL}; policy accept;"
fi
NFT_SINK_CHAIN="sink"
NFT_SINK_LOCAL_CHAIN="sink_local"
NFT_ACTION_FILTER_CHAIN="action_filter"
NFT_ACTION_NAT_CHAIN="action_nat"
NFT_ACTION_NAT_LOCAL_CHAIN="action_nat_local"
case "$ALLOWED_HOSTS_MODE" in
"1")
NFT_ALLOWED_HOSTS_EXPR="ip saddr @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}"
NFT_ALLOWED_HOSTS_PATTERN="ip saddr @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}%s"
;;
"2")
NFT_ALLOWED_HOSTS_EXPR="ip saddr != @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}"
NFT_ALLOWED_HOSTS_PATTERN="ip saddr != @${NFTSET_ALLOWED_HOSTS} jump ${NFT_BLLIST_CHAIN}%s"
;;
*)
NFT_ALLOWED_HOSTS_EXPR="jump ${NFT_BLLIST_CHAIN}"
NFT_ALLOWED_HOSTS_PATTERN="jump ${NFT_BLLIST_CHAIN}%s"
;;
esac
if [ "$NFTSET_DNSMASQ_TIMEOUT_UPDATE" = "1" ]; then
NFT_DNSMASQ_RULE_TARGET="$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
else
NFT_DNSMASQ_RULE_TARGET="$NFT_ACTION_CHAIN"
fi
NftCmdWrapper() {
local _i=0 _attempts=10 _return_code=1
while [ $_i -lt $_attempts ]
@@ -44,105 +35,247 @@ NftCmdWrapper() {
return $_return_code
}
NftVpnRouteDelete() {
$IP_CMD route flush table $VPN_ROUTE_TABLE_ID
$IP_CMD rule del table $VPN_ROUTE_TABLE_ID
NftRouteDelete() {
local _route_table_id=$1
$IP_CMD route flush table $_route_table_id
$IP_CMD rule del table $_route_table_id
}
NftVpnRouteAdd() {
local _vpn_ip
if [ -n "$VPN_GW_IP" ]; then
_vpn_ip="$VPN_GW_IP"
NftRouteAdd() {
local _vpn_ip _type="$1" _route_table_id=$2 _pkts_mark=$3 _if_vpn="$4" _vpn_gw_ip="$5"
if [ "$_type" = "lo" ]; then
echo 0 > /proc/sys/net/ipv4/conf/lo/rp_filter
$IP_CMD rule add fwmark $_pkts_mark table $_route_table_id priority $LO_RULE_PRIO
$IP_CMD route add local default dev lo table $_route_table_id
if [ $DEBUG -ge 1 ]; then
echo " nft_functions.NftRouteAdd: ${IP_CMD} rule add fwmark ${_pkts_mark} table ${_route_table_id} priority ${LO_RULE_PRIO}" >&2
MakeLogRecord "debug" "nft_functions.NftRouteAdd: ${IP_CMD} rule add fwmark ${_pkts_mark} table ${_route_table_id} priority ${LO_RULE_PRIO}"
echo " nft_functions.NftRouteAdd: ${IP_CMD} route add local default dev lo table ${_route_table_id}" >&2
MakeLogRecord "debug" "nft_functions.NftRouteAdd: ${IP_CMD} route add local default dev lo table ${_route_table_id}"
fi
else
_vpn_ip=`$IP_CMD addr list dev $IF_VPN 2> /dev/null | $AWK_CMD '/inet/{f=($3 == "peer") ? 4 : 2; sub("/[0-9]{1,2}$", "", $f); print $f; exit}'`
fi
if [ -n "$_vpn_ip" ]; then
echo 0 > /proc/sys/net/ipv4/conf/$IF_VPN/rp_filter
NftVpnRouteDelete 2> /dev/null
$IP_CMD rule add fwmark $VPN_PKTS_MARK table $VPN_ROUTE_TABLE_ID priority $VPN_RULE_PRIO
$IP_CMD route add default via $_vpn_ip table $VPN_ROUTE_TABLE_ID
if [ -n "$_vpn_gw_ip" ]; then
_vpn_ip="$_vpn_gw_ip"
else
_vpn_ip=`$IP_CMD addr list dev $_if_vpn 2> /dev/null | $AWK_CMD '/inet/{f=($3 == "peer") ? 4 : 2; sub("/[0-9]{1,2}$", "", $f); print $f; exit}'`
fi
if [ -n "$_vpn_ip" -a "$_type" = "vpn" ]; then
echo 0 > /proc/sys/net/ipv4/conf/$_if_vpn/rp_filter
NftRouteDelete $_route_table_id 2> /dev/null
$IP_CMD rule add fwmark $_pkts_mark table $_route_table_id priority $VPN_RULE_PRIO
$IP_CMD route add default via $_vpn_ip table $_route_table_id
if [ $? -ne 0 ]; then
echo " Error! An error occurred while adding the route. Routing table id=${_route_table_id}, VPN gateway IP=${_vpn_ip}" >&2
MakeLogRecord "err" "Error! An error occurred while adding the route. Routing table id=${_route_table_id}, VPN gateway IP=${_vpn_ip}"
fi
if [ $DEBUG -ge 1 ]; then
echo " nft_functions.NftRouteAdd: ${IP_CMD} rule add fwmark ${_pkts_mark} table ${_route_table_id} priority ${VPN_RULE_PRIO}" >&2
MakeLogRecord "debug" "nft_functions.NftRouteAdd: ${IP_CMD} rule add fwmark ${_pkts_mark} table ${_route_table_id} priority ${VPN_RULE_PRIO}"
echo " nft_functions.NftRouteAdd: ${IP_CMD} route add default via ${_vpn_ip} table ${_route_table_id}" >&2
MakeLogRecord "debug" "nft_functions.NftRouteAdd: ${IP_CMD} route add default via ${_vpn_ip} table ${_route_table_id}"
fi
fi
fi
}
NftVpnRouteStatus() {
[ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0
NftRouteStatus() {
local _route_table_id=$1
[ -n "`$IP_CMD route show table $_route_table_id 2> /dev/null`" ] && return 0
return 1
}
NftMainAdd() {
local _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_FPROXY_FILTER"
$NFT_CMD add chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_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_FPROXY_FILTER ip daddr "@${NFTSET_FPROXY_PRIVATE}" return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_FILTER" jump "$NFT_ACTION_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" ct state new set update ip daddr "@${NFTSET_DNSMASQ}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" jump "$NFT_ACTION_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" $NFT_ALLOWED_HOSTS_EXPR
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
NftAddSinkChains() {
local _chain_prio_sink=$1
$NFT_CMD add chain $NFT_TABLE "${NFT_SINK_CHAIN}" { type filter hook prerouting priority ${_chain_prio_sink}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" { type route hook output priority ${_chain_prio_sink}\; policy accept\; }
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta iif lo return
}
NftDeleteSinkChains() {
$NFT_CMD delete chain $NFT_TABLE "${NFT_SINK_CHAIN}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}"
}
NftAddActionChains() {
local _chain_prio_action=$1
$NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_FILTER_CHAIN}" { type filter hook prerouting priority ${_chain_prio_action}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}" { type nat hook prerouting priority ${_chain_prio_action}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}" { type nat hook output priority ${_chain_prio_action}\; policy accept\; }
}
NftDeleteActionChains() {
$NFT_CMD delete chain $NFT_TABLE "${NFT_ACTION_FILTER_CHAIN}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}"
}
NftInstanceAdd() {
local _i _inst _first_chain_type _t_proxy_statement _chain_action_type _set
for _i in "_name" "_pkts_mark" "_chain_prio_first" "_chain_prio_local" "_proxy_mode" "_tor_trans_port" "_route_table_id" "_if_vpn" "_t_proxy_type" "_t_proxy_port_tcp" "_t_proxy_port_udp" "_t_proxy_allow_udp" "_enable_bllist_proxy" "_enable_fproxy" "_skip_marked_packets" "_vpn_gw_ip"
do
eval "local $_i=$1"
shift
done
_inst="$_name"
if [ "$_name" = " " ]; then
_name=""
else
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $TOR_TRANS_PORT
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_ONION}" counter goto "$NFT_ACTION_CHAIN"
_name="-${_name}"
fi
if [ "$ENABLE_FPROXY" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip saddr "@${NFTSET_FPROXY}" counter goto "$NFT_FPROXY_FILTER"
if [ $DEBUG -ge 1 ]; then
echo " nft_functions.NftInstanceAdd.args: _name=${_name} _pkts_mark=${_pkts_mark} _chain_prio_first=${_chain_prio_first} _chain_prio_local=${_chain_prio_local} _proxy_mode=${_proxy_mode} _tor_trans_port=${_tor_trans_port} _route_table_id=${_route_table_id} _if_vpn=${_if_vpn} _t_proxy_type=${_t_proxy_type} _t_proxy_port_tcp=${_t_proxy_port_tcp} _t_proxy_port_udp=${_t_proxy_port_udp} _t_proxy_allow_udp=${_t_proxy_allow_udp} _enable_bllist_proxy=${_enable_bllist_proxy} _enable_fproxy=${_enable_fproxy} _skip_marked_packets=${_skip_marked_packets} _vpn_gw_ip=${_vpn_gw_ip}" >&2
MakeLogRecord "debug" "nft_functions.NftInstanceAdd.args: _name=${_name} _pkts_mark=${_pkts_mark} _chain_prio_first=${_chain_prio_first} _chain_prio_local=${_chain_prio_local} _proxy_mode=${_proxy_mode} _tor_trans_port=${_tor_trans_port} _route_table_id=${_route_table_id} _if_vpn=${_if_vpn} _t_proxy_type=${_t_proxy_type} _t_proxy_port_tcp=${_t_proxy_port_tcp} _t_proxy_port_udp=${_t_proxy_port_udp} _t_proxy_allow_udp=${_t_proxy_allow_udp} _enable_bllist_proxy=${_enable_bllist_proxy} _enable_fproxy=${_enable_fproxy} _skip_marked_packets=${_skip_marked_packets} _vpn_gw_ip=${_vpn_gw_ip}"
fi
if [ "$NFTSET_DNSMASQ_TIMEOUT_UPDATE" = "1" ]; then
_nft_dnsmasq_rule_target="${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}"
else
_nft_dnsmasq_rule_target="${NFT_MARK_CHAIN}${_name}"
fi
$NFT_CMD add chain $NFT_TABLE "${NFT_LOCAL_CLIENTS_CHAIN}${_name}" { type route hook output priority ${_chain_prio_local}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "${NFT_MARK_CHAIN}${_name}"
$NFT_CMD add chain $NFT_TABLE "${NFT_FPROXY_FILTER}${_name}"
$NFT_CMD add chain $NFT_TABLE "${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}"
$NFT_CMD add chain $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}"
$NFT_CMD add chain $NFT_TABLE "${NFT_ALLOWED_HOSTS_CHAIN}${_name}" { type filter hook prerouting priority ${_chain_prio_first}\; policy accept\; }
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_FPROXY_FILTER}${_name}" ip daddr "@${NFTSET_FPROXY_PRIVATE}" return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_FPROXY_FILTER}${_name}" jump "${NFT_MARK_CHAIN}${_name}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}" ct state new set update ip daddr "@${NFTSET_DNSMASQ}${_name}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}" jump "${NFT_MARK_CHAIN}${_name}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ALLOWED_HOSTS_CHAIN}${_name}" "`printf "$NFT_ALLOWED_HOSTS_PATTERN" "$_name"`"
if [ "$_proxy_mode" = "2" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta mark $_pkts_mark counter comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" meta mark $_pkts_mark counter comment \""$_inst"\"
elif [ "$_proxy_mode" = "3" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta l4proto tcp meta mark $_pkts_mark counter comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" meta l4proto tcp meta mark $_pkts_mark counter comment \""$_inst"\"
if [ "$_t_proxy_type" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_FILTER_CHAIN}" meta l4proto tcp meta mark $_pkts_mark tproxy to ":${_t_proxy_port_tcp}" comment \""$_inst"\"
if [ "$_t_proxy_allow_udp" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_FILTER_CHAIN}" meta l4proto udp meta mark $_pkts_mark tproxy to ":${_t_proxy_port_udp}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta l4proto udp meta mark $_pkts_mark counter comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" meta l4proto udp meta mark $_pkts_mark counter comment \""$_inst"\"
fi
else
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}" meta l4proto tcp meta mark $_pkts_mark redirect to ":${_t_proxy_port_tcp}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}" meta l4proto tcp meta mark $_pkts_mark redirect to ":${_t_proxy_port_tcp}" comment \""$_inst"\"
if [ "$_t_proxy_allow_udp" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}" meta l4proto udp meta mark $_pkts_mark redirect to ":${_t_proxy_port_udp}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}" meta l4proto udp meta mark $_pkts_mark redirect to ":${_t_proxy_port_udp}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta l4proto udp meta mark $_pkts_mark counter comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" meta l4proto udp meta mark $_pkts_mark counter comment \""$_inst"\"
fi
fi
elif [ "$_proxy_mode" != "2" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}" meta l4proto tcp meta mark $_pkts_mark redirect to ":${_tor_trans_port}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}" meta l4proto tcp meta mark $_pkts_mark redirect to ":${_tor_trans_port}" comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta l4proto tcp meta mark $_pkts_mark counter comment \""$_inst"\"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" meta l4proto tcp meta mark $_pkts_mark counter comment \""$_inst"\"
fi
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_MARK_CHAIN}${_name}" mark set $_pkts_mark
if [ "$_proxy_mode" != "2" -a "$_proxy_mode" != "3" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" ip daddr "@${NFTSET_ONION}${_name}" counter goto "${NFT_MARK_CHAIN}${_name}"
fi
if [ "$_skip_marked_packets" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" meta mark "@${NFTSET_MARK_SET}" return
fi
if [ "$_enable_fproxy" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" ip saddr "@${NFTSET_FPROXY}${_name}" goto "${NFT_FPROXY_FILTER}${_name}"
fi
if [ "$BYPASS_MODE" = "1" ]; then
for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN"
do
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${_set}" counter accept
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" ip daddr "@${_set}" accept
done
fi
for _set in "$NFTSET_CIDR" "$NFTSET_IP"
for _set in "${NFTSET_CIDR}${_name}" "${NFTSET_IP}${_name}"
do
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${_set}" counter goto "$NFT_ACTION_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" ip daddr "@${_set}" counter goto "${NFT_MARK_CHAIN}${_name}"
done
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_DNSMASQ}" counter goto "$NFT_DNSMASQ_RULE_TARGET"
if [ "$PROXY_MODE" = "2" ]; then
NftVpnRouteAdd
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}" ip daddr "@${NFTSET_DNSMASQ}${_name}" counter goto "$_nft_dnsmasq_rule_target"
if [ "$_proxy_mode" = "2" ]; then
NftRouteAdd vpn $_route_table_id $_pkts_mark "$_if_vpn" "$_vpn_gw_ip"
elif [ "$_proxy_mode" = "3" -a "$_t_proxy_type" = "1" ]; then
NftRouteAdd lo $_route_table_id $_pkts_mark
fi
if [ "$ENABLE_BLLIST_PROXY" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" ip daddr "@${NFTSET_BLLIST_PROXY}" counter goto "$NFT_ACTION_CHAIN"
if [ "$_enable_bllist_proxy" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_LOCAL_CLIENTS_CHAIN}${_name}" ip daddr "@${NFTSET_BLLIST_PROXY}${_name}" counter goto "${NFT_MARK_CHAIN}${_name}"
fi
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" jump "$NFT_BLLIST_CHAIN"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_LOCAL_CLIENTS_CHAIN}${_name}" jump "${NFT_BLLIST_CHAIN}${_name}"
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_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
$NFT_CMD delete chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN"
$NFT_CMD flush chain $NFT_TABLE "$NFT_FPROXY_FILTER"
$NFT_CMD delete chain $NFT_TABLE "$NFT_FPROXY_FILTER"
$NFT_CMD flush chain $NFT_TABLE "$NFT_ACTION_CHAIN"
$NFT_CMD delete chain $NFT_TABLE "$NFT_ACTION_CHAIN"
NftVpnRouteDelete 2> /dev/null
NftInstanceDelete() {
local _name="$1"
if [ -z "$_name" -o "$_name" = " " ]; then
_name=""
else
_name="-${_name}"
fi
$NFT_CMD delete chain $NFT_TABLE "${NFT_ALLOWED_HOSTS_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_LOCAL_CLIENTS_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_FPROXY_FILTER}${_name}"
$NFT_CMD delete chain $NFT_TABLE "${NFT_MARK_CHAIN}${_name}"
}
NftListBllistChain() {
$NFT_CMD -t list chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
local _name="$1"
if [ -z "$_name" -o "$_name" = " " ]; then
_name=""
else
_name="-${_name}"
fi
$NFT_CMD -t list chain $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}"
}
NftListBllistChainJson() {
$NFT_CMD -t -j list chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
local _name="$1"
if [ -z "$_name" -o "$_name" = " " ]; then
_name=""
else
_name="-${_name}"
fi
$NFT_CMD -t -j list chain $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}"
}
NftReturnStatus() {
$NFT_CMD -c add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" continue &> /dev/null
NftListSinkChain() {
$NFT_CMD -t list chain $NFT_TABLE "$NFT_SINK_CHAIN"
}
NftListSinkChainJson() {
$NFT_CMD -t -j list chain $NFT_TABLE "$NFT_SINK_CHAIN"
}
NftListSinkLocalChain() {
$NFT_CMD -t list chain $NFT_TABLE "$NFT_SINK_LOCAL_CHAIN"
}
NftListSinkLocalChainJson() {
$NFT_CMD -t -j list chain $NFT_TABLE "$NFT_SINK_LOCAL_CHAIN"
}
NftReturnInstanceStatus() {
local _name="$1"
if [ -z "$_name" -o "$_name" = " " ]; then
_name=""
else
_name="-${_name}"
fi
$NFT_CMD -c add rule $NFT_TABLE "${NFT_ALLOWED_HOSTS_CHAIN}${_name}" continue &> /dev/null
return $?
}
@@ -0,0 +1,75 @@
if [ $USER_INSTANCES_MAX -gt 50 ]; then
USER_INSTANCES_MAX=50
fi
IncludeUserInstanceVars() {
local _inst="$1"
. "${USER_INSTANCES_DIR}/${_inst}"
if [ $DEBUG -ge 2 ]; then
echo " user_instances_common.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}" >&2
MakeLogRecord "debug" "user_instances_common.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}"
fi
}
ClearUserInstanceVars() {
unset $USER_INSTANCE_VARS
}
ListUserInstances() {
ls -1 "$USER_INSTANCES_DIR"
}
[ -f "$CONFIG_SCRIPT_USER_INSTANCES" ] && . "$CONFIG_SCRIPT_USER_INSTANCES"
GetUserInstances() {
local _type="$1" _fnames="$2" _i=0 _inst _instances=""
for _inst in `ListUserInstances`
do
IncludeUserInstanceVars "$_inst"
if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then
if [ "$_type" = "0" -o "$U_PROXY_MODE" = "$_type" ]; then
if [ "$_fnames" = "fnames" ]; then
_instances="${_instances}${_inst} "
else
_instances="${_instances}${U_NAME} "
fi
fi
_i=$(($_i + 1))
fi
ClearUserInstanceVars
done
printf "$_instances"
}
SetUserInstancesItems() {
local _i=0 _inst _instances_all="" _instances_all_fnames="" _instances_vpn="" _instances_vpn_fnames="" _instances_cfg="" _instances_cfg_fnames=""
for _inst in `ListUserInstances`
do
IncludeUserInstanceVars "$_inst"
if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then
_instances_all="${_instances_all}${U_NAME} "
_instances_all_fnames="${_instances_all_fnames}${_inst} "
if [ "$U_PROXY_MODE" = "2" ]; then
_instances_vpn="${_instances_vpn}${U_NAME} "
_instances_vpn_fnames="${_instances_vpn_fnames}${_inst} "
fi
_i=$(($_i + 1))
fi
_instances_cfg="${_instances_cfg}${U_NAME} "
_instances_cfg_fnames="${_instances_cfg_fnames}${_inst} "
ClearUserInstanceVars
done
USER_INSTANCES_ALL="$_instances_all"
USER_INSTANCES_ALL_FNAMES="$_instances_all_fnames"
USER_INSTANCES_VPN="$_instances_vpn"
USER_INSTANCES_VPN_FNAMES="$_instances_vpn_fnames"
USER_INSTANCES_CFG="$_instances_cfg"
USER_INSTANCES_CFG_FNAMES="$_instances_cfg_fnames"
if [ $DEBUG -ge 2 ]; then
echo " user_instances_common.SetUserInstancesItems: USER_INSTANCES_ALL=\"${USER_INSTANCES_ALL}\"; USER_INSTANCES_ALL_FNAMES=\"${USER_INSTANCES_ALL_FNAMES}\"; USER_INSTANCES_VPN=\"${USER_INSTANCES_VPN}\"; USER_INSTANCES_VPN_FNAMES=\"${USER_INSTANCES_VPN_FNAMES}\"" >&2
MakeLogRecord "debug" "user_instances_common.SetUserInstancesItems: USER_INSTANCES_ALL=\"${USER_INSTANCES_ALL}\"; USER_INSTANCES_ALL_FNAMES=\"${USER_INSTANCES_ALL_FNAMES}\"; USER_INSTANCES_VPN=\"${USER_INSTANCES_VPN}\"; USER_INSTANCES_VPN_FNAMES=\"${USER_INSTANCES_VPN_FNAMES}\""
fi
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB