Minor improvements. luci-app-ruantiblock: updated log.

This commit is contained in:
gSpot
2025-04-14 19:05:04 +03:00
parent 82fd11b612
commit ba8011c8ba
20 changed files with 425 additions and 248 deletions
+14 -20
View File
@@ -10,9 +10,9 @@ LUCI_APP=1
HTTPS_DNS_PROXY=1 HTTPS_DNS_PROXY=1
OWRT_VERSION="current" OWRT_VERSION="current"
RUAB_VERSION="2.1.4-r3" RUAB_VERSION="2.1.5-r1"
RUAB_MOD_LUA_VERSION="2.1.4-r1" RUAB_MOD_LUA_VERSION="2.1.5-r1"
RUAB_LUCI_APP_VERSION="2.1.4-r1" RUAB_LUCI_APP_VERSION="2.1.5-r1"
BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master" BASE_URL="https://raw.githubusercontent.com/gSpotx2f/packages-openwrt/master"
PKG_DIR="/tmp" PKG_DIR="/tmp"
@@ -29,7 +29,6 @@ URL_LUCI_APP_PKG="${BASE_URL}/${OWRT_VERSION}/luci-app-ruantiblock_${RUAB_LUCI_A
URL_LUCI_APP_RU_PKG="${BASE_URL}/${OWRT_VERSION}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk" URL_LUCI_APP_RU_PKG="${BASE_URL}/${OWRT_VERSION}/luci-i18n-ruantiblock-ru_${RUAB_LUCI_APP_VERSION}_all.ipk"
### tor ### tor
URL_TORRC="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master/tor/etc/tor/torrc" URL_TORRC="https://raw.githubusercontent.com/gSpotx2f/ruantiblock_openwrt/master/tor/etc/tor/torrc"
### ruantiblock-mod-lua
URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua" URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua"
### Local files ### Local files
@@ -37,7 +36,7 @@ URL_LUA_IDN="https://raw.githubusercontent.com/haste/lua-idn/master/idn.lua"
CONFIG_DIR="${PREFIX}/etc/ruantiblock" CONFIG_DIR="${PREFIX}/etc/ruantiblock"
USER_LISTS_DIR="${CONFIG_DIR}/user_lists" USER_LISTS_DIR="${CONFIG_DIR}/user_lists"
EXEC_DIR="${PREFIX}/usr/bin" EXEC_DIR="${PREFIX}/usr/bin"
BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`" BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.$(date +%s)"
### packages ### packages
FILE_RUAB_PKG="${PKG_DIR}/ruantiblock_${RUAB_VERSION}_all.ipk" FILE_RUAB_PKG="${PKG_DIR}/ruantiblock_${RUAB_VERSION}_all.ipk"
FILE_MOD_LUA_PKG="${PKG_DIR}/ruantiblock-mod-lua_${RUAB_MOD_LUA_VERSION}_all.ipk" FILE_MOD_LUA_PKG="${PKG_DIR}/ruantiblock-mod-lua_${RUAB_MOD_LUA_VERSION}_all.ipk"
@@ -56,23 +55,21 @@ FILE_INIT_SCRIPT="${PREFIX}/etc/init.d/ruantiblock"
FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock" FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
### tor ### tor
FILE_TORRC="${PREFIX}/etc/tor/torrc" FILE_TORRC="${PREFIX}/etc/tor/torrc"
### ruantiblock-mod-lua
#FILE_LUA_IPTOOL="${PREFIX}/usr/lib/lua/iptool.lua"
FILE_LUA_IDN="${PREFIX}/usr/lib/lua/idn.lua" FILE_LUA_IDN="${PREFIX}/usr/lib/lua/idn.lua"
AWK_CMD="awk" AWK_CMD="awk"
WGET_CMD=`which wget` WGET_CMD="$(which wget)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! wget doesn't exists" >&2 echo " Error! wget doesn't exists" >&2
exit 1 exit 1
fi fi
WGET_PARAMS="--no-check-certificate -q -O " WGET_PARAMS="--no-check-certificate -q -O "
OPKG_CMD=`which opkg` OPKG_CMD="$(which opkg)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! opkg doesn't exists" >&2 echo " Error! opkg doesn't exists" >&2
exit 1 exit 1
fi fi
UCI_CMD=`which uci` UCI_CMD="$(which uci)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! uci doesn't exists" >&2 echo " Error! uci doesn't exists" >&2
exit 1 exit 1
@@ -104,7 +101,7 @@ RemoveFile() {
DlFile() { DlFile() {
local _dir _file local _dir _file
if [ -n "$2" ]; then if [ -n "$2" ]; then
_dir=`dirname "$2"` _dir=$(dirname "$2")
MakeDir "$_dir" MakeDir "$_dir"
_file="$2" _file="$2"
else else
@@ -119,19 +116,19 @@ DlFile() {
} }
BackupFile() { BackupFile() {
[ -e "$1" ] && cp -f "$1" "${1}.bak.`date +%s`" [ -e "$1" ] && cp -f "$1" "${1}.bak.$(date +%s)"
} }
BackupCurrentConfig() { BackupCurrentConfig() {
local _file local _file
MakeDir "$BACKUP_DIR" MakeDir "$BACKUP_DIR"
for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"` for _file in $(ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)")
do do
cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}" cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}"
done done
for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC" for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC"
do do
[ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`" [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/$(basename ${_file})"
done done
} }
@@ -165,7 +162,7 @@ InstallPackages() {
local _pkg local _pkg
for _pkg in $@ for _pkg in $@
do do
if [ -z "`$OPKG_CMD list-installed $_pkg`" ]; then if [ -z "$($OPKG_CMD list-installed $_pkg)" ]; then
$OPKG_CMD --force-overwrite install $_pkg $OPKG_CMD --force-overwrite install $_pkg
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "Error during installation of the package (${_pkg})" >&2 echo "Error during installation of the package (${_pkg})" >&2
@@ -181,7 +178,6 @@ InstallBaseConfig() {
RemoveFile "$FILE_RUAB_PKG" > /dev/null RemoveFile "$FILE_RUAB_PKG" > /dev/null
DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null DlFile "$URL_RUAB_PKG" "$FILE_RUAB_PKG" && $OPKG_CMD install "$FILE_RUAB_PKG" > /dev/null
_return_code=$? _return_code=$?
# костыль для остановки сервиса, который запускается автоматически после установки пакета!
AppStop AppStop
return $_return_code return $_return_code
} }
@@ -205,7 +201,7 @@ InstallTPConfig() {
} }
TorrcSettings() { TorrcSettings() {
local _lan_ip=`$UCI_CMD get network.lan.ipaddr | $AWK_CMD -F "/" '{print $1}'` local _lan_ip=$($UCI_CMD get network.lan.ipaddr | $AWK_CMD -F "/" '{print $1}')
if [ -z "$_lan_ip" ]; then if [ -z "$_lan_ip" ]; then
_lan_ip="0.0.0.0" _lan_ip="0.0.0.0"
fi fi
@@ -223,7 +219,6 @@ InstallTorConfig() {
TorrcSettings TorrcSettings
$UCI_CMD set ruantiblock.config.proxy_mode="1" $UCI_CMD set ruantiblock.config.proxy_mode="1"
$UCI_CMD commit ruantiblock $UCI_CMD commit ruantiblock
# dnsmasq rebind protection
$UCI_CMD add_list dhcp.@dnsmasq[0].rebind_domain='onion' $UCI_CMD add_list dhcp.@dnsmasq[0].rebind_domain='onion'
$UCI_CMD commit dhcp $UCI_CMD commit dhcp
} }
@@ -392,7 +387,6 @@ ConfirmProcessing() {
ConfirmProxyMode ConfirmProxyMode
ConfirmBlacklist ConfirmBlacklist
#ConfirmLuaModule
ConfirmLuciApp ConfirmLuciApp
ConfirmHttpsDnsProxy ConfirmHttpsDnsProxy
ConfirmProcessing ConfirmProcessing
@@ -414,7 +408,7 @@ if [ $? -eq 0 ]; then
else else
PrintBold "Installing Tor configuration..." PrintBold "Installing Tor configuration..."
InstallTorConfig InstallTorConfig
if `/etc/init.d/tor enabled`; then if $(/etc/init.d/tor enabled); then
/etc/init.d/tor restart /etc/init.d/tor restart
fi fi
fi fi
+5 -5
View File
@@ -7,7 +7,7 @@ PREFIX=""
CONFIG_DIR="${PREFIX}/etc/ruantiblock" CONFIG_DIR="${PREFIX}/etc/ruantiblock"
USER_LISTS_DIR="${CONFIG_DIR}/user_lists" USER_LISTS_DIR="${CONFIG_DIR}/user_lists"
EXEC_DIR="${PREFIX}/usr/bin" EXEC_DIR="${PREFIX}/usr/bin"
BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.`date +%s`" BACKUP_DIR="${CONFIG_DIR}/autoinstall.bak.$(date +%s)"
HTDOCS_VIEW="${PREFIX}/www/luci-static/resources/view" HTDOCS_VIEW="${PREFIX}/www/luci-static/resources/view"
HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock" HTDOCS_RUAB="${HTDOCS_VIEW}/ruantiblock"
CRONTAB_FILE="/etc/crontabs/root" CRONTAB_FILE="/etc/crontabs/root"
@@ -33,7 +33,7 @@ FILE_MAIN_SCRIPT="${EXEC_DIR}/ruantiblock"
FILE_TORRC="${PREFIX}/etc/tor/torrc" FILE_TORRC="${PREFIX}/etc/tor/torrc"
AWK_CMD="awk" AWK_CMD="awk"
OPKG_CMD=`which opkg` OPKG_CMD="$(which opkg)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! opkg doesn't exists" >&2 echo " Error! opkg doesn't exists" >&2
exit 1 exit 1
@@ -61,13 +61,13 @@ RemoveFile() {
BackupCurrentConfig() { BackupCurrentConfig() {
local _file local _file
MakeDir "$BACKUP_DIR" MakeDir "$BACKUP_DIR"
for _file in `ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)"` for _file in $(ls -1 "$CONFIG_DIR" | grep -v "$(basename $BACKUP_DIR)")
do do
cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}" cp -af "${CONFIG_DIR}/${_file}" "${BACKUP_DIR}/${_file}"
done done
for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC" for _file in "$FILE_UCI_CONFIG" "$FILE_TORRC"
do do
[ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/`basename ${_file}`" [ -e "$_file" ] && cp -af "$_file" "${BACKUP_DIR}/$(basename ${_file})"
done done
} }
@@ -91,7 +91,7 @@ RemoveCronTask() {
RestoreTorConfig() { RestoreTorConfig() {
[ -e "${FILE_TORRC}.bak" ] && mv -f "${FILE_TORRC}.bak" "$FILE_TORRC" [ -e "${FILE_TORRC}.bak" ] && mv -f "${FILE_TORRC}.bak" "$FILE_TORRC"
if [ -x "/etc/init.d/tor" ]; then if [ -x "/etc/init.d/tor" ]; then
if `/etc/init.d/tor enabled`; then if $(/etc/init.d/tor enabled); then
/etc/init.d/tor restart /etc/init.d/tor restart
fi fi
fi fi
+2 -2
View File
@@ -1,11 +1,11 @@
# #
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ruantiblock PKG_NAME:=luci-app-ruantiblock
PKG_VERSION:=2.1.4 PKG_VERSION:=2.1.5
PKG_RELEASE:=1 PKG_RELEASE:=1
LUCI_TITLE:=LuCI support for ruantiblock LUCI_TITLE:=LuCI support for ruantiblock
LUCI_DEPENDS:=+ruantiblock LUCI_DEPENDS:=+ruantiblock
@@ -10,6 +10,7 @@ document.head.append(E('style', {'type': 'text/css'},
--app-log-dark-font-color: #2e2e2e; --app-log-dark-font-color: #2e2e2e;
--app-log-light-font-color: #fff; --app-log-light-font-color: #fff;
--app-log-debug-font-color: #737373; --app-log-debug-font-color: #737373;
--app-log-raw-font-color: #737373;
--app-log-emerg-color: #a93734; --app-log-emerg-color: #a93734;
--app-log-alert: #ff7968; --app-log-alert: #ff7968;
--app-log-crit: #fcc3bf; --app-log-crit: #fcc3bf;
@@ -18,12 +19,14 @@ document.head.append(E('style', {'type': 'text/css'},
--app-log-notice: #e3ffec; --app-log-notice: #e3ffec;
--app-log-info: rgba(0,0,0,0); --app-log-info: rgba(0,0,0,0);
--app-log-debug: #ebf6ff; --app-log-debug: #ebf6ff;
--app-log-raw: #eee;
--app-log-entries-count-border: #ccc; --app-log-entries-count-border: #ccc;
} }
:root[data-darkmode="true"] { :root[data-darkmode="true"] {
--app-log-dark-font-color: #fff; --app-log-dark-font-color: #fff;
--app-log-light-font-color: #fff; --app-log-light-font-color: #fff;
--app-log-debug-font-color: #e7e7e7; --app-log-debug-font-color: #e7e7e7;
--app-log-raw-font-color: #aaa;
--app-log-emerg-color: #960909; --app-log-emerg-color: #960909;
--app-log-alert: #eb5050; --app-log-alert: #eb5050;
--app-log-crit: #dc7f79; --app-log-crit: #dc7f79;
@@ -32,6 +35,7 @@ document.head.append(E('style', {'type': 'text/css'},
--app-log-notice: #007627; --app-log-notice: #007627;
--app-log-info: rgba(0,0,0,0); --app-log-info: rgba(0,0,0,0);
--app-log-debug: #5986b1; --app-log-debug: #5986b1;
--app-log-raw: #353535;
--app-log-entries-count-border: #555; --app-log-entries-count-border: #555;
} }
#logWrapper { #logWrapper {
@@ -114,6 +118,16 @@ log-emerg td {
.log-debug td { .log-debug td {
color: var(--app-log-debug-font-color) !important; color: var(--app-log-debug-font-color) !important;
} }
.log-raw {
background-color: var(--app-log-raw) !important;
color: var(--app-log-raw-font-color) !important;
}
.log-raw .td {
color: var(--app-log-raw-font-color) !important;
}
.log-raw td {
color: var(--app-log-raw-font-color) !important;
}
.log-highlight-item { .log-highlight-item {
background-color: #ffef00; background-color: #ffef00;
color: #2e2e2e; color: #2e2e2e;
@@ -168,25 +182,32 @@ return baseclass.extend({
* *
* @property {string} viewName * @property {string} viewName
*/ */
viewName : null, viewName : null,
/** /**
* Page title. * Page title.
* *
* @property {string} title * @property {string} title
*/ */
title : null, title : null,
/** /**
* Enable auto refresh log. * Enable auto refresh log.
* *
* @property {bool} autoRefresh * @property {bool} enableAutoRefresh
*/ */
autoRefresh : false, enableAutoRefresh : false,
pollInterval : L.env.pollinterval, /**
* Enable timestamp conversion.
*
* @property {bool} enableConvertTimestamp
*/
enableConvertTimestamp: false,
logFacilities : { pollInterval : L.env.pollinterval,
logFacilities : {
'kern' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'kern')), 'kern' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'kern')),
'user' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'user')), 'user' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'user')),
'mail' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'mail')), 'mail' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'mail')),
@@ -211,7 +232,7 @@ return baseclass.extend({
'local7' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'local7')), 'local7' : E('span', { 'class': 'zonebadge log-facility-dropdown-item' }, E('strong', 'local7')),
}, },
logLevels : { logLevels : {
'emerg' : E('span', { 'class': 'zonebadge log-emerg' }, E('strong', 'Emergency')), 'emerg' : E('span', { 'class': 'zonebadge log-emerg' }, E('strong', 'Emergency')),
'alert' : E('span', { 'class': 'zonebadge log-alert' }, E('strong', 'Alert')), 'alert' : E('span', { 'class': 'zonebadge log-alert' }, E('strong', 'Alert')),
'crit' : E('span', { 'class': 'zonebadge log-crit' }, E('strong', 'Critical')), 'crit' : E('span', { 'class': 'zonebadge log-crit' }, E('strong', 'Critical')),
@@ -246,13 +267,15 @@ return baseclass.extend({
autoRefreshValue : true, autoRefreshValue : true,
isAutorefresh : true, autorefreshOn : true,
isHosts : false, logTimestampFlag : false,
isFacilities : false, logHostsFlag : false,
isLevels : false, logFacilitiesFlag : false,
logLevelsFlag : false,
logHosts : {}, logHosts : {},
@@ -266,7 +289,13 @@ return baseclass.extend({
totalLogLines : 0, totalLogLines : 0,
lastHash : null, logCols : [ '#', null, null, null, null, _('Message') ],
convertTimestampValue: false,
convertTimestampOn : false,
lastHash : null,
actionButtons : [], actionButtons : [],
@@ -283,6 +312,68 @@ return baseclass.extend({
return (/^[0-9]+$/.test(value)) ? value : 0 return (/^[0-9]+$/.test(value)) ? value : 0
}, },
makeLogConvertTimestampSection() {
if(!this.enableConvertTimestamp) {
return '';
};
return E('div', { 'class': 'cbi-value' }, [
E('label', {
'class': 'cbi-value-title',
'for' : 'convertTimestamp',
}, _('Date')),
E('div', { 'class': 'cbi-value-field' }, [
E('div', { 'class': 'cbi-checkbox' }, [
this.convertTimestamp,
E('label', {}),
]),
E('div', { 'class': 'cbi-value-description' },
_('Convert timestamps to a human readable date')
),
]),
]);
},
makeLogTimeFilterSection() {
return E('div', { 'class': 'cbi-value' }, [
E('label', {
'class': 'cbi-value-title',
'for' : 'timeFilter',
}, _('Timestamp filter')),
E('div', { 'class': 'cbi-value-field' },
E('span', { 'class': 'control-group' }, [
this.timeFilter,
E('button', {
'class': 'cbi-button btn',
'click': L.bind(ev => {
ev.target.blur();
ev.preventDefault();
this.timeFilter.value = null;
this.timeFilter.focus();
}, this),
}, '⌫'),
])
),
]);
},
makeLogtimeFilterReSection() {
return E('div', { 'class': 'cbi-value' }, [
E('label', {
'class': 'cbi-value-title',
'for' : 'timeFilterRe',
}, _('Filter is regexp')),
E('div', { 'class': 'cbi-value-field' }, [
E('div', { 'class': 'cbi-checkbox' }, [
this.timeFilterRe,
E('label', {}),
]),
E('div', { 'class': 'cbi-value-description' },
_('Apply timestamp filter as regular expression')
),
]),
]);
},
makeLogHostsDropdownItem(host) { makeLogHostsDropdownItem(host) {
return E( return E(
'span', 'span',
@@ -385,23 +476,28 @@ return baseclass.extend({
}, },
setFilterSettings() { setFilterSettings() {
this.tailValue = this.checkZeroValue(this.tailInput.value); this.tailValue = this.checkZeroValue(this.tailInput.value);
this.timeFilterValue = this.timeFilter.value; if(this.logTimestampFlag) {
this.timeFilterReValue = this.timeFilterRe.checked; if(this.enableConvertTimestamp) {
if(this.isHosts) { this.convertTimestampValue = this.convertTimestamp.checked;
};
this.timeFilterValue = this.timeFilter.value;
this.timeFilterReValue = this.timeFilterRe.checked;
};
if(this.logHostsFlag) {
this.hostFilterValue = this.logHostsDropdown.getValue(); this.hostFilterValue = this.logHostsDropdown.getValue();
}; };
if(this.isFacilities) { if(this.logFacilitiesFlag) {
this.facilityFilterValue = this.logFacilitiesDropdown.getValue(); this.facilityFilterValue = this.logFacilitiesDropdown.getValue();
}; };
if(this.isLevels) { if(this.logLevelsFlag) {
this.levelFilterValue = this.logLevelsDropdown.getValue(); this.levelFilterValue = this.logLevelsDropdown.getValue();
}; };
this.msgFilterValue = this.msgFilter.value; this.msgFilterValue = this.msgFilter.value;
this.msgFilterReValue = this.msgFilterRe.checked; this.msgFilterReValue = this.msgFilterRe.checked;
this.logSortingValue = this.logSorting.value; this.logSortingValue = this.logSorting.value;
this.autoRefreshValue = this.autoRefresh.checked; this.autoRefreshValue = this.autoRefresh.checked;
if(this.isAutorefresh) { if(this.autorefreshOn) {
if(this.autoRefreshValue) { if(this.autoRefreshValue) {
poll.add(this.pollFuncWrapper, this.pollInterval); poll.add(this.pollFuncWrapper, this.pollInterval);
this.refreshBtn.style.visibility = 'hidden'; this.refreshBtn.style.visibility = 'hidden';
@@ -413,16 +509,21 @@ return baseclass.extend({
}, },
resetFormValues() { resetFormValues() {
this.tailInput.value = this.tailValue; this.tailInput.value = this.tailValue;
this.timeFilter.value = this.timeFilterValue; if(this.logTimestampFlag) {
this.timeFilterRe.checked = this.timeFilterReValue; if(this.enableConvertTimestamp) {
if(this.isHosts) { this.convertTimestamp.checked = this.convertTimestampValue;
};
this.timeFilter.value = this.timeFilterValue;
this.timeFilterRe.checked = this.timeFilterReValue;
};
if(this.logHostsFlag) {
this.logHostsDropdown.setValue(this.hostFilterValue); this.logHostsDropdown.setValue(this.hostFilterValue);
}; };
if(this.isFacilities) { if(this.logFacilitiesFlag) {
this.logFacilitiesDropdown.setValue(this.facilityFilterValue); this.logFacilitiesDropdown.setValue(this.facilityFilterValue);
}; };
if(this.isLevels) { if(this.logLevelsFlag) {
this.logLevelsDropdown.setValue(this.levelFilterValue); this.logLevelsDropdown.setValue(this.levelFilterValue);
}; };
this.msgFilter.value = this.msgFilterValue; this.msgFilter.value = this.msgFilterValue;
@@ -508,7 +609,7 @@ return baseclass.extend({
regExp.lastIndex = 0; regExp.lastIndex = 0;
}); });
} catch(err) { } catch(err) {
if(err.name === 'SyntaxError') { if(err.name == 'SyntaxError') {
ui.addNotification(null, ui.addNotification(null,
E('p', {}, _('Invalid regular expression') + ': ' + err.message)); E('p', {}, _('Invalid regular expression') + ': ' + err.message));
return entriesArray; return entriesArray;
@@ -533,7 +634,7 @@ return baseclass.extend({
let logHostsKeys = Object.keys(this.logHosts); let logHostsKeys = Object.keys(this.logHosts);
if(logHostsKeys.length > 0 && this.logHostsDropdown) { if(logHostsKeys.length > 0 && this.logHostsDropdown) {
this.logHostsDropdown.addChoices(logHostsKeys, this.logHosts); this.logHostsDropdown.addChoices(logHostsKeys, this.logHosts);
if(this.hostFilterValue.length === 0 || logHostsKeys.length === this.hostFilterValue.length) { if(this.hostFilterValue.length == 0) {
return entriesArray; return entriesArray;
}; };
return entriesArray.filter(e => this.hostFilterValue.includes(e[2])); return entriesArray.filter(e => this.hostFilterValue.includes(e[2]));
@@ -544,7 +645,7 @@ return baseclass.extend({
setFacilityFilter(entriesArray) { setFacilityFilter(entriesArray) {
let logFacilitiesKeys = Object.keys(this.logFacilities); let logFacilitiesKeys = Object.keys(this.logFacilities);
if(logFacilitiesKeys.length > 0 && this.logFacilitiesDropdown) { if(logFacilitiesKeys.length > 0 && this.logFacilitiesDropdown) {
if(this.facilityFilterValue.length === 0 || logFacilitiesKeys.length === this.facilityFilterValue.length) { if(this.facilityFilterValue.length == 0) {
return entriesArray; return entriesArray;
}; };
return entriesArray.filter(e => this.facilityFilterValue.includes(e[3])); return entriesArray.filter(e => this.facilityFilterValue.includes(e[3]));
@@ -555,7 +656,7 @@ return baseclass.extend({
setLevelFilter(entriesArray) { setLevelFilter(entriesArray) {
let logLevelsKeys = Object.keys(this.logLevels); let logLevelsKeys = Object.keys(this.logLevels);
if(logLevelsKeys.length > 0 && this.logLevelsDropdown) { if(logLevelsKeys.length > 0 && this.logLevelsDropdown) {
if(this.levelFilterValue.length === 0 || logLevelsKeys.length === this.levelFilterValue.length) { if(this.levelFilterValue.length == 0) {
return entriesArray; return entriesArray;
}; };
return entriesArray.filter(e => this.levelFilterValue.includes(e[4])); return entriesArray.filter(e => this.levelFilterValue.includes(e[4]));
@@ -630,7 +731,13 @@ return baseclass.extend({
if(logSortingLocal) { if(logSortingLocal) {
this.logSortingValue = logSortingLocal; this.logSortingValue = logSortingLocal;
}; };
if(this.isAutorefresh) { if(this.enableConvertTimestamp) {
let convertTimestampLocal = localStorage.getItem(`luci-app-${this.viewName}-convertTimestampValue`);
if(convertTimestampLocal) {
this.convertTimestampValue = Boolean(Number(convertTimestampLocal));
};
};
if(this.enableAutoRefresh) {
let autoRefreshLocal = localStorage.getItem(`luci-app-${this.viewName}-autoRefreshValue`); let autoRefreshLocal = localStorage.getItem(`luci-app-${this.viewName}-autoRefreshValue`);
if(autoRefreshLocal) { if(autoRefreshLocal) {
this.autoRefreshValue = Boolean(Number(autoRefreshLocal)); this.autoRefreshValue = Boolean(Number(autoRefreshLocal));
@@ -638,7 +745,7 @@ return baseclass.extend({
}; };
}, },
saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue) { saveSettingsToLocalStorage(tailValue, logSortingValue, autoRefreshValue, convertTimestampValue) {
tailValue = this.checkZeroValue(tailValue); tailValue = this.checkZeroValue(tailValue);
if(this.tailValue != tailValue) { if(this.tailValue != tailValue) {
localStorage.setItem( localStorage.setItem(
@@ -648,7 +755,13 @@ return baseclass.extend({
localStorage.setItem( localStorage.setItem(
`luci-app-${this.viewName}-logSortingValue`, logSortingValue); `luci-app-${this.viewName}-logSortingValue`, logSortingValue);
}; };
if(this.isAutorefresh) { if(this.convertTimestampOn) {
if(this.convertTimestampValue != convertTimestampValue) {
localStorage.setItem(
`luci-app-${this.viewName}-convertTimestampValue`, String(Number(convertTimestampValue)));
};
};
if(this.autorefreshOn) {
if(this.autoRefreshValue != autoRefreshValue) { if(this.autoRefreshValue != autoRefreshValue) {
localStorage.setItem( localStorage.setItem(
`luci-app-${this.viewName}-autoRefreshValue`, String(Number(autoRefreshValue))); `luci-app-${this.viewName}-autoRefreshValue`, String(Number(autoRefreshValue)));
@@ -681,13 +794,23 @@ return baseclass.extend({
) )
); );
if(logdata && logdata !== '') { if(logdata && logdata !== '') {
if(this.isFacilities && !this.logFacilitiesDropdown) { if(this.enableConvertTimestamp && !this.logConvertTimestampElem) {
this.logConvertTimestampElem = this.makeLogConvertTimestampSection();
};
if(this.logTimestampFlag && !this.logTimeFilterElem) {
this.logTimeFilterElem = this.makeLogTimeFilterSection();
};
if(this.logTimestampFlag && !this.logtimeFilterReElem) {
this.logtimeFilterReElem = this.makeLogtimeFilterReSection();
};
if(this.logFacilitiesFlag && !this.logFacilitiesDropdown) {
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection(); this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
}; };
if(this.isLevels && !this.logLevelsDropdown) { if(this.logLevelsFlag && !this.logLevelsDropdown) {
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection(); this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection();
}; };
if(this.isHosts && !this.logHostsDropdown) { if(this.logHostsFlag && !this.logHostsDropdown) {
this.logHostsDropdownElem = this.makeLogHostsDropdownSection(); this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
}; };
}; };
@@ -730,41 +853,9 @@ return baseclass.extend({
]) ])
), ),
]), ]),
E('div', { 'class': 'cbi-value' }, [ this.logConvertTimestampElem,
E('label', { this.logTimeFilterElem,
'class': 'cbi-value-title', this.logtimeFilterReElem,
'for' : 'timeFilter',
}, _('Timestamp filter')),
E('div', { 'class': 'cbi-value-field' },
E('span', { 'class': 'control-group' }, [
this.timeFilter,
E('button', {
'class': 'cbi-button btn',
'click': L.bind(ev => {
ev.target.blur();
ev.preventDefault();
this.timeFilter.value = null;
this.timeFilter.focus();
}, this),
}, '⌫'),
])
),
]),
E('div', { 'class': 'cbi-value' }, [
E('label', {
'class': 'cbi-value-title',
'for' : 'timeFilterRe',
}, _('Filter is regexp')),
E('div', { 'class': 'cbi-value-field' }, [
E('div', { 'class': 'cbi-checkbox' }, [
this.timeFilterRe,
E('label', {}),
]),
E('div', { 'class': 'cbi-value-description' },
_('Apply timestamp filter as regular expression')
),
]),
]),
this.logHostsDropdownElem, this.logHostsDropdownElem,
this.logFacilitiesDropdownElem, this.logFacilitiesDropdownElem,
this.logLevelsDropdownElem, this.logLevelsDropdownElem,
@@ -810,7 +901,7 @@ return baseclass.extend({
}, _('Sorting entries')), }, _('Sorting entries')),
E('div', { 'class': 'cbi-value-field' }, this.logSorting), E('div', { 'class': 'cbi-value-field' }, this.logSorting),
]), ]),
((this.isAutorefresh) ? ((this.autorefreshOn) ?
E('div', { 'class': 'cbi-value' }, [ E('div', { 'class': 'cbi-value' }, [
E('label', { E('label', {
'class': 'cbi-value-title', 'class': 'cbi-value-title',
@@ -877,6 +968,25 @@ return baseclass.extend({
throw new Error('getLogHash must be overridden by a subclass'); throw new Error('getLogHash must be overridden by a subclass');
}, },
/**
* Converts the timestamp format.
* Abstract method, must be overridden by a subclass!
*
* To completely disable the convert timrstamp option, views extending
* this base class should overwrite the `convertTimestampFunc` function
* with `null`.
*
* @instance
* @abstract
*
* @param {string} t
* @returns {String}
* Returns the converted timestamp string.
*/
convertTimestampFunc(t) {
throw new Error('convertTimestampFunc must be overridden by a subclass');
},
async pollFunc() { async pollFunc() {
await this.getLogHash().then(async hash => { await this.getLogHash().then(async hash => {
if(this.lastHash !== hash) { if(this.lastHash !== hash) {
@@ -895,7 +1005,8 @@ return baseclass.extend({
}; };
}; };
this.saveSettingsToLocalStorage( this.saveSettingsToLocalStorage(
this.tailInput.value, this.logSorting.value, this.autoRefresh.checked); this.tailInput.value, this.logSorting.value,
this.autoRefresh.checked, this.convertTimestamp.checked);
this.setFilterSettings(); this.setFilterSettings();
this.fastTailValue = Number(this.tailValue); this.fastTailValue = Number(this.tailValue);
return this.reloadLog(Number(this.tailValue), true); return this.reloadLog(Number(this.tailValue), true);
@@ -911,10 +1022,13 @@ return baseclass.extend({
load() { load() {
this.restoreSettingsFromLocalStorage(); this.restoreSettingsFromLocalStorage();
if(!this.autoRefresh || typeof(this.getLogHash) != 'function') { if(!this.enableAutoRefresh || typeof(this.getLogHash) != 'function') {
this.isAutorefresh = false; this.autorefreshOn = false;
this.autoRefreshValue = false; this.autoRefreshValue = false;
}; };
if(this.enableConvertTimestamp && typeof(this.convertTimestampFunc) == 'function') {
this.convertTimestampOn = true;
};
return this.getLogData(this.tailValue); return this.getLogData(this.tailValue);
}, },
@@ -939,18 +1053,13 @@ return baseclass.extend({
this.tailInput.value = this.tailValue; this.tailInput.value = this.tailValue;
ui.addValidator(this.tailInput, 'uinteger', true); ui.addValidator(this.tailInput, 'uinteger', true);
this.logHostsDropdownElem = ''; this.convertTimestamp = E('input', {
this.logFacilitiesDropdownElem = ''; 'id' : 'convertTimestamp',
this.logLevelsDropdownElem = ''; 'name' : 'convertTimestamp',
if(this.isLevels) { 'type' : 'checkbox',
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection(); 'form' : 'logFilterForm',
}; });
if(this.isFacilities) { this.convertTimestamp.checked = this.convertTimestampValue;
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
};
if(this.isHosts) {
this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
};
this.timeFilter = E('input', { this.timeFilter = E('input', {
'id' : 'timeFilter', 'id' : 'timeFilter',
@@ -971,6 +1080,28 @@ return baseclass.extend({
this.setRegexpValidator(this.timeFilter, this.timeFilterRe); this.setRegexpValidator(this.timeFilter, this.timeFilterRe);
this.logConvertTimestampElem = '';
this.logTimeFilterElem = '';
this.logtimeFilterReElem = '';
this.logHostsDropdownElem = '';
this.logFacilitiesDropdownElem = '';
this.logLevelsDropdownElem = '';
if(this.logTimestampFlag) {
this.logConvertTimestampElem = this.makeLogConvertTimestampSection();
this.logTimeFilterElem = this.makeLogTimeFilterSection();
this.logtimeFilterReElem = this.makeLogtimeFilterReSection();
};
if(this.logLevelsFlag) {
this.logLevelsDropdownElem = this.makeLogLevelsDropdownSection();
};
if(this.logFacilitiesFlag) {
this.logFacilitiesDropdownElem = this.makeLogFacilitiesDropdownSection();
};
if(this.logHostsFlag) {
this.logHostsDropdownElem = this.makeLogHostsDropdownSection();
};
this.msgFilter = E('input', { this.msgFilter = E('input', {
'id' : 'msgFilter', 'id' : 'msgFilter',
'name' : 'msgFilter', 'name' : 'msgFilter',
@@ -1123,7 +1254,7 @@ return baseclass.extend({
]) ])
); );
if(this.isAutorefresh && this.autoRefreshValue) { if(this.autorefreshOn && this.autoRefreshValue) {
poll.add(this.pollFuncWrapper, this.pollInterval); poll.add(this.pollFuncWrapper, this.pollInterval);
}; };
@@ -1,17 +1,18 @@
'use strict'; 'use strict';
'require baseclass'; 'require baseclass';
'require fs'; 'require fs';
'require ui';
'require view.ruantiblock.log-widget as widget'; 'require view.ruantiblock.log-widget as widget';
return baseclass.extend({ return baseclass.extend({
view: widget.view.extend({ view: widget.view.extend({
enableAutoRefresh: true,
/** /**
* Pattern for picking application-specific entries from the log. * Pattern for picking application-specific entries from the log.
* *
* @property {string} appPattern * @property {string} appPattern
*/ */
appPattern : '^', appPattern : '^',
/** /**
* Enable "tail" option for the logread (logread -l). * Enable "tail" option for the logread (logread -l).
@@ -19,19 +20,19 @@ return baseclass.extend({
* *
* @property {bool} loggerTail * @property {bool} loggerTail
*/ */
loggerTail : false, loggerTail : false,
logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/), logdRegexp : new RegExp(/^([^\s]{3}\s+[^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2}\s+\d{4})\s+([a-z0-9]+)\.([a-z]+)\s+(.*)$/),
syslog_ngRegexp: new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/), syslog_ngRegexp : new RegExp(/^([^\s]{3}\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2})\s+([^\s]+)\s+(.*)$/),
entryRegexp : null, entryRegexp : null,
isLoggerChecked: false, loggerChecked : false,
entriesHandler : null, entriesHandler : null,
logger : null, logger : null,
getLogHash() { getLogHash() {
return this.getLogData(1, true).then(data => { return this.getLogData(1, true).then(data => {
@@ -66,6 +67,18 @@ return baseclass.extend({
]; ];
}, },
// unsupported log handler
unsupportedLogHandler(line, lineNum) {
return [
lineNum, // # (Number)
null, // Timestamp (String)
null, // Host (String)
null, // Facility (String)
null, // Level (String)
this.htmlEntities(line) || ' ', // Message (String)
];
},
checkLogread() { checkLogread() {
return Promise.all([ return Promise.all([
L.resolveDefault(fs.stat('/sbin/logread'), null), L.resolveDefault(fs.stat('/sbin/logread'), null),
@@ -102,8 +115,7 @@ return baseclass.extend({
return []; return [];
}; };
let unsupportedLog = false; let strings = logdata.trim().split(/\n/);
let strings = logdata.trim().split(/\n/);
if(!this.loggerTail && tail && tail > 0 && strings) { if(!this.loggerTail && tail && tail > 0 && strings) {
strings = strings.slice(-tail); strings = strings.slice(-tail);
@@ -111,45 +123,61 @@ return baseclass.extend({
this.totalLogLines = strings.length; this.totalLogLines = strings.length;
let entriesArray = strings.map((e, i) => { let entriesArray = strings.map((e, i) => {
if(!this.isLoggerChecked) { if(!this.loggerChecked) {
if(this.logdRegexp.test(e)) { if(this.logdRegexp.test(e)) {
this.entryRegexp = this.logdRegexp; this.entryRegexp = this.logdRegexp;
this.isFacilities = true; this.logTimestampFlag = true;
this.isLevels = true; this.logFacilitiesFlag = true;
this.logHosts = {}; this.logLevelsFlag = true;
this.entriesHandler = this.logdHandler; this.logHostsFlag = false;
this.logHosts = {};
this.entriesHandler = this.logdHandler;
this.logCols = [
'#',
_('Timestamp'),
null,
_('Facility'),
_('Level'),
_('Message'),
];
this.loggerChecked = true;
} }
else if(this.syslog_ngRegexp.test(e)) { else if(this.syslog_ngRegexp.test(e)) {
this.entryRegexp = this.syslog_ngRegexp; this.entryRegexp = this.syslog_ngRegexp;
this.isHosts = true; this.logTimestampFlag = true;
this.logFacilities = {}; this.logFacilitiesFlag = false;
this.logLevels = {}; this.logLevelsFlag = false;
this.entriesHandler = this.syslog_ngHandler; this.logHostsFlag = true;
this.logFacilities = {};
this.logLevels = {};
this.entriesHandler = this.syslog_ngHandler;
this.logCols = [
'#',
_('Timestamp'),
_('Host'),
null,
null,
_('Message'),
];
this.loggerChecked = true;
} else { } else {
unsupportedLog = true; return this.unsupportedLogHandler(e, i + 1);
return;
}; };
this.isLoggerChecked = true;
}; };
let strArray = e.match(this.entryRegexp); let strArray = e.match(this.entryRegexp);
if(strArray) { if(strArray) {
return this.entriesHandler(strArray, i + 1); return this.entriesHandler(strArray, i + 1);
} else { } else {
unsupportedLog = true; return this.unsupportedLogHandler(e, i + 1);
return;
}; };
}); });
if(unsupportedLog) { if(this.logSortingValue == 'desc') {
throw new Error(_('Unable to load log data:') + ' ' + _('Unsupported log format')); entriesArray.reverse();
} else {
if(this.logSortingValue === 'desc') {
entriesArray.reverse();
};
return entriesArray;
}; };
return entriesArray;
}, },
}), }),
}); });
@@ -46,38 +46,50 @@ return baseclass.extend({
if(e[4] in this.logLevels) { if(e[4] in this.logLevels) {
this.logLevelsStat[e[4]] = this.logLevelsStat[e[4]] + 1; this.logLevelsStat[e[4]] = this.logLevelsStat[e[4]] + 1;
}; };
lines.push(
`<tr class="tr log-${e[4] || 'empty'}"><td class="td left log-entry-text-nowrap" data-title="#">${e[0]}</td>` + let line = [ `<tr class="tr log-${(e[1]) ? e[4] || 'empty' : (this.entriesHandler) ? 'raw' : 'empty'}">` ];
((e[1]) ? `<td class="td left log-entry-time-cell" data-title="${_('Timestamp')}">${e[1]}</td>` : '') + this.logCols.forEach((c, i) => {
((e[2]) ? `<td class="td left log-entry-host-cell" data-title="${_('Host')}">${e[2]}</td>` : '') + if(c) {
((e[3]) ? `<td class="td left log-entry-text-nowrap" data-title="${_('Facility')}">${e[3]}</td>` : '') + let cellClass = '';
((e[4]) ? `<td class="td left log-entry-text-nowrap" data-title="${_('Level')}">${e[4]}</td>` : '') + switch(i) {
((e[5]) ? `<td class="td left log-entry-message-cell" data-title="${_('Message')}">${e[5]}</td>` : '') + case 0:
'</tr>' case 3:
); case 4:
cellClass = 'log-entry-text-nowrap';
break;
case 1:
cellClass = 'log-entry-time-cell';
break;
case 2:
cellClass = 'log-entry-host-cell';
break;
case 5:
cellClass = 'log-entry-message-cell';
break;
};
line.push(`<td class="td left ${cellClass}" data-title="${c}">${e[i] || '&#160;'}</td>`);
};
});
line.push('</tr>');
lines.push(line.join(''));
}); });
lines = lines.join(''); lines = lines.join('');
logTable.append(
E('tr', { 'class': 'tr table-titles' }, [ let logTableHeader = E('tr', { 'class': 'tr table-titles' });
E('th', { 'class': 'th left log-entry-text-nowrap' }, '#'), this.logCols.forEach(e => {
(logdataArray[0][1]) ? if(e) {
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Timestamp')) : '', logTableHeader.append(
(logdataArray[0][2]) ? E('th', { 'class': 'th left log-entry-text-nowrap' }, e)
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Host')) : '', );
(logdataArray[0][3]) ? };
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Facility')) : '', });
(logdataArray[0][4]) ? logTable.append(logTableHeader);
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Level')) : '',
(logdataArray[0][5]) ?
E('th', { 'class': 'th left log-entry-text-nowrap' }, _('Message')) : '',
])
);
}; };
try { try {
logTable.insertAdjacentHTML('beforeend', lines); logTable.insertAdjacentHTML('beforeend', lines);
} catch(err) { } catch(err) {
if(err.name === 'SyntaxError') { if(err.name == 'SyntaxError') {
ui.addNotification(null, ui.addNotification(null,
E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error'); E('p', {}, _('HTML/XML error') + ': ' + err.message), 'error');
}; };
@@ -1,10 +1,10 @@
'use strict'; 'use strict';
'require view.ruantiblock.log-abstract as abc'; 'require view.ruantiblock.log-system as abc';
'require view.ruantiblock.tools as tools'; 'require view.ruantiblock.tools as tools';
return abc.view.extend({ return abc.view.extend({
viewName : 'ruantiblock', viewName : 'ruantiblock',
title : _('Ruantiblock') + ' - ' + _('Log'), title : _('Ruantiblock') + ' - ' + _('Log'),
autoRefresh: false, enableAutoRefresh: false,
appPattern : tools.appName + ':', appPattern : tools.appName + ':',
}); });
+2 -2
View File
@@ -1,11 +1,11 @@
# #
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-lua PKG_NAME:=ruantiblock-mod-lua
PKG_VERSION:=2.1.4 PKG_VERSION:=2.1.5
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -1,7 +1,7 @@
#!/usr/bin/env lua #!/usr/bin/env lua
--[[ --[[
(с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
lua == 5.1 lua == 5.1
--]] --]]
+2 -2
View File
@@ -1,11 +1,11 @@
# #
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock-mod-py PKG_NAME:=ruantiblock-mod-py
PKG_VERSION:=2.1.4 PKG_VERSION:=2.1.5
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
(с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
Python >= 3.6 Python >= 3.6
""" """
+3 -3
View File
@@ -1,12 +1,12 @@
# #
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
# #
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=ruantiblock PKG_NAME:=ruantiblock
PKG_VERSION:=2.1.4 PKG_VERSION:=2.1.5
PKG_RELEASE:=3 PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/ruantiblock_openwrt>
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@@ -12,10 +12,10 @@ if [ "$ACTION" = "ifup" ]; then
DEBUG=0 DEBUG=0
IF_VPN_CURRENT="" IF_VPN_CURRENT=""
ruab_route_status=`$RUAB_CMD raw-status` ruab_route_status=$($RUAB_CMD raw-status)
[ $ruab_route_status -eq 1 -o $ruab_route_status -eq 2 ] && exit 0 [ $ruab_route_status -eq 1 -o $ruab_route_status -eq 2 ] && exit 0
UCI_CMD=`which uci` UCI_CMD="$(which uci)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2 echo " Error! UCI doesn't exists" >&2
exit 1 exit 1
@@ -23,19 +23,19 @@ if [ "$ACTION" = "ifup" ]; then
[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE" [ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"
VPN_ROUTE_CHECK=`$UCI_CMD get ruantiblock.config.vpn_route_check` VPN_ROUTE_CHECK=$($UCI_CMD get ruantiblock.config.vpn_route_check)
[ "$VPN_ROUTE_CHECK" != "0" ] && exit 0 [ "$VPN_ROUTE_CHECK" != "0" ] && exit 0
PROXY_MODE=`$UCI_CMD get ruantiblock.config.proxy_mode` PROXY_MODE=$($UCI_CMD get ruantiblock.config.proxy_mode)
if [ "$PROXY_MODE" = "2" ]; then if [ "$PROXY_MODE" = "2" ]; then
IF_VPN_CURRENT=`$UCI_CMD get ruantiblock.config.if_vpn` IF_VPN_CURRENT=$($UCI_CMD get ruantiblock.config.if_vpn)
fi fi
if [ "$DEVICE" != "$IF_VPN_CURRENT" ]; then if [ "$DEVICE" != "$IF_VPN_CURRENT" ]; then
. "$USER_INSTANCES_COMMON" . "$USER_INSTANCES_COMMON"
for inst in `GetUserInstances 2` for inst in $(GetUserInstances 2)
do do
IncludeUserInstanceVars "$inst" IncludeUserInstanceVars "$inst"
if [ "$DEVICE" = "$U_IF_VPN" ]; then if [ "$DEVICE" = "$U_IF_VPN" ]; then
+41 -29
View File
@@ -3,13 +3,13 @@
######################################################################## ########################################################################
# #
# Ruantiblock # Ruantiblock
# (с) 2024 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt) # (с) 2025 gSpot (https://github.com/gSpotx2f/ruantiblock_openwrt)
# #
######################################################################## ########################################################################
export NAME="ruantiblock" export NAME="ruantiblock"
export APP_EXEC="$0" export APP_EXEC="$0"
export APP_NAME="`basename $0`" export APP_NAME="$(basename $0)"
export LANG="en_US.UTF-8" export LANG="en_US.UTF-8"
export LANGUAGE="en" export LANGUAGE="en"
@@ -182,6 +182,18 @@ export BLLIST_ALT_NSLOOKUP=0
### Альтернативный DNS-сервер ### Альтернативный DNS-сервер
export BLLIST_ALT_DNS_ADDR="8.8.8.8" export BLLIST_ALT_DNS_ADDR="8.8.8.8"
########################## Instances defaults ##########################
INSTANCES_DEF_PROXY_MODE=$PROXY_MODE
INSTANCES_DEF_TOR_TRANS_PORT=$TOR_TRANS_PORT
INSTANCES_DEF_IF_VPN=$IF_VPN
INSTANCES_DEF_T_PROXY_TYPE=$T_PROXY_TYPE
INSTANCES_DEF_T_PROXY_PORT_TCP=$T_PROXY_PORT_TCP
INSTANCES_DEF_T_PROXY_PORT_UDP=$T_PROXY_PORT_UDP
INSTANCES_DEF_T_PROXY_ALLOW_UDP=$T_PROXY_ALLOW_UDP
INSTANCES_DEF_ENABLE_BLLIST_PROXY=$ENABLE_BLLIST_PROXY
INSTANCES_DEF_ENABLE_FPROXY=$ENABLE_FPROXY
############################ Configuration ############################# ############################ Configuration #############################
### External config ### External config
@@ -207,24 +219,24 @@ export DNSMASQ_DATA_FILE="${DNSMASQ_CONFDIR}/02-${NAME}.dnsmasq"
### Utilities ### Utilities
AWK_CMD="awk" AWK_CMD="awk"
NFT_CMD=`which nft` NFT_CMD="$(which nft)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! Nftables doesn't exists" >&2 echo " Error! Nftables doesn't exists" >&2
exit 1 exit 1
fi fi
LOGGER_CMD=`which logger` LOGGER_CMD="$(which logger)"
if [ $ENABLE_LOGGING = "1" -a $? -ne 0 ]; then if [ $ENABLE_LOGGING = "1" -a $? -ne 0 ]; then
echo " Logger doesn't exists" >&2 echo " Logger doesn't exists" >&2
ENABLE_LOGGING=0 ENABLE_LOGGING=0
fi fi
LOGGER_PARAMS="-t ${APP_NAME}" LOGGER_PARAMS="-t ${APP_NAME}"
WGET_CMD=`which wget` WGET_CMD="$(which wget)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! Wget doesn't exists" >&2 echo " Error! Wget doesn't exists" >&2
exit 1 exit 1
fi fi
WGET_PARAMS="--no-check-certificate -q -O" WGET_PARAMS="--no-check-certificate -q -O"
NSLOOKUP_CMD=`which nslookup` NSLOOKUP_CMD="$(which nslookup)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! Nslookup doesn't exists" >&2 echo " Error! Nslookup doesn't exists" >&2
exit 1 exit 1
@@ -261,8 +273,8 @@ export NFTSET_IP_TYPE="ipv4_addr"
export NFTSET_DNSMASQ_TYPE="ipv4_addr" export NFTSET_DNSMASQ_TYPE="ipv4_addr"
export NFTSET_CIDR_PATTERN="set %s {type ${NFTSET_CIDR_TYPE};size ${NFTSET_MAXELEM_CIDR};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" export NFTSET_CIDR_PATTERN="set %s {type ${NFTSET_CIDR_TYPE};size ${NFTSET_MAXELEM_CIDR};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;"
export NFTSET_IP_PATTERN="set %s {type ${NFTSET_IP_TYPE};size ${NFTSET_MAXELEM_IP};policy ${NFTSET_POLICY_IP};flags dynamic;" export NFTSET_IP_PATTERN="set %s {type ${NFTSET_IP_TYPE};size ${NFTSET_MAXELEM_IP};policy ${NFTSET_POLICY_IP};flags dynamic;"
export NFTSET_CIDR_STRING_MAIN=`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}"` export NFTSET_CIDR_STRING_MAIN=$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}")
export NFTSET_IP_STRING_MAIN=`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}"` export NFTSET_IP_STRING_MAIN=$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}")
export NFTSET_BYPASS_IP_STRING="set ${NFTSET_BYPASS_IP} {type ${NFTSET_BYPASS_IP_TYPE};size ${NFTSET_MAXELEM_BYPASS_IP};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;" export NFTSET_BYPASS_IP_STRING="set ${NFTSET_BYPASS_IP} {type ${NFTSET_BYPASS_IP_TYPE};size ${NFTSET_MAXELEM_BYPASS_IP};policy ${NFTSET_POLICY_CIDR};flags interval;auto-merge;"
export UPDATE_STATUS_FILE="${DATA_DIR}/update_status" export UPDATE_STATUS_FILE="${DATA_DIR}/update_status"
export USER_ENTRIES_STATUS_FILE="${DATA_DIR}/user_entries_status" export USER_ENTRIES_STATUS_FILE="${DATA_DIR}/user_entries_status"
@@ -402,7 +414,7 @@ DownloadNativeBlacklist() {
} }
RestartDnsmasq() { RestartDnsmasq() {
eval `echo "$DNSMASQ_RESTART_CMD"` eval $(echo "$DNSMASQ_RESTART_CMD")
} }
FlushNftSets() { FlushNftSets() {
@@ -443,14 +455,14 @@ FormatNftSetElemsList() {
AddBaseNftSets() { AddBaseNftSets() {
local _allowed_hosts _fproxy_private local _allowed_hosts _fproxy_private
$NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { type "$NFTSET_ALLOWED_HOSTS_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_allowed_hosts=`FormatNftSetElemsList "$ALLOWED_HOSTS_LIST"` _allowed_hosts=$(FormatNftSetElemsList "$ALLOWED_HOSTS_LIST")
if [ -n "$_allowed_hosts" ]; then if [ -n "$_allowed_hosts" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_allowed_hosts" } $NFT_CMD add element $NFT_TABLE "$NFTSET_ALLOWED_HOSTS" { "$_allowed_hosts" }
fi fi
$NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_IP" { type "$NFTSET_BYPASS_IP_TYPE"\; size $NFTSET_MAXELEM_BYPASS_IP\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_IP" { type "$NFTSET_BYPASS_IP_TYPE"\; size $NFTSET_MAXELEM_BYPASS_IP\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_FQDN" { type "$NFTSET_BYPASS_FQDN_TYPE"\; size $NFTSET_MAXELEM_BYPASS_FQDN\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_BYPASS_FQDN" { type "$NFTSET_BYPASS_FQDN_TYPE"\; size $NFTSET_MAXELEM_BYPASS_FQDN\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { type "$NFTSET_FPROXY_PRIVATE_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { type "$NFTSET_FPROXY_PRIVATE_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_fproxy_private=`FormatNftSetElemsList "$FPROXY_PRIVATE_NETS"` _fproxy_private=$(FormatNftSetElemsList "$FPROXY_PRIVATE_NETS")
if [ -n "$_fproxy_private" ]; then if [ -n "$_fproxy_private" ]; then
$NFT_CMD add element $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { "$_fproxy_private" } $NFT_CMD add element $NFT_TABLE "$NFTSET_FPROXY_PRIVATE" { "$_fproxy_private" }
fi fi
@@ -468,7 +480,7 @@ MakeInstanceNftSets() {
$NFT_CMD add set $NFT_TABLE "${NFTSET_DNSMASQ}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "${NFTSET_DNSMASQ}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "${NFTSET_ONION}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; } $NFT_CMD add set $NFT_TABLE "${NFTSET_ONION}${_name}" { type "$NFTSET_DNSMASQ_TYPE"\; size $NFTSET_MAXELEM_DNSMASQ\; policy "$NFTSET_POLICY_DNSMASQ"\; flags dynamic,timeout\; timeout "$NFTSET_DNSMASQ_TIMEOUT"\; }
$NFT_CMD add set $NFT_TABLE "${NFTSET_FPROXY}${_name}" { type "$NFTSET_FPROXY_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; } $NFT_CMD add set $NFT_TABLE "${NFTSET_FPROXY}${_name}" { type "$NFTSET_FPROXY_TYPE"\; policy "$NFTSET_POLICY_CIDR"\; flags interval\; auto-merge\; }
_fproxy_hosts=`FormatNftSetElemsList "$_fproxy_list"` _fproxy_hosts=$(FormatNftSetElemsList "$_fproxy_list")
if [ -n "$_fproxy_hosts" ]; then if [ -n "$_fproxy_hosts" ]; then
$NFT_CMD add element $NFT_TABLE "${NFTSET_FPROXY}${_name}" { "$_fproxy_hosts" } $NFT_CMD add element $NFT_TABLE "${NFTSET_FPROXY}${_name}" { "$_fproxy_hosts" }
fi fi
@@ -494,7 +506,7 @@ UpdateBllistProxySet() {
_name=".${_name}" _name=".${_name}"
fi fi
FlushNftSets "${NFTSET_BLLIST_PROXY}${_name}" FlushNftSets "${NFTSET_BLLIST_PROXY}${_name}"
for _host in `echo "$_urls" | $AWK_CMD ' for _host in $(echo "$_urls" | $AWK_CMD '
BEGIN { BEGIN {
RS = " "; RS = " ";
} }
@@ -511,15 +523,15 @@ UpdateBllistProxySet() {
for(i in hosts_arr) { for(i in hosts_arr) {
printf i " "; printf i " ";
}; };
}'` }')
do do
if printf "$_host" | $AWK_CMD '{exit ($0 ~ /^([0-9]{1,3}.){3}[0-9]{1,3}$/) ? 0 : 1}'; then if printf "$_host" | $AWK_CMD '{exit ($0 ~ /^([0-9]{1,3}.){3}[0-9]{1,3}$/) ? 0 : 1}'; then
_ip_string="${_ip_string}${_host} " _ip_string="${_ip_string}${_host} "
else else
_ip_string="${_ip_string}`$NSLOOKUP_CMD $_host 2> /dev/null | $AWK_CMD '/^Address: ([0-9]{1,3}.){3}[0-9]{1,3}$/ {printf $2" "}'`" _ip_string="${_ip_string}$($NSLOOKUP_CMD $_host 2> /dev/null | $AWK_CMD '/^Address: ([0-9]{1,3}.){3}[0-9]{1,3}$/ {printf $2" "}')"
fi fi
done done
_ip_string=`FormatNftSetElemsList "$_ip_string"` _ip_string=$(FormatNftSetElemsList "$_ip_string")
if [ $DEBUG -ge 1 ]; then if [ $DEBUG -ge 1 ]; then
echo " ruantiblock.UpdateBllistProxySet()._ip_string=${_ip_string}; _name=${_name}" >&2 echo " ruantiblock.UpdateBllistProxySet()._ip_string=${_ip_string}; _name=${_name}" >&2
@@ -570,7 +582,7 @@ AddUserInstancesNftRules() {
_route_table_id=$_tproxy_route_table_id _route_table_id=$_tproxy_route_table_id
fi fi
_pkts_mark=$(($_pkts_mark + 1)) _pkts_mark=$(($_pkts_mark + 1))
NftInstanceAdd "\"$U_NAME\"" $_pkts_mark $U_PROXY_MODE $U_TOR_TRANS_PORT $_route_table_id "\"$U_IF_VPN\"" $U_T_PROXY_TYPE $U_T_PROXY_PORT_TCP $U_T_PROXY_PORT_UDP $U_T_PROXY_ALLOW_UDP $U_ENABLE_ENTRIES_REMOTE_PROXY $U_ENABLE_FPROXY "\"$U_VPN_GW_IP\"" NftInstanceAdd "\"$U_NAME\"" $_pkts_mark ${U_PROXY_MODE:=$INSTANCES_DEF_PROXY_MODE} ${U_TOR_TRANS_PORT:=$INSTANCES_DEF_TOR_TRANS_PORT} $_route_table_id "\"${U_IF_VPN:=$INSTANCES_DEF_IF_VPN}\"" ${U_T_PROXY_TYPE:=$INSTANCES_DEF_T_PROXY_TYPE} ${U_T_PROXY_PORT_TCP:=$INSTANCES_DEF_T_PROXY_PORT_TCP} ${U_T_PROXY_PORT_UDP:=$INSTANCES_DEF_T_PROXY_PORT_UDP} ${U_T_PROXY_ALLOW_UDP:=$INSTANCES_DEF_T_PROXY_ALLOW_UDP} ${U_ENABLE_ENTRIES_REMOTE_PROXY:=$INSTANCES_DEF_ENABLE_BLLIST_PROXY} ${U_ENABLE_FPROXY:=$INSTANCES_DEF_ENABLE_FPROXY} "\"$U_VPN_GW_IP\""
ClearUserInstanceVars ClearUserInstanceVars
_prio_offset=$(($_prio_offset - 1)) _prio_offset=$(($_prio_offset - 1))
done done
@@ -603,7 +615,7 @@ AddNftRules() {
NftAddBaseChains $_chain_prio_first $_chain_prio_local $_chain_prio_fproxy NftAddBaseChains $_chain_prio_first $_chain_prio_local $_chain_prio_fproxy
NftAddActionChains $_chain_prio_action NftAddActionChains $_chain_prio_action
AddUserInstancesNftRules AddUserInstancesNftRules
NftInstanceAdd "\" \"" $PKTS_MARK_START $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 "\"$VPN_GW_IP\"" NftInstanceAdd "\" \"" $PKTS_MARK_START ${PROXY_MODE:=$INSTANCES_DEF_PROXY_MODE} ${TOR_TRANS_PORT:=$INSTANCES_DEF_TOR_TRANS_PORT} $_route_table_id "\"${IF_VPN:=$INSTANCES_DEF_IF_VPN}\"" ${T_PROXY_TYPE:=$INSTANCES_DEF_T_PROXY_TYPE} ${T_PROXY_PORT_TCP:=$INSTANCES_DEF_T_PROXY_PORT_TCP} ${T_PROXY_PORT_UDP:=$INSTANCES_DEF_T_PROXY_PORT_UDP} ${T_PROXY_ALLOW_UDP:=$INSTANCES_DEF_T_PROXY_ALLOW_UDP} ${ENABLE_BLLIST_PROXY:=$INSTANCES_DEF_ENABLE_BLLIST_PROXY} ${ENABLE_FPROXY:=$INSTANCES_DEF_ENABLE_FPROXY} "\"$VPN_GW_IP\""
if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then if [ "$PROXY_LOCAL_CLIENTS" = "1" ]; then
NftAddLocalClientsRule NftAddLocalClientsRule
fi fi
@@ -864,7 +876,7 @@ AddUserEntries() {
printf "server=/onion/%s\nnftset=/onion/%s#%s\n" "$U_ONION_DNS_ADDR" "$NFT_TABLE_DNSMASQ" "${NFTSET_ONION}.${U_NAME}" >> "$_dnsmasq_data_file_user_instances" printf "server=/onion/%s\nnftset=/onion/%s#%s\n" "$U_ONION_DNS_ADDR" "$NFT_TABLE_DNSMASQ" "${NFTSET_ONION}.${U_NAME}" >> "$_dnsmasq_data_file_user_instances"
fi fi
if [ -f "$_instance_entries_file" ]; then if [ -f "$_instance_entries_file" ]; then
{ cat "$_instance_entries_file"; printf "\n0\n"; } | ParseUserEntries "`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}"`" "`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}"`" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:local" "$U_ENTRIES_DNS" { cat "$_instance_entries_file"; printf "\n0\n"; } | ParseUserEntries "$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}")" "$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}")" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:local" "$U_ENTRIES_DNS"
fi fi
if [ -n "$U_ENTRIES_REMOTE" ]; then if [ -n "$U_ENTRIES_REMOTE" ]; then
for _url in $U_ENTRIES_REMOTE for _url in $U_ENTRIES_REMOTE
@@ -876,7 +888,7 @@ AddUserEntries() {
if [ "$U_ENABLE_ENTRIES_REMOTE_PROXY" = "1" ]; then if [ "$U_ENABLE_ENTRIES_REMOTE_PROXY" = "1" ]; then
UpdateBllistProxySet "$U_NAME" "$_url" UpdateBllistProxySet "$U_NAME" "$_url"
fi fi
{ Download - "$_url"; printf "\n$?\n"; } | ParseUserEntries "`printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}"`" "`printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}"`" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:${_url}" "$U_ENTRIES_DNS" { Download - "$_url"; printf "\n$?\n"; } | ParseUserEntries "$(printf "$NFTSET_IP_PATTERN" "${NFTSET_IP}.${U_NAME}")" "$(printf "$NFTSET_CIDR_PATTERN" "${NFTSET_CIDR}.${U_NAME}")" "${NFTSET_DNSMASQ}.${U_NAME}" "$_ip_data_file_user_instances" "$_dnsmasq_data_file_user_instances" "$_user_entries_status_file" "${U_NAME}:${_url}" "$U_ENTRIES_DNS"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
_instance_return_code=0 _instance_return_code=0
break break
@@ -922,11 +934,11 @@ AddUserEntries() {
if [ "$ENABLE_TMP_DOWNLOADS" != "1" ] || [ "$ENABLE_TMP_DOWNLOADS" = "1" -a $_return_code -eq 0 ]; then if [ "$ENABLE_TMP_DOWNLOADS" != "1" ] || [ "$ENABLE_TMP_DOWNLOADS" = "1" -a $_return_code -eq 0 ]; then
while read _str while read _str
do do
_update_string=`printf "$_str" | $AWK_CMD '{ _update_string=$(printf "$_str" | $AWK_CMD '{
if(NF == 4) { if(NF == 4) {
printf "User entries (%s): CIDR: %s, IP: %s, FQDN: %s", $4, $1, $2, $3; printf "User entries (%s): CIDR: %s, IP: %s, FQDN: %s", $4, $1, $2, $3;
}; };
}'` }')
if [ -n "$_update_string" ]; then if [ -n "$_update_string" ]; then
### STDOUT ### STDOUT
echo " ${_update_string}" echo " ${_update_string}"
@@ -983,14 +995,14 @@ GetMainInstanceEntries() {
FlushNftSets "$NFTSET_BLLIST_PROXY" FlushNftSets "$NFTSET_BLLIST_PROXY"
fi fi
if [ $_return_code -eq 0 ]; then if [ $_return_code -eq 0 ]; then
_update_string=`$AWK_CMD '{ _update_string=$($AWK_CMD '{
printf "Received entries: %s\n", (NF < 3) ? "No data" : "CIDR: "$1", IP: "$2", FQDN: "$3; printf "Received entries: %s\n", (NF < 3) ? "No data" : "CIDR: "$1", IP: "$2", FQDN: "$3;
exit; exit;
}' "$UPDATE_STATUS_FILE"` }' "$UPDATE_STATUS_FILE")
### STDOUT ### STDOUT
echo " ${_update_string}" echo " ${_update_string}"
MakeLogRecord "notice" "${_update_string}" MakeLogRecord "notice" "${_update_string}"
printf " `date +%d.%m.%Y-%H:%M`\n" >> "$UPDATE_STATUS_FILE" printf " $(date +%d.%m.%Y-%H:%M)\n" >> "$UPDATE_STATUS_FILE"
fi fi
elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then elif [ -z "$BLLIST_PRESET" -a -z "$BLLIST_MODULE" ]; then
ClearDataFiles main_instance ClearDataFiles main_instance
@@ -1199,20 +1211,20 @@ Reload() {
Status() { Status() {
local _update_status _user_entries_status _vpn_error local _update_status _user_entries_status _vpn_error
if [ -f "$UPDATE_STATUS_FILE" ]; then if [ -f "$UPDATE_STATUS_FILE" ]; then
_update_status=`$AWK_CMD '{ _update_status=$($AWK_CMD '{
update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")"; update_string=(NF < 4) ? "No data" : $4" (CIDR: "$1" | IP: "$2" | FQDN: "$3")";
printf "Last blacklist update: %s", update_string; printf "Last blacklist update: %s", update_string;
}' "$UPDATE_STATUS_FILE"` }' "$UPDATE_STATUS_FILE")
else else
_update_status="Last blacklist update: No data" _update_status="Last blacklist update: No data"
fi fi
if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then
_user_entries_status=`$AWK_CMD '{ _user_entries_status=$($AWK_CMD '{
if(NF == 4) { if(NF == 4) {
printf " User entries (%s): CIDR: %s | IP: %s | FQDN: %s\n", $4, $1, $2, $3; printf " User entries (%s): CIDR: %s | IP: %s | FQDN: %s\n", $4, $1, $2, $3;
}; };
}' "$USER_ENTRIES_STATUS_FILE"` }' "$USER_ENTRIES_STATUS_FILE")
fi fi
if ! GetVpnRouteStatus; then if ! GetVpnRouteStatus; then
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
PID_FILE="/var/run/`basename $0`.pid" PID_FILE="/var/run/$(basename $0).pid"
APP_EXEC="/usr/bin/ruantiblock" APP_EXEC="/usr/bin/ruantiblock"
. "$USER_INSTANCES_COMMON" . "$USER_INSTANCES_COMMON"
@@ -9,7 +9,7 @@ VPN_IFACES_STATUS=1
CheckIfaceStatus() { CheckIfaceStatus() {
local _iface="$1" _ret_val=0 local _iface="$1" _ret_val=0
if [ -z "`$IP_CMD link show dev $_iface up 2> /dev/null`" ]; then if [ -z "$($IP_CMD link show dev $_iface up 2> /dev/null)" ]; then
_ret_val=1 _ret_val=1
if [ $DEBUG -ge 1 ]; then if [ $DEBUG -ge 1 ]; then
@@ -23,7 +23,7 @@ CheckIfaceStatus() {
VpnRouteInstanceStatus() { VpnRouteInstanceStatus() {
local _vpn_route_table_id=$1 local _vpn_route_table_id=$1
[ -n "`$IP_CMD route show table $_vpn_route_table_id 2> /dev/null`" ] && return 0 [ -n "$($IP_CMD route show table $_vpn_route_table_id 2> /dev/null)" ] && return 0
return 1 return 1
} }
@@ -83,7 +83,7 @@ Start() {
} }
Stop() { Stop() {
kill -s SIGKILL `cat "$PID_FILE"` 2> /dev/null kill -s SIGKILL $(cat "$PID_FILE") 2> /dev/null
rm -f "$PID_FILE" rm -f "$PID_FILE"
} }
@@ -104,7 +104,7 @@ case "$1" in
fi fi
;; ;;
*) *)
echo "Usage: `basename $0` start|stop" echo "Usage: $(basename $0) start|stop"
exit 1 exit 1
;; ;;
esac esac
@@ -1,13 +1,14 @@
UCI_SECTION="ruantiblock.config" UCI_SECTION="ruantiblock.config"
UCI_VARS="dnsmasq_confdir 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_VARS="dnsmasq_confdir proxy_mode proxy_local_clients nftset_clear_sets allowed_hosts_mode allowed_hosts_list bypass_mode bypass_entries_dns enable_fproxy fproxy_list enable_bllist_proxy if_vpn vpn_gw_ip vpn_route_check tor_trans_port onion_dns_addr t_proxy_type t_proxy_port_tcp t_proxy_port_udp t_proxy_allow_udp enable_logging bllist_min_entries bllist_module bllist_preset bllist_ip_limit bllist_summarize_ip bllist_summarize_cidr bllist_ip_filter bllist_ip_filter_type bllist_sd_limit bllist_fqdn_filter bllist_fqdn_filter_type bllist_enable_idn bllist_alt_nslookup bllist_alt_dns_addr update_at_startup enable_tmp_downloads"
UCI_CMD=`which uci` UCI_CMD="$(which uci)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2 echo " Error! UCI doesn't exists" >&2
exit 1 exit 1
fi fi
AWK_CMD="awk" AWK_CMD="awk"
eval `$UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' eval $($UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
BEGIN { BEGIN {
split(UCI_VARS, split_array, " "); split(UCI_VARS, split_array, " ");
for(i in split_array) for(i in split_array)
@@ -26,7 +27,7 @@ eval `$UCI_CMD show "$UCI_SECTION" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
for(i in vars_array) for(i in vars_array)
print toupper(i) "=\"""\""; print toupper(i) "=\"""\"";
}; };
}'` }')
. /lib/functions/network.sh . /lib/functions/network.sh
network_get_subnet subnet_lan "lan" network_get_subnet subnet_lan "lan"
@@ -1,5 +1,6 @@
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" 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"
UCI_CMD=`which uci` UCI_CMD="$(which uci)"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo " Error! UCI doesn't exists" >&2 echo " Error! UCI doesn't exists" >&2
exit 1 exit 1
@@ -26,7 +27,7 @@ IncludeUserInstanceVars() {
local _inst="$1" local _inst="$1"
local _uci_section="${NAME}.${_inst}" local _uci_section="${NAME}.${_inst}"
U_NAME="$_inst" U_NAME="$_inst"
eval `$UCI_CMD show "$_uci_section" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" ' eval $($UCI_CMD show "$_uci_section" | $AWK_CMD -F "=" -v UCI_VARS="$UCI_VARS" '
BEGIN { BEGIN {
split(UCI_VARS, split_array, " "); split(UCI_VARS, split_array, " ");
for(i in split_array) for(i in split_array)
@@ -45,7 +46,7 @@ IncludeUserInstanceVars() {
for(i in vars_array) for(i in vars_array)
print toupper(i) "=\"""\""; print toupper(i) "=\"""\"";
}; };
}'` }')
if [ $DEBUG -ge 2 ]; then if [ $DEBUG -ge 2 ]; then
echo " user_instances_config_script.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}" >&2 echo " user_instances_config_script.IncludeUserInstanceVars: _inst=${_inst} U_NAME=${U_NAME} U_PROXY_MODE=${U_PROXY_MODE}" >&2
@@ -1,18 +1,18 @@
Info() { Info() {
local _update_status _user_entries_status _inst local _update_status _user_entries_status _inst
if [ -f "$UPDATE_STATUS_FILE" ]; then if [ -f "$UPDATE_STATUS_FILE" ]; then
_update_status=`$AWK_CMD '{ _update_status=$($AWK_CMD '{
if(NF < 4) { if(NF < 4) {
printf "{\"status\":false}"; printf "{\"status\":false}";
} else { } else {
printf "{\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}"; printf "{\"status\":true,\"date\":\""$4"\",\"cidr\":\""$1"\",\"ip\":\""$2"\",\"fqdn\":\""$3"\"}";
}; };
}' "$UPDATE_STATUS_FILE"` }' "$UPDATE_STATUS_FILE")
else else
_update_status="{\"status\":false}" _update_status="{\"status\":false}"
fi fi
if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then if [ -f "$USER_ENTRIES_STATUS_FILE" ]; then
_user_entries_status=`$AWK_CMD ' _user_entries_status=$($AWK_CMD '
BEGIN { BEGIN {
items = 0; items = 0;
printf "["; printf "[";
@@ -29,7 +29,7 @@ Info() {
} }
END { END {
printf "]"; printf "]";
}' "$USER_ENTRIES_STATUS_FILE"` }' "$USER_ENTRIES_STATUS_FILE")
else else
_user_entries_status="[]" _user_entries_status="[]"
fi fi
@@ -56,7 +56,7 @@ NftRouteAdd() {
if [ -n "$_vpn_gw_ip" ]; then if [ -n "$_vpn_gw_ip" ]; then
_vpn_ip="$_vpn_gw_ip" _vpn_ip="$_vpn_gw_ip"
else else
_vpn_ip=`$IP_CMD addr list dev "$_if_vpn" 2> /dev/null | $AWK_CMD '/inet/{f=($3 == "peer") ? 4 : 2; sub("/[0-9]{1,2}$", "", $f); print $f; exit}'` _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 fi
if [ -n "$_vpn_ip" -a "$_type" = "vpn" ]; then if [ -n "$_vpn_ip" -a "$_type" = "vpn" ]; then
echo 0 > "/proc/sys/net/ipv4/conf/${_if_vpn}/rp_filter" echo 0 > "/proc/sys/net/ipv4/conf/${_if_vpn}/rp_filter"
@@ -80,7 +80,7 @@ NftRouteAdd() {
NftRouteStatus() { NftRouteStatus() {
local _route_table_id=$1 local _route_table_id=$1
[ -n "`$IP_CMD route show table "$_route_table_id" 2> /dev/null`" ] && return 0 [ -n "$($IP_CMD route show table "$_route_table_id" 2> /dev/null)" ] && return 0
return 1 return 1
} }
@@ -90,9 +90,7 @@ NftAddBaseChains() {
$NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN" $NFT_CMD add chain $NFT_TABLE "$NFT_BLLIST_CHAIN"
$NFT_CMD add chain $NFT_TABLE "$NFT_FPROXY_CHAIN" { type filter hook prerouting priority ${_chain_prio_fproxy}\; policy accept\; } $NFT_CMD add chain $NFT_TABLE "$NFT_FPROXY_CHAIN" { type filter hook prerouting priority ${_chain_prio_fproxy}\; policy accept\; }
$NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { type filter hook prerouting priority ${_chain_prio_first}\; policy accept\; } $NFT_CMD add chain $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" { type filter hook prerouting priority ${_chain_prio_first}\; policy accept\; }
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_CHAIN" meta iif lo return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_CHAIN" ip daddr "@${NFTSET_FPROXY_PRIVATE}" return NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_FPROXY_CHAIN" ip daddr "@${NFTSET_FPROXY_PRIVATE}" return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" meta iif lo return
NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" "$NFT_ALLOWED_HOSTS_PATTERN" NftCmdWrapper $NFT_CMD add rule $NFT_TABLE "$NFT_ALLOWED_HOSTS_CHAIN" "$NFT_ALLOWED_HOSTS_PATTERN"
if [ "$BYPASS_MODE" = "1" ]; then if [ "$BYPASS_MODE" = "1" ]; then
for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN" for _set in "$NFTSET_BYPASS_IP" "$NFTSET_BYPASS_FQDN"
@@ -25,7 +25,7 @@ ListUserInstances() {
GetUserInstances() { GetUserInstances() {
local _type="$1" _fnames="$2" _i=0 _inst _instances="" local _type="$1" _fnames="$2" _i=0 _inst _instances=""
for _inst in `ListUserInstances` for _inst in $(ListUserInstances)
do do
IncludeUserInstanceVars "$_inst" IncludeUserInstanceVars "$_inst"
if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then
@@ -45,7 +45,7 @@ GetUserInstances() {
SetUserInstancesItems() { SetUserInstancesItems() {
local _i=0 _inst _instances_all="" _instances_all_fnames="" _instances_vpn="" _instances_vpn_fnames="" _instances_cfg="" _instances_cfg_fnames="" local _i=0 _inst _instances_all="" _instances_all_fnames="" _instances_vpn="" _instances_vpn_fnames="" _instances_cfg="" _instances_cfg_fnames=""
for _inst in `ListUserInstances` for _inst in $(ListUserInstances)
do do
IncludeUserInstanceVars "$_inst" IncludeUserInstanceVars "$_inst"
if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then if [ $_i -lt $USER_INSTANCES_MAX -a -n "$U_NAME" -a "$U_ENABLED" != "0" ]; then