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