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 BLACKLIST=0
LUA_MODULE=0 LUA_MODULE=0
LUCI_APP=1 LUCI_APP=1
HTTPS_DNS_PROXY=1
OWRT_VERSION="22.03" OWRT_VERSION="current"
RUAB_VERSION="0.9.7-1" RUAB_VERSION="2.0.0-r1"
RUAB_MOD_LUA_VERSION="0.9.7-1" RUAB_MOD_LUA_VERSION="2.0.0-r1"
RUAB_LUCI_APP_VERSION="0.9.7-0" RUAB_LUCI_APP_VERSION="2.0.0-1"
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master" BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master"
PKG_DIR="/tmp" 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_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" URL_LUCI_APP_RU_PKG="${BASE_URL}/${OWRT_VERSION}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk"
### tor ### 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 ### 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" URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua"
### Local files ### 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" EXEC_DIR="${PREFIX}/usr/bin"
BACKUP_DIR="${RUAB_CFG_DIR}/autoinstall.bak.`date +%s`" BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`"
### packages ### packages
FILE_RUAB_PKG="${PKG_DIR}/ruantiblock_${RUAB_VERSION}_all.ipk" 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_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_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" FILE_LUCI_APP_RU_PKG="${PKG_DIR}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk"
### ruantiblock ### ruantiblock
FILE_CONFIG="${RUAB_CFG_DIR}/ruantiblock.conf" FILE_CONFIG="${CONFIG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${RUAB_CFG_DIR}/fqdn_filter" FILE_FQDN_FILTER="${CONFIG_DIR}/fqdn_filter"
FILE_IP_FILTER="${RUAB_CFG_DIR}/ip_filter" FILE_IP_FILTER="${CONFIG_DIR}/ip_filter"
FILE_USER_ENTRIES="${RUAB_CFG_DIR}/user_entries" 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_UCI_CONFIG="${PREFIX}/etc/config/ruantiblock"
FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock" FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock" FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
### tor ### tor
FILE_TORRC="${PREFIX}/etc/tor/torrc" FILE_TORRC="${PREFIX}/etc/tor/torrc"
### ruantiblock-mod-lua ### 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" FILE_LUA_IDN="${PREFIX}/usr/lib/lua/idn.lua"
AWK_CMD="awk" AWK_CMD="awk"
@@ -121,9 +125,13 @@ BackupFile() {
BackupCurrentConfig() { BackupCurrentConfig() {
local _file local _file
MakeDir "$BACKUP_DIR" 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 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 done
} }
@@ -136,11 +144,6 @@ AppStop() {
} }
AppStart() { 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 $FILE_INIT_SCRIPT start
} }
@@ -174,10 +177,11 @@ InstallPackages() {
InstallBaseConfig() { InstallBaseConfig() {
_return_code=1 _return_code=1
InstallPackages "ipset" "kmod-ipt-ipset" "dnsmasq-full" InstallPackages "dnsmasq-full" "kmod-nft-tproxy"
RemoveFile "$FILE_RUAB_PKG" > /dev/null RemoveFile "$FILE_RUAB_PKG" > /dev/null
DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null
_return_code=$? _return_code=$?
# костыль для остановки сервиса, который запускается автоматически после установки пакета!
AppStop AppStop
return $_return_code return $_return_code
} }
@@ -219,6 +223,7 @@ InstallTorConfig() {
TorrcSettings TorrcSettings
$UCI_CMD set ruantiblock.config.proxy_mode="1" $UCI_CMD set ruantiblock.config.proxy_mode="1"
$UCI_CMD commit ruantiblock $UCI_CMD commit ruantiblock
# dnsmasq rebind protection
$UCI_CMD set dhcp.@dnsmasq[0].rebind_domain='onion' $UCI_CMD set dhcp.@dnsmasq[0].rebind_domain='onion'
$UCI_CMD commit dhcp $UCI_CMD commit dhcp
} }
@@ -227,7 +232,6 @@ InstallLuaModule() {
InstallPackages "lua" "luasocket" "luasec" "luabitop" InstallPackages "lua" "luasocket" "luasec" "luabitop"
RemoveFile "$FILE_MOD_LUA_PKG" > /dev/null RemoveFile "$FILE_MOD_LUA_PKG" > /dev/null
DlFile "$URL_MOD_LUA_PKG" "$FILE_MOD_LUA_PKG" && $OPKG_CMD install "$FILE_MOD_LUA_PKG" 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" 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 set ruantiblock.config.bllist_module="/usr/libexec/ruantiblock/ruab_parser.lua"
$UCI_CMD commit ruantiblock $UCI_CMD commit ruantiblock
@@ -243,6 +247,10 @@ InstallLuciApp() {
/etc/init.d/uhttpd restart /etc/init.d/uhttpd restart
} }
InstallHttpsDnsProxy() {
InstallPackages "https-dns-proxy" "luci-app-https-dns-proxy" "luci-i18n-https-dns-proxy-ru"
}
PrintBold() { PrintBold() {
printf "\033[1m - ${1}\033[0m\n" printf "\033[1m - ${1}\033[0m\n"
} }
@@ -279,7 +287,7 @@ ConfirmProxyMode() {
ConfirmBlacklist() { ConfirmBlacklist() {
local _reply 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 read _reply
case $_reply in case $_reply in
1|"") 1|"")
@@ -343,6 +351,28 @@ ConfirmLuciApp() {
esac 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() { ConfirmProcessing() {
local _reply local _reply
printf " Next, the installation will begin... Continue? [ y | n ] (default: y, quit: q) > " printf " Next, the installation will begin... Continue? [ y | n ] (default: y, quit: q) > "
@@ -364,11 +394,13 @@ ConfirmProxyMode
ConfirmBlacklist ConfirmBlacklist
#ConfirmLuaModule #ConfirmLuaModule
ConfirmLuciApp ConfirmLuciApp
ConfirmHttpsDnsProxy
ConfirmProcessing ConfirmProcessing
AppStop AppStop
PrintBold "Updating packages list..." PrintBold "Updating packages list..."
UpdatePackagesList UpdatePackagesList
PrintBold "Saving current configuration..." PrintBold "Saving current configuration..."
#BackupCurrentConfig
PrintBold "Installing basic configuration..." PrintBold "Installing basic configuration..."
InstallBaseConfig InstallBaseConfig
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
@@ -388,7 +420,7 @@ if [ $? -eq 0 ]; then
fi fi
if [ $BLACKLIST = 2 ]; then if [ $BLACKLIST = 2 ]; then
PrintBold "Set RKN blacklist..." PrintBold "Set full blacklist..."
EnableBlacklist EnableBlacklist
fi fi
@@ -402,6 +434,11 @@ if [ $? -eq 0 ]; then
InstallLuciApp InstallLuciApp
fi fi
if [ $HTTPS_DNS_PROXY = 1 ]; then
PrintBold "Installing https-dns-proxy..."
InstallHttpsDnsProxy
fi
RunAtStartup RunAtStartup
SetCronTask SetCronTask
else else
@@ -4,19 +4,27 @@ PREFIX=""
### Local files ### 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" 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_VIEW="${PREFIX}/www/luci-static/resources/view"
HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock" HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock"
CRONTAB_FILE="/etc/crontabs/root" CRONTAB_FILE="/etc/crontabs/root"
DATA_DIR="/tmp/ruantiblock" 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 ### ruantiblock
FILE_CONFIG="${RUAB_CFG_DIR}/ruantiblock.conf" FILE_CONFIG="${CONFIG_DIR}/ruantiblock.conf"
FILE_FQDN_FILTER="${RUAB_CFG_DIR}/fqdn_filter" FILE_FQDN_FILTER="${CONFIG_DIR}/fqdn_filter"
FILE_IP_FILTER="${RUAB_CFG_DIR}/ip_filter" FILE_IP_FILTER="${CONFIG_DIR}/ip_filter"
FILE_USER_ENTRIES="${RUAB_CFG_DIR}/user_entries" 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_UCI_CONFIG="${PREFIX}/etc/config/ruantiblock"
FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock" FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock" FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
@@ -52,9 +60,13 @@ RemoveFile() {
BackupCurrentConfig() { BackupCurrentConfig() {
local _file local _file
MakeDir "$BACKUP_DIR" 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 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 done
} }
@@ -67,10 +79,12 @@ DisableStartup() {
} }
RemoveCronTask() { RemoveCronTask() {
$AWK_CMD -v FILE_MAIN_SCRIPT="$FILE_MAIN_SCRIPT" '$0 !~ FILE_MAIN_SCRIPT { if [ -e "$CRONTAB_FILE" ]; then
print $0; $AWK_CMD -v FILE_MAIN_SCRIPT="$FILE_MAIN_SCRIPT" '$0 !~ FILE_MAIN_SCRIPT {
}' "$CRONTAB_FILE" > "${CRONTAB_FILE}.tmp" && mv -f "${CRONTAB_FILE}.tmp" "$CRONTAB_FILE" print $0;
/etc/init.d/cron restart }' "$CRONTAB_FILE" > "${CRONTAB_FILE}.tmp" && mv -f "${CRONTAB_FILE}.tmp" "$CRONTAB_FILE"
/etc/init.d/cron restart
fi
} }
RestoreTorConfig() { RestoreTorConfig() {
@@ -85,9 +99,25 @@ RestoreTorConfig() {
RemoveAppFiles() { RemoveAppFiles() {
RestoreTorConfig RestoreTorConfig
$OPKG_CMD remove ruantiblock-mod-py ruantiblock-mod-lua luci-i18n-ruantiblock-ru luci-app-ruantiblock ruantiblock $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"
rm -f "$DNSMASQ_DATA_FILE_BYPASS"
rm -rf "$DATA_DIR"/* 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 rmdir "$HTDOCS_RUAB" 2> /dev/null
rm -f /tmp/luci-modulecache/* /tmp/luci-indexcache* rm -f /tmp/luci-modulecache/* /tmp/luci-indexcache*
/etc/init.d/rpcd restart /etc/init.d/rpcd restart
@@ -117,7 +147,7 @@ ConfirmRemove() {
ConfirmRemove ConfirmRemove
AppStop AppStop
#BackupCurrentConfig BackupCurrentConfig
DisableStartup DisableStartup
RemoveCronTask RemoveCronTask
RemoveAppFiles RemoveAppFiles
+3 -1
View File
@@ -4,7 +4,9 @@
include $(TOPDIR)/rules.mk 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_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock LUCI_DEPENDS:=+ruantiblock
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
@@ -10,26 +10,26 @@ return view.extend({
currentCrontabLines: [], currentCrontabLines: [],
toDD: function(n){ toDD(n){
return String(n).replace(/^(\d)$/, "0$1"); return String(n).replace(/^(\d)$/, "0$1");
}, },
cronStatusString: function(s) { cronStatusString(s) {
return s || _('No Sсhedule'); return s || _('No Sсhedule');
}, },
stringifyRuabTasks: function(str_array) { stringifyRuabTasks(str_array) {
let current_tasks = str_array.filter(s => s.match(this.crontabRegexp)); let current_tasks = str_array.filter(s => s.match(this.crontabRegexp));
return current_tasks.join('\n'); return current_tasks.join('\n');
}, },
setCronStatus: function(value) { setCronStatus(value) {
document.getElementById('cron_status').value = this.cronStatusString(value); document.getElementById('cron_status').value = this.cronStatusString(value);
document.getElementById("btn_cron_del").style.visibility = (value) ? document.getElementById("btn_cron_del").style.visibility = (value) ?
'visible' : 'hidden'; 'visible' : 'hidden';
}, },
writeCronFile: function() { writeCronFile() {
let btn_cron_add = document.getElementById('btn_cron_add'); let btn_cron_add = document.getElementById('btn_cron_add');
let btn_cron_del = document.getElementById('btn_cron_del'); let btn_cron_del = document.getElementById('btn_cron_del');
let crontab_string = this.currentCrontabLines.join('\n'); let crontab_string = this.currentCrontabLines.join('\n');
@@ -53,17 +53,17 @@ return view.extend({
}); });
}, },
delRuabShedules: function() { delRuabShedules() {
this.currentCrontabLines = this.currentCrontabLines.filter( this.currentCrontabLines = this.currentCrontabLines.filter(
s => s.match(this.crontabRegexp) ? false : true); s => s.match(this.crontabRegexp) ? false : true);
}, },
delCronSchedule: function(ev) { delCronSchedule(ev) {
this.delRuabShedules(); this.delRuabShedules();
return this.writeCronFile(); return this.writeCronFile();
}, },
setCronSchedule: function(ev) { setCronSchedule(ev) {
let hour_interval = document.getElementById('cron_hour_interval').value; let hour_interval = document.getElementById('cron_hour_interval').value;
let day_interval = document.getElementById('cron_day_interval').value; let day_interval = document.getElementById('cron_day_interval').value;
let hour = document.getElementById('cron_hour').value; let hour = document.getElementById('cron_hour').value;
@@ -88,7 +88,7 @@ return view.extend({
return this.writeCronFile(); return this.writeCronFile();
}, },
onchangeHourInterval: function(e) { onchangeHourInterval(e) {
let value = e.target.value; let value = e.target.value;
let bool = (value != ''); let bool = (value != '');
let cron_hour = document.getElementById('cron_hour'); let cron_hour = document.getElementById('cron_hour');
@@ -106,7 +106,7 @@ return view.extend({
}; };
}, },
load: function() { load() {
return fs.lines(tools.crontabFile).catch(e => { return fs.lines(tools.crontabFile).catch(e => {
ui.addNotification(null, E('p', _('Unable to read the contents') ui.addNotification(null, E('p', _('Unable to read the contents')
+ ': %s [ %s ]'.format( + ': %s [ %s ]'.format(
@@ -115,7 +115,7 @@ return view.extend({
}); });
}, },
render: function(content) { render(content) {
this.currentCrontabLines = content; this.currentCrontabLines = content;
let current_task = this.stringifyRuabTasks(content); let current_task = this.stringifyRuabTasks(content);
@@ -17,7 +17,7 @@ document.head.append(E('style', {'type': 'text/css'},
return view.extend({ return view.extend({
pollInterval : L.env.pollinterval, pollInterval : L.env.pollinterval,
secToTimeString: function(value) { secToTimeString(value) {
let string = ''; let string = '';
if(/^\d+$/.test(value)) { if(/^\d+$/.test(value)) {
value = Number(value); value = Number(value);
@@ -42,50 +42,103 @@ return view.extend({
return string; return string;
}, },
formatNftJson: function(data) { formatNftJson(data) {
let output = { 'rules': [] }; let output = { 'sink': [] };
if(data.rules.nftables && data.rules.nftables.length > 1) { if(data.sink.nftables && data.sink.nftables.length > 1) {
for(let i of data.rules.nftables) { let rules = [];
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 ]);
};
function parseDnsmasqData(set) { for(let i of data.sink.nftables) {
let sArray = []; if(i.rule) {
if(data[set].nftables && data[set].nftables.length > 1) { let instance = (i.rule.comment === ' ') ? '-main-' : i.rule.comment;
data[set].nftables.forEach(e => { let proto, bytes;
if(e.set && e.set.elem) { i.rule.expr.forEach(e => {
e.set.elem.forEach(i => { if(e.match && e.match.left && e.match.left.meta && e.match.left.meta.key && e.match.left.meta.key == "l4proto") {
if(i.elem) { proto = e.match.right;
sArray.push([ i.elem.val, i.elem.expires ]); }
}; else if(e.counter) {
}); bytes = e.counter.bytes;
}; };
}); });
rules.push([ instance, proto, bytes ]);
} else {
continue;
}; };
return sArray;
}; };
if(data.dnsmasq) { if(rules.length > 0) {
output.dnsmasq = parseDnsmasqData('dnsmasq'); 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; return output;
}, },
makeDnsmasqTable: function(ipDataArray) { makeDnsmasqTable(ipDataArray, title) {
let lines = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`; let lines = `<tr class="tr"><td class="td center">${_('No entries available...')}</td></tr>`;
let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' }); let ipTable = E('table', { 'id': 'ipTable', 'class': 'table' });
@@ -122,6 +175,7 @@ return view.extend({
}; };
return E([ return E([
E('h3', {}, title),
E('div', { 'class': 'log-entries-count' }, E('div', { 'class': 'log-entries-count' },
`${_('Entries')}: ${ipDataArray.length}` `${_('Entries')}: ${ipDataArray.length}`
), ),
@@ -129,7 +183,7 @@ return view.extend({
]); ]);
}, },
pollInfo: function() { pollInfo() {
return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => { return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => {
ui.addNotification(null, E('p', _('Unable to execute or read contents') ui.addNotification(null, E('p', _('Unable to execute or read contents')
+ ': %s [ %s ]'.format(e.message, tools.execPath) + ': %s [ %s ]'.format(e.message, tools.execPath)
@@ -174,11 +228,20 @@ return view.extend({
let nft_data = this.formatNftJson(data); let nft_data = this.formatNftJson(data);
if(nft_data.rules.length > 0) { if(nft_data.sink.length > 0) {
for(let [set, bytes] of nft_data.rules) { for(let i of nft_data.sink) {
let elem = document.getElementById('rules.' + set); let elem = document.getElementById('sink.' + i[0] + '.' + (i[1] || 'all'));
if(elem) { 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'); let rdTableWrapper = document.getElementById('rdTableWrapper');
if(rdTableWrapper) { if(rdTableWrapper) {
rdTableWrapper.innerHTML = ''; rdTableWrapper.innerHTML = '';
rdTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq)); rdTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq, _('Dnsmasq')));
}; };
let rdbTableWrapper = document.getElementById('rdbTableWrapper'); let rdsTableWrapper = document.getElementById('rdsTableWrapper');
if(rdbTableWrapper) { if(rdsTableWrapper) {
rdbTableWrapper.innerHTML = ''; rdsTableWrapper.innerHTML = '';
rdbTableWrapper.append(this.makeDnsmasqTable(nft_data.dnsmasq_bypass)); for(let i of nft_data.dnsmasq_user_instances) {
rdsTableWrapper.append(this.makeDnsmasqTable(i[1], _('Dnsmasq') + ' ' + i[0]));
};
}; };
} else { } else {
if(poll.active()) { if(poll.active()) {
poll.stop(); poll.stop();
@@ -203,7 +267,7 @@ return view.extend({
}); });
}, },
load: function() { load() {
return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => { return fs.exec_direct(tools.execPath, [ 'html-info' ], 'json').catch(e => {
ui.addNotification(null, E('p', _('Unable to execute or read contents') ui.addNotification(null, E('p', _('Unable to execute or read contents')
+ ': %s [ %s ]'.format(e.message, tools.execPath) + ': %s [ %s ]'.format(e.message, tools.execPath)
@@ -211,7 +275,7 @@ return view.extend({
}) })
}, },
render: function(data) { render(data) {
if(!data) { if(!data) {
return; return;
}; };
@@ -220,11 +284,12 @@ return view.extend({
data = JSON.parse(data); data = JSON.parse(data);
} catch(e) {}; } catch(e) {};
let update_status = null, let update_status = null,
user_entries = null, user_entries = null,
rules = null, sink = null,
dnsmasq = null, sink_local = null,
dnsmasqBypass = null; dnsmasq = null,
dnsmasqUserInstances = null;
if(data) { if(data) {
if(data.status === 'enabled') { if(data.status === 'enabled') {
@@ -285,39 +350,87 @@ return view.extend({
let nft_data = this.formatNftJson(data); let nft_data = this.formatNftJson(data);
if(nft_data.rules) { if(nft_data.sink) {
let table_rules = E('table', { 'class': 'table' }, [ let table = E('table', { 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [ E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th left', 'style': 'min-width:33%' }, E('th', { 'class': 'th left', 'style': 'min-width:33%' },
_('Match-set')), _('Instance')),
E('th', { 'class': 'th left' }, _('Protocol')),
E('th', { 'class': 'th left' }, _('Bytes')), 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(!instance) {
if(!set) {
continue; continue;
}; };
table_rules.append( table.append(
E('tr', { 'class': 'tr' }, [ 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', { E('td', {
'class' : 'td left', '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'), 'data-title': _('Bytes'),
}, bytes), }, bytes),
]) ])
); );
};
rules = E([ };
E('h3', {}, _('Nftables rules')), sink = E([
table_rules, 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', { let rdTableWrapper = E('div', {
'id' : 'rdTableWrapper', 'id' : 'rdTableWrapper',
'style': 'width:100%' 'style': 'width:100%'
}, this.makeDnsmasqTable(nft_data.dnsmasq)); }, this.makeDnsmasqTable(nft_data.dnsmasq, _('Dnsmasq')));
dnsmasq = E([ dnsmasq = E([
E('h3', {}, _('Dnsmasq')),
rdTableWrapper, rdTableWrapper,
]); ]);
}; };
if(nft_data.dnsmasq_bypass) { if(nft_data.dnsmasq_user_instances) {
let rdbTableWrapper = E('div', { let rdsTableWrapper = E('div', {
'id' : 'rdbTableWrapper', 'id' : 'rdsTableWrapper',
'style': 'width:100%' 'style': 'width:100%'
}, this.makeDnsmasqTable(nft_data.dnsmasq_bypass)); });
dnsmasqBypass = E([ for(let i of nft_data.dnsmasq_user_instances) {
E('h3', {}, _('Dnsmasq bypass')), rdsTableWrapper.append(this.makeDnsmasqTable(i[1], _('Dnsmasq') + ' ' + i[0]));
rdbTableWrapper, };
]);
if(nft_data.dnsmasq_user_instances.length > 0) {
dnsmasqUserInstances = E([
rdsTableWrapper,
]);
};
}; };
poll.add(L.bind(this.pollInfo, this), this.pollInterval); 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-node' }, update_status)
), ),
E('div', { 'class': 'cbi-section fade-in' }, 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, layout.splice(5, 0,
E('div', { 'class': 'cbi-section fade-in' }, 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) { if(dnsmasq) {
layout.splice(6, 0, layout.splice(7, 0,
E('div', { 'class': 'cbi-section fade-in' }, E('div', { 'class': 'cbi-section fade-in' },
E('div', { 'class': 'cbi-section-node' }, dnsmasq) E('div', { 'class': 'cbi-section-node' }, dnsmasq)
) )
@@ -1,6 +1,7 @@
'use strict'; 'use strict';
'require baseclass'; 'require baseclass';
'require fs'; 'require fs';
'require ui';
'require view.ruantiblock.log-widget as widget'; 'require view.ruantiblock.log-widget as widget';
return baseclass.extend({ return baseclass.extend({
@@ -1,4 +1,5 @@
'use strict'; 'use strict';
'require baseclass';
'require fs'; 'require fs';
'require poll'; 'require poll';
'require uci'; 'require uci';
@@ -15,7 +16,121 @@ const btn_style_warning = 'btn cbi-button-negative important'
return view.extend({ return view.extend({
statusTokenValue: null, 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_start = elems[1] || document.getElementById("btn_start");
let btn_destroy = elems[4] || document.getElementById("btn_destroy"); let btn_destroy = elems[4] || document.getElementById("btn_destroy");
let btn_enable = elems[2] || document.getElementById("btn_enable"); let btn_enable = elems[2] || document.getElementById("btn_enable");
@@ -31,7 +146,7 @@ return view.extend({
}; };
}, },
getAppStatus: function() { getAppStatus() {
return Promise.all([ return Promise.all([
fs.exec(tools.execPath, [ 'raw-status' ]), fs.exec(tools.execPath, [ 'raw-status' ]),
fs.exec(tools.execPath, [ 'vpn-route-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'); let section = uci.get(tools.appName, 'config');
if(!status_array || typeof(section) !== 'object') { if(!status_array || typeof(section) !== 'object') {
(elems[0] || document.getElementById("status")).innerHTML = tools.makeStatusString(1); (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 app_status_code = (force_app_code) ? force_app_code : status_array[0].code;
let vpn_route_status_code = status_array[1].code; let vpn_route_status_code = status_array[1].code;
let enabled_flag = status_array[2]; let enabled_flag = status_array[2];
let proxy_local_clients = section.proxy_local_clients; let dnsmasq_cfg_dir = section.dnsmasq_cfg_dir;
let proxy_mode = section.proxy_mode;
let bllist_preset = section.bllist_preset; let bllist_preset = section.bllist_preset;
let bllist_module = section.bllist_module; let bllist_module = section.bllist_module;
@@ -122,7 +236,6 @@ return view.extend({
(elems[0] || document.getElementById("status")).innerHTML = tools.makeStatusString( (elems[0] || document.getElementById("status")).innerHTML = tools.makeStatusString(
app_status_code, app_status_code,
proxy_mode,
bllist_preset, bllist_preset,
bllist_module, bllist_module,
vpn_route_status_code); vpn_route_status_code);
@@ -132,7 +245,7 @@ return view.extend({
}; };
}, },
serviceAction: function(action, button) { serviceAction(action, button) {
if(button) { if(button) {
let elem = document.getElementById(button); let elem = document.getElementById(button);
this.disableButtons(true, elem); this.disableButtons(true, elem);
@@ -149,7 +262,7 @@ return view.extend({
}); });
}, },
appAction: function(action, button) { appAction(action, button) {
if(button) { if(button) {
let elem = document.getElementById(button); let elem = document.getElementById(button);
this.disableButtons(true, elem); this.disableButtons(true, elem);
@@ -167,13 +280,12 @@ return view.extend({
return this.getAppStatus().then( return this.getAppStatus().then(
(status_array) => { (status_array) => {
this.setAppStatus(status_array); this.setAppStatus(status_array);
ui.hideModal();
} }
); );
}); });
}, },
statusPoll: function() { statusPoll() {
return fs.read(tools.tokenFile).then(v => { return fs.read(tools.tokenFile).then(v => {
v = tools.normalizeValue(v); v = tools.normalizeValue(v);
if(v != this.statusTokenValue) { if(v != this.statusTokenValue) {
@@ -187,48 +299,21 @@ return view.extend({
}); });
}, },
dialogDestroy: function(ev) { load() {
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() {
return this.getAppStatus(); return this.getAppStatus();
}, },
render: function(status_array) { render(status_array) {
if(!status_array) { if(!status_array) {
return; return;
}; };
let section = uci.get(tools.appName, 'config'); 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)) ? this.statusTokenValue = (Array.isArray(status_array)) ?
tools.normalizeValue(status_array[4]) : null; tools.normalizeValue(status_array[4]) : null;
let dialog_destroy = new this.dialogDestroy(this);
let status_string = E('div', { let status_string = E('div', {
'id' : 'status', 'id' : 'status',
'name' : 'status', 'name' : 'status',
@@ -281,7 +366,7 @@ return view.extend({
'name' : 'btn_destroy', 'name' : 'btn_destroy',
'class': btn_style_negative, 'class': btn_style_negative,
}, _('Shutdown')); }, _('Shutdown'));
btn_destroy.onclick = L.bind(this.dialogDestroy, this); btn_destroy.onclick = () => dialog_destroy.show();
layout_append(btn_destroy, _('Shutdown'), layout_append(btn_destroy, _('Shutdown'),
_('Complete service shutdown, as well as deleting nftsets and blacklist data')); _('Complete service shutdown, as well as deleting nftsets and blacklist data'));
@@ -8,11 +8,11 @@
'require view.ruantiblock.tools as tools'; 'require view.ruantiblock.tools as tools';
return view.extend({ return view.extend({
parsers : {}, parsers : {},
appStatusCode: null, appStatusCode : null,
depends : function(elem, key, array, empty=true) { depends(elem, key, array, empty=true) {
if(empty && array.length === 0) { if(empty && array.length === 0) {
elem.depends(key, '_dummy'); elem.depends(key, '_dummy');
} else { } else {
@@ -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:') 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`; + ` ${_('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:') return (/^$|^https?:\/\/[\w.-]+(:[0-9]{2,5})?[\w\/~.&?+=-]*$/.test(value)) ? true : _('Expecting:')
+ ` ${_('valid URL')}\n`; + ` ${_('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([ return Promise.all([
L.resolveDefault(fs.exec(tools.execPath, [ 'raw-status' ]), 1), L.resolveDefault(fs.exec(tools.execPath, [ 'raw-status' ]), 1),
L.resolveDefault(fs.list(tools.parsersDir), null), L.resolveDefault(fs.list(tools.parsersDir), null),
L.resolveDefault(fs.list(tools.dnsmasqCfgDirsRoot), null),
uci.load(tools.appName), uci.load(tools.appName),
]).catch(e => { ]).catch(e => {
ui.addNotification(null, E('p', _('Unable to read the contents') ui.addNotification(null, E('p', _('Unable to read the contents')
@@ -43,14 +105,14 @@ return view.extend({
}); });
}, },
render: function(data) { render(data) {
if(!data) { if(!data) {
return; return;
}; };
this.appStatusCode = data[0].code; this.appStatusCode = data[0].code;
let p_dir_arr = data[1]; let p_dir_arr = data[1];
let curent_module = uci.get(tools.appName, 'config', 'bllist_module'); let curent_module = uci.get(tools.appName, 'config', 'bllist_module');
let curent_preset = uci.get(tools.appName, 'config', 'bllist_preset'); let curent_preset = uci.get(tools.appName, 'config', 'bllist_preset');
if(p_dir_arr) { if(p_dir_arr) {
p_dir_arr.forEach(e => { p_dir_arr.forEach(e => {
@@ -129,7 +191,7 @@ return view.extend({
'<br /><code>#comment<br />domain.net<br />anotherdomain.com</code>' '<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')); m = new form.Map(tools.appName, _('Ruantiblock') + ' - ' + _('Settings'));
@@ -140,39 +202,32 @@ return view.extend({
/* Main settings tab */ /* Main settings tab */
s.tab('main_settings', _('Main settings')); s.tab('main_tab', _('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;
// ENABLE_LOGGING // ENABLE_LOGGING
o = s.taboption('main_settings', form.Flag, 'enable_logging', o = s.taboption('main_tab', form.Flag, 'enable_logging',
_('Logging events')); _('Logging events'));
o.rmempty = false; o.rmempty = false;
// update_at_startup // 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')); _('Update at startup'));
o.description = _('Update blacklist after system startup'); o.description = _('Update blacklist after system startup');
o.rmempty = false; 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 // 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')); _('Clean up nftsets before updating blacklist'));
o.description = _('Reduces RAM consumption during update'); o.description = _('Reduces RAM consumption during update');
o.rmempty = false; o.rmempty = false;
// ALLOWED_HOSTS_MODE // 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')); _('Host filter'));
o.value('0', _('Disabled')); o.value('0', _('Disabled'));
o.value('1', _('Only listed hosts')); o.value('1', _('Only listed hosts'));
@@ -180,40 +235,29 @@ return view.extend({
o.description = _('Restriction of hosts that are allowed to bypass blocking'); o.description = _('Restriction of hosts that are allowed to bypass blocking');
// ALLOWED_HOSTS_LIST // 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')); _('IP addresses for host filter'));
o.datatype = 'ip4addr'; 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 */ /* Tor tab */
s.tab('tor_settings', _('Tor mode')); s.tab('tor_tab', _('Tor mode'));
// TOR_TRANS_PORT // 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')); _('Transparent proxy port'));
o.rmempty = false; o.rmempty = false;
o.datatype = 'port'; o.datatype = 'port';
// ONION_DNS_ADDR // 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>'); _("Optional DNS resolver for '.onion' zone"), '<code>ipaddress#port</code>');
o.rmempty = false; o.rmempty = false;
o.validate = this.validateIpPort; o.validate = this.validateIpPort;
// Torrc edit dialog // Torrc edit dialog
o = s.taboption('tor_settings', form.Button, '_torrc_btn', o = s.taboption('tor_tab', form.Button, '_torrc_btn',
_('Tor configuration file')); _('Tor configuration file'));
o.onclick = () => torrc_edit.show(); o.onclick = () => torrc_edit.show();
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
@@ -222,10 +266,10 @@ return view.extend({
/* VPN tab */ /* VPN tab */
s.tab('vpn_settings', _('VPN mode')); s.tab('vpn_tab', _('VPN mode'));
// IF_VPN // IF_VPN
o = s.taboption('vpn_settings', widgets.DeviceSelect, 'if_vpn', o = s.taboption('vpn_tab', widgets.DeviceSelect, 'if_vpn',
_('VPN interface')); _('VPN interface'));
o.multiple = false; o.multiple = false;
o.noaliases = true; o.noaliases = true;
@@ -233,13 +277,13 @@ return view.extend({
o.default = 'tun0'; o.default = 'tun0';
// VPN_GW_IP // 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'), _('VPN gateway IP address'),
_('If not specified, the VPN interface address is used (or peer address for PPP protocols)')); _('If not specified, the VPN interface address is used (or peer address for PPP protocols)'));
o.datatype = 'ip4addr(1)'; o.datatype = 'ip4addr(1)';
// VPN_ROUTE_CHECK // 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')); _('Type of adding a VPN rule to the routing table'));
o.value('0', 'hotplug.d'); o.value('0', 'hotplug.d');
o.value('1', 'ruab_route_check'); 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.'); _('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 // 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')); _('Transparent proxy TCP port'));
o.rmempty = false; o.rmempty = false;
o.datatype = 'port'; o.datatype = 'port';
// T_PROXY_ALLOW_UDP // 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')); _('Send UDP traffic to transparent proxy'));
o.rmempty = false; o.rmempty = false;
// T_PROXY_PORT_UDP // 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')); _('Transparent proxy UDP port'));
o.rmempty = false; o.rmempty = false;
o.datatype = 'port'; o.datatype = 'port';
/* Blacklist module tab */ /* Blacklist tab */
s.tab('blacklist_tab', _('Blacklist settings')); 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 // BLLIST_PRESET
let bllist_preset = s.taboption('blacklist_tab', form.ListValue, let bllist_preset = s.taboption('blacklist_tab', form.ListValue,
'bllist_preset', _('Blacklist update mode')); 'bllist_preset', _('Blacklist update mode'));
@@ -312,29 +370,16 @@ return view.extend({
o.rmempty = false; o.rmempty = false;
o.default = 0; o.default = 0;
// ADD_USER_ENTRIES // ENABLE_FPROXY
o = s.taboption('blacklist_tab', form.Flag, 'add_user_entries', o = s.taboption('blacklist_tab', form.Flag, 'enable_fproxy',
_('Enable user entries'), _('Add user entries to the blacklist when updating')); _('Enable full proxy mode'));
o.description = _('All traffic of the specified hosts passes through the proxy, without a blacklist');
o.rmempty = false; o.rmempty = false;
o.default = 0;
o.depends({ bllist_preset: '', '!reverse': true });
// USER_ENTRIES edit dialog // FPROXY_LIST
o = s.taboption('blacklist_tab', form.Button, '_user_entries_btn', o = s.taboption('blacklist_tab', form.DynamicList, 'fproxy_list',
_('User entries')); _('IP addresses for full proxy mode'));
o.onclick = () => user_entries_edit.show(); o.datatype = 'ip4addr';
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;
// BYPASS_MODE // BYPASS_MODE
o = s.taboption('blacklist_tab', form.Flag, '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>'); _('DNS server that is used for the FQDN entries of exclusion list'), '<code>ipaddress[#port]</code>');
o.validate = this.validateIpPort; o.validate = this.validateIpPort;
if(availableParsers) { if(availableParsers) {
bllist_preset.description += '<br /> ( * - ' + _('requires installed blacklist module') + ' )'; bllist_preset.description += '<br /> ( * - ' + _('requires installed blacklist module') + ' )';
@@ -398,10 +444,9 @@ return view.extend({
// BLLIST_GR_EXCLUDED_SLD_FILE edit dialog // BLLIST_GR_EXCLUDED_SLD_FILE edit dialog
o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_sld_btn', o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_sld_btn',
_('2nd level domains that are excluded from optimization')); _('2nd level domains that are excluded from optimization'));
o.onclick = () => gr_excluded_sld_edit.show(); o.onclick = () => gr_excluded_sld_edit.show();
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
//o.description = _('e.g:') + ' <code>livejournal.com</code>';
// BLLIST_ENABLE_IDN // BLLIST_ENABLE_IDN
o = s.taboption('parser_settings_tab', form.Flag, '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 // BLLIST_GR_EXCLUDED_NETS_FILE edit dialog
o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_nets_btn', o = s.taboption('parser_settings_tab', form.Button, '_gr_excluded_nets_btn',
_('IP subnet patterns (/24) that are excluded from optimization')); _('IP subnet patterns (/24) that are excluded from optimization'));
o.onclick = () => gr_excluded_nets_edit.show(); o.onclick = () => gr_excluded_nets_edit.show();
o.inputtitle = _('Edit'); o.inputtitle = _('Edit');
o.inputstyle = 'edit btn'; o.inputstyle = 'edit btn';
//o.description = _('e.g:') + ' <code>192.168.1.</code>';
// BLLIST_SUMMARIZE_IP // BLLIST_SUMMARIZE_IP
o = s.taboption('parser_settings_tab', form.Flag, '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', o = s.taboption('parser_settings_tab', form.Flag, 'bllist_summarize_cidr',
_("Summarize '/24' networks")); _("Summarize '/24' networks"));
o.rmempty = false; 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(); let map_promise = m.render();
@@ -469,12 +686,28 @@ return view.extend({
return map_promise; return map_promise;
}, },
handleSaveApply: function(ev, mode) { handleSave(ev, restart) {
return this.handleSave(ev).then(() => { 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'); 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', execPath : '/usr/bin/ruantiblock',
tokenFile : '/var/run/ruantiblock.token', tokenFile : '/var/run/ruantiblock.token',
parsersDir : '/usr/libexec/ruantiblock', parsersDir : '/usr/libexec/ruantiblock',
dnsmasqCfgDirsRoot: '/tmp',
torrcFile : '/etc/tor/torrc', torrcFile : '/etc/tor/torrc',
userEntriesFile : '/etc/ruantiblock/user_entries', userEntriesFile : '/etc/ruantiblock/user_entries',
userListsDir : '/etc/ruantiblock/user_lists',
bypassEntriesFile : '/etc/ruantiblock/bypass_entries', bypassEntriesFile : '/etc/ruantiblock/bypass_entries',
fqdnFilterFile : '/etc/ruantiblock/fqdn_filter', fqdnFilterFile : '/etc/ruantiblock/fqdn_filter',
ipFilterFile : '/etc/ruantiblock/ip_filter', ipFilterFile : '/etc/ruantiblock/ip_filter',
@@ -76,7 +78,7 @@ return baseclass.extend({
expect: { result: false } expect: { result: false }
}), }),
getInitStatus: function(name) { getInitStatus(name) {
return this.callInitStatus(name).then(res => { return this.callInitStatus(name).then(res => {
if(res) { if(res) {
return res[name].enabled; 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 => { return this.callInitAction(name, action).then(success => {
if(!success) { if(!success) {
throw _('Command failed'); 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; return (v && typeof(v) === 'string') ? v.trim().replace(/\r?\n/g, '') : v;
}, },
makeStatusString: function( makeStatusString: function(
app_status_code, app_status_code,
proxy_mode,
bllist_preset, bllist_preset,
bllist_module, bllist_module,
vpn_route_status_code) { vpn_route_status_code) {
@@ -152,14 +153,6 @@ return baseclass.extend({
%s %s %s %s
</td> </td>
</tr> </tr>
<tr class="tr">
<td class="td left">
${_('Proxy mode')}:
</td>
<td class="td left">
%s
</td>
</tr>
<tr class="tr"> <tr class="tr">
<td class="td left"> <td class="td left">
${_('Blacklist update mode')}: ${_('Blacklist update mode')}:
@@ -172,10 +165,9 @@ return baseclass.extend({
`.format( `.format(
spinning, spinning,
app_status_label, 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">' ? '<span class="label-status error">'
+ _('VPN routing error! Need restart') + '</span>' : '', + _('VPN routing error! Need restart') + '</span>' : '',
(proxy_mode == 3) ? _('Transparent proxy') : (proxy_mode == 2) ? 'VPN' : 'Tor',
(!bllist_preset || bllist_preset === '') ? _('user entries only') : (!bllist_preset || bllist_preset === '') ? _('user entries only') :
(this.blacklistPresets[bllist_preset]) ? (this.blacklistPresets[bllist_preset]) ?
`<span style="cursor:help; border-bottom:1px dotted" data-tooltip="${this.blacklistPresets[bllist_preset][2]}"> `<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({ fileEditDialog: baseclass.extend({
__init__: function(file, title, description, callback, file_exists=false) { __init__(file, title, description, callback, file_exists=false) {
this.file = file; this.file = file;
this.title = title; this.title = title;
this.description = description; this.description = description;
@@ -193,11 +185,11 @@ return baseclass.extend({
this.file_exists = file_exists; this.file_exists = file_exists;
}, },
load: function() { load() {
return L.resolveDefault(fs.read(this.file), ''); return L.resolveDefault(fs.read(this.file), '');
}, },
render: function(content) { render(content) {
ui.showModal(this.title, [ ui.showModal(this.title, [
E('div', { 'class': 'cbi-section' }, [ E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-section-descr' }, this.description), 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 textarea = document.getElementById('widget.modal_content');
let value = textarea.value.trim().replace(/\r\n/g, '\n') + '\n'; 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') { if(!this.file_exists && e instanceof Error && e.name === 'NotFoundError') {
return this.render(); return this.render();
} else { } else {
@@ -268,7 +260,7 @@ return baseclass.extend({
}; };
}, },
show: function() { show() {
ui.showModal(null, ui.showModal(null,
E('p', { 'class': 'spinning' }, _('Loading')) E('p', { 'class': 'spinning' }, _('Loading'))
); );
+50 -5
View File
@@ -70,6 +70,9 @@ msgstr "Байты"
msgid "Cancel" msgid "Cancel"
msgstr "Отмена" msgstr "Отмена"
msgid "Change dnsmasq config directory"
msgstr "Изменить директорию конфигов dnsmasq"
msgid "Changes have been saved." msgid "Changes have been saved."
msgstr "Изменения сохранены." msgstr "Изменения сохранены."
@@ -110,12 +113,18 @@ msgstr "День"
msgid "Debug" msgid "Debug"
msgstr "Отладка" msgstr "Отладка"
msgid "Description"
msgstr "Описание"
msgid "Disabled" msgid "Disabled"
msgstr "Отключено" msgstr "Отключено"
msgid "Dismiss" msgid "Dismiss"
msgstr "Закрыть" msgstr "Закрыть"
msgid "Dnsmasq config directory"
msgstr "Директория конфигов dnsmasq"
msgid "Download error" msgid "Download error"
msgstr "Ошибка загрузки" msgstr "Ошибка загрузки"
@@ -125,9 +134,15 @@ msgstr "Скачать журнал"
msgid "Downloading a blacklist via proxy" msgid "Downloading a blacklist via proxy"
msgstr "Скачивать блэклист через прокси" msgstr "Скачивать блэклист через прокси"
msgid "Downloading files via proxy"
msgstr "Скачивать файлы через прокси"
msgid "Edit" msgid "Edit"
msgstr "Изменить" msgstr "Изменить"
msgid "Edit entries"
msgstr "Изменить записи"
msgid "Emergency" msgid "Emergency"
msgstr "Чрезвычайная ситуация" msgstr "Чрезвычайная ситуация"
@@ -233,15 +248,15 @@ msgstr "Шаблоны IP подсетей (/24) не подлежащих оп
msgid "Info" msgid "Info"
msgstr "Информация" msgstr "Информация"
msgid "Instance"
msgstr "Экземпляр"
msgid "Interval" msgid "Interval"
msgstr "Интервал" msgstr "Интервал"
msgid "Invalid regular expression" msgid "Invalid regular expression"
msgstr "Неправильное регулярное выражение" msgstr "Неправильное регулярное выражение"
msgid "Nftables rules"
msgstr "Правила nftables"
msgid "Last blacklist update" msgid "Last blacklist update"
msgstr "Последнее обновление блэклиста" msgstr "Последнее обновление блэклиста"
@@ -257,6 +272,9 @@ msgstr "Список хостов, которые исключаются из о
msgid "Loading" msgid "Loading"
msgstr "Загрузка" msgstr "Загрузка"
msgid "Local traffic"
msgstr "Локальный трафик"
msgid "Log" msgid "Log"
msgstr "Лог" msgstr "Лог"
@@ -269,6 +287,9 @@ msgstr "Уровни логирования"
msgid "Logread not found" msgid "Logread not found"
msgstr "Logread не найден" msgstr "Logread не найден"
msgid "Lowest priority"
msgstr "Самый низкий приоритет"
msgid "Main settings" msgid "Main settings"
msgstr "Основные настройки" msgstr "Основные настройки"
@@ -373,9 +394,15 @@ msgstr "Отбор IP адресов из блэклиста по шаблона
msgid "Pick domains from blacklist by FQDN filter patterns" msgid "Pick domains from blacklist by FQDN filter patterns"
msgstr "Отбор доменов из блэклиста по шаблонам фильтра FQDN" msgstr "Отбор доменов из блэклиста по шаблонам фильтра FQDN"
msgid "Protocol"
msgstr "Протокол"
msgid "Proxy mode" msgid "Proxy mode"
msgstr "Режим прокси" msgstr "Режим прокси"
msgid "Proxy type"
msgstr "Тип прокси"
msgid "Reduces RAM consumption during update" msgid "Reduces RAM consumption during update"
msgstr "Уменьшает потребление оперативной памяти при обновлении" msgstr "Уменьшает потребление оперативной памяти при обновлении"
@@ -418,8 +445,11 @@ msgstr "Настройки"
msgid "Shutdown" msgid "Shutdown"
msgstr "Выключение" msgstr "Выключение"
msgid "Size in memory" msgid "Skip marked packets"
msgstr "Размер в памяти" msgstr "Пропускать помеченные пакеты"
msgid "Skip packets that have already been marked in previous rules"
msgstr "Пропускать пакеты, которые уже были помечены в предыдущих правилах"
msgid "Sorting entries" msgid "Sorting entries"
msgstr "Сортировка записей" msgstr "Сортировка записей"
@@ -430,6 +460,9 @@ msgstr "Запускается"
msgid "Statistics" msgid "Statistics"
msgstr "Статистика" msgstr "Статистика"
msgid "Statement in nftables rules"
msgstr "Действие в правилах nftables"
msgid "Status" msgid "Status"
msgstr "Статус" msgstr "Статус"
@@ -469,6 +502,9 @@ msgid ""
msgstr "" msgstr ""
"Служба будет выключена и все данные блэклиста будут удалены. Продолжить?" "Служба будет выключена и все данные блэклиста будут удалены. Продолжить?"
msgid "This proxy will receive traffic last, even after the main blacklist"
msgstr "В этот прокси трафик будет попадать в последнюю очередь, даже после основного блэклиста"
msgid "Time" msgid "Time"
msgstr "Время" msgstr "Время"
@@ -487,6 +523,9 @@ msgstr "Конфигурационный файл Tor"
msgid "Tor mode" msgid "Tor mode"
msgstr "Режим Tor" msgstr "Режим Tor"
msgid "Transit traffic"
msgstr "Транзитный трафик"
msgid "Transparent proxy" msgid "Transparent proxy"
msgstr "Прозрачный прокси" msgstr "Прозрачный прокси"
@@ -505,6 +544,9 @@ msgstr "UDP порт прозрачного прокси"
msgid "Turn on if blacklist source is blocked" msgid "Turn on if blacklist source is blocked"
msgstr "Включите, если источник блэклиста заблокирован" msgstr "Включите, если источник блэклиста заблокирован"
msgid "Turn on if files are blocked"
msgstr "Включите, если файлы заблокированы"
msgid "Type a search pattern..." msgid "Type a search pattern..."
msgstr "Введите шаблон для поиска" msgstr "Введите шаблон для поиска"
@@ -568,6 +610,9 @@ msgstr "Ошибка маршрутизации VPN! Необходим пере
msgid "Warning" msgid "Warning"
msgstr "Внимание" msgstr "Внимание"
msgid "all"
msgstr "все"
msgid "ascending" msgid "ascending"
msgstr "по возрастанию" msgstr "по возрастанию"
@@ -55,6 +55,9 @@ msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
msgid "Change dnsmasq config directory"
msgstr ""
msgid "Changes have been saved." msgid "Changes have been saved."
msgstr "" msgstr ""
@@ -95,12 +98,18 @@ msgstr ""
msgid "Debug" msgid "Debug"
msgstr "" msgstr ""
msgid "Description"
msgstr ""
msgid "Disabled" msgid "Disabled"
msgstr "" msgstr ""
msgid "Dismiss" msgid "Dismiss"
msgstr "" msgstr ""
msgid "Dnsmasq config directory"
msgstr ""
msgid "Download error" msgid "Download error"
msgstr "" msgstr ""
@@ -110,9 +119,15 @@ msgstr ""
msgid "Downloading a blacklist via proxy" msgid "Downloading a blacklist via proxy"
msgstr "" msgstr ""
msgid "Downloading files via proxy"
msgstr ""
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
msgid "Edit entries"
msgstr ""
msgid "Emergency" msgid "Emergency"
msgstr "" msgstr ""
msgid "Enable" msgid "Enable"
@@ -214,15 +229,15 @@ msgstr ""
msgid "Info" msgid "Info"
msgstr "" msgstr ""
msgid "Instance"
msgstr ""
msgid "Interval" msgid "Interval"
msgstr "" msgstr ""
msgid "Invalid regular expression" msgid "Invalid regular expression"
msgstr "" msgstr ""
msgid "Nftables rules"
msgstr ""
msgid "Last blacklist update" msgid "Last blacklist update"
msgstr "" msgstr ""
@@ -238,6 +253,9 @@ msgstr ""
msgid "Loading" msgid "Loading"
msgstr "" msgstr ""
msgid "Local traffic"
msgstr ""
msgid "Log" msgid "Log"
msgstr "" msgstr ""
@@ -250,6 +268,9 @@ msgstr ""
msgid "Logread not found" msgid "Logread not found"
msgstr "" msgstr ""
msgid "Lowest priority"
msgstr ""
msgid "Main settings" msgid "Main settings"
msgstr "" msgstr ""
@@ -342,9 +363,15 @@ msgstr ""
msgid "Pick domains from blacklist by FQDN filter patterns" msgid "Pick domains from blacklist by FQDN filter patterns"
msgstr "" msgstr ""
msgid "Protocol"
msgstr ""
msgid "Proxy mode" msgid "Proxy mode"
msgstr "" msgstr ""
msgid "Proxy type"
msgstr ""
msgid "Reduces RAM consumption during update" msgid "Reduces RAM consumption during update"
msgstr "" msgstr ""
@@ -386,9 +413,6 @@ msgstr ""
msgid "Shutdown" msgid "Shutdown"
msgstr "" msgstr ""
msgid "Size in memory"
msgstr ""
msgid "Sorting entries" msgid "Sorting entries"
msgstr "" msgstr ""
@@ -397,6 +421,10 @@ msgstr ""
msgid "Statistics" msgid "Statistics"
msgstr "" msgstr ""
msgid "Statement in nftables rules"
msgstr ""
msgid "Status" msgid "Status"
msgstr "" msgstr ""
@@ -429,6 +457,9 @@ msgid ""
"Continue?" "Continue?"
msgstr "" msgstr ""
msgid "This proxy will receive traffic last, even after the main blacklist"
msgstr ""
msgid "Time" msgid "Time"
msgstr "" msgstr ""
@@ -447,6 +478,9 @@ msgstr ""
msgid "Tor mode" msgid "Tor mode"
msgstr "" msgstr ""
msgid "Transit traffic"
msgstr ""
msgid "Transparent proxy" msgid "Transparent proxy"
msgstr "" msgstr ""
@@ -465,6 +499,9 @@ msgstr ""
msgid "Turn on if blacklist source is blocked" msgid "Turn on if blacklist source is blocked"
msgstr "" msgstr ""
msgid "Turn on if files are blocked"
msgstr ""
msgid "Type a search pattern..." msgid "Type a search pattern..."
msgstr "" msgstr ""
@@ -509,6 +546,7 @@ msgid "URLs of remote user entries file"
msgid "Use optional DNS resolver" msgid "Use optional DNS resolver"
msgstr "" msgstr ""
msgid "User entries" msgid "User entries"
msgstr "" msgstr ""
@@ -527,6 +565,9 @@ msgstr ""
msgid "Warning" msgid "Warning"
msgstr "" msgstr ""
msgid "all"
msgstr "все"
msgid "ascending" msgid "ascending"
msgstr "" msgstr ""
@@ -7,7 +7,7 @@
"/usr/libexec/ruantiblock": [ "list" ], "/usr/libexec/ruantiblock": [ "list" ],
"/etc/ruantiblock/fqdn_filter": [ "read" ], "/etc/ruantiblock/fqdn_filter": [ "read" ],
"/etc/ruantiblock/ip_filter": [ "read" ], "/etc/ruantiblock/ip_filter": [ "read" ],
"/etc/ruantiblock/user_entries": [ "read" ], "/etc/ruantiblock/user_lists/*": [ "read" ],
"/etc/ruantiblock/bypass_entries": [ "read" ], "/etc/ruantiblock/bypass_entries": [ "read" ],
"/etc/ruantiblock/gr_excluded_nets": [ "read" ], "/etc/ruantiblock/gr_excluded_nets": [ "read" ],
"/etc/ruantiblock/gr_excluded_sld": [ "read" ], "/etc/ruantiblock/gr_excluded_sld": [ "read" ],
@@ -16,7 +16,8 @@
"/etc/crontabs/root": [ "read" ], "/etc/crontabs/root": [ "read" ],
"/usr/bin/ruantiblock*": [ "exec" ], "/usr/bin/ruantiblock*": [ "exec" ],
"/sbin/logread -e ruantiblock:": [ "exec" ], "/sbin/logread -e ruantiblock:": [ "exec" ],
"/usr/sbin/logread -e ruantiblock:": [ "exec" ] "/usr/sbin/logread -e ruantiblock:": [ "exec" ],
"/tmp": [ "list" ]
}, },
"uci": [ "network", "ruantiblock" ], "uci": [ "network", "ruantiblock" ],
"ubus": { "ubus": {
@@ -27,7 +28,7 @@
"file": { "file": {
"/etc/ruantiblock/fqdn_filter": [ "write" ], "/etc/ruantiblock/fqdn_filter": [ "write" ],
"/etc/ruantiblock/ip_filter": [ "write" ], "/etc/ruantiblock/ip_filter": [ "write" ],
"/etc/ruantiblock/user_entries": [ "write" ], "/etc/ruantiblock/user_lists/*": [ "write" ],
"/etc/ruantiblock/bypass_entries": [ "write" ], "/etc/ruantiblock/bypass_entries": [ "write" ],
"/etc/ruantiblock/gr_excluded_nets": [ "write" ], "/etc/ruantiblock/gr_excluded_nets": [ "write" ],
"/etc/ruantiblock/gr_excluded_sld": [ "write" ], "/etc/ruantiblock/gr_excluded_sld": [ "write" ],
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-lua PKG_NAME:=ruantiblock-mod-lua
PKG_VERSION:=1.6.0 PKG_VERSION:=2.0.0
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -58,9 +58,8 @@ local Config = Class(nil, {
["NFTSET_CIDR"] = true, ["NFTSET_CIDR"] = true,
["NFTSET_IP"] = true, ["NFTSET_IP"] = true,
["NFTSET_DNSMASQ"] = true, ["NFTSET_DNSMASQ"] = true,
["NFTSET_CIDR_CFG"] = true, ["NFTSET_CIDR_STRING_MAIN"] = true,
["NFTSET_IP_CFG"] = true, ["NFTSET_IP_STRING_MAIN"] = true,
["NFTSET_DNSMASQ"] = true,
["DNSMASQ_DATA_FILE"] = true, ["DNSMASQ_DATA_FILE"] = true,
["IP_DATA_FILE"] = true, ["IP_DATA_FILE"] = true,
["UPDATE_STATUS_FILE"] = true, ["UPDATE_STATUS_FILE"] = true,
@@ -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)) file_handler:write(string.format("flush set %s %s\n", self.NFT_TABLE, v))
end end
file_handler:write( 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 local c = 0
if next(cidr_table) then if next(cidr_table) then
@@ -801,7 +800,7 @@ function WriteConfigFiles:write_ipset_config(ip_table, cidr_table)
end end
self.cidr_count = c self.cidr_count = c
file_handler:write( file_handler:write(
string.format("}\n%s", self.NFTSET_IP_CFG) string.format("}\n%s", self.NFTSET_IP_STRING_MAIN)
) )
local i = 0 local i = 0
if next(ip_table) then if next(ip_table) then
@@ -1076,6 +1075,7 @@ if parser_classes then
for _, i in ipairs(parser_instances) do for _, i in ipairs(parser_instances) do
ret_list[i:run()] = true ret_list[i:run()] = true
end end
local return_sum = 0 local return_sum = 0
for i, _ in pairs(ret_list) do for i, _ in pairs(ret_list) do
return_sum = return_sum + i return_sum = return_sum + i
+1 -1
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-py PKG_NAME:=ruantiblock-mod-py
PKG_VERSION:=1.6.0 PKG_VERSION:=2.0.0
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -42,9 +42,8 @@ class Config:
"NFTSET_CIDR", "NFTSET_CIDR",
"NFTSET_IP", "NFTSET_IP",
"NFTSET_DNSMASQ", "NFTSET_DNSMASQ",
"NFTSET_CIDR_CFG", "NFTSET_CIDR_STRING_MAIN",
"NFTSET_IP_CFG", "NFTSET_IP_STRING_MAIN",
"NFTSET_DNSMASQ",
"DNSMASQ_DATA_FILE", "DNSMASQ_DATA_FILE",
"IP_DATA_FILE", "IP_DATA_FILE",
"UPDATE_STATUS_FILE", "UPDATE_STATUS_FILE",
@@ -459,6 +458,7 @@ class Summarize:
@classmethod @classmethod
def _group_nets(cls, cidr_list, raw_list=None): def _group_nets(cls, cidr_list, raw_list=None):
def remove_items(start, end): def remove_items(start, end):
for ip in range(int(start), int(end) + 1, 256): for ip in range(int(start), int(end) + 1, 256):
raw_list.remove(str(IPv4Address(ip)) + "/24") raw_list.remove(str(IPv4Address(ip)) + "/24")
@@ -570,7 +570,7 @@ class WriteConfigFiles(Config):
for i in (self.NFTSET_CIDR, self.NFTSET_IP): for i in (self.NFTSET_CIDR, self.NFTSET_IP):
file_handler.write("flush set {} {}\n".format(self.NFT_TABLE, i)) file_handler.write("flush set {} {}\n".format(self.NFT_TABLE, i))
file_handler.write( 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: if len(cidr_set) > 0:
file_handler.write("elements={") file_handler.write("elements={")
@@ -578,7 +578,7 @@ class WriteConfigFiles(Config):
file_handler.write(f"{i},") file_handler.write(f"{i},")
file_handler.write("};") file_handler.write("};")
file_handler.write( file_handler.write(
"}}\n{}".format(self.NFTSET_IP_CFG) "}}\n{}".format(self.NFTSET_IP_STRING_MAIN)
) )
if len(ip_dict) > 0: if len(ip_dict) > 0:
file_handler.write("elements={") file_handler.write("elements={")
+22 -9
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock PKG_NAME:=ruantiblock
PKG_VERSION:=1.6.0 PKG_VERSION:=2.0.0
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -17,7 +17,7 @@ define Package/$(PKG_NAME)
TITLE:=Ruantiblock TITLE:=Ruantiblock
URL:=https://github.com/gSpotx2f/ruantiblock_openwrt URL:=https://github.com/gSpotx2f/ruantiblock_openwrt
PKGARCH:=all PKGARCH:=all
DEPENDS:=+dnsmasq-full DEPENDS:=+dnsmasq-full +kmod-nft-tproxy
endef endef
define Package/$(PKG_NAME)/description define Package/$(PKG_NAME)/description
@@ -28,10 +28,14 @@ define Package/$(PKG_NAME)/conffiles
/etc/ruantiblock/ruantiblock.conf /etc/ruantiblock/ruantiblock.conf
/etc/ruantiblock/fqdn_filter /etc/ruantiblock/fqdn_filter
/etc/ruantiblock/ip_filter /etc/ruantiblock/ip_filter
/etc/ruantiblock/user_entries
/etc/ruantiblock/bypass_entries /etc/ruantiblock/bypass_entries
/etc/ruantiblock/gr_excluded_nets /etc/ruantiblock/gr_excluded_nets
/etc/ruantiblock/gr_excluded_sld /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 endef
define Build/Configure 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_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/fqdn_filter $(1)/etc/ruantiblock/fqdn_filter
$(INSTALL_DATA) ./files/etc/ruantiblock/ip_filter $(1)/etc/ruantiblock/ip_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/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_nets $(1)/etc/ruantiblock/gr_excluded_nets
$(INSTALL_DATA) ./files/etc/ruantiblock/gr_excluded_sld $(1)/etc/ruantiblock/gr_excluded_sld $(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_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 $(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/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/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_DIR) $(1)/usr/libexec/ruantiblock
$(INSTALL_BIN) ./files/usr/libexec/ruantiblock/ruab_route_check $(1)/usr/libexec/ruantiblock/ruab_route_check $(INSTALL_BIN) ./files/usr/libexec/ruantiblock/ruab_route_check $(1)/usr/libexec/ruantiblock/ruab_route_check
$(INSTALL_DIR) $(1)/usr/bin $(INSTALL_DIR) $(1)/usr/bin
@@ -82,14 +93,16 @@ define Package/$(PKG_NAME)/prerm
FILE_INIT_SCRIPT="/etc/init.d/ruantiblock" FILE_INIT_SCRIPT="/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="/usr/bin/ruantiblock" FILE_MAIN_SCRIPT="/usr/bin/ruantiblock"
CRONTAB_FILE="/etc/crontabs/root" 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_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_MAIN_SCRIPT" && $$FILE_MAIN_SCRIPT destroy
test -e "$$FILE_INIT_SCRIPT" && $$FILE_INIT_SCRIPT disable 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 { awk -v FILE_MAIN_SCRIPT="$$FILE_MAIN_SCRIPT" '$$0 !~ FILE_MAIN_SCRIPT {
print $$0; print $$0;
+76 -1
View File
@@ -11,13 +11,13 @@ config main 'config'
option vpn_route_check '0' option vpn_route_check '0'
option tor_trans_port '9040' option tor_trans_port '9040'
option onion_dns_addr '127.0.0.1#9053' option onion_dns_addr '127.0.0.1#9053'
option t_proxy_type '0'
option t_proxy_port_tcp '1100' option t_proxy_port_tcp '1100'
option t_proxy_port_udp '1100' option t_proxy_port_udp '1100'
option t_proxy_allow_udp '0' option t_proxy_allow_udp '0'
option bypass_mode '0' option bypass_mode '0'
option enable_bllist_proxy '0' option enable_bllist_proxy '0'
option enable_tmp_downloads '0' option enable_tmp_downloads '0'
option add_user_entries '0'
option bllist_min_entries '3000' option bllist_min_entries '3000'
option bllist_ip_limit '0' option bllist_ip_limit '0'
option bllist_summarize_ip '1' option bllist_summarize_ip '1'
@@ -30,3 +30,78 @@ config main 'config'
option bllist_enable_idn '0' option bllist_enable_idn '0'
option bllist_alt_nslookup '0' option bllist_alt_nslookup '0'
option bllist_alt_dns_addr '8.8.8.8' 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 #!/bin/sh
UCI_CMD=`which uci` if [ "$ACTION" = "ifup" ]; then
if [ $? -ne 0 ]; then NAME="ruantiblock"
echo " Error! UCI doesn't exists" >&2 RUAB_CMD="/usr/bin/ruantiblock"
exit 1 CONFIG_FILE="/etc/ruantiblock/ruantiblock.conf"
fi USER_INSTANCES_COMMON="/usr/share/ruantiblock/user_instances_common"
RUAB_CMD="/usr/bin/ruantiblock" CONFIG_SCRIPT_USER_INSTANCES="/usr/share/ruantiblock/config_script_user_instances"
PROXY_MODE=`$UCI_CMD get ruantiblock.config.proxy_mode` USER_INSTANCES_DIR="/etc/ruantiblock/user_instances"
IF_VPN=`$UCI_CMD get ruantiblock.config.if_vpn` 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"
VPN_ROUTE_CHECK=`$UCI_CMD get ruantiblock.config.vpn_route_check` 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 UCI_CMD=`which uci`
if [ `$RUAB_CMD raw-status` -ne 2 ]; then if [ $? -ne 0 ]; then
sleep 5 echo " Error! UCI doesn't exists" >&2
$RUAB_CMD reload exit 1
fi 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 fi
+29 -3
View File
@@ -5,14 +5,40 @@ STOP=01
APP_NAME="ruantiblock" APP_NAME="ruantiblock"
APP_EXEC="/usr/bin/${APP_NAME}" APP_EXEC="/usr/bin/${APP_NAME}"
DNSMASQ_VAR_DIR="/tmp"
config_load $APP_NAME 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() { start() {
local update_at_startup local _update_at_startup _dnsmasq_cfg_dir
config_get update_at_startup config update_at_startup 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 $APP_EXEC start
if [ $? -eq 0 -a "$update_at_startup" = "1" ]; then if [ $? -eq 0 -a "$_update_at_startup" = "1" ]; then
$APP_EXEC update $APP_EXEC update
else else
/etc/init.d/dnsmasq restart /etc/init.d/dnsmasq restart
@@ -82,4 +82,3 @@ birds
forex forex
kraken kraken
zerkalo zerkalo
#lord
@@ -5,9 +5,10 @@
DATA_DIR="/tmp/ruantiblock" DATA_DIR="/tmp/ruantiblock"
### Директория модулей ### Директория модулей
MODULES_DIR="/usr/libexec/ruantiblock" MODULES_DIR="/usr/libexec/ruantiblock"
### Дополнительный конфиг dnsmasq с FQDN записями блэклиста ### Директория PID-файлов и файлов статуса
DNSMASQ_DATA_FILE="/tmp/dnsmasq.d/02-ruantiblock.dnsmasq" RUN_FILES_DIR="/tmp/run"
DNSMASQ_DATA_FILE_BYPASS="/tmp/dnsmasq.d/01-ruantiblock_bypass.dnsmasq" ### Директория доп. конфигов dnsmasq
DNSMASQ_CFG_DIR="/tmp/dnsmasq.d"
### Команда для перезапуска dnsmasq ### Команда для перезапуска dnsmasq
DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart" DNSMASQ_RESTART_CMD="/etc/init.d/dnsmasq restart"
### Директория для html-страницы статуса (не используется в OpenWrt) ### Директория для html-страницы статуса (не используется в OpenWrt)
@@ -31,26 +32,26 @@ ONION_DNS_ADDR="127.0.0.1#9053"
IF_VPN="tun0" IF_VPN="tun0"
### IP адрес шлюза для VPN конфигурации. Если не задан, используется адрес VPN интерфейса (или адрес пира для протоколов PPP) ### IP адрес шлюза для VPN конфигурации. Если не задан, используется адрес VPN интерфейса (или адрес пира для протоколов PPP)
VPN_GW_IP="" 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 туннель (0 - hotplug.d, 1 - скрипт ruab_route_check)
VPN_ROUTE_CHECK=0 VPN_ROUTE_CHECK=0
### Тип прозрачного прокси (0 - redirect, 1 - tproxy)
T_PROXY_TYPE=0
### TCP порт прокси в режиме прозрачного прокси ### TCP порт прокси в режиме прозрачного прокси
T_PROXY_PORT_TCP=1100 T_PROXY_PORT_TCP=1100
### UDP порт прокси в режиме прозрачного прокси ### UDP порт прокси в режиме прозрачного прокси
T_PROXY_PORT_UDP=1100 T_PROXY_PORT_UDP=1100
### Отправлять в прозрачный прокси UDP-трафик (0 - выкл, 1 - вкл) ### Отправлять в прозрачный прокси UDP-трафик (0 - выкл, 1 - вкл)
T_PROXY_ALLOW_UDP=0 T_PROXY_ALLOW_UDP=0
### Начальное значение метки для отбора пакетов в фильтрах
PKTS_MARK_START=8
### Запись событий в syslog (0 - выкл, 1 - вкл) ### Запись событий в syslog (0 - выкл, 1 - вкл)
ENABLE_LOGGING=1 ENABLE_LOGGING=1
### Вывод дополнительных сообщений в лог (0 - выкл, 1, 2)
DEBUG=0
### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt) ### Html-страница с инфо о текущем статусе (0 - выкл, 1 - вкл) (не используется в OpenWrt)
ENABLE_HTML_INFO=0 ENABLE_HTML_INFO=0
### Максимальное кол-во элементов списка nftables ### Максимальное кол-во элементов списка nftables
#NFTSET_MAXELEM_CIDR=65535 NFTSET_MAXELEM_CIDR=65535
NFTSET_MAXELEM_IP=1000000 NFTSET_MAXELEM_IP=1000000
NFTSET_MAXELEM_DNSMASQ=65535 NFTSET_MAXELEM_DNSMASQ=65535
NFTSET_MAXELEM_BYPASS_IP=65535 NFTSET_MAXELEM_BYPASS_IP=65535
@@ -63,29 +64,14 @@ NFTSET_POLICY_DNSMASQ="performance"
NFTSET_DNSMASQ_TIMEOUT="150m" NFTSET_DNSMASQ_TIMEOUT="150m"
### Динамическое обновление таймаута записей в сете $NFTSET_DNSMASQ (0 - выкл, 1 - вкл) ### Динамическое обновление таймаута записей в сете $NFTSET_DNSMASQ (0 - выкл, 1 - вкл)
NFTSET_DNSMASQ_TIMEOUT_UPDATE=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_ATTEMPTS=3
### Таймаут между попытками скачивания ### Таймаут между попытками скачивания
USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT=60 USER_ENTRIES_REMOTE_DOWNLOAD_TIMEOUT=60
### Кол-во экземпляров записей пользователя (не более 50!)
USER_INSTANCES_MAX=5
### Пропускать мимо фильтра пакеты уже помеченные в записях пользователя (0 - выкл, 1 - вкл)
SKIP_MARKED_PACKETS=0
### Режим списка записей, исключаемых из обхода блокировок (0 - выкл, 1 - вкл) ### Режим списка записей, исключаемых из обхода блокировок (0 - выкл, 1 - вкл)
BYPASS_MODE=0 BYPASS_MODE=0
### DNS-сервер для исключаемых записей (пустая строка - без DNS-сервера). Можно с портом: 8.8.8.8#53. Если в записи указан свой DNS-сервер - он имеет приоритет ### 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" BLLIST_GR_EXCLUDED_SLD_FILE="/etc/ruantiblock/gr_excluded_sld"
### Файл с масками SLD не подлежащими группировке при оптимизации (одна запись на строку) ### Файл с масками SLD не подлежащими группировке при оптимизации (одна запись на строку)
BLLIST_GR_EXCLUDED_SLD_MASKS_FILE="/etc/ruantiblock/gr_excluded_sld_mask" 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 BLLIST_FQDN_FILTER=0
### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами) ### Тип фильтра FQDN (0 - все записи, кроме совпадающих с шаблонами; 1 - только записи, совпадающие с шаблонами)
BLLIST_FQDN_FILTER_TYPE=0 BLLIST_FQDN_FILTER_TYPE=0
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,69 @@
#!/bin/sh #!/bin/sh
PID_FILE="/var/run/`basename $0`.pid" PID_FILE="/var/run/`basename $0`.pid"
APP_EXEC="/usr/bin/ruantiblock"
VpnRouteStatus() { . "$USER_INSTANCES_COMMON"
[ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0
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 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() { Main() {
while [ -e "$PID_FILE" ] while [ -e "$PID_FILE" ]
do do
if ! VpnRouteStatus; then VPN_IFACES_STATUS=1
if $IP_CMD link show $IF_VPN &> /dev/null; then 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 $APP_EXEC reload
fi fi
fi fi
@@ -6,7 +6,6 @@ export RBL_DPI_URL="https://reestr.rublacklist.net/api/v3/dpi/"
export RBL_ENCODING="" export RBL_ENCODING=""
## zapret-info ## zapret-info
export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv" export ZI_ALL_URL="https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv"
#export ZI_ALL_URL="https://app.assembla.com/spaces/z-i/git/source/master/dump.csv?_format=raw"
export ZI_ENCODING="CP1251" export ZI_ENCODING="CP1251"
## antifilter ## antifilter
export AF_IP_URL="https://antifilter.download/list/allyouneed.lst" export AF_IP_URL="https://antifilter.download/list/allyouneed.lst"
@@ -52,7 +51,6 @@ case "$BLLIST_PRESET" in
export BLLIST_SOURCE="ruantiblock" export BLLIST_SOURCE="ruantiblock"
export BLLIST_MODE="ip" export BLLIST_MODE="ip"
BLLIST_MODULE="DownloadNativeBlacklist" BLLIST_MODULE="DownloadNativeBlacklist"
# github
DL_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/ip/ruantiblock.ip" 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_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" 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_SOURCE="ruantiblock"
export BLLIST_MODE="fqdn" export BLLIST_MODE="fqdn"
BLLIST_MODULE="DownloadNativeBlacklist" BLLIST_MODULE="DownloadNativeBlacklist"
# github
DL_IPSET_URL="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_blacklist/master/blacklist-1.1/fqdn/ruantiblock.ip" 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_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" 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_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` UCI_CMD=`which uci`
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2 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() { Info() {
local _update_status _user_entries_status local _update_status _user_entries_status _inst
if [ -f "$UPDATE_STATUS_FILE" ]; then if [ -f "$UPDATE_STATUS_FILE" ]; then
_update_status=`$AWK_CMD '{ _update_status=`$AWK_CMD '{
if(NF < 4) { if(NF < 4) {
@@ -33,29 +33,30 @@ Info() {
else else
_user_entries_status="[]" _user_entries_status="[]"
fi fi
NftListBllistChainJson 2> /dev/null | $AWK_CMD -v UPDATE_STATUS="$_update_status" -v USER_ENTRIES_STATUS="$_user_entries_status" ' NftListSinkChainJson 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;
}
END { END {
if(NR == 0) { if(NR == 0) {
printf "{\"status\": \"disabled\"}"; printf "{\"status\": \"disabled\"}";
exit 1; exit 1;
} else { } 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; exit 0;
}; };
}' }'
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
printf ",\"sink_local\":"
NftListSinkLocalChainJson 2> /dev/null
fi
printf ",\"dnsmasq\":" printf ",\"dnsmasq\":"
$NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ" 2> /dev/null $NFT_CMD -j list set $NFT_TABLE "$NFTSET_DNSMASQ" 2> /dev/null
if [ "$BYPASS_MODE" = "1" ]; then printf ",\"dnsmasq_user_instances\":["
printf ",\"dnsmasq_bypass\":" for _inst in $USER_INSTANCES_ALL
$NFT_CMD -j list set $NFT_TABLE "$NFTSET_BYPASS_FQDN" 2> /dev/null do
fi $NFT_CMD -j list set $NFT_TABLE "${NFTSET_DNSMASQ}-${_inst}" 2> /dev/null
printf ","
done
printf "{\"dummy\": {}}]"
printf "}" printf "}"
fi fi
} }
@@ -2,35 +2,26 @@ NFT_ALLOWED_HOSTS_CHAIN="allowed_hosts"
NFT_BLLIST_CHAIN="blacklist" NFT_BLLIST_CHAIN="blacklist"
NFT_FPROXY_FILTER="fproxy_filter" NFT_FPROXY_FILTER="fproxy_filter"
NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN="dnsmasq_timeout_update" NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN="dnsmasq_timeout_update"
NFT_ACTION_CHAIN="action" NFT_MARK_CHAIN="mark_chain"
NFT_LOCAL_CLIENTS_CHAIN="local_clients" NFT_LOCAL_CLIENTS_CHAIN="local_clients"
NFT_SINK_CHAIN="sink"
if [ "$PROXY_MODE" = "2" ]; then NFT_SINK_LOCAL_CHAIN="sink_local"
MAIN_CHAIN_TYPE="type filter hook prerouting priority ${NFT_PRIO_ROUTE}; policy accept;" NFT_ACTION_FILTER_CHAIN="action_filter"
LOCAL_CLIENTS_CHAIN_TYPE="type route hook output priority ${NFT_PRIO_ROUTE_LOCAL}; policy accept;" NFT_ACTION_NAT_CHAIN="action_nat"
else NFT_ACTION_NAT_LOCAL_CHAIN="action_nat_local"
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
case "$ALLOWED_HOSTS_MODE" in case "$ALLOWED_HOSTS_MODE" in
"1") "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") "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 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() { NftCmdWrapper() {
local _i=0 _attempts=10 _return_code=1 local _i=0 _attempts=10 _return_code=1
while [ $_i -lt $_attempts ] while [ $_i -lt $_attempts ]
@@ -44,105 +35,247 @@ NftCmdWrapper() {
return $_return_code return $_return_code
} }
NftVpnRouteDelete() { NftRouteDelete() {
$IP_CMD route flush table $VPN_ROUTE_TABLE_ID local _route_table_id=$1
$IP_CMD rule del table $VPN_ROUTE_TABLE_ID $IP_CMD route flush table $_route_table_id
$IP_CMD rule del table $_route_table_id
} }
NftVpnRouteAdd() { NftRouteAdd() {
local _vpn_ip local _vpn_ip _type="$1" _route_table_id=$2 _pkts_mark=$3 _if_vpn="$4" _vpn_gw_ip="$5"
if [ -n "$VPN_GW_IP" ]; then if [ "$_type" = "lo" ]; then
_vpn_ip="$VPN_GW_IP" 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 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}'` if [ -n "$_vpn_gw_ip" ]; then
fi _vpn_ip="$_vpn_gw_ip"
if [ -n "$_vpn_ip" ]; then else
echo 0 > /proc/sys/net/ipv4/conf/$IF_VPN/rp_filter _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}'`
NftVpnRouteDelete 2> /dev/null fi
$IP_CMD rule add fwmark $VPN_PKTS_MARK table $VPN_ROUTE_TABLE_ID priority $VPN_RULE_PRIO if [ -n "$_vpn_ip" -a "$_type" = "vpn" ]; then
$IP_CMD route add default via $_vpn_ip table $VPN_ROUTE_TABLE_ID 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 fi
} }
NftVpnRouteStatus() { NftRouteStatus() {
[ -n "`$IP_CMD route show table $VPN_ROUTE_TABLE_ID 2> /dev/null`" ] && return 0 local _route_table_id=$1
[ -n "`$IP_CMD route show table $_route_table_id 2> /dev/null`" ] && return 0
return 1 return 1
} }
NftMainAdd() { NftAddSinkChains() {
local _set local _chain_prio_sink=$1
$NFT_CMD add chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" { $LOCAL_CLIENTS_CHAIN_TYPE } $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_ACTION_CHAIN" $NFT_CMD add chain $NFT_TABLE "${NFT_SINK_LOCAL_CHAIN}" { type route hook output priority ${_chain_prio_sink}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "$NFT_FPROXY_FILTER" NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "${NFT_SINK_CHAIN}" meta iif lo return
$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 } NftDeleteSinkChains() {
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE $NFT_FPROXY_FILTER ip daddr "@${NFTSET_FPROXY_PRIVATE}" return $NFT_CMD delete chain $NFT_TABLE "${NFT_SINK_CHAIN}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_FILTER" jump "$NFT_ACTION_CHAIN" $NFT_CMD delete chain $NFT_TABLE "${NFT_SINK_LOCAL_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 NftAddActionChains() {
if [ "$PROXY_MODE" = "2" ]; then local _chain_prio_action=$1
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" mark set $VPN_PKTS_MARK $NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_FILTER_CHAIN}" { type filter hook prerouting priority ${_chain_prio_action}\; policy accept\; }
elif [ "$PROXY_MODE" = "3" ]; then $NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_NAT_CHAIN}" { type nat hook prerouting priority ${_chain_prio_action}\; policy accept\; }
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $T_PROXY_PORT_TCP $NFT_CMD add chain $NFT_TABLE "${NFT_ACTION_NAT_LOCAL_CHAIN}" { type nat hook output priority ${_chain_prio_action}\; policy accept\; }
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 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 else
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ACTION_CHAIN" tcp dport { 0-65535 } redirect to $TOR_TRANS_PORT _name="-${_name}"
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_ONION}" counter goto "$NFT_ACTION_CHAIN"
fi 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 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 if [ "$BYPASS_MODE" = "1" ]; then
for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN"
do 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 done
fi fi
for _set in "$NFTSET_CIDR" "$NFTSET_IP"
for _set in "${NFTSET_CIDR}${_name}" "${NFTSET_IP}${_name}"
do 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 done
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" ip daddr "@${NFTSET_DNSMASQ}" counter goto "$NFT_DNSMASQ_RULE_TARGET" 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
NftVpnRouteAdd 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 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 fi
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then 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 fi
} }
NftMainDelete() { NftInstanceDelete() {
$NFT_CMD flush chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" local _name="$1"
$NFT_CMD delete chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" if [ -z "$_name" -o "$_name" = " " ]; then
$NFT_CMD flush chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" _name=""
$NFT_CMD delete chain $NFT_TABLE "$NFT_LOCAL_CLIENTS_CHAIN" else
$NFT_CMD flush chain $NFT_TABLE "$NFT_BLLIST_CHAIN" _name="-${_name}"
$NFT_CMD delete chain $NFT_TABLE "$NFT_BLLIST_CHAIN" fi
$NFT_CMD flush chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" $NFT_CMD delete chain $NFT_TABLE "${NFT_ALLOWED_HOSTS_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "$NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN" $NFT_CMD delete chain $NFT_TABLE "${NFT_LOCAL_CLIENTS_CHAIN}${_name}"
$NFT_CMD flush chain $NFT_TABLE "$NFT_FPROXY_FILTER" $NFT_CMD delete chain $NFT_TABLE "${NFT_BLLIST_CHAIN}${_name}"
$NFT_CMD delete chain $NFT_TABLE "$NFT_FPROXY_FILTER" $NFT_CMD delete chain $NFT_TABLE "${NFT_DNSMASQ_TIMEOUT_UPDATE_CHAIN}${_name}"
$NFT_CMD flush chain $NFT_TABLE "$NFT_ACTION_CHAIN" $NFT_CMD delete chain $NFT_TABLE "${NFT_FPROXY_FILTER}${_name}"
$NFT_CMD delete chain $NFT_TABLE "$NFT_ACTION_CHAIN" $NFT_CMD delete chain $NFT_TABLE "${NFT_MARK_CHAIN}${_name}"
NftVpnRouteDelete 2> /dev/null
} }
NftListBllistChain() { 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() { 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() { NftListSinkChain() {
$NFT_CMD -c add rule $NFT_TABLE "$NFT_BLLIST_CHAIN" continue &> /dev/null $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 $? 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