🌴 Sync 2026-07-14 04:31:14

This commit is contained in:
github-actions[bot] committed 2026-07-14 04:31:14 +08:00
1 parent e652a38f70
commit fd29dc0037
47 files changed
+926 -789

No files matched your search

+2 -2
View File
@@ -6,9 +6,9 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=dae PKG_NAME:=dae
PKG_VERSION:=2026.07.08 PKG_VERSION:=2026.07.08
PKG_RELEASE:=15 PKG_RELEASE:=16
PKG_SOURCE:=dae-src-2026.07.08-ca25ef2aa396.tar.gz PKG_SOURCE:=dae-src-2026.07.08-6a60ae809f8b.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip PKG_HASH:=skip
+2 -2
View File
@@ -6,9 +6,9 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=daed PKG_NAME:=daed
PKG_VERSION:=2026.07.08 PKG_VERSION:=2026.07.08
PKG_RELEASE:=21 PKG_RELEASE:=22
PKG_SOURCE:=daed-src-2026.07.08-71b818ad193b.tar.gz PKG_SOURCE:=daed-src-2026.07.08-e83da9ff800e.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_HASH:=skip PKG_HASH:=skip
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=hysteria PKG_NAME:=hysteria
PKG_VERSION:=2.9.3 PKG_VERSION:=2.10.0
PKG_RELEASE:=11 PKG_RELEASE:=12
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/apernet/hysteria/tar.gz/app/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/apernet/hysteria/tar.gz/app/v$(PKG_VERSION)?
+12 -1
View File
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector PKG_NAME:=internet-detector
PKG_VERSION:=1.7.3 PKG_VERSION:=1.7.3
PKG_RELEASE:=3 PKG_RELEASE:=4
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector> PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@@ -64,4 +64,15 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DATA) ./files/usr/lib/lua/internet-detector/modules/mod_regular_script.lua $(1)/usr/lib/lua/internet-detector/modules/mod_regular_script.lua $(INSTALL_DATA) ./files/usr/lib/lua/internet-detector/modules/mod_regular_script.lua $(1)/usr/lib/lua/internet-detector/modules/mod_regular_script.lua
endef endef
define Package/$(PKG_NAME)/postinst
#!/bin/sh
ID_CONF="/etc/internet-detector"
SYSUP_CONF="/etc/sysupgrade.conf"
grep -e "^$${ID_CONF}" "$$SYSUP_CONF" > /dev/null || echo "$$ID_CONF" >> "$$SYSUP_CONF"
exit 0
endef
$(eval $(call BuildPackage,$(PKG_NAME))) $(eval $(call BuildPackage,$(PKG_NAME)))
+1 -1
View File
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-daede PKG_NAME:=luci-app-daede
PKG_VERSION:=1.14.7 PKG_VERSION:=1.14.7
PKG_RELEASE:=31 PKG_RELEASE:=32
PKG_MAINTAINER:=kenzok8 PKG_MAINTAINER:=kenzok8
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
@@ -52,19 +52,26 @@ fi
( (
flock 9 flock 9
apk update 2>&1 apk update 2>&1
# pin exact latest version + --force-broken-world so unrelated broken
# packages can't block this upgrade (cf. clashoo component_update)
ver=$(apk list "$PKG" 2>/dev/null | awk -v p="$PKG" '$1 ~ "^" p "-[0-9]" { v=$1; sub("^" p "-", "", v); print v }' | sort -V | tail -1) ver=$(apk list "$PKG" 2>/dev/null | awk -v p="$PKG" '$1 ~ "^" p "-[0-9]" { v=$1; sub("^" p "-", "", v); print v }' | sort -V | tail -1)
if [ -n "$ver" ]; then if [ -n "$ver" ]; then
echo "--- apk add $PKG=$ver ---" constraint="$PKG=$ver"
apk add "$PKG=$ver" --force-broken-world 2>&1
else else
echo "--- apk add $PKG ---" constraint="$PKG"
apk add "$PKG" --force-broken-world 2>&1 fi
echo "--- apk add -s $constraint ---"
if apk add -s "$constraint" 2>&1; then
echo "--- apk add $constraint ---"
apk add "$constraint" 2>&1
else
echo "result: apk cannot resolve $constraint; no packages were changed"
exit 1
fi fi
) 9>/tmp/luci-app-daede.apk.lock ) 9>/tmp/luci-app-daede.apk.lock
# apk's exit code is unreliable (broken-world noise); judge by state instead rc=$?
if ! apk list --installed 2>/dev/null | grep -q "^${PKG}-"; then if [ "$rc" != 0 ]; then
:
elif ! apk list --installed 2>/dev/null | grep -q "^${PKG}-"; then
echo "result: $PKG is not installed" echo "result: $PKG is not installed"
rc=1 rc=1
elif apk list -u 2>/dev/null | grep -q "^${PKG}-"; then elif apk list -u 2>/dev/null | grep -q "^${PKG}-"; then
@@ -164,7 +164,7 @@ const inbound_type = [
['anytls', _('AnyTLS') + ' - ' + _('TCP')], ['anytls', _('AnyTLS') + ' - ' + _('TCP')],
['tuic', _('TUIC') + ' - ' + _('UDP')], ['tuic', _('TUIC') + ' - ' + _('UDP')],
['hysteria2', _('Hysteria2') + ' - ' + _('UDP')], ['hysteria2', _('Hysteria2') + ' - ' + _('UDP')],
['hysteria2-realm', _('Hysteria2 Realm') + ' - ' + _('TCP/UDP')], ['hysteria2-realm', _('Hysteria2 Realm Server') + ' - ' + _('TCP/UDP')],
['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')], ['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')],
['tunnel', _('Tunnel') + ' - ' + _('TCP/UDP')] ['tunnel', _('Tunnel') + ' - ' + _('TCP/UDP')]
]; ];
@@ -198,12 +198,12 @@ const outbound_type = [
['vless', _('VLESS') + ' - ' + _('TCP')], ['vless', _('VLESS') + ' - ' + _('TCP')],
['trojan', _('Trojan') + ' - ' + _('TCP')], ['trojan', _('Trojan') + ' - ' + _('TCP')],
['anytls', _('AnyTLS') + ' - ' + _('TCP')], ['anytls', _('AnyTLS') + ' - ' + _('TCP')],
['tuic', _('TUIC') + ' - ' + _('UDP')],
//['hysteria', _('Hysteria') + ' - ' + _('UDP')], //['hysteria', _('Hysteria') + ' - ' + _('UDP')],
['hysteria2', _('Hysteria2') + ' - ' + _('UDP')], ['hysteria2', _('Hysteria2') + ' - ' + _('UDP')],
['tuic', _('TUIC') + ' - ' + _('UDP')],
['masque', _('Masque') + ' - ' + _('UDP')], // https://blog.cloudflare.com/post-quantum-warp/
['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')], ['trusttunnel', _('TrustTunnel') + ' - ' + _('TCP/UDP')],
['wireguard', _('WireGuard') + ' - ' + _('UDP')], ['wireguard', _('WireGuard') + ' - ' + _('UDP')],
['masque', _('Masque') + ' - ' + _('UDP')], // https://blog.cloudflare.com/post-quantum-warp/
['ssh', _('SSH') + ' - ' + _('TCP')] ['ssh', _('SSH') + ' - ' + _('TCP')]
]; ];
@@ -171,86 +171,6 @@ function renderListeners(s, uciconfig, isClient) {
o.depends({type: /^(tuic)$/, uuid: /.+/}); o.depends({type: /^(tuic)$/, uuid: /.+/});
o.modalonly = true; o.modalonly = true;
/* Hysteria2 fields */
o = s.taboption('field_general', form.Value, 'hysteria_up_mbps', _('Max upload speed'),
_('In Mbps.'));
o.datatype = 'uinteger';
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_down_mbps', _('Max download speed'),
_('In Mbps.'));
o.datatype = 'uinteger';
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', form.Flag, 'hysteria_ignore_client_bandwidth', _('Ignore client bandwidth'),
_('Tell the client to use the BBR flow control algorithm instead of Hysteria CC.'));
o.default = o.disabled;
o.depends({type: 'hysteria2', hysteria_up_mbps: '', hysteria_down_mbps: ''});
o.modalonly = true;
o = s.taboption('field_general', form.ListValue, 'hysteria_obfs_type', _('Obfuscate type'));
o.value('', _('Disable'));
o.value('salamander', _('Salamander'));
o.value('gecko', _('Gecko'));
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', hm.GenValue, 'hysteria_obfs_password', _('Obfuscate password'),
_('Enabling obfuscation will make the server incompatible with standard QUIC connections, losing the ability to masquerade with HTTP/3.'));
o.password = true;
o.rmempty = false;
o.depends('type', 'hysteria');
o.depends({type: 'hysteria2', hysteria_obfs_type: /.+/});
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_obfs_min_packet_size', _('Obfuscate minimum packet size'));
o.placeholder = '512'
o.depends('hysteria_obfs_type', 'gecko');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_obfs_max_packet_size', _('Obfuscate maximum packet size'));
o.placeholder = '1200'
o.depends('hysteria_obfs_type', 'gecko');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_masquerade', _('Masquerade'),
_('HTTP3 server behavior when authentication fails.<br/>A 404 page will be returned if empty.'));
o.placeholder = 'file:///var/www or http://127.0.0.1:8080'
o.depends('type', 'hysteria2');
o.modalonly = true;
/* Hysteria2 Realmserver fields */
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_token', _('Pre-shared key'));
o.placeholder = 'public';
o.rmempty = false;
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms', _('Max realms'));
o.datatype = 'uinteger';
o.placeholder = '65536';
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms_per_ip', _('Max realms per client IP'));
o.datatype = 'uinteger';
o.placeholder = '4';
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_trusted_proxy_header', _('Trusted proxy header'),
_('Header to read real client IP from (e.g. X-Forwarded-For)'));
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_realm_name_pattern', _('Realm name pattern'));
o.default = '^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$';
o.rmempty = false;
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
/* Shadowsocks fields */ /* Shadowsocks fields */
o = s.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher')); o = s.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher'));
o.default = hm.shadowsocks_cipher_methods[1][0]; o.default = hm.shadowsocks_cipher_methods[1][0];
@@ -470,31 +390,26 @@ function renderListeners(s, uciconfig, isClient) {
o.depends('type', 'snell'); o.depends('type', 'snell');
o.modalonly = true; o.modalonly = true;
/* Tuic fields */ /* VMess / VLESS fields */
o = s.taboption('field_general', hm.GenValue, 'uuid', _('UUID')); o = s.taboption('field_general', hm.GenValue, 'vmess_uuid', _('UUID'));
o.rmempty = false; o.rmempty = false;
o.validate = hm.validateUUID; o.validate = hm.validateUUID;
o.depends('type', 'tuic'); o.depends({type: /^(vmess|vless)$/});
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_general', form.Value, 'tuic_max_udp_relay_packet_size', _('Max UDP relay packet size')); o = s.taboption('field_general', form.ListValue, 'vless_flow', _('Flow'));
o.default = hm.vless_flow[0][0];
hm.vless_flow.forEach((res) => {
o.value.apply(o, res);
})
o.depends('type', 'vless');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'vmess_alterid', _('Alter ID'),
_('Legacy protocol support (VMess MD5 Authentication) is provided for compatibility purposes only, use of alterId > 1 is not recommended.'));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
o.default = '1500'; o.placeholder = '0';
o.depends('type', 'tuic'); o.depends('type', 'vmess');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'tuic_max_idle_time', _('Idle timeout'),
_('In seconds.'));
o.default = '15000';
o.validate = hm.validateTimeDuration;
o.depends('type', 'tuic');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'tuic_authentication_timeout', _('Auth timeout'),
_('In seconds.'));
o.default = '1000';
o.validate = hm.validateTimeDuration;
o.depends('type', 'tuic');
o.modalonly = true; o.modalonly = true;
/* Trojan fields */ /* Trojan fields */
@@ -525,26 +440,111 @@ function renderListeners(s, uciconfig, isClient) {
o.depends('type', 'anytls'); o.depends('type', 'anytls');
o.modalonly = true; o.modalonly = true;
/* VMess / VLESS fields */ /* Tuic fields */
o = s.taboption('field_general', hm.GenValue, 'vmess_uuid', _('UUID')); o = s.taboption('field_general', hm.GenValue, 'uuid', _('UUID'));
o.rmempty = false; o.rmempty = false;
o.validate = hm.validateUUID; o.validate = hm.validateUUID;
o.depends({type: /^(vmess|vless)$/}); o.depends('type', 'tuic');
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_general', form.ListValue, 'vless_flow', _('Flow')); o = s.taboption('field_general', form.Value, 'tuic_max_udp_relay_packet_size', _('Max UDP relay packet size'));
o.default = hm.vless_flow[0][0];
hm.vless_flow.forEach((res) => {
o.value.apply(o, res);
})
o.depends('type', 'vless');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'vmess_alterid', _('Alter ID'),
_('Legacy protocol support (VMess MD5 Authentication) is provided for compatibility purposes only, use of alterId > 1 is not recommended.'));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
o.placeholder = '0'; o.default = '1500';
o.depends('type', 'vmess'); o.depends('type', 'tuic');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'tuic_max_idle_time', _('Idle timeout'),
_('In seconds.'));
o.default = '15000';
o.validate = hm.validateTimeDuration;
o.depends('type', 'tuic');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'tuic_authentication_timeout', _('Auth timeout'),
_('In seconds.'));
o.default = '1000';
o.validate = hm.validateTimeDuration;
o.depends('type', 'tuic');
o.modalonly = true;
/* Hysteria2 fields */
o = s.taboption('field_general', form.Value, 'hysteria_up_mbps', _('Max upload speed'),
_('In Mbps.'));
o.datatype = 'uinteger';
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_down_mbps', _('Max download speed'),
_('In Mbps.'));
o.datatype = 'uinteger';
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', form.Flag, 'hysteria_ignore_client_bandwidth', _('Ignore client bandwidth'),
_('Tell the client to use the BBR flow control algorithm instead of Hysteria CC.'));
o.default = o.disabled;
o.depends({type: 'hysteria2', hysteria_up_mbps: '', hysteria_down_mbps: ''});
o.modalonly = true;
o = s.taboption('field_general', form.ListValue, 'hysteria_obfs_type', _('Obfuscate type'));
o.value('', _('Disable'));
o.value('salamander', _('Salamander'));
o.value('gecko', _('Gecko'));
o.depends('type', 'hysteria2');
o.modalonly = true;
o = s.taboption('field_general', hm.GenValue, 'hysteria_obfs_password', _('Obfuscate password'),
_('Enabling obfuscation will make the server incompatible with standard QUIC connections, losing the ability to masquerade with HTTP/3.'));
o.password = true;
o.rmempty = false;
o.depends('type', 'hysteria');
o.depends({type: 'hysteria2', hysteria_obfs_type: /.+/});
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_obfs_min_packet_size', _('Obfuscate minimum packet size'));
o.placeholder = '512'
o.depends('hysteria_obfs_type', 'gecko');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_obfs_max_packet_size', _('Obfuscate maximum packet size'));
o.placeholder = '1200'
o.depends('hysteria_obfs_type', 'gecko');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria_masquerade', _('Masquerade'),
_('HTTP3 server behavior when authentication fails.<br/>A 404 page will be returned if empty.'));
o.placeholder = 'file:///var/www or http://127.0.0.1:8080'
o.depends('type', 'hysteria2');
o.modalonly = true;
/* Hysteria2 Realmserver fields */
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_token', _('Pre-shared key'));
o.placeholder = 'public';
o.rmempty = false;
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms', _('Max realms'));
o.datatype = 'uinteger';
o.placeholder = '65536';
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_max_realms_per_ip', _('Max realms per client IP'));
o.datatype = 'uinteger';
o.placeholder = '4';
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_trusted_proxy_header', _('Trusted proxy header'),
_('Header to read real client IP from (e.g. X-Forwarded-For)'));
o.depends('type', 'hysteria2-realm');
o.modalonly = true;
o = s.taboption('field_general', form.Value, 'hysteria2_realmserver_realm_name_pattern', _('Realm name pattern'));
o.default = '^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$';
o.rmempty = false;
o.depends('type', 'hysteria2-realm');
o.modalonly = true; o.modalonly = true;
/* TrustTunnel fields */ /* TrustTunnel fields */
@@ -622,6 +622,7 @@ function renderListeners(s, uciconfig, isClient) {
if (isClient) { if (isClient) {
o = s.taboption('field_general', form.Value, 'routing_mark', _('Routing mark (Fwmark)')); o = s.taboption('field_general', form.Value, 'routing_mark', _('Routing mark (Fwmark)'));
o.datatype = 'uinteger'; o.datatype = 'uinteger';
o.modalonly = false;
o.editable = true; o.editable = true;
o = s.taboption('field_general', hm.ListValue, 'rule', _('Sub rule'), o = s.taboption('field_general', hm.ListValue, 'rule', _('Sub rule'),
@@ -633,6 +634,7 @@ function renderListeners(s, uciconfig, isClient) {
...hm.loadLabelValues(this.config, 'subrule-group') ...hm.loadLabelValues(this.config, 'subrule-group')
], section_id); ], section_id);
} }
o.modalonly = false;
o.editable = true; o.editable = true;
o = s.taboption('field_general', hm.ListValue, 'proxy', _('Proxy group'), o = s.taboption('field_general', hm.ListValue, 'proxy', _('Proxy group'),
@@ -647,6 +649,7 @@ function renderListeners(s, uciconfig, isClient) {
...hm.loadLabelValues(this.config, 'proxy_group') ...hm.loadLabelValues(this.config, 'proxy_group')
], section_id); ], section_id);
} }
o.modalonly = false;
o.editable = true; o.editable = true;
} }
@@ -947,8 +950,8 @@ function renderListeners(s, uciconfig, isClient) {
let def_alpn; let def_alpn;
switch (type) { switch (type) {
case 'hysteria2':
case 'tuic': case 'tuic':
case 'hysteria2':
def_alpn = ['h3']; def_alpn = ['h3'];
break; break;
case 'hysteria2-realm': case 'hysteria2-realm':
@@ -1032,7 +1035,7 @@ function renderListeners(s, uciconfig, isClient) {
hm.tls_client_auth_types.forEach((res) => { hm.tls_client_auth_types.forEach((res) => {
o.value.apply(o, res); o.value.apply(o, res);
}) })
o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|hysteria2-realm|trusttunnel)$/});
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_tls', form.Value, 'tls_client_auth_cert_path', _('Client Auth Certificate path') + _(' (mTLS)'), o = s.taboption('field_tls', form.Value, 'tls_client_auth_cert_path', _('Client Auth Certificate path') + _(' (mTLS)'),
@@ -1041,7 +1044,7 @@ function renderListeners(s, uciconfig, isClient) {
o.validate = function(/* ... */) { o.validate = function(/* ... */) {
return hm.validateMTLSClientAuth.call(this, 'tls_client_auth_type', ...arguments); return hm.validateMTLSClientAuth.call(this, 'tls_client_auth_type', ...arguments);
} }
o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|hysteria2-realm|trusttunnel)$/});
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_tls', form.Button, '_upload_client_auth_cert', _('Upload certificate') + _(' (mTLS)'), o = s.taboption('field_tls', form.Button, '_upload_client_auth_cert', _('Upload certificate') + _(' (mTLS)'),
@@ -1090,13 +1093,13 @@ function renderListeners(s, uciconfig, isClient) {
return node; return node;
} }
o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|hysteria2-realm|trusttunnel)$/});
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_tls', hm.CopyValue, 'tls_ech_config', _('ECH config'), o = s.taboption('field_tls', hm.CopyValue, 'tls_ech_config', _('ECH config'),
_('This ECH parameter needs to be added to the HTTPS record of the domain.')); _('This ECH parameter needs to be added to the HTTPS record of the domain.'));
o.placeholder = 'AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA'; o.placeholder = 'AEn+DQBFKwAgACABWIHUGj4u+PIggYXcR5JF0gYk3dCRioBW8uJq9H4mKAAIAAEAAQABAANAEnB1YmxpYy50bHMtZWNoLmRldgAA';
o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|hysteria2|hysteria2-realm|tuic|trusttunnel)$/}); o.depends({tls: '1', type: /^(http|socks|mixed|vmess|vless|trojan|anytls|tuic|hysteria2|hysteria2-realm|trusttunnel)$/});
o.modalonly = true; o.modalonly = true;
// uTLS fields // uTLS fields
@@ -1235,7 +1238,7 @@ function renderListeners(s, uciconfig, isClient) {
/* Multiplex fields */ /* Multiplex fields */
o = s.taboption('field_general', form.Flag, 'smux_enabled', _('Multiplex')); o = s.taboption('field_general', form.Flag, 'smux_enabled', _('Multiplex'));
o.default = o.disabled; o.default = o.disabled;
o.depends({type: /^(shadowsocks|vmess|vless|trojan|tuic|hysteria2|sudoku)$/}); o.depends({type: /^(shadowsocks|sudoku|vmess|vless|trojan|tuic|hysteria2)$/});
o.modalonly = true; o.modalonly = true;
o = s.taboption('field_multiplex', form.Flag, 'smux_padding', _('Enable padding')); o = s.taboption('field_multiplex', form.Flag, 'smux_padding', _('Enable padding'));
@@ -130,7 +130,7 @@ const parseProviderYaml = hm.parseYaml.extend({
override_prefix: this.jq(cfg, "override.additional-prefix"), override_prefix: this.jq(cfg, "override.additional-prefix"),
override_suffix: this.jq(cfg, "override.additional-suffix"), override_suffix: this.jq(cfg, "override.additional-suffix"),
override_replace: (this.jq(cfg, "override.proxy-name") || []).map((obj) => JSON.stringify(obj)), // array.string: array.object override_replace: (this.jq(cfg, "override.proxy-name") || []).map((obj) => JSON.stringify(obj)), // array.string: array.object
// Configuration Items // Other configuration items
override_tfo: this.bool2str(this.jq(cfg, "override.tfo")), // bool override_tfo: this.bool2str(this.jq(cfg, "override.tfo")), // bool
override_mptcp: this.bool2str(this.jq(cfg, "override.mptcp")), // bool override_mptcp: this.bool2str(this.jq(cfg, "override.mptcp")), // bool
override_udp: this.bool2str(this.jq(cfg, "override.udp")), // bool override_udp: this.bool2str(this.jq(cfg, "override.udp")), // bool
@@ -306,7 +306,7 @@ return view.extend({
so = ss.taboption('field_general', form.Value, 'password', _('Password')); so = ss.taboption('field_general', form.Value, 'password', _('Password'));
so.password = true; so.password = true;
so.validate = hm.validateAuthPassword; so.validate = hm.validateAuthPassword;
so.depends({type: /^(http|socks5|mieru|trojan|anytls|hysteria2|tuic|trusttunnel|ssh)$/}); so.depends({type: /^(http|socks5|mieru|trojan|anytls|tuic|hysteria2|trusttunnel|ssh)$/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', hm.TextValue, 'headers', _('HTTP header')); so = ss.taboption('field_general', hm.TextValue, 'headers', _('HTTP header'));
@@ -315,75 +315,6 @@ return view.extend({
so.depends('type', 'http'); so.depends('type', 'http');
so.modalonly = true; so.modalonly = true;
/* Hysteria / Hysteria2 fields */
so = ss.taboption('field_general', form.DynamicList, 'hysteria_ports', _('Ports pool'));
so.datatype = 'or(port, portrange)';
so.depends({type: /^(hysteria|hysteria2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_hop_interval', _('Port hop interval'),
_('In seconds. <code>%s</code> will be used if empty.').format('30'));
so.placeholder = '15 OR 15-30';
so.depends('type', 'hysteria2');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_up_mbps', _('Max upload speed'),
_('In Mbps.'));
so.datatype = 'uinteger';
so.depends({type: /^(hysteria|hysteria2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_down_mbps', _('Max download speed'),
_('In Mbps.'));
so.datatype = 'uinteger';
so.depends({type: /^(hysteria|hysteria2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'hysteria_obfs_type', _('Obfuscate type'));
so.value('', _('Disable'));
so.value('salamander', _('Salamander'));
so.value('gecko', _('Gecko'));
so.depends('type', 'hysteria2');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_obfs_password', _('Obfuscate password'),
_('Enabling obfuscation will make the server incompatible with standard QUIC connections, losing the ability to masquerade with HTTP/3.'));
so.password = true;
so.rmempty = false;
so.depends('type', 'hysteria');
so.depends({type: 'hysteria2', hysteria_obfs_type: /.+/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_obfs_min_packet_size', _('Obfuscate minimum packet size'));
so.placeholder = '512'
so.depends('hysteria_obfs_type', 'gecko');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'hysteria_obfs_max_packet_size', _('Obfuscate maximum packet size'));
so.placeholder = '1200'
so.depends('hysteria_obfs_type', 'gecko');
so.modalonly = true;
/* SSH fields */
so = ss.taboption('field_general', form.TextValue, 'ssh_priv_key', _('Priv-key'));
so.depends('type', 'ssh');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'ssh_priv_key_passphrase', _('Priv-key passphrase'));
so.password = true;
so.depends({type: 'ssh', ssh_priv_key: /.+/});
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key_algorithms', _('Host-key algorithms'));
so.placeholder = 'rsa';
so.depends('type', 'ssh');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key', _('Host-key'));
so.placeholder = 'ssh-rsa AAAAB3NzaC1yc2EAA...';
so.depends({type: 'ssh', ssh_host_key_algorithms: /.+/});
so.modalonly = true;
/* Shadowsocks fields */ /* Shadowsocks fields */
so = ss.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher')); so = ss.taboption('field_general', form.ListValue, 'shadowsocks_chipher', _('Chipher'));
so.default = hm.shadowsocks_cipher_methods[1][0]; so.default = hm.shadowsocks_cipher_methods[1][0];
@@ -574,6 +505,100 @@ return view.extend({
so.depends({type: 'snell', snell_version: /^(4|5)$/}); so.depends({type: 'snell', snell_version: /^(4|5)$/});
so.modalonly = true; so.modalonly = true;
/* VMess / VLESS fields */
so = ss.taboption('field_general', form.Value, 'vmess_uuid', _('UUID'));
so.rmempty = false;
so.validate = hm.validateUUID;
so.depends({type: /^(vmess|vless)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vless_flow', _('Flow'));
so.default = hm.vless_flow[0][0];
hm.vless_flow.forEach((res) => {
so.value.apply(so, res);
})
so.depends('type', 'vless');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'vmess_alterid', _('Alter ID'));
so.datatype = 'uinteger';
so.default = '0';
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vmess_chipher', _('Chipher'));
so.default = 'auto';
so.value('auto', _('auto'));
so.value('none', _('none'));
so.value('zero', _('zero'));
so.value('aes-128-gcm', _('aes-128-gcm'));
so.value('chacha20-poly1305', _('chacha20-poly1305'));
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'vmess_global_padding', _('Global padding'),
_('Protocol parameter. Will waste traffic randomly if enabled (enabled by default in v2ray and cannot be disabled).'));
so.default = so.enabled;
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'vmess_authenticated_length', _('Authenticated length'),
_('Protocol parameter. Enable length block encryption.'));
so.default = so.disabled;
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vmess_packet_encoding', _('Packet encoding'));
so.value('', _('none'));
so.value('packetaddr', _('packet addr (v2ray-core v5+)'));
so.value('xudp', _('Xudp (Xray-core)'));
so.depends({type: /^(vmess|vless)$/});
so.modalonly = true;
/* Trojan fields */
so = ss.taboption('field_general', form.Flag, 'trojan_ss_enabled', _('Shadowsocks encrypt'));
so.default = so.disabled;
so.depends('type', 'trojan');
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'trojan_ss_chipher', _('Shadowsocks chipher'));
so.default = hm.trojan_cipher_methods[0][0];
hm.trojan_cipher_methods.forEach((res) => {
so.value.apply(so, res);
})
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'trojan_ss_password', _('Shadowsocks password'));
so.password = true;
so.validate = function(section_id, value) {
const encmode = this.section.getOption('trojan_ss_chipher').formvalue(section_id);
return hm.validateShadowsocksPassword.call(this, encmode, section_id, value);
}
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
so.modalonly = true;
/* AnyTLS fields */
so = ss.taboption('field_general', form.Value, 'anytls_idle_session_check_interval', _('Idle session check interval'),
_('In seconds.'));
so.placeholder = '30';
so.validate = hm.validateTimeDuration;
so.depends('type', 'anytls');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'anytls_idle_session_timeout', _('Idle session timeout'),
_('In seconds.'));
so.placeholder = '30';
so.validate = hm.validateTimeDuration;
so.depends('type', 'anytls');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'anytls_min_idle_session', _('Min of idle sessions to keep'));
so.datatype = 'uinteger';
so.placeholder = '0';
so.depends('type', 'anytls');
so.modalonly = true;
/* TUIC fields */ /* TUIC fields */
so = ss.taboption('field_general', form.Value, 'uuid', _('UUID')); so = ss.taboption('field_general', form.Value, 'uuid', _('UUID'));
so.rmempty = false; so.rmempty = false;
@@ -644,165 +669,53 @@ return view.extend({
so.depends('type', 'tuic'); so.depends('type', 'tuic');
so.modalonly = true; so.modalonly = true;
/* Trojan fields */ /* Hysteria / Hysteria2 fields */
so = ss.taboption('field_general', form.Flag, 'trojan_ss_enabled', _('Shadowsocks encrypt')); so = ss.taboption('field_general', form.DynamicList, 'hysteria_ports', _('Ports pool'));
so.default = so.disabled; so.datatype = 'or(port, portrange)';
so.depends('type', 'trojan'); so.depends({type: /^(hysteria|hysteria2)$/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'trojan_ss_chipher', _('Shadowsocks chipher')); so = ss.taboption('field_general', form.Value, 'hysteria_hop_interval', _('Port hop interval'),
so.default = hm.trojan_cipher_methods[0][0]; _('In seconds. <code>%s</code> will be used if empty.').format('30'));
hm.trojan_cipher_methods.forEach((res) => { so.placeholder = '15 OR 15-30';
so.value.apply(so, res); so.depends('type', 'hysteria2');
})
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'trojan_ss_password', _('Shadowsocks password')); so = ss.taboption('field_general', form.Value, 'hysteria_up_mbps', _('Max upload speed'),
so.password = true; _('In Mbps.'));
so.validate = function(section_id, value) {
const encmode = this.section.getOption('trojan_ss_chipher').formvalue(section_id);
return hm.validateShadowsocksPassword.call(this, encmode, section_id, value);
}
so.depends({type: 'trojan', trojan_ss_enabled: '1'});
so.modalonly = true;
/* AnyTLS fields */
so = ss.taboption('field_general', form.Value, 'anytls_idle_session_check_interval', _('Idle session check interval'),
_('In seconds.'));
so.placeholder = '30';
so.validate = hm.validateTimeDuration;
so.depends('type', 'anytls');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'anytls_idle_session_timeout', _('Idle session timeout'),
_('In seconds.'));
so.placeholder = '30';
so.validate = hm.validateTimeDuration;
so.depends('type', 'anytls');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'anytls_min_idle_session', _('Min of idle sessions to keep'));
so.datatype = 'uinteger'; so.datatype = 'uinteger';
so.placeholder = '0'; so.depends({type: /^(hysteria|hysteria2)$/});
so.depends('type', 'anytls');
so.modalonly = true; so.modalonly = true;
/* VMess / VLESS fields */ so = ss.taboption('field_general', form.Value, 'hysteria_down_mbps', _('Max download speed'),
so = ss.taboption('field_general', form.Value, 'vmess_uuid', _('UUID')); _('In Mbps.'));
so.rmempty = false;
so.validate = hm.validateUUID;
so.depends({type: /^(vmess|vless)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vless_flow', _('Flow'));
so.default = hm.vless_flow[0][0];
hm.vless_flow.forEach((res) => {
so.value.apply(so, res);
})
so.depends('type', 'vless');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'vmess_alterid', _('Alter ID'));
so.datatype = 'uinteger'; so.datatype = 'uinteger';
so.default = '0'; so.depends({type: /^(hysteria|hysteria2)$/});
so.depends('type', 'vmess');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vmess_chipher', _('Chipher')); so = ss.taboption('field_general', form.ListValue, 'hysteria_obfs_type', _('Obfuscate type'));
so.default = 'auto'; so.value('', _('Disable'));
so.value('auto', _('auto')); so.value('salamander', _('Salamander'));
so.value('none', _('none')); so.value('gecko', _('Gecko'));
so.value('zero', _('zero')); so.depends('type', 'hysteria2');
so.value('aes-128-gcm', _('aes-128-gcm'));
so.value('chacha20-poly1305', _('chacha20-poly1305'));
so.depends('type', 'vmess');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'vmess_global_padding', _('Global padding'), so = ss.taboption('field_general', form.Value, 'hysteria_obfs_password', _('Obfuscate password'),
_('Protocol parameter. Will waste traffic randomly if enabled (enabled by default in v2ray and cannot be disabled).')); _('Enabling obfuscation will make the server incompatible with standard QUIC connections, losing the ability to masquerade with HTTP/3.'));
so.default = so.enabled;
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'vmess_authenticated_length', _('Authenticated length'),
_('Protocol parameter. Enable length block encryption.'));
so.default = so.disabled;
so.depends('type', 'vmess');
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'vmess_packet_encoding', _('Packet encoding'));
so.value('', _('none'));
so.value('packetaddr', _('packet addr (v2ray-core v5+)'));
so.value('xudp', _('Xudp (Xray-core)'));
so.depends({type: /^(vmess|vless)$/});
so.modalonly = true;
/* Masque fields */
so = ss.taboption('field_general', form.Value, 'masque_private_key', _('Private key'),
_('Base64 encoded ECDSA private key on the NIST P-256 curve.'));
so.password = true; so.password = true;
so.validate = L.bind(hm.validateBase64Key, so, 164);
so.rmempty = false; so.rmempty = false;
so.depends('type', 'masque'); so.depends('type', 'hysteria');
so.depends({type: 'hysteria2', hysteria_obfs_type: /.+/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Endpoint pubkic key'), so = ss.taboption('field_general', form.Value, 'hysteria_obfs_min_packet_size', _('Obfuscate minimum packet size'));
_('Base64 encoded ECDSA public key on the NIST P-256 curve.')); so.placeholder = '512'
so.validate = L.bind(hm.validateBase64Key, so, 124); so.depends('hysteria_obfs_type', 'gecko');
so.rmempty = false;
so.depends('type', 'masque');
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ip', _('Local address'), so = ss.taboption('field_general', form.Value, 'hysteria_obfs_max_packet_size', _('Obfuscate maximum packet size'));
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv4')); so.placeholder = '1200'
so.datatype = 'ip4addr(1)'; so.depends('hysteria_obfs_type', 'gecko');
so.placeholder = '172.16.0.2';
so.rmempty = false;
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ipv6', _('Local IPv6 address'),
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv6'));
so.datatype = 'ip6addr(1)';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_mtu', _('MTU'));
so.datatype = 'range(0,9000)';
so.placeholder = '1280';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'masque_network', _('Network'));
so.default = '';
so.value('', _('h3'));
so.value('h3-l4proxy', _('h3-l4proxy'));
so.value('h2', _('h2'));
so.validate = function(section_id, value) {
const udp = this.section.getUIElement(section_id, 'udp').node.querySelector('input');
// Force disabled
if (value === 'h3-l4proxy') {
udp.checked = false;
udp.disabled = true;
} else
udp.removeAttribute('disabled');
return true;
}
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'masque_remote_dns_resolve', _('Remote DNS resolve'),
_('Force DNS remote resolution.'));
so.default = so.disabled;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'masque_dns', _('DNS server'));
so.datatype = 'or(host, hostport)';
so.depends('masque_remote_dns_resolve', '1');
so.modalonly = true; so.modalonly = true;
/* TrustTunnel fields */ /* TrustTunnel fields */
@@ -888,6 +801,93 @@ return view.extend({
so.depends('wireguard_remote_dns_resolve', '1'); so.depends('wireguard_remote_dns_resolve', '1');
so.modalonly = true; so.modalonly = true;
/* Masque fields */
so = ss.taboption('field_general', form.Value, 'masque_private_key', _('Private key'),
_('Base64 encoded ECDSA private key on the NIST P-256 curve.'));
so.password = true;
so.validate = L.bind(hm.validateBase64Key, so, 164);
so.rmempty = false;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_endpoint_public_key', _('Endpoint pubkic key'),
_('Base64 encoded ECDSA public key on the NIST P-256 curve.'));
so.validate = L.bind(hm.validateBase64Key, so, 124);
so.rmempty = false;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ip', _('Local address'),
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv4'));
so.datatype = 'ip4addr(1)';
so.placeholder = '172.16.0.2';
so.rmempty = false;
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_ipv6', _('Local IPv6 address'),
_('The %s address used by local machine in the Cloudflare WARP network.').format('IPv6'));
so.datatype = 'ip6addr(1)';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'masque_mtu', _('MTU'));
so.datatype = 'range(0,9000)';
so.placeholder = '1280';
so.depends({type: 'masque', masque_network: /^(|h2)$/});
so.modalonly = true;
so = ss.taboption('field_general', form.ListValue, 'masque_network', _('Network'));
so.default = '';
so.value('', _('h3'));
so.value('h3-l4proxy', _('h3-l4proxy'));
so.value('h2', _('h2'));
so.validate = function(section_id, value) {
const udp = this.section.getUIElement(section_id, 'udp').node.querySelector('input');
// Force disabled
if (value === 'h3-l4proxy') {
udp.checked = false;
udp.disabled = true;
} else
udp.removeAttribute('disabled');
return true;
}
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'masque_remote_dns_resolve', _('Remote DNS resolve'),
_('Force DNS remote resolution.'));
so.default = so.disabled;
so.depends('type', 'masque');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'masque_dns', _('DNS server'));
so.datatype = 'or(host, hostport)';
so.depends('masque_remote_dns_resolve', '1');
so.modalonly = true;
/* SSH fields */
so = ss.taboption('field_general', form.TextValue, 'ssh_priv_key', _('Priv-key'));
so.depends('type', 'ssh');
so.modalonly = true;
so = ss.taboption('field_general', form.Value, 'ssh_priv_key_passphrase', _('Priv-key passphrase'));
so.password = true;
so.depends({type: 'ssh', ssh_priv_key: /.+/});
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key_algorithms', _('Host-key algorithms'));
so.placeholder = 'rsa';
so.depends('type', 'ssh');
so.modalonly = true;
so = ss.taboption('field_general', form.DynamicList, 'ssh_host_key', _('Host-key'));
so.placeholder = 'ssh-rsa AAAAB3NzaC1yc2EAA...';
so.depends({type: 'ssh', ssh_host_key_algorithms: /.+/});
so.modalonly = true;
/* Plugin fields */ /* Plugin fields */
so = ss.taboption('field_general', form.ListValue, 'plugin', _('Plugin')); so = ss.taboption('field_general', form.ListValue, 'plugin', _('Plugin'));
so.value('', _('none')); so.value('', _('none'));
@@ -975,12 +975,12 @@ return view.extend({
_('The default value is <code>%s</code>, indicating that only the outer connection timeout is used.').format('0')); _('The default value is <code>%s</code>, indicating that only the outer connection timeout is used.').format('0'));
so.datatype = 'uinteger'; so.datatype = 'uinteger';
so.placeholder = '30'; so.placeholder = '30';
so.depends({type: /^(masque|openvpn)$/}); so.depends({type: /^(openvpn|masque)$/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_general', form.Flag, 'udp', _('UDP')); so = ss.taboption('field_general', form.Flag, 'udp', _('UDP'));
so.default = so.disabled; so.default = so.disabled;
so.depends({type: /^(rematch|direct|socks5|ss|mieru|vmess|vless|trojan|anytls|trusttunnel|masque|wireguard)$/}); so.depends({type: /^(rematch|direct|socks5|ss|mieru|vmess|vless|trojan|anytls|trusttunnel|wireguard|masque)$/});
so.depends({type: 'snell', snell_version: /^(3|4|5)$/}); so.depends({type: 'snell', snell_version: /^(3|4|5)$/});
so.modalonly = true; so.modalonly = true;
@@ -1115,7 +1115,7 @@ return view.extend({
return true; return true;
} }
so.depends({type: /^(http|socks5|vmess|vless|trojan|anytls|hysteria|hysteria2|tuic|trusttunnel|masque)$/}); so.depends({type: /^(http|socks5|vmess|vless|trojan|anytls|tuic|hysteria|hysteria2|trusttunnel|masque)$/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_tls', form.Flag, 'tls_disable_sni', _('Disable SNI'), so = ss.taboption('field_tls', form.Flag, 'tls_disable_sni', _('Disable SNI'),
@@ -1146,9 +1146,9 @@ return view.extend({
case 'snell': case 'snell':
def_alpn = ['h2', 'http/1.1']; // when plugin === 'shadow-tls' def_alpn = ['h2', 'http/1.1']; // when plugin === 'shadow-tls'
break; break;
case 'tuic':
case 'hysteria': case 'hysteria':
case 'hysteria2': case 'hysteria2':
case 'tuic':
def_alpn = ['h3']; def_alpn = ['h3'];
break; break;
case 'vmess': case 'vmess':
@@ -1171,7 +1171,7 @@ return view.extend({
return true; return true;
} }
so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|hysteria|hysteria2|tuic|trusttunnel)$/}); so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|tuic|hysteria|hysteria2|trusttunnel)$/});
so.depends({type: /^(ss|snell)$/, plugin: 'shadow-tls'}); so.depends({type: /^(ss|snell)$/, plugin: 'shadow-tls'});
so.modalonly = true; so.modalonly = true;
@@ -1193,7 +1193,7 @@ return view.extend({
'<br/>' + '<br/>' +
_('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!')); _('This is <strong>DANGEROUS</strong>, your traffic is almost like <strong>PLAIN TEXT</strong>! Use at your own risk!'));
so.default = so.disabled; so.default = so.disabled;
so.depends({tls: '1', type: /^(http|socks5|vmess|vless|trojan|anytls|hysteria|hysteria2|tuic|trusttunnel)$/}); so.depends({tls: '1', type: /^(http|socks5|vmess|vless|trojan|anytls|tuic|hysteria|hysteria2|trusttunnel)$/});
so.modalonly = true; so.modalonly = true;
so = ss.taboption('field_tls', form.Value, 'tls_cert_path', _('Certificate path') + _(' (mTLS)'), so = ss.taboption('field_tls', form.Value, 'tls_cert_path', _('Certificate path') + _(' (mTLS)'),
@@ -1226,7 +1226,7 @@ return view.extend({
so = ss.taboption('field_tls', form.Flag, 'tls_ech', _('Enable ECH')); so = ss.taboption('field_tls', form.Flag, 'tls_ech', _('Enable ECH'));
so.default = so.disabled; so.default = so.disabled;
so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|hysteria|hysteria2|tuic)$/}); so.depends({tls: '1', type: /^(vmess|vless|trojan|anytls|tuic|hysteria|hysteria2)$/});
so.depends({type: 'ss', plugin: /^(v2ray-plugin|gost-plugin)$/}); so.depends({type: 'ss', plugin: /^(v2ray-plugin|gost-plugin)$/});
so.modalonly = true; so.modalonly = true;
@@ -1899,7 +1899,7 @@ return view.extend({
so = ss.taboption('field_override', form.DummyValue, '_config_items', null); so = ss.taboption('field_override', form.DummyValue, '_config_items', null);
so.load = function() { so.load = function() {
return '<a target="_blank" href="%s" rel="noreferrer noopener">%s</a>' return '<a target="_blank" href="%s" rel="noreferrer noopener">%s</a>'
.format('https://wiki.metacubex.one/config/proxy-providers/#_2', _('Configuration Items')); .format('https://wiki.metacubex.one/config/proxy-providers/#override_1', _('Other configuration items'));
} }
so.rawhtml = true; so.rawhtml = true;
so.depends({type: 'inline', '!reverse': true}); so.depends({type: 'inline', '!reverse': true});
+2 -2
View File
@@ -566,7 +566,7 @@ msgid "Complete"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/view/fchomo/node.js:1898 #: htdocs/luci-static/resources/view/fchomo/node.js:1898
msgid "Configuration Items" msgid "Other configuration items"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/fchomo/listeners.js:653 #: htdocs/luci-static/resources/fchomo/listeners.js:653
@@ -1442,7 +1442,7 @@ msgid "Hysteria2"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/fchomo.js:167 #: htdocs/luci-static/resources/fchomo.js:167
msgid "Hysteria2 Realm" msgid "Hysteria2 Realm Server"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/fchomo/listeners.js:121 #: htdocs/luci-static/resources/fchomo/listeners.js:121
+4 -4
View File
@@ -580,8 +580,8 @@ msgid "Complete"
msgstr "完成" msgstr "完成"
#: htdocs/luci-static/resources/view/fchomo/node.js:1898 #: htdocs/luci-static/resources/view/fchomo/node.js:1898
msgid "Configuration Items" msgid "Other configuration items"
msgstr "配置项" msgstr "其他配置项"
#: htdocs/luci-static/resources/fchomo/listeners.js:653 #: htdocs/luci-static/resources/fchomo/listeners.js:653
#: htdocs/luci-static/resources/view/fchomo/node.js:955 #: htdocs/luci-static/resources/view/fchomo/node.js:955
@@ -1468,8 +1468,8 @@ msgid "Hysteria2"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/fchomo.js:167 #: htdocs/luci-static/resources/fchomo.js:167
msgid "Hysteria2 Realm" msgid "Hysteria2 Realm Server"
msgstr "Hysteria2 Realm" msgstr "Hysteria2 Realm 服务器"
#: htdocs/luci-static/resources/fchomo/listeners.js:121 #: htdocs/luci-static/resources/fchomo/listeners.js:121
#: htdocs/luci-static/resources/view/fchomo/node.js:235 #: htdocs/luci-static/resources/view/fchomo/node.js:235
+4 -4
View File
@@ -580,8 +580,8 @@ msgid "Complete"
msgstr "完成" msgstr "完成"
#: htdocs/luci-static/resources/view/fchomo/node.js:1898 #: htdocs/luci-static/resources/view/fchomo/node.js:1898
msgid "Configuration Items" msgid "Other configuration items"
msgstr "配置項" msgstr "其他配置項"
#: htdocs/luci-static/resources/fchomo/listeners.js:653 #: htdocs/luci-static/resources/fchomo/listeners.js:653
#: htdocs/luci-static/resources/view/fchomo/node.js:955 #: htdocs/luci-static/resources/view/fchomo/node.js:955
@@ -1468,8 +1468,8 @@ msgid "Hysteria2"
msgstr "" msgstr ""
#: htdocs/luci-static/resources/fchomo.js:167 #: htdocs/luci-static/resources/fchomo.js:167
msgid "Hysteria2 Realm" msgid "Hysteria2 Realm Server"
msgstr "Hysteria2 Realm" msgstr "Hysteria2 Realm 伺服器"
#: htdocs/luci-static/resources/fchomo/listeners.js:121 #: htdocs/luci-static/resources/fchomo/listeners.js:121
#: htdocs/luci-static/resources/view/fchomo/node.js:235 #: htdocs/luci-static/resources/view/fchomo/node.js:235
@@ -490,7 +490,7 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"target-rematch-name": cfg.target_rematch_name, "target-rematch-name": cfg.target_rematch_name,
"target-sub-rule": cfg.target_sub_rule, "target-sub-rule": cfg.target_sub_rule,
/* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / hysteria2 / TUIC / WireGuard / Masque */ /* HTTP / SOCKS / Shadowsocks / VMess / VLESS / Trojan / TUIC / hysteria2 / WireGuard / Masque */
username: cfg.username, username: cfg.username,
uuid: cfg.vmess_uuid || cfg.uuid, uuid: cfg.vmess_uuid || cfg.uuid,
cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher, cipher: cfg.vmess_chipher || cfg.shadowsocks_chipher,
@@ -502,35 +502,6 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"remote-dns-resolve": strToBool(cfg.masque_remote_dns_resolve ?? cfg.wireguard_remote_dns_resolve), "remote-dns-resolve": strToBool(cfg.masque_remote_dns_resolve ?? cfg.wireguard_remote_dns_resolve),
dns: cfg.masque_dns || cfg.wireguard_dns, dns: cfg.masque_dns || cfg.wireguard_dns,
/* Hysteria / Hysteria2 */
ports: isEmpty(cfg.hysteria_ports) ? null : join(',', cfg.hysteria_ports),
"hop-interval": strToInt(cfg.hysteria_hop_interval), // @DEBUG ERROR data type *utils.IntRanges[uint16]
up: cfg.hysteria_up_mbps ? cfg.hysteria_up_mbps + ' Mbps' : null,
down: cfg.hysteria_down_mbps ? cfg.hysteria_down_mbps + ' Mbps' : null,
obfs: cfg.hysteria_obfs_type,
"obfs-password": cfg.hysteria_obfs_password,
"obfs-min-packet-size": strToInt(cfg.hysteria_obfs_min_packet_size),
"obfs-max-packet-size": strToInt(cfg.hysteria_obfs_max_packet_size),
"realm-opts": cfg.hysteria2_realm === '1' ? {
enable: true,
"server-url": cfg.hysteria2_realm_server_url,
token: cfg.hysteria2_realm_token,
"realm-id": cfg.hysteria2_realm_id,
"stun-servers": cfg.hysteria2_realm_stun_servers,
// @TLS of server-url
//sni,
//alpn,
//"skip-cert-verify",
//fingerprint,
//certificate,
//"private-key"
} : null,
/* SSH */
"private-key-passphrase": cfg.ssh_priv_key_passphrase,
"host-key-algorithms": cfg.ssh_host_key_algorithms,
"host-key": cfg.ssh_host_key,
/* Shadowsocks */ /* Shadowsocks */
/* Mieru */ /* Mieru */
@@ -564,17 +535,13 @@ uci.foreach(uciconf, ucinode, (cfg) => {
version: cfg.snell_version, version: cfg.snell_version,
reuse: strToBool(cfg.snell_reuse), reuse: strToBool(cfg.snell_reuse),
/* TUIC */ /* VMess / VLESS */
ip: cfg.tuic_ip, flow: cfg.vless_flow,
"udp-relay-mode": cfg.tuic_udp_relay_mode, alterId: strToInt(cfg.vmess_alterid),
"udp-over-stream": strToBool(cfg.tuic_udp_over_stream), "global-padding": cfg.type === 'vmess' ? (cfg.vmess_global_padding === '0' ? false : true) : null,
"udp-over-stream-version": cfg.tuic_udp_over_stream_version, "authenticated-length": strToBool(cfg.vmess_authenticated_length),
"max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size) || null, "packet-encoding": cfg.vmess_packet_encoding,
"fast-open": strToBool(cfg.tuic_fast_open), encryption: cfg.vless_encryption === '1' ? cfg.vless_encryption_encryption : null,
"reduce-rtt": strToBool(cfg.tuic_reduce_rtt),
"heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null,
"request-timeout": strToInt(cfg.tuic_request_timeout) || null,
"max-open-streams": strToInt(cfg.tuic_max_open_streams) || null,
/* Trojan */ /* Trojan */
"ss-opts": cfg.trojan_ss_enabled === '1' ? { "ss-opts": cfg.trojan_ss_enabled === '1' ? {
@@ -588,16 +555,41 @@ uci.foreach(uciconf, ucinode, (cfg) => {
"idle-session-timeout": durationToSecond(cfg.anytls_idle_session_timeout), "idle-session-timeout": durationToSecond(cfg.anytls_idle_session_timeout),
"min-idle-session": strToInt(cfg.anytls_min_idle_session), "min-idle-session": strToInt(cfg.anytls_min_idle_session),
/* VMess / VLESS */ /* TUIC */
flow: cfg.vless_flow, ip: cfg.tuic_ip,
alterId: strToInt(cfg.vmess_alterid), "udp-relay-mode": cfg.tuic_udp_relay_mode,
"global-padding": cfg.type === 'vmess' ? (cfg.vmess_global_padding === '0' ? false : true) : null, "udp-over-stream": strToBool(cfg.tuic_udp_over_stream),
"authenticated-length": strToBool(cfg.vmess_authenticated_length), "udp-over-stream-version": cfg.tuic_udp_over_stream_version,
"packet-encoding": cfg.vmess_packet_encoding, "max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size) || null,
encryption: cfg.vless_encryption === '1' ? cfg.vless_encryption_encryption : null, "fast-open": strToBool(cfg.tuic_fast_open),
"reduce-rtt": strToBool(cfg.tuic_reduce_rtt),
"heartbeat-interval": strToInt(cfg.tuic_heartbeat) || null,
"request-timeout": strToInt(cfg.tuic_request_timeout) || null,
"max-open-streams": strToInt(cfg.tuic_max_open_streams) || null,
/* Masque */ /* Hysteria / Hysteria2 */
network: cfg.masque_network || null, ports: isEmpty(cfg.hysteria_ports) ? null : join(',', cfg.hysteria_ports),
"hop-interval": strToInt(cfg.hysteria_hop_interval), // @DEBUG ERROR data type *utils.IntRanges[uint16]
up: cfg.hysteria_up_mbps ? cfg.hysteria_up_mbps + ' Mbps' : null,
down: cfg.hysteria_down_mbps ? cfg.hysteria_down_mbps + ' Mbps' : null,
obfs: cfg.hysteria_obfs_type,
"obfs-password": cfg.hysteria_obfs_password,
"obfs-min-packet-size": strToInt(cfg.hysteria_obfs_min_packet_size),
"obfs-max-packet-size": strToInt(cfg.hysteria_obfs_max_packet_size),
"realm-opts": cfg.hysteria2_realm === '1' ? {
enable: true,
"server-url": cfg.hysteria2_realm_server_url,
token: cfg.hysteria2_realm_token,
"realm-id": cfg.hysteria2_realm_id,
"stun-servers": cfg.hysteria2_realm_stun_servers,
// @TLS of server-url
//sni,
//alpn,
//"skip-cert-verify",
//fingerprint,
//certificate,
//"private-key"
} : null,
/* TrustTunnel */ /* TrustTunnel */
"health-check": cfg.type === 'trusttunnel' ? (cfg.trusttunnel_health_check === '0' ? false : true) : null, "health-check": cfg.type === 'trusttunnel' ? (cfg.trusttunnel_health_check === '0' ? false : true) : null,
@@ -609,6 +601,14 @@ uci.foreach(uciconf, ucinode, (cfg) => {
reserved: cfg.wireguard_reserved, reserved: cfg.wireguard_reserved,
"persistent-keepalive": strToInt(cfg.wireguard_persistent_keepalive), "persistent-keepalive": strToInt(cfg.wireguard_persistent_keepalive),
/* Masque */
network: cfg.masque_network || null,
/* SSH */
"private-key-passphrase": cfg.ssh_priv_key_passphrase,
"host-key-algorithms": cfg.ssh_host_key_algorithms,
"host-key": cfg.ssh_host_key,
/* Plugin fields */ /* Plugin fields */
...(cfg.plugin ? ( ...(cfg.plugin ? (
cfg.type === 'snell' ? { cfg.type === 'snell' ? {
@@ -820,7 +820,7 @@ uci.foreach(uciconf, uciprov, (cfg) => {
"additional-prefix": cfg.override_prefix, "additional-prefix": cfg.override_prefix,
"additional-suffix": cfg.override_suffix, "additional-suffix": cfg.override_suffix,
"proxy-name": isEmpty(cfg.override_replace) ? null : map(cfg.override_replace, obj => json(obj)), "proxy-name": isEmpty(cfg.override_replace) ? null : map(cfg.override_replace, obj => json(obj)),
// Configuration Items // Other configuration items
tfo: strToBool(cfg.override_tfo), tfo: strToBool(cfg.override_tfo),
mptcp: strToBool(cfg.override_mptcp), mptcp: strToBool(cfg.override_mptcp),
udp: (cfg.override_udp === '0') ? null : true, udp: (cfg.override_udp === '0') ? null : true,
+39 -37
View File
@@ -246,37 +246,6 @@ export function parseListener(cfg, isClient, label) {
...arrToObj([[cfg.uuid, cfg.password]]) ...arrToObj([[cfg.uuid, cfg.password]])
} : null), } : null),
/* Hysteria2 */
up: strToInt(cfg.hysteria_up_mbps),
down: strToInt(cfg.hysteria_down_mbps),
"ignore-client-bandwidth": strToBool(cfg.hysteria_ignore_client_bandwidth),
obfs: cfg.hysteria_obfs_type,
"obfs-password": cfg.hysteria_obfs_password,
"obfs-min-packet-size": strToInt(cfg.hysteria_obfs_min_packet_size),
"obfs-max-packet-size": strToInt(cfg.hysteria_obfs_max_packet_size),
masquerade: cfg.hysteria_masquerade,
"realm-opts": cfg.hysteria2_realm === '1' ? {
enable: true,
"server-url": cfg.hysteria2_realm_server_url,
token: cfg.hysteria2_realm_token,
"realm-id": cfg.hysteria2_realm_id,
"stun-servers": cfg.hysteria2_realm_stun_servers,
// @TLS of server-url
//sni,
//alpn,
//"skip-cert-verify",
//fingerprint,
//certificate,
//"private-key"
} : null,
/* Hysteria2 Realmserver */
token: cfg.hysteria2_realmserver_token,
"max-realms": strToInt(cfg.hysteria2_realmserver_max_realms),
"max-realms-per-ip": strToInt(cfg.hysteria2_realmserver_max_realms_per_ip),
"trusted-proxy-header": cfg.hysteria2_realmserver_trusted_proxy_header,
"realm-name-pattern": cfg.hysteria2_realmserver_realm_name_pattern,
/* Shadowsocks */ /* Shadowsocks */
cipher: cfg.shadowsocks_chipher, cipher: cfg.shadowsocks_chipher,
password: cfg.shadowsocks_password, password: cfg.shadowsocks_password,
@@ -308,10 +277,8 @@ export function parseListener(cfg, isClient, label) {
psk: cfg.snell_psk, psk: cfg.snell_psk,
version: cfg.snell_version, version: cfg.snell_version,
/* Tuic */ /* VMess / VLESS */
"max-idle-time": durationToSecond(cfg.tuic_max_idle_time), decryption: cfg.vless_decryption === '1' ? parseVlessEncryption(cfg.vless_encryption_hmpayload, 'server') : null,
"authentication-timeout": durationToSecond(cfg.tuic_authentication_timeout),
"max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size),
/* Trojan */ /* Trojan */
"ss-option": cfg.trojan_ss_enabled === '1' ? { "ss-option": cfg.trojan_ss_enabled === '1' ? {
@@ -323,8 +290,43 @@ export function parseListener(cfg, isClient, label) {
/* AnyTLS */ /* AnyTLS */
"padding-scheme": cfg.anytls_padding_scheme, "padding-scheme": cfg.anytls_padding_scheme,
/* VMess / VLESS */ /* Tuic */
decryption: cfg.vless_decryption === '1' ? parseVlessEncryption(cfg.vless_encryption_hmpayload, 'server') : null, "max-idle-time": durationToSecond(cfg.tuic_max_idle_time),
"authentication-timeout": durationToSecond(cfg.tuic_authentication_timeout),
"max-udp-relay-packet-size": strToInt(cfg.tuic_max_udp_relay_packet_size),
/* Hysteria2 */
up: strToInt(cfg.hysteria_up_mbps),
down: strToInt(cfg.hysteria_down_mbps),
"ignore-client-bandwidth": strToBool(cfg.hysteria_ignore_client_bandwidth),
obfs: cfg.hysteria_obfs_type,
"obfs-password": cfg.hysteria_obfs_password,
"obfs-min-packet-size": strToInt(cfg.hysteria_obfs_min_packet_size),
"obfs-max-packet-size": strToInt(cfg.hysteria_obfs_max_packet_size),
masquerade: cfg.hysteria_masquerade,
"realm-opts": cfg.hysteria2_realm === '1' ? {
enable: true,
"server-url": cfg.hysteria2_realm_server_url,
token: cfg.hysteria2_realm_token,
"realm-id": cfg.hysteria2_realm_id,
"stun-servers": cfg.hysteria2_realm_stun_servers,
// @TLS of server-url
//sni,
//alpn,
//"skip-cert-verify",
//fingerprint,
//certificate,
//"private-key"
} : null,
/* Hysteria2 Realmserver */
token: cfg.hysteria2_realmserver_token,
"max-realms": strToInt(cfg.hysteria2_realmserver_max_realms),
"max-realms-per-ip": strToInt(cfg.hysteria2_realmserver_max_realms_per_ip),
"trusted-proxy-header": cfg.hysteria2_realmserver_trusted_proxy_header,
"realm-name-pattern": cfg.hysteria2_realmserver_realm_name_pattern,
/* TrustTunnel */
/* Tunnel */ /* Tunnel */
target: cfg.tunnel_target, target: cfg.tunnel_target,
+1 -1
View File
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.7.1 PKG_VERSION:=26.7.1
PKG_RELEASE:=177 PKG_RELEASE:=178
PKG_PO_VERSION:=$(PKG_VERSION) PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \
@@ -109,6 +109,7 @@ function index()
for _, com in ipairs(coms.order) do for _, com in ipairs(coms.order) do
entry({"admin", "services", appname, "check_" .. com}, call("com_check", com)).leaf = true entry({"admin", "services", appname, "check_" .. com}, call("com_check", com)).leaf = true
entry({"admin", "services", appname, "update_" .. com}, call("com_update", com)).leaf = true entry({"admin", "services", appname, "update_" .. com}, call("com_update", com)).leaf = true
entry({"admin", "services", appname, "version_" .. com}, call("com_version", com)).leaf = true
end end
--[[Backup]] --[[Backup]]
@@ -881,6 +882,11 @@ function com_update(comname)
http_write_json(json) http_write_json(json)
end end
function com_version(comname)
local version = api.get_app_version(comname)
http_write_json_ok(version)
end
function read_rulelist() function read_rulelist()
local rule_type = http.formvalue("type") local rule_type = http.formvalue("type")
local rule_path local rule_path
@@ -1,22 +1,24 @@
local api = require "luci.passwall.api" local api = require "luci.passwall.api"
local com = require "luci.passwall.com"
local appname = "passwall" local appname = "passwall"
m = Map(appname) m = Map(appname)
api.set_apply_on_parse(m) api.set_apply_on_parse(m)
-- [[ App Settings ]]-- -- [[ App Settings ]]--
s = m:section(TypedSection, "global_app", translate("App Update"), s = m:section(TypedSection, "global_app", translate("App Update"))
"<font color='red'>" ..
translate("Please confirm that your firmware supports FPU.") ..
"</font>")
s.anonymous = true s.anonymous = true
s:append(Template(appname .. "/app_update/app_version"))
local app_version = Template(appname .. "/app_update/app_version")
app_version.api = api
app_version.config = m.config
app_version.com = com
s:append(app_version)
o = s:option(Flag, "github_proxy", translate("GitHub Proxy"), translate("Use gh-proxy instead of proxy nodes for component updates.")) o = s:option(Flag, "github_proxy", translate("GitHub Proxy"), translate("Use gh-proxy instead of proxy nodes for component updates."))
o.default = 0 o.default = 0
local k, v local k, v
local com = require "luci.passwall.com"
for _, k in ipairs(com.order) do for _, k in ipairs(com.order) do
v = com[k] v = com[k]
if k ~= "chinadns-ng" then if k ~= "chinadns-ng" then
@@ -229,13 +229,8 @@ end
o = s:option(Flag, "boot_update", translate("Update Once on Boot"), translate("Updates the subscription the first time PassWall runs automatically after each system boot.")) o = s:option(Flag, "boot_update", translate("Update Once on Boot"), translate("Updates the subscription the first time PassWall runs automatically after each system boot."))
o.default = 0 o.default = 0
---- Enable auto update subscribe o = s:option(ListValue, "update_week_mode", translate("Auto Update Mode"))
o = s:option(Flag, "auto_update", translate("Enable auto update subscribe")) o:value("", translate("Disable"))
o.default = 0
o.rmempty = false
---- Week Update
o = s:option(ListValue, "week_update", translate("Update Mode"))
o:value(8, translate("Loop Mode")) o:value(8, translate("Loop Mode"))
o:value(7, translate("Every day")) o:value(7, translate("Every day"))
o:value(1, translate("Every Monday")) o:value(1, translate("Every Monday"))
@@ -245,29 +240,30 @@ o:value(4, translate("Every Thursday"))
o:value(5, translate("Every Friday")) o:value(5, translate("Every Friday"))
o:value(6, translate("Every Saturday")) o:value(6, translate("Every Saturday"))
o:value(0, translate("Every Sunday")) o:value(0, translate("Every Sunday"))
o.default = 7
o:depends("auto_update", true)
o.rmempty = true
---- Time Update o = s:option(Value, "update_time_mode", translate("Update Time"))
o = s:option(ListValue, "time_update", translate("Update Time(every day)")) for t = 0, 23 do o:value(t .. ":00") end
for t = 0, 23 do o:value(t, t .. ":00") end o.default = "0:00"
o.default = 0 o.validate = function(self, value)
o:depends("week_update", "0") local b = api.is_timehhmm(value)
o:depends("week_update", "1") if b then
o:depends("week_update", "2") return value
o:depends("week_update", "3") end
o:depends("week_update", "4") return nil
o:depends("week_update", "5") end
o:depends("week_update", "6") o:depends("update_week_mode", "0")
o:depends("week_update", "7") o:depends("update_week_mode", "1")
o.rmempty = true o:depends("update_week_mode", "2")
o:depends("update_week_mode", "3")
o:depends("update_week_mode", "4")
o:depends("update_week_mode", "5")
o:depends("update_week_mode", "6")
o:depends("update_week_mode", "7")
---- Interval Update o = s:option(ListValue, "update_interval_mode", translate("Update Interval(hour)"))
o = s:option(ListValue, "interval_update", translate("Update Interval(hour)"))
for t = 1, 24 do o:value(t, t .. " " .. translate("hour")) end for t = 1, 24 do o:value(t, t .. " " .. translate("hour")) end
o.default = 2 o.default = 2
o:depends("week_update", "8") o:depends("update_week_mode", "8")
o.rmempty = true o.rmempty = true
o = s:option(ListValue, "access_mode", translate("Subscribe URL Access Method")) o = s:option(ListValue, "access_mode", translate("Subscribe URL Access Method"))
@@ -29,7 +29,9 @@ o.rmempty = true
for index, value in ipairs({"stop", "start", "restart"}) do for index, value in ipairs({"stop", "start", "restart"}) do
o = s:option(ListValue, value .. "_week_mode", translate(value .. " automatically mode")) o = s:option(ListValue, value .. "_week_mode", translate(value .. " automatically mode"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value(8, translate("Loop Mode")) if value == "restart" then
o:value(8, translate("Loop Mode"))
end
o:value(7, translate("Every day")) o:value(7, translate("Every day"))
o:value(1, translate("Every Monday")) o:value(1, translate("Every Monday"))
o:value(2, translate("Every Tuesday")) o:value(2, translate("Every Tuesday"))
@@ -38,9 +40,16 @@ for index, value in ipairs({"stop", "start", "restart"}) do
o:value(5, translate("Every Friday")) o:value(5, translate("Every Friday"))
o:value(6, translate("Every Saturday")) o:value(6, translate("Every Saturday"))
o:value(0, translate("Every Sunday")) o:value(0, translate("Every Sunday"))
o = s:option(ListValue, value .. "_time_mode", translate(value .. " Time(Every day)")) o = s:option(Value, value .. "_time_mode", translate(value .. " Time"))
for t = 0, 23 do o:value(t, t .. ":00") end for t = 0, 23 do o:value(t .. ":00") end
o.default = 0 o.default = "0:00"
o.validate = function(self, value)
local b = api.is_timehhmm(value)
if b then
return value
end
return nil
end
o:depends(value .. "_week_mode", "0") o:depends(value .. "_week_mode", "0")
o:depends(value .. "_week_mode", "1") o:depends(value .. "_week_mode", "1")
o:depends(value .. "_week_mode", "2") o:depends(value .. "_week_mode", "2")
@@ -97,13 +97,8 @@ if has_xray or has_singbox then
end end
end end
---- Auto Update o = s:option(ListValue, "update_week_mode", translate("Auto Update Mode"))
o = s:option(Flag, "auto_update", translate("Enable auto update rules")) o:value("", translate("Disable"))
o.default = 0
o.rmempty = false
---- Week Update
o = s:option(ListValue, "week_update", translate("Update Mode"))
o:value(8, translate("Loop Mode")) o:value(8, translate("Loop Mode"))
o:value(7, translate("Every day")) o:value(7, translate("Every day"))
o:value(1, translate("Every Monday")) o:value(1, translate("Every Monday"))
@@ -113,29 +108,30 @@ o:value(4, translate("Every Thursday"))
o:value(5, translate("Every Friday")) o:value(5, translate("Every Friday"))
o:value(6, translate("Every Saturday")) o:value(6, translate("Every Saturday"))
o:value(0, translate("Every Sunday")) o:value(0, translate("Every Sunday"))
o.default = 7
o:depends("auto_update", true)
o.rmempty = true
---- Time Update o = s:option(Value, "update_time_mode", translate("Update Time"))
o = s:option(ListValue, "time_update", translate("Update Time(every day)")) for t = 0, 23 do o:value(t .. ":00") end
for t = 0, 23 do o:value(t, t .. ":00") end o.default = "0:00"
o.default = 0 o.validate = function(self, value)
o:depends("week_update", "0") local b = api.is_timehhmm(value)
o:depends("week_update", "1") if b then
o:depends("week_update", "2") return value
o:depends("week_update", "3") end
o:depends("week_update", "4") return nil
o:depends("week_update", "5") end
o:depends("week_update", "6") o:depends("update_week_mode", "0")
o:depends("week_update", "7") o:depends("update_week_mode", "1")
o.rmempty = true o:depends("update_week_mode", "2")
o:depends("update_week_mode", "3")
o:depends("update_week_mode", "4")
o:depends("update_week_mode", "5")
o:depends("update_week_mode", "6")
o:depends("update_week_mode", "7")
---- Interval Update o = s:option(ListValue, "update_interval_mode", translate("Update Interval(hour)"))
o = s:option(ListValue, "interval_update", translate("Update Interval(hour)"))
for t = 1, 24 do o:value(t, t .. " " .. translate("hour")) end for t = 1, 24 do o:value(t, t .. " " .. translate("hour")) end
o.default = 2 o.default = 2
o:depends("week_update", "8") o:depends("update_week_mode", "8")
o.rmempty = true o.rmempty = true
---- 更新选项,始终被js隐藏 ---- 更新选项,始终被js隐藏
@@ -152,9 +152,10 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o:depends({ [_n("node_add_mode")] = "batch" }) o:depends({ [_n("node_add_mode")] = "batch" })
local descrStr = "Example: <code>^A && B && !C && D$</code><br>" local descrStr = "Example: <code>^A && B && !C && D$</code><br>"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
descrStr = descrStr .. "Conditions are joined by <code>&&</code>, and their order does not affect the result." descrStr = descrStr .. "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
o.description = translate(descrStr) .. string.format("<br><font color='red'>%s</font>", descrStr = descrStr .. "Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
translate("Keep the match scope small. Too many nodes can impact router performance.")) descrStr = descrStr .. "Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
o.description = translate(descrStr)
o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy")) o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
o:depends({ [_n("protocol")] = "_balancing" }) o:depends({ [_n("protocol")] = "_balancing" })
@@ -151,9 +151,10 @@ if load_urltest_options then -- [[ URLTest Start ]]
o:depends({ [_n("node_add_mode")] = "batch" }) o:depends({ [_n("node_add_mode")] = "batch" })
local descrStr = "Example: <code>^A && B && !C && D$</code><br>" local descrStr = "Example: <code>^A && B && !C && D$</code><br>"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
descrStr = descrStr .. "Conditions are joined by <code>&&</code>, and their order does not affect the result." descrStr = descrStr .. "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
o.description = translate(descrStr) .. string.format("<br><font color='red'>%s</font>", descrStr = descrStr .. "Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
translate("Keep the match scope small. Too many nodes can impact router performance.")) descrStr = descrStr .. "Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
o.description = translate(descrStr)
o = s:option(Value, _n("urltest_url"), translate("Probe URL")) o = s:option(Value, _n("urltest_url"), translate("Probe URL"))
o:depends({ [_n("protocol")] = "_urltest" }) o:depends({ [_n("protocol")] = "_urltest" })
+39 -7
View File
@@ -348,6 +348,18 @@ function strToTable(str)
return loadstring("return " .. str)() return loadstring("return " .. str)()
end end
function is_timehhmm(timeStr)
local hour, minute = string.match(timeStr, "^(%d?%d):(%d%d)$")
if hour and minute then
hour = tonumber(hour)
minute = tonumber(minute)
if hour >= 0 and hour <= 23 and minute >= 0 and minute <= 59 then
return true
end
end
return false
end
function is_normal_node(e) function is_normal_node(e)
if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then
return false return false
@@ -1522,11 +1534,22 @@ end
function match_node_rule(name, rule) function match_node_rule(name, rule)
if not name then return false end if not name then return false end
if not rule or rule == "" then return true end if not rule or rule == "" then return true end
-- split rule by || into OR groups
local function split_or(expr)
local t = {}
for part in (expr .. "||"):gmatch("(.-)%|%|") do
part = trim(part)
if part ~= "" then
table.insert(t, part)
end
end
return t
end
-- split rule by && -- split rule by &&
local function split_and(expr) local function split_and(expr)
local t = {} local t = {}
for part in expr:gmatch("[^&]+") do for part in (expr .. "&&"):gmatch("(.-)%&%&") do
part = part:gsub("^%s+", ""):gsub("%s+$", "") part = trim(part)
if part ~= "" then if part ~= "" then
table.insert(t, part) table.insert(t, part)
end end
@@ -1557,13 +1580,22 @@ function match_node_rule(name, rule)
-- contains -- contains
return str:find(cond, 1, true) ~= nil return str:find(cond, 1, true) ~= nil
end end
-- AND logic -- check if all conditions in AND group match
for _, cond in ipairs(split_and(rule)) do local function match_and_group(str, group_expr)
if not match_cond(name, cond) then for _, cond in ipairs(split_and(group_expr)) do
return false if not match_cond(str, cond) then
return false
end
end
return true
end
-- OR logic: return true if any group matches
for _, group in ipairs(split_or(rule)) do
if match_and_group(name, group) then
return true
end end
end end
return true return false
end end
function get_core(field, candidates) function get_core(field, candidates)
@@ -900,10 +900,10 @@ function gen_config(var)
fragment_table = { fragment_table = {
type = "fragment", type = "fragment",
settings = { settings = {
packets = xray_settings.fragment_packets, packets = xray_settings.fragment_packets or "tlshello",
lengths = #lengths > 0 and lengths or nil, lengths = #lengths > 0 and lengths or {"3-5","6-8","10-20"},
delays = #delays > 0 and delays or nil, delays = #delays > 0 and delays or {"10-20"},
maxSplit = xray_settings.fragment_maxSplit maxSplit = xray_settings.fragment_maxSplit or "3-6"
} }
} }
end end
@@ -1,7 +1,7 @@
<div id="app_version">
<% <%
local api = require "luci.passwall.api" local api = self.api
local com = require "luci.passwall.com" local com = self.com
local version = {}
-%> -%>
<script type="text/javascript"> <script type="text/javascript">
@@ -194,14 +194,14 @@ local version = {}
<%for _, k in ipairs(com.order) do <%for _, k in ipairs(com.order) do
local v = com[k] local v = com[k]
version[k] = api.get_app_version(k)%> %>
<div class="cbi-value"> <div class="cbi-value">
<label class="cbi-value-title"><%=v.name%> <label class="cbi-value-title"><%=v.name%>
<%:Version%> <%:Version%>
</label> </label>
<div class="cbi-value-field"> <div class="cbi-value-field">
<!--div class="cbi-value-description"--> <!--div class="cbi-value-description"-->
<span>【 <%=version[k] ~="" and version[k] or translate("Null") %> 】</span> <span>【 <span class="com_version" key="<%=k%>"><%=translate("Null")%></span> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-check_btn" <input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-check_btn"
onclick="onBtnClick(this,'<%=k%>');" value="<%:Check update%>" /> onclick="onBtnClick(this,'<%=k%>');" value="<%:Check update%>" />
<input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-force_btn" <input class="btn cbi-button cbi-button-apply" type="button" id="_<%=k%>-force_btn"
@@ -211,3 +211,27 @@ local version = {}
</div> </div>
</div> </div>
<%end%> <%end%>
<script type="text/javascript">
//<![CDATA[
document.addEventListener("DOMContentLoaded", function () {
let coms = document.getElementsByClassName("com_version");
if (coms.length > 0) {
for (let i = 0; i < coms.length; i++) {
let key = coms[i].getAttribute("key");
coms[i].innerHTML = "<%=translate("Collecting data...")%>";
XHR.get('<%=api.url("version_")%>' + key, null, function(x, result) {
if (x.status == 200 && result.code == 1) {
let data = result.data;
let t = "<%=translate("Null")%>";
if (data && data != "")
t = data;
coms[i].innerHTML = t;
}
});
}
}
});
//]]>
</script>
</div>
+16 -21
View File
@@ -532,14 +532,15 @@ msgstr "节点匹配规则"
msgid "" msgid ""
"Example: <code>^A && B && !C && D$</code><br>" "Example: <code>^A && B && !C && D$</code><br>"
"This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
"Conditions are joined by <code>&&</code>, and their order does not affect the result." "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
"Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
"Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
msgstr "" msgstr ""
"示例:<code>^A && B && !C && D$</code><br>" "示例:<code>^A && B && !C && D$</code><br>"
"表示节点备注需同时满足:以 A 开头(^)、包含 B、不包含 C(!)、并以 D 结尾($)。<br>" "表示节点备注需同时满足:以 A 开头(^)、包含 B、不包含 C(!)、并以 D 结尾($)。<br>"
"多个条件使用 <code>&&</code> 连接,条件顺序不影响结果。" "多个条件使用 <code>&&</code>(与)连接,条件顺序不影响结果。<br>"
"多组条件之间可使用 <code>||</code>(或)分隔,任意一组匹配即视为成功。<br>"
msgid "Keep the match scope small. Too many nodes can impact router performance." "示例:<code>A && B || C && D</code> 表示 (A 且 B) 或 (C 且 D)。"
msgstr "建议尽量缩小匹配范围,节点过多会增加路由器负载。"
msgid "Balancing Strategy" msgid "Balancing Strategy"
msgstr "负载均衡策略" msgstr "负载均衡策略"
@@ -823,8 +824,8 @@ msgstr "单位:分钟"
msgid "stop automatically mode" msgid "stop automatically mode"
msgstr "定时关闭模式" msgstr "定时关闭模式"
msgid "stop Time(Every day)" msgid "stop Time"
msgstr "关闭时间(每天)" msgstr "关闭时间"
msgid "stop Interval(Hour)" msgid "stop Interval(Hour)"
msgstr "关闭间隔(小时)" msgstr "关闭间隔(小时)"
@@ -832,8 +833,8 @@ msgstr "关闭间隔(小时)"
msgid "start automatically mode" msgid "start automatically mode"
msgstr "定时开启模式" msgstr "定时开启模式"
msgid "start Time(Every day)" msgid "start Time"
msgstr "开启时间(每天)" msgstr "开启时间"
msgid "start Interval(Hour)" msgid "start Interval(Hour)"
msgstr "开启间隔(小时)" msgstr "开启间隔(小时)"
@@ -841,8 +842,8 @@ msgstr "开启间隔(小时)"
msgid "restart automatically mode" msgid "restart automatically mode"
msgstr "定时重启模式" msgstr "定时重启模式"
msgid "restart Time(Every day)" msgid "restart Time"
msgstr "重启时间(每天)" msgstr "重启时间"
msgid "restart Interval(Hour)" msgid "restart Interval(Hour)"
msgstr "重启间隔(小时)" msgstr "重启间隔(小时)"
@@ -1057,17 +1058,14 @@ msgstr "中国域名列表(Chnlist)更新URL"
msgid "Rule status" msgid "Rule status"
msgstr "规则版本" msgstr "规则版本"
msgid "Enable auto update rules" msgid "Update Time"
msgstr "开启自动更新规则" msgstr "更新时间"
msgid "Update Time(every day)"
msgstr "更新时间(每天)"
msgid "Update Interval(hour)" msgid "Update Interval(hour)"
msgstr "更新间隔(小时)" msgstr "更新间隔(小时)"
msgid "Update Mode" msgid "Auto Update Mode"
msgstr "更新模式" msgstr "自动更新模式"
msgid "Loop Mode" msgid "Loop Mode"
msgstr "循环" msgstr "循环"
@@ -1177,9 +1175,6 @@ msgstr "移动中"
msgid "App Update" msgid "App Update"
msgstr "组件更新" msgstr "组件更新"
msgid "Please confirm that your firmware supports FPU."
msgstr "请确认你的固件支持 FPU。"
msgid "if you want to run from memory, change the path, /tmp beginning then save the application and update it manually." msgid "if you want to run from memory, change the path, /tmp beginning then save the application and update it manually."
msgstr "如果你希望从内存中运行,请更改路径,/tmp 开头,然后保存应用后,再手动更新。" msgstr "如果你希望从内存中运行,请更改路径,/tmp 开头,然后保存应用后,再手动更新。"
@@ -55,17 +55,12 @@ config global_other
option show_node_info '0' option show_node_info '0'
config global_rules config global_rules
option auto_update '1'
option chnlist_update '1' option chnlist_update '1'
option chnroute_update '1' option chnroute_update '1'
option chnroute6_update '1' option chnroute6_update '1'
option gfwlist_update '1' option gfwlist_update '1'
option geosite_update '1' option geosite_update '0'
option geoip_update '1' option geoip_update '0'
option enable_geoview '1'
option geo2rule '1'
option week_update '7'
option time_update '4'
list gfwlist_url 'https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt' list gfwlist_url 'https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt'
list chnroute_url 'https://ispip.clang.cn/all_cn.txt' list chnroute_url 'https://ispip.clang.cn/all_cn.txt'
list chnroute_url 'https://cdn.jsdelivr.net/gh/gaoyifan/china-operator-ip@ip-lists/china.txt' list chnroute_url 'https://cdn.jsdelivr.net/gh/gaoyifan/china-operator-ip@ip-lists/china.txt'
@@ -74,8 +69,8 @@ config global_rules
list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf' list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf'
list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf' list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf'
option v2ray_location_asset '/usr/share/v2ray/' option v2ray_location_asset '/usr/share/v2ray/'
option geoip_url 'https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/geoip.dat' option geoip_url 'https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip.dat'
option geosite_url 'https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat' option geosite_url 'https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat'
config global_app config global_app
option geoview_file '/usr/bin/geoview' option geoview_file '/usr/bin/geoview'
@@ -74,7 +74,7 @@ check_run_environment() {
run_ipt2socks() { run_ipt2socks() {
local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file local flag proto tcp_tproxy local_port socks_address socks_port socks_username socks_password log_file
local _extra_param="" local _extra_param=""
eval_set_val $@ eval_set_val "$@"
[ -n "$log_file" ] || log_file="/dev/null" [ -n "$log_file" ] || log_file="/dev/null"
socks_address=$(get_host_ip "ipv4" ${socks_address}) socks_address=$(get_host_ip "ipv4" ${socks_address})
[ -n "$socks_username" ] && [ -n "$socks_password" ] && _extra_param="${_extra_param} -a $socks_username -k $socks_password" [ -n "$socks_username" ] && [ -n "$socks_password" ] && _extra_param="${_extra_param} -a $socks_username -k $socks_password"
@@ -100,7 +100,7 @@ run_singbox() {
local flag type node tcp_redir_port tcp_proxy_way udp_redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag type node tcp_redir_port tcp_proxy_way udp_redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port
local loglevel log_file config_file server_host server_port no_run local loglevel log_file config_file server_host server_port no_run
eval_set_val $@ eval_set_val "$@"
[ -z "$type" ] && { [ -z "$type" ] && {
type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
[ "$type" != "sing-box" ] && [ -n "$SINGBOX_BIN" ] && type="sing-box" [ "$type" != "sing-box" ] && [ -n "$SINGBOX_BIN" ] && type="sing-box"
@@ -198,7 +198,7 @@ run_xray() {
local flag type node tcp_redir_port tcp_proxy_way udp_redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password local flag type node tcp_redir_port tcp_proxy_way udp_redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password
local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port local dns_listen_port direct_dns_query_strategy direct_dns_port direct_dns_udp_server direct_dns_tcp_server remote_dns_protocol remote_dns_udp_server remote_dns_tcp_server remote_dns_doh remote_dns_client_ip remote_fakedns remote_dns_query_strategy dns_cache dns_socks_address dns_socks_port
local loglevel log_file config_file server_host server_port no_run local loglevel log_file config_file server_host server_port no_run
eval_set_val $@ eval_set_val "$@"
[ -z "$type" ] && { [ -z "$type" ] && {
type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
[ "$type" != "xray" ] && [ -n "$XRAY_BIN" ] && type="xray" [ "$type" != "xray" ] && [ -n "$XRAY_BIN" ] && type="xray"
@@ -287,7 +287,7 @@ run_xray() {
run_dns2socks() { run_dns2socks() {
local flag socks socks_address socks_port socks_username socks_password listen_address listen_port dns cache log_file local flag socks socks_address socks_port socks_username socks_password listen_address listen_port dns cache log_file
local _extra_param="" local _extra_param=""
eval_set_val $@ eval_set_val "$@"
[ -n "$flag" ] && flag="_${flag}" [ -n "$flag" ] && flag="_${flag}"
[ -n "$log_file" ] || log_file="/dev/null" [ -n "$log_file" ] || log_file="/dev/null"
dns=$(get_first_dns dns 53 | sed 's/#/:/g') dns=$(get_first_dns dns 53 | sed 's/#/:/g')
@@ -305,11 +305,11 @@ run_dns2socks() {
run_chinadns_ng() { run_chinadns_ng() {
local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag _no_logic_log _tcp_node _remote_fakedns _filter_https local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag _no_logic_log _tcp_node _remote_fakedns _filter_https
local _extra_param="" local _extra_param=""
eval_set_val $@ eval_set_val "$@"
local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf
local _LOG_FILE="/dev/null" local _LOG_FILE="/dev/null"
[ "$(config_t_get global log_chinadns_ng "0")" == "1" ] && _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log [ "$(config_t_get global log_chinadns_ng "0")" = "1" ] && _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log
_extra_param="-FLAG ${_flag} -TCP_NODE ${_tcp_node} -LISTEN_PORT ${_listen_port} -DNS_LOCAL ${_dns_local} -DNS_TRUST ${_dns_trust}" _extra_param="-FLAG ${_flag} -TCP_NODE ${_tcp_node} -LISTEN_PORT ${_listen_port} -DNS_LOCAL ${_dns_local} -DNS_TRUST ${_dns_trust}"
_extra_param="${_extra_param} -USE_DIRECT_LIST ${_use_direct_list} -USE_PROXY_LIST ${_use_proxy_list} -USE_BLOCK_LIST ${_use_block_list}" _extra_param="${_extra_param} -USE_DIRECT_LIST ${_use_direct_list} -USE_PROXY_LIST ${_use_proxy_list} -USE_BLOCK_LIST ${_use_block_list}"
@@ -323,7 +323,7 @@ run_chinadns_ng() {
run_socks() { run_socks() {
local flag node bind socks_port config_file http_port http_config_file relay_port log_file no_run local flag node bind socks_port config_file http_port http_config_file relay_port log_file no_run
eval_set_val $@ eval_set_val "$@"
[ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=$TMP_PATH/$config_file [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=$TMP_PATH/$config_file
[ -n "$http_port" ] || http_port=0 [ -n "$http_port" ] || http_port=0
[ -n "$http_config_file" ] && [ -z "$(echo ${http_config_file} | grep $TMP_PATH)" ] && http_config_file=$TMP_PATH/$http_config_file [ -n "$http_config_file" ] && [ -z "$(echo ${http_config_file} | grep $TMP_PATH)" ] && http_config_file=$TMP_PATH/$http_config_file
@@ -367,14 +367,14 @@ run_socks() {
error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!" error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!"
fi fi
if [ "$type" == "sing-box" ] || [ "$type" == "xray" ]; then if [ "$type" = "sing-box" ] || [ "$type" = "xray" ]; then
local protocol=$(config_n_get $node protocol) local protocol=$(config_n_get $node protocol)
if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ] || [ "$protocol" == "_urltest" ]; then if [ "$protocol" = "_balancing" ] || [ "$protocol" = "_shunt" ] || [ "$protocol" = "_iface" ] || [ "$protocol" = "_urltest" ]; then
unset error_msg unset error_msg
fi fi
fi fi
if [ -n "${error_msg}" ] && ([ -n "$(config_n_get $node hysteria_hop)" ] || [ -n "$(config_n_get $node hysteria2_hop)" ] || [ "$(config_n_get $node hysteria2_realms)" = "1" ]); then if [ -n "${error_msg}" ] && { [ -n "$(config_n_get $node hysteria_hop)" ] || [ -n "$(config_n_get $node hysteria2_hop)" ] || [ "$(config_n_get $node hysteria2_realms)" = "1" ]; }; then
unset error_msg unset error_msg
fi fi
@@ -527,7 +527,7 @@ run_socks() {
run_redir() { run_redir() {
local node proto bind local_port config_file log_file local node proto bind local_port config_file log_file
eval_set_val $@ eval_set_val "$@"
local tcp_node_socks_flag tcp_node_http_flag local tcp_node_socks_flag tcp_node_http_flag
[ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${GLOBAL_ACL_PATH}/${config_file} [ -n "$config_file" ] && [ -z "$(echo ${config_file} | grep $TMP_PATH)" ] && config_file=${GLOBAL_ACL_PATH}/${config_file}
if [ -n "$log_file" ] && [ -z "$(echo ${log_file} | grep $TMP_PATH)" ]; then if [ -n "$log_file" ] && [ -z "$(echo ${log_file} | grep $TMP_PATH)" ]; then
@@ -644,7 +644,7 @@ run_redir() {
tcp_node_socks_port=$(get_new_port $(config_t_get global tcp_node_socks_port 1070)) tcp_node_socks_port=$(get_new_port $(config_t_get global tcp_node_socks_port 1070))
tcp_node_http_port=$(config_t_get global tcp_node_http_port 0) tcp_node_http_port=$(config_t_get global tcp_node_http_port 0)
[ "$tcp_node_http_port" != "0" ] && tcp_node_http=1 [ "$tcp_node_http_port" != "0" ] && tcp_node_http=1
if [ $PROXY_IPV6 == "1" ]; then if [ $PROXY_IPV6 = "1" ]; then
echolog "开启实验性IPv6透明代理(TProxy),请确认您的节点及类型支持IPv6!" echolog "开启实验性IPv6透明代理(TProxy),请确认您的节点及类型支持IPv6!"
fi fi
@@ -725,7 +725,7 @@ run_redir() {
DNSMASQ_FILTER_PROXY_IPV6=0 DNSMASQ_FILTER_PROXY_IPV6=0
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip) local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}" [ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
[ "${DNS_CACHE}" == "0" ] && _args="${_args} dns_cache=0" [ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
resolve_dns_port=${NEXT_DNS_LISTEN_PORT} resolve_dns_port=${NEXT_DNS_LISTEN_PORT}
_args="${_args} dns_listen_port=${resolve_dns_port}" _args="${_args} dns_listen_port=${resolve_dns_port}"
@@ -811,7 +811,7 @@ run_redir() {
DNSMASQ_FILTER_PROXY_IPV6=0 DNSMASQ_FILTER_PROXY_IPV6=0
local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip) local _remote_dns_client_ip=$(config_t_get global remote_dns_client_ip)
[ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}" [ -n "${_remote_dns_client_ip}" ] && _args="${_args} remote_dns_client_ip=${_remote_dns_client_ip}"
[ "${DNS_CACHE}" == "0" ] && _args="${_args} dns_cache=0" [ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
resolve_dns_port=${NEXT_DNS_LISTEN_PORT} resolve_dns_port=${NEXT_DNS_LISTEN_PORT}
_args="${_args} dns_listen_port=${resolve_dns_port}" _args="${_args} dns_listen_port=${resolve_dns_port}"
@@ -984,7 +984,7 @@ start_socks() {
echolog "分析 Socks 服务的节点配置..." echolog "分析 Socks 服务的节点配置..."
for id in $ids; do for id in $ids; do
local enabled=$(config_n_get $id enabled 0) local enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "0" ] && continue [ "$enabled" = "0" ] && continue
local node=$(config_n_get $id node) local node=$(config_n_get $id node)
[ -z "$node" ] && continue [ -z "$node" ] && continue
local bind_local=$(config_n_get $id bind_local 0) local bind_local=$(config_n_get $id bind_local 0)
@@ -994,7 +994,7 @@ start_socks() {
local config_file="SOCKS_${id}.json" local config_file="SOCKS_${id}.json"
local log_file="SOCKS_${id}.log" local log_file="SOCKS_${id}.log"
local log=$(config_n_get $id log 1) local log=$(config_n_get $id log 1)
[ "$log" == "0" ] && log_file="" [ "$log" = "0" ] && log_file=""
local http_port=$(config_n_get $id http_port 0) local http_port=$(config_n_get $id http_port 0)
local http_config_file="HTTP2SOCKS_${id}.json" local http_config_file="HTTP2SOCKS_${id}.json"
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0) local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
@@ -1012,7 +1012,7 @@ start_socks() {
socks_node_switch() { socks_node_switch() {
local flag new_node local flag new_node
eval_set_val $@ eval_set_val "$@"
[ -n "$flag" ] && [ -n "$new_node" ] && { [ -n "$flag" ] && [ -n "$new_node" ] && {
local prefix pf filename local prefix pf filename
# 结束 SS 插件进程 # 结束 SS 插件进程
@@ -1037,7 +1037,7 @@ socks_node_switch() {
local config_file="SOCKS_${flag}.json" local config_file="SOCKS_${flag}.json"
local log_file="SOCKS_${flag}.log" local log_file="SOCKS_${flag}.log"
local log=$(config_n_get $flag log 1) local log=$(config_n_get $flag log 1)
[ "$log" == "0" ] && log_file="" [ "$log" = "0" ] && log_file=""
local http_port=$(config_n_get $flag http_port 0) local http_port=$(config_n_get $flag http_port 0)
local http_config_file="HTTP2SOCKS_${flag}.json" local http_config_file="HTTP2SOCKS_${flag}.json"
LOG_FILE="/dev/null" LOG_FILE="/dev/null"
@@ -1045,7 +1045,7 @@ socks_node_switch() {
set_cache_var "socks_${flag}" "$new_node" set_cache_var "socks_${flag}" "$new_node"
local ENABLED_DEFAULT_ACL=$(get_cache_var "ENABLED_DEFAULT_ACL") local ENABLED_DEFAULT_ACL=$(get_cache_var "ENABLED_DEFAULT_ACL")
local ENABLED_ACLS=$(get_cache_var "ENABLED_ACLS") local ENABLED_ACLS=$(get_cache_var "ENABLED_ACLS")
[ "$ENABLED_DEFAULT_ACL" != "1" -a "$ENABLED_ACLS" != "1" ] && return [ "$ENABLED_DEFAULT_ACL" != "1" ] && [ "$ENABLED_ACLS" != "1" ] && return
local USE_TABLES=$(get_cache_var "USE_TABLES") local USE_TABLES=$(get_cache_var "USE_TABLES")
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh filter_direct_node_list [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh filter_direct_node_list
} }
@@ -1086,19 +1086,29 @@ start_crontab() {
build_time() { build_time() {
local w="$1" local w="$1"
local h="$2" local t="$2"
local expr="0 $h * * $w" local h m
[ "$w" = "7" ] && expr="0 $h * * *" if echo "$t" | grep -q ':'; then
h="${t%%:*}"
m="${t##*:}"
else
h="$t"
m=0
fi
h=$(printf '%d' "$h")
m=$(printf '%d' "$m")
local expr="$m $h * * $w"
[ "$w" = "7" ] && expr="$m $h * * *"
echo "$expr" echo "$expr"
} }
add_service_cron() { add_service_cron() {
local week="$1" local week="$1"
local hour="$2" local time="$2"
local action="$3" local action="$3"
local logmsg="$4" local logmsg="$4"
[ -z "$week" ] && return [ -z "$week" ] && return
local svr_t=$(build_time "$week" "$hour") local svr_t=$(build_time "$week" "$time")
if [ "$week" = "8" ]; then if [ "$week" = "8" ]; then
update_loop=1 update_loop=1
else else
@@ -1115,12 +1125,11 @@ start_crontab() {
add_service_cron "$(config_t_get global_delay restart_week_mode)" "$(config_t_get global_delay restart_time_mode)" "restart" "配置定时任务:自动重启服务。" add_service_cron "$(config_t_get global_delay restart_week_mode)" "$(config_t_get global_delay restart_time_mode)" "restart" "配置定时任务:自动重启服务。"
# ===== rule update ===== # ===== rule update =====
local autoupdate=$(config_t_get global_rules auto_update) local rules_update_week_mode=$(config_t_get global_rules update_week_mode)
local weekupdate=$(config_t_get global_rules week_update) local rules_update_time_mode=$(config_t_get global_rules update_time_mode)
local dayupdate=$(config_t_get global_rules time_update) if [ -n "$rules_update_week_mode" ]; then
if [ "$autoupdate" = "1" ]; then local rule_t=$(build_time "$rules_update_week_mode" "$rules_update_time_mode")
local rule_t=$(build_time "$weekupdate" "$dayupdate") if [ "$rules_update_week_mode" = "8" ]; then
if [ "$weekupdate" = "8" ]; then
update_loop=1 update_loop=1
else else
echo "$rule_t lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 &" >>/etc/crontabs/root echo "$rule_t lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 &" >>/etc/crontabs/root
@@ -1131,25 +1140,25 @@ start_crontab() {
# ===== subscribe ===== # ===== subscribe =====
local TMP_SUB_PATH=$TMP_PATH/sub_crontabs local TMP_SUB_PATH=$TMP_PATH/sub_crontabs
mkdir -p "$TMP_SUB_PATH" mkdir -p "$TMP_SUB_PATH"
local item cfgid remark week_update time_update local item cfgid remark sub_update_week_mode sub_update_time_mode
for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
if [ "$(config_n_get "$item" auto_update 0)" = "1" ]; then sub_update_week_mode=$(config_n_get $item update_week_mode)
if [ -n "$sub_update_week_mode" ]; then
cfgid=$(uci show ${CONFIG}.$item | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1) cfgid=$(uci show ${CONFIG}.$item | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1)
remark=$(config_n_get "$item" remark) remark=$(config_n_get "$item" remark)
week_update=$(config_n_get "$item" week_update) sub_update_time_mode=$(config_n_get $item update_time_mode)
time_update=$(config_n_get "$item" time_update) echo "$cfgid" >> "$TMP_SUB_PATH/${sub_update_week_mode}_${sub_update_time_mode}"
echo "$cfgid" >> "$TMP_SUB_PATH/${week_update}_${time_update}"
echolog "配置定时任务:自动更新【$remark】订阅。" echolog "配置定时任务:自动更新【$remark】订阅。"
fi fi
done done
if [ -d "$TMP_SUB_PATH" ]; then if [ -d "$TMP_SUB_PATH" ]; then
local name cfgids local name cfgids
for name in $(ls "$TMP_SUB_PATH"); do for name in $(ls "$TMP_SUB_PATH"); do
week_update=${name%_*} sub_update_week_mode=${name%_*}
time_update=${name#*_} sub_update_time_mode=${name#*_}
cfgids=$(tr '\n' ',' < "$TMP_SUB_PATH/$name" | sed 's/,$//') cfgids=$(tr '\n' ',' < "$TMP_SUB_PATH/$name" | sed 's/,$//')
local sub_t=$(build_time "$week_update" "$time_update") local sub_t=$(build_time "$sub_update_week_mode" "$sub_update_time_mode")
if [ "$week_update" = "8" ]; then if [ "$sub_update_week_mode" = "8" ]; then
update_loop=1 update_loop=1
else else
echo "$sub_t lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 &" >>/etc/crontabs/root echo "$sub_t lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 &" >>/etc/crontabs/root
@@ -1253,7 +1262,7 @@ start_dns() {
local log_file=$TMP_PATH/DNS.log local log_file=$TMP_PATH/DNS.log
local log_file=/dev/null local log_file=/dev/null
local _args="type=$DNS_MODE config_file=$config_file log_file=$log_file" local _args="type=$DNS_MODE config_file=$config_file log_file=$log_file"
[ "${DNS_CACHE}" == "0" ] && _args="${_args} dns_cache=0" [ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
_args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}" _args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}"
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}" _args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
DNSMASQ_FILTER_PROXY_IPV6=0 DNSMASQ_FILTER_PROXY_IPV6=0
@@ -1292,7 +1301,7 @@ start_dns() {
local log_file=$TMP_PATH/DNS.log local log_file=$TMP_PATH/DNS.log
local log_file=/dev/null local log_file=/dev/null
local _args="type=$DNS_MODE config_file=$config_file log_file=$log_file" local _args="type=$DNS_MODE config_file=$config_file log_file=$log_file"
[ "${DNS_CACHE}" == "0" ] && _args="${_args} dns_cache=0" [ "${DNS_CACHE}" = "0" ] && _args="${_args} dns_cache=0"
_args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}" _args="${_args} direct_dns_query_strategy=${DIRECT_DNS_QUERY_STRATEGY}"
_args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}" _args="${_args} remote_dns_query_strategy=${REMOTE_DNS_QUERY_STRATEGY}"
DNSMASQ_FILTER_PROXY_IPV6=0 DNSMASQ_FILTER_PROXY_IPV6=0
@@ -1363,7 +1372,7 @@ start_dns() {
rm -rf $TMP_PATH2/dnsmasq_default* rm -rf $TMP_PATH2/dnsmasq_default*
local group_domestic=$(config_t_get global group_domestic) local group_domestic=$(config_t_get global group_domestic)
local smartdns_remote_dns=$(config_t_get global smartdns_remote_dns) local smartdns_remote_dns=$(config_t_get global smartdns_remote_dns)
if [ -n "${smartdns_remote_dns}" -a "${smartdns_remote_dns}" != "nil" ]; then if [ -n "${smartdns_remote_dns}" ] && [ "${smartdns_remote_dns}" != "nil" ]; then
smartdns_remote_dns=$(echo ${smartdns_remote_dns} | tr -s ' ' '|') smartdns_remote_dns=$(echo ${smartdns_remote_dns} | tr -s ' ' '|')
else else
smartdns_remote_dns="tcp://1.1.1.1" smartdns_remote_dns="tcp://1.1.1.1"
@@ -1430,13 +1439,13 @@ start_dns() {
[ "$USE_DEFAULT_DNS" = "remote" ] && { [ "$USE_DEFAULT_DNS" = "remote" ] && {
dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}') dnsmasq_version=$(dnsmasq -v | grep -i "Dnsmasq version " | awk '{print $3}')
[ "$(expr $dnsmasq_version \>= 2.87)" == 0 ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!" [ "$(check_ver "$dnsmasq_version" "2.87")" = "1" ] && echolog "Dnsmasq版本低于2.87,有可能无法正常使用!!!"
} }
local DNSMASQ_TUN_DNS=$(get_first_dns TUN_DNS 53) local DNSMASQ_TUN_DNS=$(get_first_dns TUN_DNS 53)
local RUN_NEW_DNSMASQ=1 local RUN_NEW_DNSMASQ=1
RUN_NEW_DNSMASQ=${DNS_REDIRECT} RUN_NEW_DNSMASQ=${DNS_REDIRECT}
if [ "${RUN_NEW_DNSMASQ}" == "0" ]; then if [ "${RUN_NEW_DNSMASQ}" = "0" ]; then
#The old logic will be removed in the future. #The old logic will be removed in the future.
#Run a copy dnsmasq instance, DNS hijack that don't need a proxy devices. #Run a copy dnsmasq instance, DNS hijack that don't need a proxy devices.
[ "1" = "0" ] && { [ "1" = "0" ] && {
@@ -1542,7 +1551,7 @@ acl_app() {
local acl_path=${TMP_ACL_PATH}/$sid local acl_path=${TMP_ACL_PATH}/$sid
mkdir -p ${acl_path} mkdir -p ${acl_path}
[ -n "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > ${acl_path}/source_list [ -n "${source_list}" ] && printf "%b\n" "${source_list}" | sed '/^$/d' > ${acl_path}/source_list
use_global_config=${use_global_config:-0} use_global_config=${use_global_config:-0}
[ "${use_global_config}" = "1" ] && { [ "${use_global_config}" = "1" ] && {
@@ -1627,7 +1636,7 @@ acl_app() {
_dns_port=$dns_port _dns_port=$dns_port
if [ "$dns_mode" = "dns2socks" ]; then if [ "$dns_mode" = "dns2socks" ]; then
run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=${_dns_port} dns=$remote_dns cache=1 run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=${_dns_port} dns=$remote_dns cache=1
elif [ "$dns_mode" = "sing-box" -o "$dns_mode" = "xray" ]; then elif [ "$dns_mode" = "sing-box" ] || [ "$dns_mode" = "xray" ]; then
config_file=$TMP_ACL_PATH/${tcp_node}_SOCKS_${socks_port}_DNS.json config_file=$TMP_ACL_PATH/${tcp_node}_SOCKS_${socks_port}_DNS.json
remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query} remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query}
local type=${dns_mode} local type=${dns_mode}
@@ -1853,8 +1862,8 @@ start() {
nftflag=0 nftflag=0
USE_TABLES="" USE_TABLES=""
check_run_environment check_run_environment
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then if [ "$ENABLED_DEFAULT_ACL" = 1 ] || [ "$ENABLED_ACLS" = 1 ]; then
[ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" == "1" ] && { [ "$(uci -q get dhcp.@dnsmasq[0].dns_redirect)" = "1" ] && {
uci -q set ${CONFIG}.@global[0].dnsmasq_dns_redirect='1' uci -q set ${CONFIG}.@global[0].dnsmasq_dns_redirect='1'
uci -q commit ${CONFIG} uci -q commit ${CONFIG}
uci -q set dhcp.@dnsmasq[0].dns_redirect='0' uci -q set dhcp.@dnsmasq[0].dns_redirect='0'
@@ -1862,7 +1871,7 @@ start() {
lua $APP_PATH/helper_dnsmasq.lua restart -LOG 0 lua $APP_PATH/helper_dnsmasq.lua restart -LOG 0
} }
fi fi
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" = 1 ] && {
mkdir -p ${GLOBAL_ACL_PATH} mkdir -p ${GLOBAL_ACL_PATH}
start_redir TCP start_redir TCP
start_redir UDP start_redir UDP
@@ -1870,11 +1879,11 @@ start() {
} }
[ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start [ -n "$USE_TABLES" ] && source $APP_PATH/${USE_TABLES}.sh start
set_cache_var "USE_TABLES" "$USE_TABLES" set_cache_var "USE_TABLES" "$USE_TABLES"
if [ "$ENABLED_DEFAULT_ACL" == 1 ] || [ "$ENABLED_ACLS" == 1 ]; then if [ "$ENABLED_DEFAULT_ACL" = 1 ] || [ "$ENABLED_ACLS" = 1 ]; then
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables) bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
set_cache_var "bak_bridge_nf_ipt" "$bridge_nf_ipt" set_cache_var "bak_bridge_nf_ipt" "$bridge_nf_ipt"
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1 sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables) bridge_nf_ip6t=$(sysctl -e -n net.bridge.bridge-nf-call-ip6tables)
set_cache_var "bak_bridge_nf_ip6t" "$bridge_nf_ip6t" set_cache_var "bak_bridge_nf_ip6t" "$bridge_nf_ip6t"
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1 sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
@@ -1981,7 +1990,7 @@ get_config() {
} }
ENABLED_ACLS=$(config_t_get global acl_enable 0) ENABLED_ACLS=$(config_t_get global acl_enable 0)
[ "$ENABLED_ACLS" = 1 ] && { [ "$ENABLED_ACLS" = 1 ] && {
[ "$(uci show ${CONFIG} | grep "@acl_rule" | grep "enabled='1'" | wc -l)" == 0 ] && ENABLED_ACLS=0 [ "$(uci show ${CONFIG} | grep "@acl_rule" | grep "enabled='1'" | wc -l)" = 0 ] && ENABLED_ACLS=0
} }
set_cache_var ENABLED_DEFAULT_ACL $ENABLED_DEFAULT_ACL set_cache_var ENABLED_DEFAULT_ACL $ENABLED_DEFAULT_ACL
set_cache_var ENABLED_ACLS $ENABLED_ACLS set_cache_var ENABLED_ACLS $ENABLED_ACLS
@@ -2004,7 +2013,7 @@ get_config() {
[ "${TCP_PROXY_MODE}" != "disable" ] && TCP_PROXY_MODE="proxy" [ "${TCP_PROXY_MODE}" != "disable" ] && TCP_PROXY_MODE="proxy"
[ "${UDP_PROXY_MODE}" != "disable" ] && UDP_PROXY_MODE="proxy" [ "${UDP_PROXY_MODE}" != "disable" ] && UDP_PROXY_MODE="proxy"
LOCALHOST_PROXY=$(config_t_get global localhost_proxy 1) LOCALHOST_PROXY=$(config_t_get global localhost_proxy 1)
[ "${LOCALHOST_PROXY}" == 1 ] && { [ "${LOCALHOST_PROXY}" = 1 ] && {
LOCALHOST_TCP_PROXY_MODE=$TCP_PROXY_MODE LOCALHOST_TCP_PROXY_MODE=$TCP_PROXY_MODE
LOCALHOST_UDP_PROXY_MODE=$UDP_PROXY_MODE LOCALHOST_UDP_PROXY_MODE=$UDP_PROXY_MODE
} }
@@ -2075,13 +2084,13 @@ arg1=$1
shift shift
case $arg1 in case $arg1 in
run_socks) run_socks)
run_socks $@ run_socks "$@"
;; ;;
socks_node_switch) socks_node_switch)
socks_node_switch $@ socks_node_switch "$@"
;; ;;
start) start)
start $@ start "$@"
;; ;;
stop) stop)
stop stop
@@ -38,8 +38,8 @@ ipt_n="$ipt -t nat -w"
ipt_m="$ipt -t mangle -w" ipt_m="$ipt -t mangle -w"
ip6t_n="$ip6t -t nat -w" ip6t_n="$ip6t -t nat -w"
ip6t_m="$ip6t -t mangle -w" ip6t_m="$ip6t -t mangle -w"
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_nat')" ] && ip6t_n="eval #$ip6t_n" [ -z "$ip6t" ] || [ -z "$(lsmod | grep 'ip6table_nat')" ] && ip6t_n="eval #$ip6t_n"
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_mangle')" ] && ip6t_m="eval #$ip6t_m" [ -z "$ip6t" ] || [ -z "$(lsmod | grep 'ip6table_mangle')" ] && ip6t_m="eval #$ip6t_m"
FWI=$(uci -q get firewall.passwall.path 2>/dev/null) FWI=$(uci -q get firewall.passwall.path 2>/dev/null)
FAKE_IP="198.18.0.0/15" FAKE_IP="198.18.0.0/15"
FAKE_IP_6="fc00::/18" FAKE_IP_6="fc00::/18"
@@ -47,7 +47,7 @@ FAKE_IP_6="fc00::/18"
factor() { factor() {
if [ -z "$1" ] || [ -z "$2" ]; then if [ -z "$1" ] || [ -z "$2" ]; then
echo "" echo ""
elif [ "$1" == "1:65535" ]; then elif [ "$1" = "1:65535" ]; then
echo "" echo ""
else else
echo "$2 $1" echo "$2 $1"
@@ -168,7 +168,7 @@ REDIRECT() {
local s="-j REDIRECT" local s="-j REDIRECT"
[ -n "$1" ] && { [ -n "$1" ] && {
local s="$s --to-ports $1" local s="$s --to-ports $1"
[ "$2" == "TPROXY" ] && { [ "$2" = "TPROXY" ] && {
local mark="-m mark --mark ${FWMARK}" local mark="-m mark --mark ${FWMARK}"
s="${mark} -j TPROXY --on-port $1" s="${mark} -j TPROXY --on-port $1"
} }
@@ -195,11 +195,11 @@ get_jump_ipt() {
} }
load_acl() { load_acl() {
([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" { [ "$ENABLED_ACLS" = "1" ] || { [ "$ENABLED_DEFAULT_ACL" = "1" ] && [ "$CLIENT_PROXY" = "1" ]; }; } && echolog " - 访问控制:"
[ "$ENABLED_ACLS" == 1 ] && { [ "$ENABLED_ACLS" = 1 ] && {
acl_app acl_app
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-) eval "$(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)"
tcp_no_redir_ports=${tcp_no_redir_ports:-default} tcp_no_redir_ports=${tcp_no_redir_ports:-default}
udp_no_redir_ports=${udp_no_redir_ports:-default} udp_no_redir_ports=${udp_no_redir_ports:-default}
@@ -379,7 +379,7 @@ load_acl() {
ipset -! create $gfw6_set_name nethash family inet6 maxelem 1048576 timeout 172800 ipset -! create $gfw6_set_name nethash family inet6 maxelem 1048576 timeout 172800
} }
} }
[ "${use_shunt_tcp}" = "1" -o "${use_shunt_udp}" = "1" ] && { [ "${use_shunt_tcp}" = "1" ] || [ "${use_shunt_udp}" = "1" ] && {
[ "${use_global_config}" = "0" ] && { [ "${use_global_config}" = "0" ] && {
shunt_set_name="psw_${sid}_shunt" shunt_set_name="psw_${sid}_shunt"
shunt6_set_name="psw_${sid}_shunt6" shunt6_set_name="psw_${sid}_shunt6"
@@ -403,16 +403,16 @@ load_acl() {
[ -z "$(get_cache_var "ACL_${sid}_tcp_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。" [ -z "$(get_cache_var "ACL_${sid}_tcp_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。"
fi fi
[ -n "$tcp_port" -o -n "$udp_port" ] && { [ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
[ "${use_block_list}" = "1" ] && $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_BLOCK) -j DROP [ "${use_block_list}" = "1" ] && $ipt_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_BLOCK) -j DROP
[ "${use_direct_list}" = "1" ] && $ipt_tmp -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITE) -j RETURN [ "${use_direct_list}" = "1" ] && $ipt_tmp -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITE) -j RETURN
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_block_list}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_BLOCK6) -j DROP 2>/dev/null [ "${use_block_list}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_BLOCK6) -j DROP 2>/dev/null
[ "${use_direct_list}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITE6) -j RETURN 2>/dev/null [ "${use_direct_list}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") ${_ipt_source} $(dst $IPSET_WHITE6) -j RETURN 2>/dev/null
} }
[ "$tcp_proxy_drop_ports" != "disable" ] && { [ "$tcp_proxy_drop_ports" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "-d $FAKE_IP_6 -j DROP" 2>/dev/null [ "${use_fakedns}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "-d $FAKE_IP_6 -j DROP" 2>/dev/null
[ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "$(dst $black6_set_name) -j DROP" 2>/dev/null [ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "$(dst $black6_set_name) -j DROP" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "$(dst $gfw6_set_name) -j DROP" 2>/dev/null [ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_proxy_drop_ports "$(dst $gfw6_set_name) -j DROP" 2>/dev/null
@@ -430,7 +430,7 @@ load_acl() {
} }
[ "$udp_proxy_drop_ports" != "disable" ] && { [ "$udp_proxy_drop_ports" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "-d $FAKE_IP_6 -j DROP" 2>/dev/null [ "${use_fakedns}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "-d $FAKE_IP_6 -j DROP" 2>/dev/null
[ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "$(dst $black6_set_name) -j DROP" 2>/dev/null [ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "$(dst $black6_set_name) -j DROP" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "$(dst $gfw6_set_name) -j DROP" 2>/dev/null [ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_proxy_drop_ports "$(dst $gfw6_set_name) -j DROP" 2>/dev/null
@@ -469,7 +469,7 @@ load_acl() {
[ "${tcp_proxy_mode}" != "disable" ] && $ipt_n -A PSW $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT) [ "${tcp_proxy_mode}" != "disable" ] && $ipt_n -A PSW $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT)
} }
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null [ "${use_fakedns}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null
[ "${use_proxy_list}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $black6_set_name) $(REDIRECT) 2>/dev/null [ "${use_proxy_list}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $black6_set_name) $(REDIRECT) 2>/dev/null
[ "${use_gfw_list}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $gfw6_set_name) $(REDIRECT) 2>/dev/null [ "${use_gfw_list}" = "1" ] && $ip6t_n -A PSW $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(dst $gfw6_set_name) $(REDIRECT) 2>/dev/null
@@ -486,7 +486,7 @@ load_acl() {
[ "${tcp_proxy_mode}" != "disable" ] && add_port_rules "$ipt_tmp -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "${ipt_j}" [ "${tcp_proxy_mode}" != "disable" ] && add_port_rules "$ipt_tmp -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "${ipt_j}"
[ -n "${is_tproxy}" ] && $ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $tcp_port TPROXY) [ -n "${is_tproxy}" ] && $ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} $(REDIRECT $tcp_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW_RULE 2>/dev/null [ "${use_fakedns}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP_6 -j PSW_RULE 2>/dev/null
[ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "$(dst $black6_set_name) -j PSW_RULE" 2>/dev/null [ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "$(dst $black6_set_name) -j PSW_RULE" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "$(dst $gfw6_set_name) -j PSW_RULE" 2>/dev/null [ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source}" $tcp_redir_ports "$(dst $gfw6_set_name) -j PSW_RULE" 2>/dev/null
@@ -517,7 +517,7 @@ load_acl() {
[ "${udp_proxy_mode}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW_RULE" [ "${udp_proxy_mode}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "-j PSW_RULE"
$ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $udp_port TPROXY) $ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} $(REDIRECT $udp_port TPROXY)
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW_RULE 2>/dev/null [ "${use_fakedns}" = "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP_6 -j PSW_RULE 2>/dev/null
[ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "$(dst $black6_set_name) -j PSW_RULE" 2>/dev/null [ "${use_proxy_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "$(dst $black6_set_name) -j PSW_RULE" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "$(dst $gfw6_set_name) -j PSW_RULE" 2>/dev/null [ "${use_gfw_list}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source}" $udp_redir_ports "$(dst $gfw6_set_name) -j PSW_RULE" 2>/dev/null
@@ -540,7 +540,7 @@ load_acl() {
done done
} }
[ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" = 1 ] && [ "$CLIENT_PROXY" = 1 ] && {
msg="【默认】," msg="【默认】,"
local ipt_tmp=$ipt_n local ipt_tmp=$ipt_n
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m [ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
@@ -586,22 +586,22 @@ load_acl() {
$ip6t_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null $ip6t_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null
fi fi
[ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
[ "${USE_BLOCK_LIST}" = "1" ] && $ipt_m -A PSW $(comment "默认") $(dst $IPSET_BLOCK) -j DROP [ "${USE_BLOCK_LIST}" = "1" ] && $ipt_m -A PSW $(comment "默认") $(dst $IPSET_BLOCK) -j DROP
[ "${USE_DIRECT_LIST}" = "1" ] && $ipt_tmp -A PSW $(comment "默认") $(dst $IPSET_WHITE) -j RETURN [ "${USE_DIRECT_LIST}" = "1" ] && $ipt_tmp -A PSW $(comment "默认") $(dst $IPSET_WHITE) -j RETURN
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_BLOCK_LIST}" = "1" ] && $ip6t_m -A PSW $(comment "默认") $(dst $IPSET_BLOCK6) -j DROP 2>/dev/null [ "${USE_BLOCK_LIST}" = "1" ] && $ip6t_m -A PSW $(comment "默认") $(dst $IPSET_BLOCK6) -j DROP 2>/dev/null
[ "${USE_DIRECT_LIST}" = "1" ] && $ip6t_m -A PSW $(comment "默认") $(dst $IPSET_WHITE6) -j RETURN 2>/dev/null [ "${USE_DIRECT_LIST}" = "1" ] && $ip6t_m -A PSW $(comment "默认") $(dst $IPSET_WHITE6) -j RETURN 2>/dev/null
} }
[ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP_6 -j DROP" [ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP_6 -j DROP"
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK6) -j DROP" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK6) -j DROP"
[ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_GFW6) -j DROP" [ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_GFW6) -j DROP"
[ "${CHN_LIST}" != "0" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_CHN6) $(get_jump_ipt ${CHN_LIST} "-j DROP")" [ "${CHN_LIST}" != "0" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_CHN6) $(get_jump_ipt ${CHN_LIST} "-j DROP")"
[ "${USE_SHUNT_TCP}" = "1" ] && $ip6t_m -A PSW $(comment "默认") -p tcp $TCP_PROXY_DROP_PORTS "$(dst $IPSET_SHUNT6) -j DROP" [ "${USE_SHUNT_TCP}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_SHUNT6) -j DROP"
[ "${TCP_PROXY_MODE}" != "disable" ] && $ip6t_m -A PSW $(comment "默认") -p tcp $TCP_PROXY_DROP_PORTS "-j DROP" [ "${TCP_PROXY_MODE}" != "disable" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-j DROP"
} }
[ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP" [ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP"
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK) -j DROP" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK) -j DROP"
@@ -613,12 +613,12 @@ load_acl() {
} }
[ "$UDP_PROXY_DROP_PORTS" != "disable" ] && { [ "$UDP_PROXY_DROP_PORTS" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-d $FAKE_IP_6 -j DROP" [ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-d $FAKE_IP_6 -j DROP"
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK6) -j DROP" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK6) -j DROP"
[ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_GFW6) -j DROP" [ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_GFW6) -j DROP"
[ "${CHN_LIST}" != "0" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_CHN6) $(get_jump_ipt ${CHN_LIST} "-j DROP")" [ "${CHN_LIST}" != "0" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_CHN6) $(get_jump_ipt ${CHN_LIST} "-j DROP")"
[ "${USE_SHUNT_TCP}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_SHUNT6) -j DROP" [ "${USE_SHUNT_UDP}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "$(dst $IPSET_SHUNT6) -j DROP"
[ "${UDP_PROXY_MODE}" != "disable" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-j DROP" [ "${UDP_PROXY_MODE}" != "disable" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-j DROP"
} }
[ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP" [ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP"
@@ -656,7 +656,7 @@ load_acl() {
[ "${TCP_PROXY_MODE}" != "disable" ] && $ipt_n -A PSW $(comment "默认") -p icmp $(REDIRECT) [ "${TCP_PROXY_MODE}" != "disable" ] && $ipt_n -A PSW $(comment "默认") -p icmp $(REDIRECT)
} }
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT) [ "${USE_FAKEDNS}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp -d $FAKE_IP_6 $(REDIRECT)
[ "${USE_PROXY_LIST}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp $(dst $IPSET_BLACK6) $(REDIRECT) [ "${USE_PROXY_LIST}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp $(dst $IPSET_BLACK6) $(REDIRECT)
[ "${USE_GFW_LIST}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp $(dst $IPSET_GFW6) $(REDIRECT) [ "${USE_GFW_LIST}" = "1" ] && $ip6t_n -A PSW $(comment "默认") -p ipv6-icmp $(dst $IPSET_GFW6) $(REDIRECT)
@@ -673,7 +673,7 @@ load_acl() {
[ "${TCP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_tmp -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "${ipt_j}" [ "${TCP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_tmp -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "${ipt_j}"
[ -n "${is_tproxy}" ]&& $ipt_tmp -A PSW $(comment "默认") -p tcp $(REDIRECT $TCP_REDIR_PORT TPROXY) [ -n "${is_tproxy}" ]&& $ipt_tmp -A PSW $(comment "默认") -p tcp $(REDIRECT $TCP_REDIR_PORT TPROXY)
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW $(comment "默认") -p tcp -d $FAKE_IP_6 -j PSW_RULE [ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW $(comment "默认") -p tcp -d $FAKE_IP_6 -j PSW_RULE
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE"
[ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_GFW6) -j PSW_RULE" [ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_GFW6) -j PSW_RULE"
@@ -692,7 +692,7 @@ load_acl() {
# 加载UDP默认代理模式 # 加载UDP默认代理模式
if [ -n "${UDP_PROXY_MODE}" ]; then if [ -n "${UDP_PROXY_MODE}" ]; then
[ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ] && { [ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ] && {
if is_socks_wrap "$UDP_NODE"; then if is_socks_wrap "$UDP_NODE"; then
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})" msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})"
else else
@@ -707,7 +707,7 @@ load_acl() {
[ "${UDP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "-j PSW_RULE" [ "${UDP_PROXY_MODE}" != "disable" ] && add_port_rules "$ipt_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "-j PSW_RULE"
$ipt_m -A PSW $(comment "默认") -p udp $(REDIRECT $UDP_REDIR_PORT TPROXY) $ipt_m -A PSW $(comment "默认") -p udp $(REDIRECT $UDP_REDIR_PORT TPROXY)
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW $(comment "默认") -p udp -d $FAKE_IP_6 -j PSW_RULE [ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW $(comment "默认") -p udp -d $FAKE_IP_6 -j PSW_RULE
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE"
[ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_GFW6) -j PSW_RULE" [ "${USE_GFW_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW $(comment "默认") -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_GFW6) -j PSW_RULE"
@@ -782,7 +782,7 @@ filter_node() {
local port=$(config_n_get "$node" port) local port=$(config_n_get "$node" port)
local hop=$(config_n_get "$node" hysteria2_hop) local hop=$(config_n_get "$node" hysteria2_hop)
[ -n "$hop" ] && port="${port:+$port,}$hop" [ -n "$hop" ] && port="${port:+$port,}$hop"
[ -z "$address" -o -z "$port" ] && return 1 [ -z "$address" ] || [ -z "$port" ] && return 1
filter_server_port "$address" "$port" "$stream" filter_server_port "$address" "$port" "$stream"
} }
@@ -1145,7 +1145,7 @@ add_firewall_rule() {
[ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE [ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" = 1 ] && {
local ipt_tmp=$ipt_n local ipt_tmp=$ipt_n
if [ -n "${is_tproxy}" ]; then if [ -n "${is_tproxy}" ]; then
ipt_tmp=$ipt_m ipt_tmp=$ipt_m
@@ -1186,7 +1186,7 @@ add_firewall_rule() {
} }
fi fi
[ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ] && {
[ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && {
[ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW_OUTPUT -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP" [ "${USE_FAKEDNS}" = "1" ] && add_port_rules "$ipt_m -A PSW_OUTPUT -p tcp" $TCP_PROXY_DROP_PORTS "-d $FAKE_IP -j DROP"
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ipt_m -A PSW_OUTPUT -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK) -j DROP" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ipt_m -A PSW_OUTPUT -p tcp" $TCP_PROXY_DROP_PORTS "$(dst $IPSET_BLACK) -j DROP"
@@ -1273,7 +1273,7 @@ add_firewall_rule() {
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -p tcp -j PSW_OUTPUT" insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -p tcp -j PSW_OUTPUT"
} }
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ -n "${LOCALHOST_TCP_PROXY_MODE}" ] && { [ -n "${LOCALHOST_TCP_PROXY_MODE}" ] && {
[ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW_RULE [ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW_OUTPUT -p tcp -d $FAKE_IP_6 -j PSW_RULE
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW_OUTPUT -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW_OUTPUT -p tcp" $TCP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE"
@@ -1289,12 +1289,12 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
if [ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ]; then if [ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ]; then
_proxy_udp_access() { _proxy_udp_access() {
[ -n "${2}" ] || return 0 [ -n "${2}" ] || return 0
if echo "${2}" | grep -q -v ':'; then if echo "${2}" | grep -q -v ':'; then
ipset -q test $IPSET_LAN ${2} ipset -q test $IPSET_LAN ${2}
[ $? == 0 ] && { [ $? = 0 ] && {
echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问"
return 0 return 0
} }
@@ -1303,7 +1303,7 @@ add_firewall_rule() {
echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 UDP 转发链" echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 UDP 转发链"
else else
ipset -q test $IPSET_LAN6 ${2} ipset -q test $IPSET_LAN6 ${2}
[ $? == 0 ] && { [ $? = 0 ] && {
echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问"
return 0 return 0
} }
@@ -1325,7 +1325,7 @@ add_firewall_rule() {
$ipt_m -A PSW $(comment "本机") -p udp -i lo -j RETURN $ipt_m -A PSW $(comment "本机") -p udp -i lo -j RETURN
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -p udp -j PSW_OUTPUT" insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -p udp -j PSW_OUTPUT"
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ -n "$LOCALHOST_UDP_PROXY_MODE" ] && { [ -n "$LOCALHOST_UDP_PROXY_MODE" ] && {
[ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW_OUTPUT -p udp -d $FAKE_IP_6 -j PSW_RULE [ "${USE_FAKEDNS}" = "1" ] && $ip6t_m -A PSW_OUTPUT -p udp -d $FAKE_IP_6 -j PSW_RULE
[ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW_OUTPUT -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && add_port_rules "$ip6t_m -A PSW_OUTPUT -p udp" $UDP_REDIR_PORTS "$(dst $IPSET_BLACK6) -j PSW_RULE"
@@ -1425,7 +1425,7 @@ gen_include() {
flush_include flush_include
extract_rules() { extract_rules() {
local _ipt="${ipt}" local _ipt="${ipt}"
[ "$1" == "6" ] && _ipt="${ip6t}" [ "$1" = "6" ] && _ipt="${ip6t}"
[ -z "${_ipt}" ] && return [ -z "${_ipt}" ] && return
echo "*$2" echo "*$2"
@@ -1497,7 +1497,7 @@ get_ip6t_bin() {
} }
start() { start() {
[ "$ENABLED_DEFAULT_ACL" == 0 -a "$ENABLED_ACLS" == 0 ] && return [ "$ENABLED_DEFAULT_ACL" = 0 ] && [ "$ENABLED_ACLS" = 0 ] && return
add_firewall_rule add_firewall_rule
gen_include gen_include
} }
@@ -1505,7 +1505,7 @@ start() {
stop() { stop() {
[ -z "$(command -v echolog)" ] && . "$UTILS_PATH" [ -z "$(command -v echolog)" ] && . "$UTILS_PATH"
del_firewall_rule del_firewall_rule
[ $(config_t_get global flush_set_on_reboot "0") = "1" -o $(config_t_get global flush_set "0") = "1" ] && { [ $(config_t_get global flush_set_on_reboot "0") = "1" ] || [ $(config_t_get global flush_set "0") = "1" ] && {
uci -q delete ${CONFIG}.@global[0].flush_set uci -q delete ${CONFIG}.@global[0].flush_set
uci -q commit ${CONFIG} uci -q commit ${CONFIG}
flush_ipset flush_ipset
@@ -121,13 +121,13 @@ REDIRECT() {
local s="counter redirect" local s="counter redirect"
[ -n "$1" ] && { [ -n "$1" ] && {
local s="$s to :$1" local s="$s to :$1"
[ "$2" == "TPROXY" ] && { [ "$2" = "TPROXY" ] && {
s="counter meta mark ${FWMARK} tproxy to :$1" s="counter meta mark ${FWMARK} tproxy to :$1"
} }
[ "$2" == "TPROXY4" ] && { [ "$2" = "TPROXY4" ] && {
s="counter meta mark ${FWMARK} tproxy ip to :$1" s="counter meta mark ${FWMARK} tproxy ip to :$1"
} }
[ "$2" == "TPROXY6" ] && { [ "$2" = "TPROXY6" ] && {
s="counter meta mark ${FWMARK} tproxy ip6 to :$1" s="counter meta mark ${FWMARK} tproxy ip6 to :$1"
} }
} }
@@ -175,25 +175,28 @@ insert_nftset() {
*) suffix=" timeout $timeout_argument" ;; *) suffix=" timeout $timeout_argument" ;;
esac esac
{ {
if [ $# -gt 0 ]; then if [ $# -gt 0 ] && [ $# -le 1000 ]; then
printf "%s\n" "$@" printf "%s\n" "$@"
elif [ $# -gt 1000 ]; then
printf "%s\n" "$*"
else else
cat cat
fi | awk -v s="$suffix" -v n="$nftset_name" -v t="$NFTABLE_NAME" ' fi | awk -v s="$suffix" -v n="$nftset_name" -v t="$NFTABLE_NAME" '
BEGIN { BEGIN {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = ""
} }
$0 != "" { $0 != "" {
if (first == 0) { if (!first) {
printf "add element %s %s { \n", t, n; printf "add element %s %s { \n", t, n
first = 1; first = 1;
} else { } else {
printf ",\n"; print ",\n"
} }
printf "%s%s", $0, s; print $0 s
} }
END { END {
if (first == 1) printf "\n }\n"; if (first) print "\n }\n"
} }
' '
} | nft -f - } | nft -f -
@@ -211,7 +214,7 @@ gen_nftset() {
local gc_interval_time="1h" local gc_interval_time="1h"
if ! nft list set $NFTABLE_NAME $nftset_name >/dev/null 2>&1; then if ! nft list set $NFTABLE_NAME $nftset_name >/dev/null 2>&1; then
if [ "$timeout_argument_set" == "0" ]; then if [ "$timeout_argument_set" = "0" ]; then
nft "add set $NFTABLE_NAME $nftset_name { type $ip_type; flags interval, timeout; auto-merge; }" nft "add set $NFTABLE_NAME $nftset_name { type $ip_type; flags interval, timeout; auto-merge; }"
else else
nft "add set $NFTABLE_NAME $nftset_name { type $ip_type; flags interval, timeout; timeout $timeout_argument_set; gc-interval $gc_interval_time; auto-merge; }" nft "add set $NFTABLE_NAME $nftset_name { type $ip_type; flags interval, timeout; timeout $timeout_argument_set; gc-interval $gc_interval_time; auto-merge; }"
@@ -236,11 +239,11 @@ get_jump_nft() {
} }
load_acl() { load_acl() {
([ "$ENABLED_ACLS" == 1 ] || ([ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ])) && echolog " - 访问控制:" { [ "$ENABLED_ACLS" = "1" ] || { [ "$ENABLED_DEFAULT_ACL" = "1" ] && [ "$CLIENT_PROXY" = "1" ]; }; } && echolog " - 访问控制:"
[ "$ENABLED_ACLS" == 1 ] && { [ "$ENABLED_ACLS" = 1 ] && {
acl_app acl_app
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-) eval "$(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)"
tcp_no_redir_ports=${tcp_no_redir_ports:-default} tcp_no_redir_ports=${tcp_no_redir_ports:-default}
udp_no_redir_ports=${udp_no_redir_ports:-default} udp_no_redir_ports=${udp_no_redir_ports:-default}
@@ -409,7 +412,7 @@ load_acl() {
gen_nftset $gfw6_set_name ipv6_addr "2d" 0 gen_nftset $gfw6_set_name ipv6_addr "2d" 0
} }
} }
[ "${use_shunt_tcp}" = "1" -o "${use_shunt_udp}" = "1" ] && { [ "${use_shunt_tcp}" = "1" ] || [ "${use_shunt_udp}" = "1" ] && {
[ "${use_global_config}" = "0" ] && { [ "${use_global_config}" = "0" ] && {
shunt_set_name="psw_${sid}_shunt" shunt_set_name="psw_${sid}_shunt"
shunt6_set_name="psw_${sid}_shunt6" shunt6_set_name="psw_${sid}_shunt6"
@@ -433,18 +436,18 @@ load_acl() {
[ -z "$(get_cache_var "ACL_${sid}_tcp_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。" [ -z "$(get_cache_var "ACL_${sid}_tcp_default")" ] && echolog " - ${msg}使用与全局配置不相同节点,已将DNS强制重定向到专用 DNS 服务器。"
fi fi
[ -n "$tcp_port" -o -n "$udp_port" ] && { [ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
[ "${use_block_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_BLOCK counter drop comment \"$remarks\"" [ "${use_block_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_BLOCK counter drop comment \"$remarks\""
[ "${use_block_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_BLOCK counter drop comment \"$remarks\"" [ "${use_block_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_BLOCK counter drop comment \"$remarks\""
[ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_WHITE counter return comment \"$remarks\"" [ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ${_ipt_source} ip daddr @$NFTSET_WHITE counter return comment \"$remarks\""
[ "${use_direct_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_WHITE counter return comment \"$remarks\"" [ "${use_direct_list}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ${_ipt_source} ip daddr @$NFTSET_WHITE counter return comment \"$remarks\""
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_block_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ${_ipt_source} ip6 daddr @$NFTSET_BLOCK6 counter drop comment \"$remarks\"" [ "${use_block_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ${_ipt_source} ip6 daddr @$NFTSET_BLOCK6 counter drop comment \"$remarks\""
[ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ${_ipt_source} ip6 daddr @$NFTSET_WHITE6 counter return comment \"$remarks\"" [ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ${_ipt_source} ip6 daddr @$NFTSET_WHITE6 counter return comment \"$remarks\""
} }
[ "$tcp_proxy_drop_ports" != "disable" ] && { [ "$tcp_proxy_drop_ports" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"$remarks\"" 2>/dev/null [ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"$remarks\"" 2>/dev/null
[ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr @$black6_set_name counter drop comment \"$remarks\"" 2>/dev/null [ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr @$black6_set_name counter drop comment \"$remarks\"" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr @$gfw6_set_name counter drop comment \"$remarks\"" 2>/dev/null [ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_proxy_drop_ports "tcp dport") ip6 daddr @$gfw6_set_name counter drop comment \"$remarks\"" 2>/dev/null
@@ -462,7 +465,7 @@ load_acl() {
} }
[ "$udp_proxy_drop_ports" != "disable" ] && { [ "$udp_proxy_drop_ports" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"$remarks\"" 2>/dev/null [ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"$remarks\"" 2>/dev/null
[ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr @$black6_set_name counter drop comment \"$remarks\"" 2>/dev/null [ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr @$black6_set_name counter drop comment \"$remarks\"" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr @$gfw6_set_name counter drop comment \"$remarks\"" 2>/dev/null [ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_proxy_drop_ports "udp dport") ip6 daddr @$gfw6_set_name counter drop comment \"$remarks\"" 2>/dev/null
@@ -504,7 +507,7 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip protocol icmp ${_ipt_source} return comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip protocol icmp ${_ipt_source} return comment \"$remarks\""
} }
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$NFTSET_WHITE6 counter return comment \"$remarks\"" 2>/dev/null [ "${use_direct_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$NFTSET_WHITE6 counter return comment \"$remarks\"" 2>/dev/null
[ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"$remarks\"" 2>/dev/null [ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"$remarks\"" 2>/dev/null
[ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$black6_set_name $(REDIRECT) comment \"$remarks\"" 2>/dev/null [ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ${_ipt_source} ip6 daddr @$black6_set_name $(REDIRECT) comment \"$remarks\"" 2>/dev/null
@@ -523,7 +526,7 @@ load_acl() {
[ "${tcp_proxy_mode}" != "disable" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ${nft_j} comment \"$remarks\"" [ "${tcp_proxy_mode}" != "disable" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ${nft_j} comment \"$remarks\""
[ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(REDIRECT $tcp_port TPROXY4) comment \"$remarks\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp ${_ipt_source} $(REDIRECT $tcp_port TPROXY4) comment \"$remarks\""
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"$remarks\"" [ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"$remarks\""
[ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr @$black6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null [ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr @$black6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr @$gfw6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null [ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} $(factor $tcp_redir_ports "tcp dport") ip6 daddr @$gfw6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null
@@ -554,7 +557,7 @@ load_acl() {
[ "${udp_proxy_mode}" != "disable" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW_RULE comment \"$remarks\"" [ "${udp_proxy_mode}" != "disable" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") counter jump PSW_RULE comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} $(REDIRECT $udp_port TPROXY4) comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} $(REDIRECT $udp_port TPROXY4) comment \"$remarks\""
[ "$PROXY_IPV6" == "1" ] && [ "$_ipv4" != "1" ] && { [ "$PROXY_IPV6" = "1" ] && [ "$_ipv4" != "1" ] && {
[ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"$remarks\"" [ "${use_fakedns}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"$remarks\""
[ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr @$black6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null [ "${use_proxy_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr @$black6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null
[ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr @$gfw6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null [ "${use_gfw_list}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} $(factor $udp_redir_ports "udp dport") ip6 daddr @$gfw6_set_name counter jump PSW_RULE comment \"$remarks\"" 2>/dev/null
@@ -577,7 +580,7 @@ load_acl() {
done done
} }
[ "$ENABLED_DEFAULT_ACL" == 1 ] && [ "$CLIENT_PROXY" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" = 1 ] && [ "$CLIENT_PROXY" = 1 ] && {
msg="【默认】," msg="【默认】,"
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\"" nft "add rule $NFTABLE_NAME $nft_prerouting_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return comment \"默认\""
@@ -620,18 +623,18 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\"" nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\""
fi fi
[ -n "${TCP_PROXY_MODE}" -o -n "${UDP_PROXY_MODE}" ] && { [ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
[ "${USE_BLOCK_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_BLOCK counter drop comment \"默认\"" [ "${USE_BLOCK_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_BLOCK counter drop comment \"默认\""
[ "${USE_BLOCK_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_BLOCK counter drop comment \"默认\"" [ "${USE_BLOCK_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_BLOCK counter drop comment \"默认\""
[ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_WHITE counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE ip daddr @$NFTSET_WHITE counter return comment \"默认\""
[ "${USE_DIRECT_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_WHITE counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW_NAT ip daddr @$NFTSET_WHITE counter return comment \"默认\""
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_BLOCK_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ip6 daddr @$NFTSET_BLOCK6 counter drop comment \"默认\"" [ "${USE_BLOCK_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ip6 daddr @$NFTSET_BLOCK6 counter drop comment \"默认\""
[ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ip6 daddr @$NFTSET_WHITE6 counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 ip6 daddr @$NFTSET_WHITE6 counter return comment \"默认\""
} }
[ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"默认\"" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"默认\""
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr @$NFTSET_BLACK6 counter drop comment \"默认\"" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr @$NFTSET_BLACK6 counter drop comment \"默认\""
[ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr @$NFTSET_GFW6 counter drop comment \"默认\"" [ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_PROXY_DROP_PORTS "tcp dport") ip6 daddr @$NFTSET_GFW6 counter drop comment \"默认\""
@@ -650,7 +653,7 @@ load_acl() {
} }
[ "$UDP_PROXY_DROP_PORTS" != "disable" ] && { [ "$UDP_PROXY_DROP_PORTS" != "disable" ] && {
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"默认\"" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr $FAKE_IP_6 counter drop comment \"默认\""
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr @$NFTSET_BLACK6 counter drop comment \"默认\"" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr @$NFTSET_BLACK6 counter drop comment \"默认\""
[ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr @$NFTSET_GFW6 counter drop comment \"默认\"" [ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_PROXY_DROP_PORTS "udp dport") ip6 daddr @$NFTSET_GFW6 counter drop comment \"默认\""
@@ -697,7 +700,7 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip protocol icmp return comment \"默认\"" nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip protocol icmp return comment \"默认\""
} }
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip6 daddr @$NFTSET_WHITE6 counter return comment \"默认\"" [ "${USE_DIRECT_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT ip6 daddr @$NFTSET_WHITE6 counter return comment \"默认\""
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"默认\"" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr $FAKE_IP_6 $(REDIRECT) comment \"默认\""
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr @$NFTSET_BLACK6 $(REDIRECT) comment \"默认\"" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT meta l4proto icmpv6 ip6 daddr @$NFTSET_BLACK6 $(REDIRECT) comment \"默认\""
@@ -717,7 +720,7 @@ load_acl() {
[ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(REDIRECT $TCP_REDIR_PORT TPROXY4) comment \"默认\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp $(REDIRECT $TCP_REDIR_PORT TPROXY4) comment \"默认\""
nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp counter return comment \"默认\"" nft "add rule $NFTABLE_NAME $nft_chain ip protocol tcp counter return comment \"默认\""
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"默认\"" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"默认\""
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr @$NFTSET_BLACK6 counter jump PSW_RULE comment \"默认\"" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr @$NFTSET_BLACK6 counter jump PSW_RULE comment \"默认\""
[ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr @$NFTSET_GFW6 counter jump PSW_RULE comment \"默认\"" [ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp $(factor $TCP_REDIR_PORTS "tcp dport") ip6 daddr @$NFTSET_GFW6 counter jump PSW_RULE comment \"默认\""
@@ -734,7 +737,7 @@ load_acl() {
# 加载UDP默认代理模式 # 加载UDP默认代理模式
if [ -n "${UDP_PROXY_MODE}" ]; then if [ -n "${UDP_PROXY_MODE}" ]; then
[ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ] && { [ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ] && {
if is_socks_wrap "$UDP_NODE"; then if is_socks_wrap "$UDP_NODE"; then
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})" msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})"
else else
@@ -750,7 +753,7 @@ load_acl() {
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp $(REDIRECT $UDP_REDIR_PORT TPROXY4) comment \"默认\"" nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp $(REDIRECT $UDP_REDIR_PORT TPROXY4) comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp counter return comment \"默认\"" nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp counter return comment \"默认\""
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"默认\"" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE comment \"默认\""
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr @$NFTSET_BLACK6 counter jump PSW_RULE comment \"默认\"" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr @$NFTSET_BLACK6 counter jump PSW_RULE comment \"默认\""
[ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr @$NFTSET_GFW6 counter jump PSW_RULE comment \"默认\"" [ "${USE_GFW_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp $(factor $UDP_REDIR_PORTS "udp dport") ip6 daddr @$NFTSET_GFW6 counter jump PSW_RULE comment \"默认\""
@@ -823,7 +826,7 @@ filter_node() {
local port=$(config_n_get "$node" port) local port=$(config_n_get "$node" port)
local hop=$(config_n_get "$node" hysteria2_hop) local hop=$(config_n_get "$node" hysteria2_hop)
[ -n "$hop" ] && port="${port:+$port,}$hop" [ -n "$hop" ] && port="${port:+$port,}$hop"
[ -z "$address" -o -z "$port" ] && return 1 [ -z "$address" ] || [ -z "$port" ] && return 1
filter_server_port "$address" "$port" "$stream" filter_server_port "$address" "$port" "$stream"
} }
@@ -1201,7 +1204,7 @@ add_firewall_rule() {
} }
# jump chains # jump chains
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto {ipv6} counter jump PSW_MANGLE_V6" nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto {ipv6} counter jump PSW_MANGLE_V6"
nft "add rule $NFTABLE_NAME mangle_output meta nfproto {ipv6} counter jump PSW_OUTPUT_MANGLE_V6 comment \"PSW_OUTPUT_MANGLE\"" nft "add rule $NFTABLE_NAME mangle_output meta nfproto {ipv6} counter jump PSW_OUTPUT_MANGLE_V6 comment \"PSW_OUTPUT_MANGLE\""
@@ -1213,7 +1216,7 @@ add_firewall_rule() {
[ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE [ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE
[ "$ENABLED_DEFAULT_ACL" == 1 ] && { [ "$ENABLED_DEFAULT_ACL" = 1 ] && {
msg="【路由器本机】," msg="【路由器本机】,"
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && { [ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
@@ -1247,7 +1250,7 @@ add_firewall_rule() {
} }
fi fi
[ -n "${LOCALHOST_TCP_PROXY_MODE}" -o -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ] && {
[ "$TCP_PROXY_DROP_PORTS" != "disable" ] && { [ "$TCP_PROXY_DROP_PORTS" != "disable" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr $FAKE_IP $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop [ "${USE_FAKEDNS}" = "1" ] && nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr $FAKE_IP $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop
[ "${USE_PROXY_LIST}" = "1" ] && nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr @$NFTSET_BLACK $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop [ "${USE_PROXY_LIST}" = "1" ] && nft add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp ip daddr @$NFTSET_BLACK $(factor $TCP_PROXY_DROP_PORTS "tcp dport") counter drop
@@ -1297,7 +1300,7 @@ add_firewall_rule() {
echolog " - [$?]将上游 DNS 服务器 [${2}]:${3} 加入到路由器自身代理的 TCP 转发链,请确保您的节点支持IPv6,并开启IPv6透明代理!" echolog " - [$?]将上游 DNS 服务器 [${2}]:${3} 加入到路由器自身代理的 TCP 转发链,请确保您的节点支持IPv6,并开启IPv6透明代理!"
fi fi
} }
[ "$TCP_PROXY_DNS" == 1 ] && hosts_foreach REMOTE_DNS _proxy_tcp_access 53 [ "$TCP_PROXY_DNS" = 1 ] && hosts_foreach REMOTE_DNS _proxy_tcp_access 53
[ "$accept_icmp" = "1" ] && { [ "$accept_icmp" = "1" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect"
@@ -1340,7 +1343,7 @@ add_firewall_rule() {
[ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME mangle_output ip protocol tcp counter jump PSW_OUTPUT_MANGLE comment \"PSW_OUTPUT_MANGLE\"" [ -n "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME mangle_output ip protocol tcp counter jump PSW_OUTPUT_MANGLE comment \"PSW_OUTPUT_MANGLE\""
[ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip protocol tcp counter jump PSW_OUTPUT_NAT" [ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME nat_output ip protocol tcp counter jump PSW_OUTPUT_NAT"
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ -n "${LOCALHOST_TCP_PROXY_MODE}" ] && { [ -n "${LOCALHOST_TCP_PROXY_MODE}" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE"
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr @$NFTSET_BLACK6 $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp ip6 daddr @$NFTSET_BLACK6 $(factor $TCP_REDIR_PORTS "tcp dport") counter jump PSW_RULE"
@@ -1355,12 +1358,12 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
if [ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ]; then if [ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ]; then
_proxy_udp_access() { _proxy_udp_access() {
[ -n "${2}" ] || return 0 [ -n "${2}" ] || return 0
if echo "${2}" | grep -q -v ':'; then if echo "${2}" | grep -q -v ':'; then
nft "get element $NFTABLE_NAME $NFTSET_LAN {${2}}" &>/dev/null nft "get element $NFTABLE_NAME $NFTSET_LAN {${2}}" &>/dev/null
[ $? == 0 ] && { [ $? = 0 ] && {
echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问"
return 0 return 0
} }
@@ -1369,7 +1372,7 @@ add_firewall_rule() {
echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 UDP 转发链" echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 UDP 转发链"
else else
nft "get element $NFTABLE_NAME $NFTSET_LAN6 {${2}}" &>/dev/null nft "get element $NFTABLE_NAME $NFTSET_LAN6 {${2}}" &>/dev/null
[ $? == 0 ] && { [ $? = 0 ] && {
echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问"
return 0 return 0
} }
@@ -1391,7 +1394,7 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp iif lo counter return comment \"本机\"" nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp iif lo counter return comment \"本机\""
nft "add rule $NFTABLE_NAME mangle_output ip protocol udp counter jump PSW_OUTPUT_MANGLE comment \"PSW_OUTPUT_MANGLE\"" nft "add rule $NFTABLE_NAME mangle_output ip protocol udp counter jump PSW_OUTPUT_MANGLE comment \"PSW_OUTPUT_MANGLE\""
[ "$PROXY_IPV6" == "1" ] && { [ "$PROXY_IPV6" = "1" ] && {
[ -n "${LOCALHOST_UDP_PROXY_MODE}" ] && { [ -n "${LOCALHOST_UDP_PROXY_MODE}" ] && {
[ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE" [ "${USE_FAKEDNS}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr $FAKE_IP_6 counter jump PSW_RULE"
[ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr @$NFTSET_BLACK6 $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW_RULE" [ "${USE_PROXY_LIST}" = "1" ] && nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr @$NFTSET_BLACK6 $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW_RULE"
@@ -1512,7 +1515,7 @@ gen_include() {
} }
start() { start() {
[ "$ENABLED_DEFAULT_ACL" == 0 -a "$ENABLED_ACLS" == 0 ] && return [ "$ENABLED_DEFAULT_ACL" = 0 ] && [ "$ENABLED_ACLS" = 0 ] && return
add_firewall_rule add_firewall_rule
gen_include gen_include
} }
@@ -1520,7 +1523,7 @@ start() {
stop() { stop() {
[ -z "$(command -v echolog)" ] && . "$UTILS_PATH" [ -z "$(command -v echolog)" ] && . "$UTILS_PATH"
del_firewall_rule del_firewall_rule
[ $(config_t_get global flush_set_on_reboot "0") = "1" -o $(config_t_get global flush_set "0") = "1" ] && { [ $(config_t_get global flush_set_on_reboot "0") = "1" ] || [ $(config_t_get global flush_set "0") = "1" ] && {
uci -q delete ${CONFIG}.@global[0].flush_set uci -q delete ${CONFIG}.@global[0].flush_set
uci -q commit ${CONFIG} uci -q commit ${CONFIG}
#flush_table #flush_table
@@ -18,24 +18,6 @@ do
if [ "$CFG_UPDATE_INT" -ne 0 ]; then if [ "$CFG_UPDATE_INT" -ne 0 ]; then
stop_week_mode=$(config_t_get global_delay stop_week_mode)
stop_interval_mode=$(config_t_get global_delay stop_interval_mode)
stop_interval_mode=$(expr "$stop_interval_mode" \* 60)
if [ -n "$stop_week_mode" ]; then
[ "$stop_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG stop > /dev/null 2>&1 & }
}
fi
start_week_mode=$(config_t_get global_delay start_week_mode)
start_interval_mode=$(config_t_get global_delay start_interval_mode)
start_interval_mode=$(expr "$start_interval_mode" \* 60)
if [ -n "$start_week_mode" ]; then
[ "$start_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && { /etc/init.d/$CONFIG start > /dev/null 2>&1 & }
}
fi
restart_week_mode=$(config_t_get global_delay restart_week_mode) restart_week_mode=$(config_t_get global_delay restart_week_mode)
restart_interval_mode=$(config_t_get global_delay restart_interval_mode) restart_interval_mode=$(config_t_get global_delay restart_interval_mode)
restart_interval_mode=$(expr "$restart_interval_mode" \* 60) restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
@@ -45,36 +27,35 @@ do
} }
fi fi
autoupdate=$(config_t_get global_rules auto_update) rules_update_week_mode=$(config_t_get global_rules update_week_mode)
weekupdate=$(config_t_get global_rules week_update) rules_update_interval_mode=$(config_t_get global_rules update_interval_mode)
hourupdate=$(config_t_get global_rules interval_update) rules_update_interval_mode=$(expr "$rules_update_interval_mode" \* 60)
hourupdate=$(expr "$hourupdate" \* 60) if [ -n "$rules_update_week_mode" ]; then
if [ "$autoupdate" = "1" ]; then [ "$rules_update_week_mode" = "8" ] && {
[ "$weekupdate" = "8" ] && { [ "$(expr "$CFG_UPDATE_INT" % "$rules_update_interval_mode")" -eq 0 ] && { lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 & }
[ "$(expr "$CFG_UPDATE_INT" % "$hourupdate")" -eq 0 ] && { lua $APP_PATH/rule_update.lua log all cron > /dev/null 2>&1 & }
} }
fi fi
TMP_SUB_PATH=$TMP_PATH/sub_tasks TMP_SUB_PATH=$TMP_PATH/sub_tasks
mkdir -p $TMP_SUB_PATH mkdir -p $TMP_SUB_PATH
for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
if [ "$(config_n_get $item auto_update 0)" = "1" ]; then sub_update_week_mode=$(config_n_get $item update_week_mode)
if [ -n "$sub_update_week_mode" ]; then
cfgid=$(uci show ${CONFIG}.$item | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1) cfgid=$(uci show ${CONFIG}.$item | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1)
remark=$(config_n_get $item remark) remark=$(config_n_get $item remark)
week_update=$(config_n_get $item week_update) sub_update_interval_mode=$(config_n_get $item update_interval_mode)
hour_update=$(config_n_get $item interval_update) echo "$cfgid" >> $TMP_SUB_PATH/${sub_update_week_mode}_${sub_update_interval_mode}
echo "$cfgid" >> $TMP_SUB_PATH/${week_update}_${hour_update}
fi fi
done done
[ -d "${TMP_SUB_PATH}" ] && { [ -d "${TMP_SUB_PATH}" ] && {
for name in $(ls ${TMP_SUB_PATH}); do for name in $(ls ${TMP_SUB_PATH}); do
week_update=$(echo $name | awk -F '_' '{print $1}') sub_update_week_mode=${name%_*}
hour_update=$(echo $name | awk -F '_' '{print $2}') sub_update_interval_mode=${name#*_}
hour_update=$(expr "$hour_update" \* 60) sub_update_interval_mode=$(expr "$sub_update_interval_mode" \* 60)
cfgids=$(echo -n $(cat ${TMP_SUB_PATH}/${name}) | sed 's# #,#g') cfgids=$(echo -n $(cat ${TMP_SUB_PATH}/${name}) | sed 's# #,#g')
[ "$week_update" = "8" ] && { [ "$sub_update_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$hour_update")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & } [ "$(expr "$CFG_UPDATE_INT" % "$sub_update_interval_mode")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & }
} }
done done
@@ -89,7 +89,7 @@ get_host_ip() {
[ -z "$count" ] && count=3 [ -z "$count" ] && count=3
local isip="" local isip=""
local ip="" local ip=""
if [ "$1" == "ipv6" ]; then if [ "$1" = "ipv6" ]; then
isip=$(echo $host | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") isip=$(echo $host | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}")
if [ -n "$isip" ]; then if [ -n "$isip" ]; then
ip=$(echo "$host" | tr -d '[]') ip=$(echo "$host" | tr -d '[]')
@@ -100,7 +100,7 @@ get_host_ip() {
fi fi
[ -z "$isip" ] && { [ -z "$isip" ] && {
local t=4 local t=4
[ "$1" == "ipv6" ] && t=6 [ "$1" = "ipv6" ] && t=6
local vpsrip=$(resolveip -$t -t $count $host | awk 'NR==1{print}') local vpsrip=$(resolveip -$t -t $count $host | awk 'NR==1{print}')
ip=$vpsrip ip=$vpsrip
} }
@@ -113,7 +113,7 @@ get_node_host_ip() {
[ -n "$address" ] && { [ -n "$address" ] && {
local use_ipv6=$(config_n_get $1 use_ipv6) local use_ipv6=$(config_n_get $1 use_ipv6)
local network_type="ipv4" local network_type="ipv4"
[ "$use_ipv6" == "1" ] && network_type="ipv6" [ "$use_ipv6" = "1" ] && network_type="ipv6"
ip=$(get_host_ip $network_type $address) ip=$(get_host_ip $network_type $address)
} }
echo $ip echo $ip
@@ -220,7 +220,7 @@ get_first_dns() {
echo "${2}#${3}" echo "${2}#${3}"
return 1 return 1
} }
eval "hosts_foreach \"${__hosts_val}\" __first \"$@\"" hosts_foreach "${__hosts_val}" __first "$@"
} }
get_last_dns() { get_last_dns() {
@@ -231,8 +231,8 @@ get_last_dns() {
__last="${2}#${3}" __last="${2}#${3}"
__first=${__first:-${__last}} __first=${__first:-${__last}}
} }
eval "hosts_foreach \"${__hosts_val}\" __every \"$@\"" hosts_foreach "${__hosts_val}" __first "$@"
[ "${__first}" == "${__last}" ] || echo "${__last}" [ "${__first}" = "${__last}" ] || echo "${__last}"
} }
normalize_dns() { normalize_dns() {
@@ -319,7 +319,7 @@ get_new_port() {
fi fi
fi fi
fi fi
[ "$port" -lt $min_port -o "$port" -gt $max_port ] && port=$default_start_port [ "$port" -lt $min_port ] || [ "$port" -gt $max_port ] && port=$default_start_port
local start_port="$port" local start_port="$port"
while :; do while :; do
if [ "$(check_port_exists "$port" "$protocol")" = 0 ]; then if [ "$(check_port_exists "$port" "$protocol")" = 0 ]; then
@@ -346,9 +346,11 @@ check_ver() {
local version1="$1" local version1="$1"
local version2="$2" local version2="$2"
local i v1 v1_1 v1_2 v1_3 v2 v2_1 v2_2 v2_3 local i v1 v1_1 v1_2 v1_3 v2 v2_1 v2_2 v2_3
IFS='.'; set -- $version1; v1_1=${1:-0}; v1_2=${2:-0}; v1_3=${3:-0} local old_ifs="$IFS"
IFS='.'; set -- $version2; v2_1=${1:-0}; v2_2=${2:-0}; v2_3=${3:-0} IFS='.'
IFS= set -- $version1; v1_1=${1:-0}; v1_2=${2:-0}; v1_3=${3:-0}
set -- $version2; v2_1=${1:-0}; v2_2=${2:-0}; v2_3=${3:-0}
IFS="$old_ifs"
for i in 1 2 3; do for i in 1 2 3; do
eval v1=\$v1_$i eval v1=\$v1_$i
eval v2=\$v2_$i eval v2=\$v2_$i
@@ -481,8 +483,10 @@ ln_run() {
if [ -z "$persist_log_path" ] && [ "$sys_log" != "1" ]; then if [ -z "$persist_log_path" ] && [ "$sys_log" != "1" ]; then
${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 & ${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 &
else else
[ "${output: -1, -7}" == "TCP.log" ] && local protocol="TCP" case "$output" in
[ "${output: -1, -7}" == "UDP.log" ] && local protocol="UDP" *TCP.log) local protocol="TCP" ;;
*UDP.log) local protocol="UDP" ;;
esac
if [ -n "${persist_log_path}" ]; then if [ -n "${persist_log_path}" ]; then
mkdir -p ${persist_log_path} mkdir -p ${persist_log_path}
local log_file=${persist_log_path}/passwall_${protocol}_${ln_name}_$(date '+%F').log local log_file=${persist_log_path}/passwall_${protocol}_${ln_name}_$(date '+%F').log
@@ -490,7 +494,7 @@ ln_run() {
${file_func:-echolog " - ${ln_name}"} "$@" >> ${log_file} 2>&1 & ${file_func:-echolog " - ${ln_name}"} "$@" >> ${log_file} 2>&1 &
sys_log=0 sys_log=0
fi fi
if [ "${sys_log}" == "1" ]; then if [ "${sys_log}" = "1" ]; then
echolog "记录 ${ln_name}_${protocol} 到系统日志" echolog "记录 ${ln_name}_${protocol} 到系统日志"
${file_func:-echolog " - ${ln_name}"} "$@" 2>&1 | logger -t PASSWALL_${protocol}_${ln_name} & ${file_func:-echolog " - ${ln_name}"} "$@" 2>&1 | logger -t PASSWALL_${protocol}_${ln_name} &
fi fi
+1 -1
View File
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2 PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.7.12 PKG_VERSION:=26.7.12
PKG_RELEASE:=60 PKG_RELEASE:=61
PKG_PO_VERSION:=$(PKG_VERSION) PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \ PKG_CONFIG_DEPENDS:= \
@@ -152,7 +152,9 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o:depends({ [_n("node_add_mode")] = "batch" }) o:depends({ [_n("node_add_mode")] = "batch" })
local descrStr = "Example: <code>^A && B && !C && D$</code><br>" local descrStr = "Example: <code>^A && B && !C && D$</code><br>"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
descrStr = descrStr .. "Conditions are joined by <code>&&</code>, and their order does not affect the result." descrStr = descrStr .. "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
descrStr = descrStr .. "Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
descrStr = descrStr .. "Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
o.description = translate(descrStr) o.description = translate(descrStr)
o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy")) o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
@@ -154,7 +154,9 @@ if load_urltest_options then -- [[ URLTest Start ]]
o:depends({ [_n("node_add_mode")] = "batch" }) o:depends({ [_n("node_add_mode")] = "batch" })
local descrStr = "Example: <code>^A && B && !C && D$</code><br>" local descrStr = "Example: <code>^A && B && !C && D$</code><br>"
descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" descrStr = descrStr .. "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
descrStr = descrStr .. "Conditions are joined by <code>&&</code>, and their order does not affect the result." descrStr = descrStr .. "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
descrStr = descrStr .. "Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
descrStr = descrStr .. "Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
o.description = translate(descrStr) o.description = translate(descrStr)
o = s:option(Value, _n("urltest_url"), translate("Probe URL")) o = s:option(Value, _n("urltest_url"), translate("Probe URL"))
+27 -7
View File
@@ -1521,11 +1521,22 @@ end
function match_node_rule(name, rule) function match_node_rule(name, rule)
if not name then return false end if not name then return false end
if not rule or rule == "" then return true end if not rule or rule == "" then return true end
-- split rule by || into OR groups
local function split_or(expr)
local t = {}
for part in (expr .. "||"):gmatch("(.-)%|%|") do
part = trim(part)
if part ~= "" then
table.insert(t, part)
end
end
return t
end
-- split rule by && -- split rule by &&
local function split_and(expr) local function split_and(expr)
local t = {} local t = {}
for part in expr:gmatch("[^&]+") do for part in (expr .. "&&"):gmatch("(.-)%&%&") do
part = part:gsub("^%s+", ""):gsub("%s+$", "") part = trim(part)
if part ~= "" then if part ~= "" then
table.insert(t, part) table.insert(t, part)
end end
@@ -1556,13 +1567,22 @@ function match_node_rule(name, rule)
-- contains -- contains
return str:find(cond, 1, true) ~= nil return str:find(cond, 1, true) ~= nil
end end
-- AND logic -- check if all conditions in AND group match
for _, cond in ipairs(split_and(rule)) do local function match_and_group(str, group_expr)
if not match_cond(name, cond) then for _, cond in ipairs(split_and(group_expr)) do
return false if not match_cond(str, cond) then
return false
end
end
return true
end
-- OR logic: return true if any group matches
for _, group in ipairs(split_or(rule)) do
if match_and_group(name, group) then
return true
end end
end end
return true return false
end end
function get_core(field, candidates) function get_core(field, candidates)
+6 -2
View File
@@ -394,11 +394,15 @@ msgstr "قوانین تطبیق گره"
msgid "" msgid ""
"Example: <code>^A && B && !C && D$</code><br>" "Example: <code>^A && B && !C && D$</code><br>"
"This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
"Conditions are joined by <code>&&</code>, and their order does not affect the result." "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
"Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
"Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
msgstr "" msgstr ""
"مثال: <code>^A && B && !C && D$</code><br>" "مثال: <code>^A && B && !C && D$</code><br>"
"این بدان معناست که توضیحات گره باید با A شروع شود (^)، شامل B باشد، فاقد C باشد (!)، و با D پایان یابد ($).<br>" "این بدان معناست که توضیحات گره باید با A شروع شود (^)، شامل B باشد، فاقد C باشد (!)، و با D پایان یابد ($).<br>"
"شرط‌ها با <code>&&</code> به هم متصل می‌شوند و ترتیب آنها تاثیری در نتیجه ندارد." "شرط‌ها با <code>&&</code> (و) به هم متصل می‌شوند و ترتیب آنها تاثیری در نتیجه ندارد.<br>"
"چندین گروه شرط می‌توانند با <code>||</code> (یا) از هم جدا شوند؛ اگر هر گروهی مطابقت داشته باشد، نتیجه موفقیت‌آمیز است.<br>"
"مثال: <code>A && B || C && D</code> به معنای (A و B) یا (C و D) است."
msgid "Balancing Strategy" msgid "Balancing Strategy"
+6 -2
View File
@@ -391,11 +391,15 @@ msgstr "Правила отбора узлов"
msgid "" msgid ""
"Example: <code>^A && B && !C && D$</code><br>" "Example: <code>^A && B && !C && D$</code><br>"
"This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
"Conditions are joined by <code>&&</code>, and their order does not affect the result." "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
"Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
"Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
msgstr "" msgstr ""
"Пример: <code>^A && B && !C && D$</code><br>" "Пример: <code>^A && B && !C && D$</code><br>"
"Описание узла должно: начинаться с A (^), содержать B, не содержать C (!), заканчиваться на D ($).<br>" "Описание узла должно: начинаться с A (^), содержать B, не содержать C (!), заканчиваться на D ($).<br>"
"Условия соединяются оператором <code>&&</code>, порядок условий не влияет на результат." "Условия соединяются оператором <code>&&</code> (И), порядок условий не влияет на результат.<br>"
"Несколько групп условий можно разделить оператором <code>||</code> (ИЛИ); совпадение любой группы считается успехом.<br>"
"Пример: <code>A && B || C && D</code> означает (A И B) ИЛИ (C И D)."
msgid "Balancing Strategy" msgid "Balancing Strategy"
msgstr "Алгоритм балансировки" msgstr "Алгоритм балансировки"
+6 -2
View File
@@ -391,11 +391,15 @@ msgstr "节点匹配规则"
msgid "" msgid ""
"Example: <code>^A && B && !C && D$</code><br>" "Example: <code>^A && B && !C && D$</code><br>"
"This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
"Conditions are joined by <code>&&</code>, and their order does not affect the result." "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
"Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
"Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
msgstr "" msgstr ""
"示例:<code>^A && B && !C && D$</code><br>" "示例:<code>^A && B && !C && D$</code><br>"
"表示节点备注需同时满足:以 A 开头(^)、包含 B、不包含 C(!)、并以 D 结尾($)。<br>" "表示节点备注需同时满足:以 A 开头(^)、包含 B、不包含 C(!)、并以 D 结尾($)。<br>"
"多个条件使用 <code>&&</code> 连接,条件顺序不影响结果。" "多个条件使用 <code>&&</code>(与)连接,条件顺序不影响结果。<br>"
"多组条件之间可使用 <code>||</code>(或)分隔,任意一组匹配即视为成功。<br>"
"示例:<code>A && B || C && D</code> 表示 (A 且 B) 或 (C 且 D)。"
msgid "Balancing Strategy" msgid "Balancing Strategy"
msgstr "负载均衡策略" msgstr "负载均衡策略"
+6 -2
View File
@@ -391,11 +391,15 @@ msgstr "節點匹配規則"
msgid "" msgid ""
"Example: <code>^A && B && !C && D$</code><br>" "Example: <code>^A && B && !C && D$</code><br>"
"This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>" "This means the node remark must start with A (^), include B, exclude C (!), and end with D ($).<br>"
"Conditions are joined by <code>&&</code>, and their order does not affect the result." "Conditions are joined by <code>&&</code> (AND), and their order does not affect the result.<br>"
"Multiple groups can be separated by <code>||</code> (OR), matching succeeds if any group matches.<br>"
"Example: <code>A && B || C && D</code> means (A AND B) OR (C AND D)."
msgstr "" msgstr ""
"示例:<code>^A && B && !C && D$</code><br>" "示例:<code>^A && B && !C && D$</code><br>"
"表示節點備註需同時滿足:以 A 開頭(^)、包含 B、不包含 C(!)、並以 D 結尾($)。<br>" "表示節點備註需同時滿足:以 A 開頭(^)、包含 B、不包含 C(!)、並以 D 結尾($)。<br>"
"多個條件使用 <code>&&</code> 連接,條件順序不影響結果。" "多個條件使用 <code>&&</code>(與)連接,條件順序不影響結果。<br>"
"多組條件之間可使用 <code>||</code>(或)分隔,任意一組匹配即視為成功。<br>"
"示例:<code>A && B || C && D</code> 表示 (A 且 B) 或 (C 且 D)。"
msgid "Balancing Strategy" msgid "Balancing Strategy"
msgstr "負載均衡策略" msgstr "負載均衡策略"
@@ -160,25 +160,28 @@ insert_nftset() {
*) suffix=" timeout $timeout_argument" ;; *) suffix=" timeout $timeout_argument" ;;
esac esac
{ {
if [ $# -gt 0 ]; then if [ $# -gt 0 ] && [ $# -le 1000 ]; then
printf "%s\n" "$@" printf "%s\n" "$@"
elif [ $# -gt 1000 ]; then
printf "%s\n" "$*"
else else
cat cat
fi | awk -v s="$suffix" -v n="$nftset_name" -v t="$NFTABLE_NAME" ' fi | awk -v s="$suffix" -v n="$nftset_name" -v t="$NFTABLE_NAME" '
BEGIN { BEGIN {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = ""
} }
$0 != "" { $0 != "" {
if (first == 0) { if (!first) {
printf "add element %s %s { \n", t, n; printf "add element %s %s { \n", t, n
first = 1; first = 1;
} else { } else {
printf ",\n"; print ",\n"
} }
printf "%s%s", $0, s; print $0 s
} }
END { END {
if (first == 1) printf "\n }\n"; if (first) print "\n }\n"
} }
' '
} | nft -f - } | nft -f -
@@ -4456,6 +4456,16 @@ return view.extend({
uci.set('network', nameval, 'device', staDevice); uci.set('network', nameval, 'device', staDevice);
} }
else if (hwtype == 'qcawifi' || hwtype == 'qcawificfg80211') {
const radioName = radioDev.getName();
const radioMatch = radioName.match(/^wifi(\d+)$/);
const radioVifs = uci.sections('wireless', 'wifi-iface')
.filter(section => section.device == radioName);
const vifIndex = radioVifs.findIndex(section => section['.name'] == section_id);
if (radioMatch && vifIndex >= 0)
uci.set('network', nameval, 'device', 'ath%s%s'.format(radioMatch[1], vifIndex || ''));
}
firewall.deleteNetwork(net.getName()); firewall.deleteNetwork(net.getName());
@@ -4540,7 +4550,8 @@ return view.extend({
if (bss.ssid != null) { if (bss.ssid != null) {
bssid = s2.option(form.Flag, 'bssid', _('Lock to BSSID'), _('Instead of joining any network with a matching SSID, only connect to the BSSID <code>%h</code>.').format(bss.bssid)); bssid = s2.option(form.Flag, 'bssid', _('Lock to BSSID'), _('Instead of joining any network with a matching SSID, only connect to the BSSID <code>%h</code>.').format(bss.bssid));
bssid.default = (uci.get('wireless', radioDev.getName(), 'type') == 'mt_dbdc') ? '1' : '0'; const radioType = uci.get('wireless', radioDev.getName(), 'type');
bssid.default = ['mt_dbdc', 'qcawifi', 'qcawificfg80211'].includes(radioType) ? '1' : '0';
} }
zone = s2.option(widgets.ZoneSelect, 'zone', _('Create / Assign firewall-zone'), _('Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>custom</em> field to define a new zone and attach the interface to it.')); zone = s2.option(widgets.ZoneSelect, 'zone', _('Create / Assign firewall-zone'), _('Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>custom</em> field to define a new zone and attach the interface to it.'));
+1 -1
View File
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=mptcp PKG_NAME:=mptcp
PKG_VERSION:=6.1 PKG_VERSION:=6.1
PKG_RELEASE:=6 PKG_RELEASE:=7
PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org> PKG_MAINTAINER:=Ycarus (Yannick Chabanois) <ycarus@zugaina.org>
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+6
View File
@@ -202,6 +202,12 @@ interface_multipath_settings() {
uci -q set openmptcprouter.${config}.multipath="$mode" uci -q set openmptcprouter.${config}.multipath="$mode"
} }
[ "$mode" != "off" ] && { [ "$mode" != "off" ] && {
# LRO, TSO and UFO break MPTCP packets scheduling, always disable them on multipath interfaces
[ -n "$iface" ] && {
for offload in lro tso ufo; do
ethtool -K $iface $offload off >/dev/null 2>&1
done
}
[ -n "$mptcpintf" ] && mptcpintf="$mptcpintf $iface" [ -n "$mptcpintf" ] && mptcpintf="$mptcpintf $iface"
[ -z "$mptcpintf" ] && mptcpintf="$iface" [ -z "$mptcpintf" ] && mptcpintf="$iface"
[ -z "$mptcpmintf" ] && mptcpmintf="$config" [ -z "$mptcpmintf" ] && mptcpmintf="$config"
+2 -2
View File
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=natflow PKG_NAME:=natflow
PKG_VERSION:=20260531 PKG_VERSION:=20260531
PKG_RELEASE:=45 PKG_RELEASE:=46
PKG_SOURCE:=$(PKG_VERSION).tar.xz PKG_SOURCE:=$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=0a3d1131b6a5094959f6441ef435b2b3b6fa4819 PKG_SOURCE_VERSION:=5bf4ff4efbdab184c5c2f4e27bf0604726589bd3
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com> PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
PKG_LICENSE:=GPL-2.0 PKG_LICENSE:=GPL-2.0
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=nps PKG_NAME:=nps
PKG_VERSION:=0.26.35 PKG_VERSION:=0.26.36
PKG_RELEASE:=10 PKG_RELEASE:=11
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/yisier/nps/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/yisier/nps/tar.gz/v$(PKG_VERSION)?
+3 -3
View File
@@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=torrserver PKG_NAME:=torrserver
PKG_VERSION:=MatriX.142 PKG_VERSION:=MatriX.142.1
PKG_RELEASE:=13 PKG_RELEASE:=14
PKG_SOURCE_PROTO:=git PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/YouROK/TorrServer.git PKG_SOURCE_URL:=https://github.com/YouROK/TorrServer.git
PKG_SOURCE_VERSION:=f0585eb7dfc92e0e5fdcb17a7e7eead212201e7d PKG_SOURCE_VERSION:=fa0e1ecb701e78826e3226e582a6ba0e76718a61
PKG_MIRROR_HASH:=skip PKG_MIRROR_HASH:=skip
PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru> PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru>