update 2026-10-31 18:07:25

This commit is contained in:
action committed 2026-10-31 18:07:25 +08:00
1 parent 6ce64f7ba2
commit 04b58d28a1
70 files changed
+209 -211

No files matched your search

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

@@ -886,17 +886,17 @@ function read_rulelist()
end end
local backup_files = { local backup_files = {
"/etc/config/passwall", "/etc/config/passwall",
"/etc/config/passwall_server", "/etc/config/passwall_server",
"/etc/passwall/rules/block_host", "/etc/passwall/rules/block_host",
"/etc/passwall/rules/block_ip", "/etc/passwall/rules/block_ip",
"/etc/passwall/rules/direct_host", "/etc/passwall/rules/direct_host",
"/etc/passwall/rules/direct_ip", "/etc/passwall/rules/direct_ip",
"/etc/passwall/rules/proxy_host", "/etc/passwall/rules/proxy_host",
"/etc/passwall/rules/proxy_ip", "/etc/passwall/rules/proxy_ip",
"/etc/passwall/rules/lanlist_ipv4", "/etc/passwall/rules/lanlist_ipv4",
"/etc/passwall/rules/lanlist_ipv6", "/etc/passwall/rules/lanlist_ipv6",
"/etc/passwall/rules/domains_excluded" "/etc/passwall/rules/domains_excluded"
} }
function create_backup() function create_backup()
@@ -172,7 +172,7 @@ o.validate = port_validate
---- UDP No Redir Ports ---- UDP No Redir Ports
local UDP_NO_REDIR_PORTS = m:get("@global_forwarding[0]", "udp_no_redir_ports") local UDP_NO_REDIR_PORTS = m:get("@global_forwarding[0]", "udp_no_redir_ports")
o = s:taboption("Proxy", Value, "udp_no_redir_ports", translate("UDP No Redir Ports"), o = s:taboption("Proxy", Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
"<font color='red'>" .. "<font color='red'>" ..
translate("Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. translate("Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
"</font>") "</font>")
o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")") o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
@@ -119,7 +119,7 @@ o.rawhtml = true
o.cfgvalue = function(self, section) o.cfgvalue = function(self, section)
return string.format([[ return string.format([[
<input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]], <input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]],
translate("Manual subscription All")) translate("Manual subscription All"))
end end
s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>") s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
@@ -68,9 +68,9 @@ o.validate = port_validate
---- UDP No Redir Ports ---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"), o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
"<font color='red'>" .. translate( "<font color='red'>" .. translate(
"Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. "Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
"</font>") "</font>")
o.default = "disable" o.default = "disable"
o:value("disable", translate("No patterns are used")) o:value("disable", translate("No patterns are used"))
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
@@ -18,7 +18,7 @@ s.type_name = type_name
s.option_prefix = "socks_" s.option_prefix = "socks_"
api.set_type_cbi(s) api.set_type_cbi(s)
o = s:option(ListValue, "del_protocol", "¡¡") --ʼÖÕÒþ²Ø£¬ÓÃÓÚɾ³ý protocol o = s:option(ListValue, "del_protocol", " ") --始终隐藏,用于删除 protocol
o:depends({ __hide = "1" }) o:depends({ __hide = "1" })
o.rewrite_option = "protocol" o.rewrite_option = "protocol"
@@ -167,7 +167,7 @@ if load_urltest_options then -- [[ URLTest Start ]]
o = s:option(Flag, "urltest_interrupt_exist_connections", translate("Interrupt existing connections")) o = s:option(Flag, "urltest_interrupt_exist_connections", translate("Interrupt existing connections"))
o:depends({ protocol = "_urltest" }) o:depends({ protocol = "_urltest" })
o.default = "0" o.default = "0"
o.description = translate("Interrupt existing connections when the selected outbound has changed.") o.description = translate("Interrupt existing connections when the selected outbound has changed.")
end -- [[ URLTest End ]] end -- [[ URLTest End ]]
if load_iface_options then -- [[ 自定义接口 Start ]] if load_iface_options then -- [[ 自定义接口 Start ]]
@@ -2037,7 +2037,7 @@ function gen_config(var)
table.insert(dns.servers, remote_server) table.insert(dns.servers, remote_server)
fakedns_tag = "remote_fakeip" fakedns_tag = "remote_fakeip"
if remote_dns_fake or inner_fakedns == "1" then if remote_dns_fake or inner_fakedns == "1" then
table.insert(dns.servers, { table.insert(dns.servers, {
tag = fakedns_tag, tag = fakedns_tag,
type = "fakeip", type = "fakeip",
@@ -2178,7 +2178,7 @@ function gen_config(var)
local remote_dns_server = api.clone(remote_server) local remote_dns_server = api.clone(remote_server)
remote_dns_server.tag = value.shunt_tag remote_dns_server.tag = value.shunt_tag
local is_local = (remote_server.address and api.is_local_ip(remote_server.address)) or local is_local = (remote_server.address and api.is_local_ip(remote_server.address)) or
(remote_server.server and api.is_local_ip(remote_server.server)) --dns为本地ip,不走代理 (remote_server.server and api.is_local_ip(remote_server.server)) --dns为本地ip,不走代理
remote_dns_server.detour = is_local and "direct" or value.outboundTag remote_dns_server.detour = is_local and "direct" or value.outboundTag
table.insert(dns.servers, remote_dns_server) table.insert(dns.servers, remote_dns_server)
dns_rule.server = remote_dns_server.tag dns_rule.server = remote_dns_server.tag
@@ -175,7 +175,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -169,7 +169,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -35,10 +35,10 @@ local groups = {}
local group_order = {} local group_order = {}
for _, item in ipairs(values) do for _, item in ipairs(values) do
local g = item.group local g = item.group
if not g or g == "" then if not g or g == "" then
g = translate("default") g = translate("default")
end end
if not groups[g] then if not groups[g] then
groups[g] = {} groups[g] = {}
table.insert(group_order, g) table.insert(group_order, g)
end end
@@ -125,7 +125,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -258,7 +258,7 @@
const keyword = searchInput.value.trim().toLowerCase(); const keyword = searchInput.value.trim().toLowerCase();
const isSearching = keyword.length > 0; const isSearching = keyword.length > 0;
// 当前实例下的所有 checkbox // 当前实例下的所有 checkbox
const cbs = isSearching const cbs = isSearching
? Array.from(nodeList.querySelectorAll("input[type=checkbox]")).filter(cb => cb.closest("li").style.display !== "none") ? Array.from(nodeList.querySelectorAll("input[type=checkbox]")).filter(cb => cb.closest("li").style.display !== "none")
: nodeList.querySelectorAll("input[type=checkbox]"); : nodeList.querySelectorAll("input[type=checkbox]");
let checked = 0; let checked = 0;
@@ -137,7 +137,7 @@ local dropdown_data = {
</select> </select>
</div> </div>
<!-- 隐藏 input(保存实际配置值) --> <!-- 隐藏 input(保存实际配置值) -->
<input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" /> <input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" />
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
<div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>"> <span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>">
@@ -164,7 +164,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -5,11 +5,11 @@ local appname = map.config
local sid = "@global[0]" local sid = "@global[0]"
-%> -%>
<style> <style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: nowrap; white-space: nowrap;
} }
@media (max-width: 1152px) { @media (max-width: 1152px) {
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: normal; white-space: normal;
} }
} }
@@ -150,7 +150,7 @@ local sid = "@global[0]"
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>'; html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>';
node_select.insertAdjacentHTML("afterend", node_select.insertAdjacentHTML("afterend",
'<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">'
+ html + '</div>' + html + '</div>'
); );
} catch(err) { } catch(err) {
@@ -187,7 +187,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
//<![CDATA[ //<![CDATA[
var imgs = document.getElementsByTagName('img'); var imgs = document.getElementsByTagName('img');
@@ -133,7 +133,7 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) { if(dom.type == 'checkbox' && dom.checked) {
checkBoxList.push(dom.name); checkBoxList.push(dom.name);
} }
@@ -162,7 +162,7 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) { if(dom.type == 'checkbox' && dom.checked) {
if(type == 'geoip' && (dom.name === 'chnroute' || dom.name === 'chnroute6')) { if(type == 'geoip' && (dom.name === 'chnroute' || dom.name === 'chnroute6')) {
checkBoxList.push(dom.name); checkBoxList.push(dom.name);
@@ -2,7 +2,7 @@
if [ -e "/etc/config/ucitrack" ]; then if [ -e "/etc/config/ucitrack" ]; then
uci -q batch <<-EOF uci -q batch <<-EOF
delete ucitrack.@passwall[-1] delete ucitrack.@passwall[-1]
add ucitrack passwall add ucitrack passwall
set ucitrack.@passwall[-1].init=passwall set ucitrack.@passwall[-1].init=passwall
commit ucitrack commit ucitrack
@@ -1088,7 +1088,7 @@ start_dns() {
local ACL_RULE_DNSMASQ=0 local ACL_RULE_DNSMASQ=0
for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
if [ "$(config_n_get $acl_section enabled)" = "1" ] && \ if [ "$(config_n_get $acl_section enabled)" = "1" ] && \
[ "$(config_n_get $acl_section dns_shunt)" = "dnsmasq" ]; then [ "$(config_n_get $acl_section dns_shunt)" = "dnsmasq" ]; then
ACL_RULE_DNSMASQ=1 ACL_RULE_DNSMASQ=1
break break
fi fi
@@ -1101,7 +1101,7 @@ start_dns() {
china_ng_local_dns=${LOCAL_DNS} china_ng_local_dns=${LOCAL_DNS}
v2ray_local_dns="direct_dns_udp_server=${LOCAL_DNS}" v2ray_local_dns="direct_dns_udp_server=${LOCAL_DNS}"
;; ;;
tcp) tcp)
local DIRECT_DNS=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)") local DIRECT_DNS=$(normalize_dns "$(config_n_get @global[0] direct_dns 223.5.5.5:53)")
china_ng_local_dns="tcp://${DIRECT_DNS}" china_ng_local_dns="tcp://${DIRECT_DNS}"
v2ray_local_dns="direct_dns_tcp_server=${DIRECT_DNS}" v2ray_local_dns="direct_dns_tcp_server=${DIRECT_DNS}"
@@ -625,7 +625,7 @@ local function encode_node(node)
end end
function parseClashNode(raw, remark) function parseClashNode(raw, remark)
if not raw then return "" end if not raw then return "" end
domain_redir = {} domain_redir = {}
local ok, lyaml = pcall(require, "lyaml") local ok, lyaml = pcall(require, "lyaml")
if not ok then return raw end if not ok then return raw end
@@ -605,7 +605,7 @@ if CHNLIST == "proxy" then DEFAULT_TAG = "chn" end
--全局模式,默认使用远程DNS --全局模式,默认使用远程DNS
if only_global then if only_global then
DEFAULT_TAG = "gfw" DEFAULT_TAG = "gfw"
if NO_IPV6_TRUST == "1" and not IS_SHUNT_NODE then if NO_IPV6_TRUST == "1" and not IS_SHUNT_NODE then
table.insert(config_lines, "no-ipv6") table.insert(config_lines, "no-ipv6")
end end
end end
@@ -761,7 +761,7 @@ function add_rule(var)
server_out:close() server_out:close()
ipset_out:close() ipset_out:close()
end end
if not GEO_SUCCESS then new_text = "" end if not GEO_SUCCESS then new_text = "" end
local f_out = io.open(CACHE_TEXT_FILE, "a") local f_out = io.open(CACHE_TEXT_FILE, "a")
f_out:write(new_text) f_out:write(new_text)
@@ -172,9 +172,7 @@ local auto_config_lines = {}
-- 直连规则显式覆盖远程兜底的缓存、IPv6、测速和双栈优选设置。 -- 直连规则显式覆盖远程兜底的缓存、IPv6、测速和双栈优选设置。
local DIRECT_RULE_OPTIONS = " -enable-cache -address -6 -speed-check-mode ping,tcp:80,tcp:443 -response-mode first-ping -d yes" local DIRECT_RULE_OPTIONS = " -enable-cache -address -6 -speed-check-mode ping,tcp:80,tcp:443 -response-mode first-ping -d yes"
--设置默认 DNS 分组(兜底组),全局代理模式仍使用远程组。 --设置默认 DNS 分组(兜底组),全局代理模式仍使用远程组。
local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and "direct") or local DEFAULT_DNS_GROUP = (USE_DEFAULT_DNS == "direct" and "direct") or (USE_DEFAULT_DNS == "remote" and "proxy") or (USE_DEFAULT_DNS == "auto" and AUTO_GROUP)
(USE_DEFAULT_DNS == "remote" and "proxy") or
(USE_DEFAULT_DNS == "auto" and AUTO_GROUP)
local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1 local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_GFW_LIST == "0") and 1
if only_global == 1 then if only_global == 1 then
DEFAULT_DNS_GROUP = "proxy" DEFAULT_DNS_GROUP = "proxy"
@@ -817,7 +817,7 @@ filter_node() {
local address=$(config_n_get "$node" address) local address=$(config_n_get "$node" address)
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" ] && return 1 [ -z "$address" ] && return 1
echo "$address" | grep -Eq "$EXCLUDE_VPSIP" && return 1 echo "$address" | grep -Eq "$EXCLUDE_VPSIP" && return 1
[ -z "$port" ] && return 1 [ -z "$port" ] && return 1
@@ -197,20 +197,20 @@ insert_nftset() {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = "" ORS = ""
} }
$0 != "" { $0 != "" {
if (!first) { if (!first) {
printf "add element %s %s { \n", t, n printf "add element %s %s { \n", t, n
first = 1 first = 1
} else { } else {
print ",\n" print ",\n"
} }
printf " %s", $0 printf " %s", $0
} }
END { END {
if (first) { if (first) {
print "\n }\n" print "\n }\n"
} }
}' | nft -f - }' | nft -f -
} }
gen_nftset() { gen_nftset() {
@@ -300,7 +300,7 @@ load_acl() {
use_shunt_node=0 use_shunt_node=0
[ -n "$node" ] && [ "$(config_n_get $node protocol)" = "_shunt" ] && use_shunt_node=1 [ -n "$node" ] && [ "$(config_n_get $node protocol)" = "_shunt" ] && use_shunt_node=1
[ "${use_global_config}" = "1" ] && { [ "${use_global_config}" = "1" ] && {
if [ "$(config_get_type $NODE)" = "socks" ]; then if [ "$(config_get_type $NODE)" = "socks" ]; then
node_remark="Socks 配置($(config_n_get $NODE port) 端口)" node_remark="Socks 配置($(config_n_get $NODE port) 端口)"
else else
@@ -856,7 +856,7 @@ filter_node() {
local address=$(config_n_get "$node" address) local address=$(config_n_get "$node" address)
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" ] && return 1 [ -z "$address" ] && return 1
echo "$address" | grep -Eq "$EXCLUDE_VPSIP" && return 1 echo "$address" | grep -Eq "$EXCLUDE_VPSIP" && return 1
[ -z "$port" ] && return 1 [ -z "$port" ] && return 1
@@ -954,7 +954,7 @@ add_firewall_rule() {
add_script_mwan3 add_script_mwan3
mwan3_start mwan3_start
set_tproxy_sysctl set_tproxy_sysctl
gen_nftset $NFTSET_WAN ipv4_addr 0 gen_nftset $NFTSET_WAN ipv4_addr 0
gen_nftset $NFTSET_VPS ipv4_addr 0 gen_nftset $NFTSET_VPS ipv4_addr 0
gen_nftset $NFTSET_GFW ipv4_addr "2d" gen_nftset $NFTSET_GFW ipv4_addr "2d"
gen_nftset $NFTSET_LOCAL ipv4_addr 0 gen_nftset $NFTSET_LOCAL ipv4_addr 0
@@ -976,7 +976,7 @@ add_firewall_rule() {
gen_nftset $NFTSET_SHUNT ipv4_addr "2d" gen_nftset $NFTSET_SHUNT ipv4_addr "2d"
gen_nftset $NFTSET_SHUNT_STATIC ipv4_addr 0 gen_nftset $NFTSET_SHUNT_STATIC ipv4_addr 0
gen_nftset $NFTSET_WAN6 ipv6_addr 0 gen_nftset $NFTSET_WAN6 ipv6_addr 0
gen_nftset $NFTSET_VPS6 ipv6_addr 0 gen_nftset $NFTSET_VPS6 ipv6_addr 0
gen_nftset $NFTSET_GFW6 ipv6_addr "2d" gen_nftset $NFTSET_GFW6 ipv6_addr "2d"
gen_nftset $NFTSET_LOCAL6 ipv6_addr 0 gen_nftset $NFTSET_LOCAL6 ipv6_addr 0
@@ -1502,7 +1502,7 @@ add_firewall_rule() {
del_firewall_rule() { del_firewall_rule() {
for nft in "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do for nft in "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
local handles=$(nft -a list chain $NFTABLE_NAME ${nft} 2>/dev/null | grep -E "PSW_" | awk -F '# handle ' '{print$2}') local handles=$(nft -a list chain $NFTABLE_NAME ${nft} 2>/dev/null | grep -E "PSW_" | awk -F '# handle ' '{print$2}')
for handle in $handles; do for handle in $handles; do
nft delete rule $NFTABLE_NAME ${nft} handle ${handle} 2>/dev/null nft delete rule $NFTABLE_NAME ${nft} handle ${handle} 2>/dev/null
done done
@@ -345,7 +345,7 @@ local function extract_domain(s)
local last_dot = nil local last_dot = nil
for i = 1, len do for i = 1, len do
local b = s:byte(i) local b = s:byte(i)
-- 允许的域名字符:a-zA-Z0-9.- -- 允许的域名字符:a-zA-Z0-9.-
if (b >= 48 and b <= 57) or (b >= 65 and b <= 90) or (b >= 97 and b <= 122) or b == 45 or b == 46 then if (b >= 48 and b <= 57) or (b >= 65 and b <= 90) or (b >= 97 and b <= 122) or b == 45 or b == 46 then
if not start then start = i end if not start then start = i end
if b == 46 then last_dot = i end if b == 46 then last_dot = i end
@@ -608,7 +608,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.protocol = hostInfo[#hostInfo-3] result.protocol = hostInfo[#hostInfo-3]
result.method = hostInfo[#hostInfo-2] result.method = hostInfo[#hostInfo-2]
result.obfs = hostInfo[#hostInfo-1] result.obfs = hostInfo[#hostInfo-1]
result.password = base64Decode(hostInfo[#hostInfo]) result.password = base64Decode(hostInfo[#hostInfo])
local params = {} local params = {}
for _, v in pairs(split(dat[2], '&')) do for _, v in pairs(split(dat[2], '&')) do
local s = v:find("=", 1, true) local s = v:find("=", 1, true)
@@ -695,7 +695,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if not info.net then info.net = "tcp" end if not info.net then info.net = "tcp" end
info.net = string.lower(info.net) info.net = string.lower(info.net)
if result.type == "sing-box" and info.net == "raw" then if result.type == "sing-box" and info.net == "raw" then
info.net = "tcp" info.net = "tcp"
elseif result.type == "Xray" and info.net == "tcp" then elseif result.type == "Xray" and info.net == "tcp" then
info.net = "raw" info.net = "raw"
@@ -962,7 +962,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if params.type then if params.type then
params.type = string.lower(params.type) params.type = string.lower(params.type)
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -1175,7 +1175,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if not params.type then params.type = "tcp" end if not params.type then params.type = "tcp" end
params.type = string.lower(params.type) params.type = string.lower(params.type)
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -1302,7 +1302,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if ({ xhttp=true, kcp=true, mkcp=true })[params.type] and result.type ~= "Xray" and has_xray then if ({ xhttp=true, kcp=true, mkcp=true })[params.type] and result.type ~= "Xray" and has_xray then
result.type = "Xray" result.type = "Xray"
end end
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -2117,7 +2117,7 @@ local function update_node(manual)
uci_set(cfgid, "chain_proxy", "3") uci_set(cfgid, "chain_proxy", "3")
uci_set(cfgid, "outbound_iface", outbound_iface_group) uci_set(cfgid, "outbound_iface", outbound_iface_group)
end end
end end
end end
end end
end end
@@ -114,7 +114,7 @@ o.rawhtml = true
o.cfgvalue = function(self, section) o.cfgvalue = function(self, section)
return string.format([[ return string.format([[
<input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]], <input type="button" class="btn cbi-button cbi-button-apply" onclick="ManualSubscribeAll()" value="%s" />]],
translate("Manual subscription All")) translate("Manual subscription All"))
end end
s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>") s = m:section(TypedSection, "subscribe_list", "", "<font color='red'>" .. translate("When adding a new subscription, please save and apply before manually subscribing. If you only change the subscription URL, you can subscribe manually, and the system will save it automatically.") .. "</font>")
@@ -201,7 +201,7 @@ if has_xray then
o = s_xray:option(Flag, "fragment", translate("Fragment"), translate("TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists.")) o = s_xray:option(Flag, "fragment", translate("Fragment"), translate("TCP fragments, which can deceive the censorship system in some cases, such as bypassing SNI blacklists."))
o.default = 0 o.default = 0
o = s_xray:option(ListValue, "fragment_packets", translate("Fragment Packets"), translate(" \"1-3\" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. \"tlshello\" is for TLS client hello packet fragmentation.")) o = s_xray:option(ListValue, "fragment_packets", translate("Fragment Packets"), translate(" \"1-3\" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. \"tlshello\" is for TLS client hello packet fragmentation."))
o.default = "tlshello" o.default = "tlshello"
o:value("tlshello", "tlshello") o:value("tlshello", "tlshello")
@@ -19,13 +19,13 @@ m.description = (m.description or "") .. [[
<style> <style>
/* Scope to passwall2 CBI fields so it won't leak elsewhere */ /* Scope to passwall2 CBI fields so it won't leak elsewhere */
div[id^="cbid.passwall2."] .cbi-value-field { div[id^="cbid.passwall2."] .cbi-value-field {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 1em; gap: 1em;
} }
div[id^="cbid.passwall2."] .cbi-checkbox { div[id^="cbid.passwall2."] .cbi-checkbox {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
} }
</style> </style>
]] ]]
@@ -160,7 +160,7 @@ o = s:option(Value, "autoswitch_retry_num", translate("Timeout retry num"))
o.datatype = "min(1)" o.datatype = "min(1)"
o.default = 1 o.default = 1
o:depends("enable_autoswitch", true) o:depends("enable_autoswitch", true)
o = s:option(Flag, "autoswitch_restore_switch", translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) o = s:option(Flag, "autoswitch_restore_switch", translate("Restore Switch"), translate("When detects main node is available, switch back to the main node."))
o:depends("enable_autoswitch", true) o:depends("enable_autoswitch", true)
@@ -715,7 +715,7 @@ if singbox_tags:find("with_utls") then
o = s:option(Value, "reality_publicKey", translate("Public Key")) o = s:option(Value, "reality_publicKey", translate("Public Key"))
o:depends({ reality = true }) o:depends({ reality = true })
o = s:option(Value, "reality_shortId", translate("Short Id")) o = s:option(Value, "reality_shortId", translate("Short Id"))
o:depends({ reality = true }) o:depends({ reality = true })
end end
@@ -304,10 +304,10 @@ if singbox_tags:find("with_utls") then
o:depends({ protocol = "vless", tls = true }) o:depends({ protocol = "vless", tls = true })
o:depends({ protocol = "trojan", tls = true }) o:depends({ protocol = "trojan", tls = true })
o:depends({ protocol = "anytls", tls = true }) o:depends({ protocol = "anytls", tls = true })
o = s:option(Value, "reality_private_key", translate("Private Key")) o = s:option(Value, "reality_private_key", translate("Private Key"))
o:depends({ reality = true }) o:depends({ reality = true })
o = s:option(Value, "reality_shortId", translate("Short Id")) o = s:option(Value, "reality_shortId", translate("Short Id"))
o:depends({ reality = true }) o:depends({ reality = true })
+2 -2
View File
@@ -536,7 +536,7 @@ function strToTable(str)
if str == nil or type(str) ~= "string" then if str == nil or type(str) ~= "string" then
return {} return {}
end end
return loadstring("return " .. str)() return loadstring("return " .. str)()
end end
@@ -922,7 +922,7 @@ function clone(org)
end end
end end
end end
local res = {} local res = {}
copy(org, res) copy(org, res)
return res return res
@@ -78,7 +78,7 @@ function gen_config(var)
fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false, fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false,
reuse_port = true reuse_port = true
} }
if node.type == "SSR" then if node.type == "SSR" then
config.protocol = node.protocol config.protocol = node.protocol
config.protocol_param = node.protocol_param config.protocol_param = node.protocol_param
@@ -115,7 +115,7 @@ function gen_config(var)
}) })
end end
end end
return jsonc.stringify(config, 1) return jsonc.stringify(config, 1)
end end
@@ -1730,7 +1730,7 @@ function gen_config(var)
end end
end end
end end
local rule = { local rule = {
action = "route", action = "route",
inbound = inboundTag, inbound = inboundTag,
@@ -2326,7 +2326,7 @@ function gen_config(var)
table.insert(route.rule_set, v) table.insert(route.rule_set, v)
end end
end end
if inbounds or outbounds then if inbounds or outbounds then
local config = { local config = {
log = { log = {
@@ -2468,7 +2468,7 @@ function gen_proto_config(var)
} }
if outbound then table.insert(outbounds, outbound) end if outbound then table.insert(outbounds, outbound) end
end end
local config = { local config = {
log = { log = {
disabled = true, disabled = true,
@@ -115,7 +115,7 @@ function gen_outbound(flag, node, tag, proxy_table)
else else
dialer_proxy_tag = proxy_tag dialer_proxy_tag = proxy_tag
end end
if node.type == "Xray" then if node.type == "Xray" then
if node.tls and node.tls == "1" then if node.tls and node.tls == "1" then
node.stream_security = "tls" node.stream_security = "tls"
@@ -982,7 +982,7 @@ function gen_config(var)
local routing = nil local routing = nil
local observatory = nil local observatory = nil
local burstObservatory = nil local burstObservatory = nil
local strategy = nil local strategy = nil
local COMMON = {} local COMMON = {}
local CACHE_TEXT_FILE = CACHE_PATH .. "/cache_" .. flag .. ".txt" local CACHE_TEXT_FILE = CACHE_PATH .. "/cache_" .. flag .. ".txt"
@@ -1253,7 +1253,7 @@ function gen_config(var)
table.insert(rules, { inboundTag = { inbound_tag }, balancerTag = balancer_tag }) table.insert(rules, { inboundTag = { inbound_tag }, balancerTag = balancer_tag })
return balancer_tag, loopback_outbound return balancer_tag, loopback_outbound
end end
function set_outbound_detour(node, outbound, outbounds_table) function set_outbound_detour(node, outbound, outbounds_table)
if not node or not outbound or not outbounds_table then return nil end if not node or not outbound or not outbounds_table then return nil end
local default_outTag = outbound.tag local default_outTag = outbound.tag
@@ -1684,7 +1684,7 @@ function gen_config(var)
rules = {} rules = {}
} }
end end
local dns_host = "" local dns_host = ""
if flag == "global" then if flag == "global" then
dns_host = api.uci_get_c("@global[0]", "dns_hosts") or "" dns_host = api.uci_get_c("@global[0]", "dns_hosts") or ""
@@ -1708,7 +1708,7 @@ function gen_config(var)
end end
end) end)
end end
local _remote_dns = { local _remote_dns = {
tag = remote_dns_tag, tag = remote_dns_tag,
queryStrategy = (remote_dns_query_strategy and remote_dns_query_strategy ~= "") and remote_dns_query_strategy or "UseIPv4" queryStrategy = (remote_dns_query_strategy and remote_dns_query_strategy ~= "") and remote_dns_query_strategy or "UseIPv4"
@@ -1858,12 +1858,12 @@ function gen_config(var)
outboundTag = "dns-out" outboundTag = "dns-out"
}) })
end end
local default_dns_tag_name = remote_dns_tag local default_dns_tag_name = remote_dns_tag
if not COMMON.default_outbound_tag or COMMON.default_outbound_tag == "direct" then if not COMMON.default_outbound_tag or COMMON.default_outbound_tag == "direct" then
default_dns_tag_name = direct_dns_tag default_dns_tag_name = direct_dns_tag
end end
if dns_servers and #dns_servers > 0 then if dns_servers and #dns_servers > 0 then
-- Default DNS logic -- Default DNS logic
local default_dns_server = nil local default_dns_server = nil
@@ -2064,7 +2064,7 @@ function gen_config(var)
udp_inbound.settings.allowedNetwork = "udp" udp_inbound.settings.allowedNetwork = "udp"
table.insert(inbounds, udp_inbound) table.insert(inbounds, udp_inbound)
end end
if inbounds or outbounds then if inbounds or outbounds then
local config = { local config = {
env = (function() env = (function()
@@ -2138,7 +2138,7 @@ function gen_config(var)
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
local s = value.settings local s = value.settings
if not value["_flag_proxy_tag"] and value["_id"] and s and not NO_RUN and if not value["_flag_proxy_tag"] and value["_id"] and s and not NO_RUN and
((s.vnext and s.vnext[1] and s.vnext[1].address and s.vnext[1].port) or ((s.vnext and s.vnext[1] and s.vnext[1].address and s.vnext[1].port) or
(s.servers and s.servers[1] and s.servers[1].address and s.servers[1].port) or (s.servers and s.servers[1] and s.servers[1].address and s.servers[1].port) or
(s.peers and s.peers[1] and s.peers[1].endpoint) or (s.peers and s.peers[1] and s.peers[1].endpoint) or
(s.address and s.port)) then (s.address and s.port)) then
@@ -2168,7 +2168,7 @@ function gen_proto_config(var)
local server_port = var["server_port"] local server_port = var["server_port"]
local server_username = var["server_username"] local server_username = var["server_username"]
local server_password = var["server_password"] local server_password = var["server_password"]
local inbounds = {} local inbounds = {}
local outbounds = {} local outbounds = {}
local routing = nil local routing = nil
@@ -2194,7 +2194,7 @@ function gen_proto_config(var)
end end
table.insert(inbounds, inbound) table.insert(inbounds, inbound)
end end
if local_http_address and local_http_port then if local_http_address and local_http_port then
local inbound = { local inbound = {
listen = local_http_address, listen = local_http_address,
@@ -2214,7 +2214,7 @@ function gen_proto_config(var)
end end
table.insert(inbounds, inbound) table.insert(inbounds, inbound)
end end
if server_proto ~= "nil" and server_address ~= "nil" and server_port ~= "nil" then if server_proto ~= "nil" and server_address ~= "nil" and server_port ~= "nil" then
local outbound = { local outbound = {
protocol = server_proto, protocol = server_proto,
@@ -2250,7 +2250,7 @@ function gen_proto_config(var)
sockopt = {mark = 255} sockopt = {mark = 255}
} }
}) })
local config = { local config = {
log = { log = {
loglevel = "warning" loglevel = "warning"
@@ -175,7 +175,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -213,7 +213,7 @@
if (!rgb) return 'unknown'; // Handle invalid colors if (!rgb) return 'unknown'; // Handle invalid colors
// Calculate YIQ brightness (human eye perception) // Calculate YIQ brightness (human eye perception)
const brightness = ((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114)) / 1000; const brightness = ((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114)) / 1000;
return brightness > 128 ? 'light' : 'dark'; return brightness > 128 ? 'light' : 'dark';
} }
@@ -169,7 +169,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -35,10 +35,10 @@ local groups = {}
local group_order = {} local group_order = {}
for _, item in ipairs(values) do for _, item in ipairs(values) do
local g = item.group local g = item.group
if not g or g == "" then if not g or g == "" then
g = translate("default") g = translate("default")
end end
if not groups[g] then if not groups[g] then
groups[g] = {} groups[g] = {}
table.insert(group_order, g) table.insert(group_order, g)
end end
@@ -125,7 +125,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -163,7 +163,7 @@
if (!rgb) return 'unknown'; // Handle invalid colors if (!rgb) return 'unknown'; // Handle invalid colors
// Calculate YIQ brightness (human eye perception) // Calculate YIQ brightness (human eye perception)
const brightness = ((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114)) / 1000; const brightness = ((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114)) / 1000;
return brightness > 128 ? 'light' : 'dark'; return brightness > 128 ? 'light' : 'dark';
} }
@@ -258,7 +258,7 @@
const keyword = searchInput.value.trim().toLowerCase(); const keyword = searchInput.value.trim().toLowerCase();
const isSearching = keyword.length > 0; const isSearching = keyword.length > 0;
// 当前实例下的所有 checkbox // 当前实例下的所有 checkbox
const cbs = isSearching const cbs = isSearching
? Array.from(nodeList.querySelectorAll("input[type=checkbox]")).filter(cb => cb.closest("li").style.display !== "none") ? Array.from(nodeList.querySelectorAll("input[type=checkbox]")).filter(cb => cb.closest("li").style.display !== "none")
: nodeList.querySelectorAll("input[type=checkbox]"); : nodeList.querySelectorAll("input[type=checkbox]");
let checked = 0; let checked = 0;
@@ -137,7 +137,7 @@ local dropdown_data = {
</select> </select>
</div> </div>
<!-- 隐藏 input(保存实际配置值) --> <!-- 隐藏 input(保存实际配置值) -->
<input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" /> <input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" />
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
<div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select v-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>"> <span id="<%=cbid%>.label" class="v-dropdown-label" title="<%=pcdata(current_label)%>">
@@ -164,7 +164,7 @@
const ctx = canvas.getContext('2d', { willReadFrequently: true }); const ctx = canvas.getContext('2d', { willReadFrequently: true });
return function(colorStr) { return function(colorStr) {
if (!colorStr) if (!colorStr)
return null; return null;
ctx.clearRect(0, 0, 1, 1); ctx.clearRect(0, 0, 1, 1);
// 2. Apply the color // 2. Apply the color
ctx.fillStyle = colorStr; ctx.fillStyle = colorStr;
@@ -36,7 +36,7 @@ local appname = self.appname or map.config
background-color: rgba(131, 191, 255, 0.7) !important; background-color: rgba(131, 191, 255, 0.7) !important;
box-shadow: 0 4px 6px rgba(0,0,0,0.1); box-shadow: 0 4px 6px rgba(0,0,0,0.1);
} }
@media screen and (max-width: 1152px) { @media screen and (max-width: 1152px) {
#cbi-<%=appname%>-<%=sectiontype%> .cbi-section-table-titles { #cbi-<%=appname%>-<%=sectiontype%> .cbi-section-table-titles {
display: none !important; display: none !important;
@@ -116,7 +116,7 @@ local appname = self.appname or map.config
hiddenInput.value = changed ? newOrder.join(" ") : ""; hiddenInput.value = changed ? newOrder.join(" ") : "";
} }
} }
// hide lua luci version up/down // hide lua luci version up/down
function hideSortColumn(section) { function hideSortColumn(section) {
var table = section.getElementsByTagName("table")[0]; var table = section.getElementsByTagName("table")[0];
@@ -153,7 +153,7 @@ local api = map.api
if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("GET",'<%= api.url("reset_config") %>', false); xhr.open("GET",'<%= api.url("reset_config") %>', false);
xhr.send(); xhr.send();
window.location.href = '<%= api.url("log") %>' window.location.href = '<%= api.url("log") %>'
} }
}, 1000); }, 1000);
@@ -4,25 +4,25 @@ local api = map.api
-%> -%>
<style> <style>
.dns-con { .dns-con {
padding: 1rem; padding: 1rem;
} }
.faq-title { .faq-title {
color: var(--primary); color: var(--primary);
font-weight: bolder; font-weight: bolder;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
display: inline-block; display: inline-block;
} }
.reset-title { .reset-title {
color: var(--primary); color: var(--primary);
font-weight: bolder; font-weight: bolder;
margin-bottom: 0.3rem; margin-bottom: 0.3rem;
display: inline-block; display: inline-block;
margin-top: 1.2rem; margin-top: 1.2rem;
text-decoration: underline; text-decoration: underline;
} }
.dns-item { .dns-item {
margin-bottom: 0.8rem; margin-bottom: 0.8rem;
line-height:1.2rem; line-height:1.2rem;
} }
.dns-list { .dns-list {
text-indent:1rem; text-indent:1rem;
@@ -50,13 +50,13 @@ local api = map.api
var origin = window.location.origin; var origin = window.location.origin;
var hide_url = origin + "<%=api.url("hide")%>"; var hide_url = origin + "<%=api.url("hide")%>";
var show_url = origin + "<%=api.url("show")%>"; var show_url = origin + "<%=api.url("show")%>";
function hide(url) { function hide(url) {
if (confirm('<%:Are you sure to hide?%>') == true) { if (confirm('<%:Are you sure to hide?%>') == true) {
window.location.href = hide_url; window.location.href = hide_url;
} }
} }
var dom = document.getElementById("faq_reset"); var dom = document.getElementById("faq_reset");
if (dom) { if (dom) {
var li = ""; var li = "";
@@ -5,11 +5,11 @@ local appname = map.config
local sid = "@global[0]" local sid = "@global[0]"
-%> -%>
<style> <style>
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: nowrap; white-space: nowrap;
} }
@media (max-width: 1152px) { @media (max-width: 1152px) {
#cbi-<%=appname%>-socks .td.cbi-value-field > div { #cbi-<%=appname%>-socks .td.cbi-value-field > div {
white-space: normal; white-space: normal;
} }
} }
@@ -162,7 +162,7 @@ local sid = "@global[0]"
html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>'; html += '<a href="#" onclick="window.open(\'' + '<%=api.url("get_socks_log")%>?name=' + id.replace("cbi-<%=appname%>-", "") + '\', \'_blank\')"><%:Log%></a>';
node_select.insertAdjacentHTML("afterend", node_select.insertAdjacentHTML("afterend",
'<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">' '<div class="node-actions" style="display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:4px;">'
+ html + '</div>' + html + '</div>'
); );
} catch(err) { } catch(err) {
@@ -54,7 +54,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
line-height: 1.8em; line-height: 1.8em;
min-height: 48px; min-height: 48px;
} }
.check { .check {
cursor: pointer; cursor: pointer;
} }
@@ -73,7 +73,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
margin: 1rem 0rem 1rem 0.5rem; margin: 1rem 0rem 1rem 0.5rem;
} }
} }
@media screen and (max-width: 480px) { @media screen and (max-width: 480px) {
.block img { .block img {
width: 36px; width: 36px;
@@ -132,7 +132,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
//<![CDATA[ //<![CDATA[
var imgs = document.getElementsByTagName('img'); var imgs = document.getElementsByTagName('img');
@@ -156,7 +156,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
} }
} }
}); });
function check_connect(type, url) { function check_connect(type, url) {
var s = document.getElementById('_' + type + '_status'); var s = document.getElementById('_' + type + '_status');
if (s) { if (s) {
@@ -99,7 +99,7 @@ local current_node = map:get(section)
}; };
return r; return r;
} }
function genQrcode(btn, urlname, sid) { function genQrcode(btn, urlname, sid) {
var qrcode_div = document.getElementById("qrcode_div"); var qrcode_div = document.getElementById("qrcode_div");
qrcode_div.style.display = null; qrcode_div.style.display = null;
@@ -203,7 +203,7 @@ local current_node = map:get(section)
url = b64encsafe(v_method.value + ":" + v_password.value) + "@" + url = b64encsafe(v_method.value + ":" + v_password.value) + "@" +
_address + ":" + _address + ":" +
v_port.value + "/?"; v_port.value + "/?";
var shadow_tls; var shadow_tls;
// Generate SS Shadow-TLS plugin parameters // Generate SS Shadow-TLS plugin parameters
const generateShadowTLSBase64 = function(paramStr) { const generateShadowTLSBase64 = function(paramStr) {
@@ -596,7 +596,7 @@ local current_node = map:get(section)
params += opt.query("pinSHA256", dom_prefix + "tls_pinSHA256"); params += opt.query("pinSHA256", dom_prefix + "tls_pinSHA256");
params += opt.query("pcs", dom_prefix + "tls_pinSHA256"); params += opt.query("pcs", dom_prefix + "tls_pinSHA256");
params += opt.query("vcn", dom_prefix + "tls_CertByName"); params += opt.query("vcn", dom_prefix + "tls_CertByName");
var v_password = opt.get(dom_prefix + "hysteria2_auth_password"); var v_password = opt.get(dom_prefix + "hysteria2_auth_password");
var dom_obfs_type = opt.get(dom_prefix + "hysteria2_obfs_type"); var dom_obfs_type = opt.get(dom_prefix + "hysteria2_obfs_type");
if (dom_obfs_type && dom_obfs_type.value != "") { if (dom_obfs_type && dom_obfs_type.value != "") {
@@ -767,7 +767,7 @@ local current_node = map:get(section)
if (!server) return ''; if (!server) return '';
return server.replace(/^\[/, '').replace(/\]$/, ''); return server.replace(/^\[/, '').replace(/\]$/, '');
} }
function tofromUrl(btn) { function tofromUrl(btn) {
let link = prompt('<%:Paste Share URL Here%>', ''); let link = prompt('<%:Paste Share URL Here%>', '');
if (link === null || link === "") { if (link === null || link === "") {
@@ -1133,7 +1133,7 @@ local current_node = map:get(section)
var kv = ws_path_params_array[i].split('='); var kv = ws_path_params_array[i].split('=');
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || ''); ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
} }
if (ws_path_params.ed) { if (ws_path_params.ed) {
opt.set(dom_prefix + 'ws_path', ws_path); opt.set(dom_prefix + 'ws_path', ws_path);
opt.set(dom_prefix + 'ws_enableEarlyData', true); opt.set(dom_prefix + 'ws_enableEarlyData', true);
@@ -1171,7 +1171,7 @@ local current_node = map:get(section)
opt.set(dom_prefix + 'uot', queryParam.udp); opt.set(dom_prefix + 'uot', queryParam.udp);
opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm); opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm);
opt.set(dom_prefix + 'finalmask', queryParam.fm || ""); opt.set(dom_prefix + 'finalmask', queryParam.fm || "");
if (queryParam["shadow-tls"]) { if (queryParam["shadow-tls"]) {
// Parsing SS Shadow-TLS plugin parameters // Parsing SS Shadow-TLS plugin parameters
const parseShadowTLSParams = function(base64Str, outObj) { const parseShadowTLSParams = function(base64Str, outObj) {
@@ -1281,7 +1281,7 @@ local current_node = map:get(section)
var kv = ws_path_params_array[i].split('='); var kv = ws_path_params_array[i].split('=');
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || ''); ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
} }
if (ws_path_params.ed) { if (ws_path_params.ed) {
opt.set(dom_prefix + 'ws_path', ws_path); opt.set(dom_prefix + 'ws_path', ws_path);
opt.set(dom_prefix + 'ws_enableEarlyData', true); opt.set(dom_prefix + 'ws_enableEarlyData', true);
@@ -1468,7 +1468,7 @@ local current_node = map:get(section)
var kv = ws_path_params_array[i].split('='); var kv = ws_path_params_array[i].split('=');
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || ''); ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
} }
if (ws_path_params.ed) { if (ws_path_params.ed) {
opt.set(dom_prefix + 'ws_path', ws_path); opt.set(dom_prefix + 'ws_path', ws_path);
opt.set(dom_prefix + 'ws_enableEarlyData', true); opt.set(dom_prefix + 'ws_enableEarlyData', true);
@@ -1504,7 +1504,7 @@ local current_node = map:get(section)
} else { } else {
dom_prefix = "xray_"; dom_prefix = "xray_";
} }
var m = parseNodeUrl(link); var m = parseNodeUrl(link);
var password = m.passwd; var password = m.passwd;
if (password === "") { if (password === "") {
@@ -1611,7 +1611,7 @@ local current_node = map:get(section)
var kv = ws_path_params_array[i].split('='); var kv = ws_path_params_array[i].split('=');
ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || ''); ws_path_params[decodeURIComponent(kv[0]).toLowerCase()] = decodeURIComponent(kv[1] || '');
} }
if (ws_path_params.ed) { if (ws_path_params.ed) {
opt.set(dom_prefix + 'ws_path', ws_path); opt.set(dom_prefix + 'ws_path', ws_path);
opt.set(dom_prefix + 'ws_enableEarlyData', true); opt.set(dom_prefix + 'ws_enableEarlyData', true);
@@ -1693,10 +1693,10 @@ local current_node = map:get(section)
opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm); opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm);
opt.set(dom_prefix + 'finalmask', queryParam.fm || ""); opt.set(dom_prefix + 'finalmask', queryParam.fm || "");
} }
opt.set(dom_prefix + 'address', unbracketIP(m.hostname)); opt.set(dom_prefix + 'address', unbracketIP(m.hostname));
opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'port', m.port || "443");
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ""); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || "");
opt.set( opt.set(
dom_prefix + 'tls_allowInsecure', dom_prefix + 'tls_allowInsecure',
@@ -1911,7 +1911,7 @@ local current_node = map:get(section)
sessionStorage.removeItem("fromUrl"); sessionStorage.removeItem("fromUrl");
return true; return true;
} }
function exportConfigFile(btn, sid) { function exportConfigFile(btn, sid) {
window.open('<%=api.url("gen_client_config")%>?id=' + sid, "_blank") window.open('<%=api.url("gen_client_config")%>?id=' + sid, "_blank")
} }
@@ -478,7 +478,7 @@ table td, .table .td {
var code = ajax.encode(data); var code = ajax.encode(data);
xhr.open("POST", url, true); xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (timeout && timeout > 1000) { if (timeout && timeout > 1000) {
xhr.timeout = timeout; xhr.timeout = timeout;
} }
@@ -645,7 +645,7 @@ table td, .table .td {
updateElement(selectAllChk); updateElement(selectAllChk);
updateElement(selectAllBtn); updateElement(selectAllBtn);
} }
function delete_select_nodes() { function delete_select_nodes() {
var ids = []; var ids = [];
var visibleContainer = document.querySelector('#cbi-<%=appname%>-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-<%=appname%>-nodes > .cbi-tabcontainer[style*="display: block"]'); var visibleContainer = document.querySelector('#cbi-<%=appname%>-nodes > .cbi-tabcontainer[style*="display:block"], #cbi-<%=appname%>-nodes > .cbi-tabcontainer[style*="display: block"]');
@@ -698,7 +698,7 @@ table td, .table .td {
address = !reg.test(address) ? address : ""; address = !reg.test(address) ? address : "";
return { address: address, port: port }; return { address: address, port: port };
} }
function get_node_order(group) { function get_node_order(group) {
let table = document.getElementById("cbi-<%=appname%>-nodes-" + group + "-table"); let table = document.getElementById("cbi-<%=appname%>-nodes-" + group + "-table");
if (!table) { if (!table) {
@@ -756,7 +756,7 @@ table td, .table .td {
} }
); );
} }
function urltest_node(cbi_id, dom) { function urltest_node(cbi_id, dom) {
if (dom.dataset.busy == "1" || !cbi_id) return; if (dom.dataset.busy == "1" || !cbi_id) return;
dom.dataset.busy = "1"; dom.dataset.busy = "1";
@@ -1165,7 +1165,7 @@ table td, .table .td {
const dom = document.getElementById('modal-mask'); const dom = document.getElementById('modal-mask');
dom.style.display = 'block'; dom.style.display = 'block';
dom.innerHTML = '<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;"><%:Processing, please wait…%></div>'; dom.innerHTML = '<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;"><%:Processing, please wait…%></div>';
const chunkSize = 1000; // Fragmented sending to overcome uhttpd's limitations, with each fragment containing 1000 characters. const chunkSize = 1000; // Fragmented sending to overcome uhttpd's limitations, with each fragment containing 1000 characters.
const totalChunks = Math.ceil(link.length / chunkSize); const totalChunks = Math.ceil(link.length / chunkSize);
let currentChunk = 0; let currentChunk = 0;
@@ -1266,7 +1266,7 @@ table td, .table .td {
} }
} }
} }
const set_node_div = { const set_node_div = {
section: '', section: '',
open(cbi_id) { open(cbi_id) {
@@ -1606,7 +1606,7 @@ table td, .table .td {
} }
}); });
} }
function dom_event() { function dom_event() {
waitForElement('input[type="checkbox"][name*="<%=appname%>"][name*="show_node_info"]', function(el) { waitForElement('input[type="checkbox"][name*="<%=appname%>"][name*="show_node_info"]', function(el) {
el.addEventListener("change", () => { el.addEventListener("change", () => {
@@ -1662,7 +1662,7 @@ table td, .table .td {
}; };
<% end -%> <% end -%>
dom_event(); dom_event();
const links = document.querySelectorAll('a'); const links = document.querySelectorAll('a');
links.forEach(link => { links.forEach(link => {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
@@ -87,9 +87,9 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
var checkBoxList = []; var checkBoxList = [];
var len = domList.length; var len = domList.length;
while(len--) { while(len--) {
var dom = domList[len];   var dom = domList[len];
if(dom.type == 'checkbox' && dom.checked) {   if(dom.type == 'checkbox' && dom.checked) {
checkBoxList.push(dom.name);   checkBoxList.push(dom.name);
} }
} }
XHR.get('<%=api.url("update_rules")%>', { XHR.get('<%=api.url("update_rules")%>', {
@@ -106,7 +106,7 @@ local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
} }
); );
} }
function rollback_rules(btn, type) { function rollback_rules(btn, type) {
let ori_val = btn.value; let ori_val = btn.value;
btn.disabled = true; btn.disabled = true;
@@ -389,7 +389,7 @@ table td, .table .td {
'' + table_html + '' + table_html +
'</div>' '</div>'
} }
function addTabDOM(li, content) { function addTabDOM(li, content) {
let tab_ul_html = '<ul class="cbi-tabmenu">'; let tab_ul_html = '<ul class="cbi-tabmenu">';
let tab_content_html = '<fieldset class="cbi-section-shunt_rule cbi-section-shunt_rule-tabbed" id="cbi-<%=appname%>-shunt_rules">'; let tab_content_html = '<fieldset class="cbi-section-shunt_rule cbi-section-shunt_rule-tabbed" id="cbi-<%=appname%>-shunt_rules">';
@@ -413,7 +413,7 @@ table td, .table .td {
if (default_group) { if (default_group) {
cbi_t_switch("<%=appname%>.shunt_rules", default_group) cbi_t_switch("<%=appname%>.shunt_rules", default_group)
} }
origin_group_shunt_rule_order = {}; origin_group_shunt_rule_order = {};
for (let group in group_shunt_rules) { for (let group in group_shunt_rules) {
origin_group_shunt_rule_order[group] = get_shunt_rule_order(group); origin_group_shunt_rule_order[group] = get_shunt_rule_order(group);
@@ -17,7 +17,7 @@ local prefix = self.option_prefix or ""
if (x && x.status == 200 && data.code == 1) { if (x && x.status == 200 && data.code == 1) {
const private_key_dom = getOption("<%=self.config%>", "<%=section%>", "<%=prefix%>wireguard_private_key"); const private_key_dom = getOption("<%=self.config%>", "<%=section%>", "<%=prefix%>wireguard_private_key");
private_key_dom.value = data.data.private_key; private_key_dom.value = data.data.private_key;
const public_key_dom = getOption("<%=self.config%>", "<%=section%>", "<%=prefix%>wireguard_public_key"); const public_key_dom = getOption("<%=self.config%>", "<%=section%>", "<%=prefix%>wireguard_public_key");
public_key_dom.value = data.data.public_key; public_key_dom.value = data.data.public_key;
} else { } else {
@@ -21,7 +21,7 @@ local sectiontype = self.sectiontype
} }
); );
} }
var edit_btn = document.getElementById("cbi-<%=config%>-<%=sectiontype%>").getElementsByClassName("cbi-button cbi-button-edit"); var edit_btn = document.getElementById("cbi-<%=config%>-<%=sectiontype%>").getElementsByClassName("cbi-button cbi-button-edit");
for (var i = 0; i < edit_btn.length; i++) { for (var i = 0; i < edit_btn.length; i++) {
try { try {
@@ -2,7 +2,7 @@
if [ -e "/etc/config/ucitrack" ]; then if [ -e "/etc/config/ucitrack" ]; then
uci -q batch <<-EOF uci -q batch <<-EOF
delete ucitrack.@passwall2[-1] delete ucitrack.@passwall2[-1]
add ucitrack passwall2 add ucitrack passwall2
set ucitrack.@passwall2[-1].init=passwall2 set ucitrack.@passwall2[-1].init=passwall2
commit ucitrack commit ucitrack
@@ -16,7 +16,7 @@ config global
dns.google.com 8.8.8.8' dns.google.com 8.8.8.8'
option log_node '1' option log_node '1'
option loglevel 'error' option loglevel 'error'
config global_haproxy config global_haproxy
option balancing_enable '0' option balancing_enable '0'
@@ -53,7 +53,7 @@ config global_app
config global_subscribe config global_subscribe
option filter_keyword_mode '1' option filter_keyword_mode '1'
config global_singbox config global_singbox
config nodes 'examplenode' config nodes 'examplenode'
@@ -781,7 +781,7 @@ run_ipset_chinadns_ng() {
node_servers=$(uci show "${CONFIG}" | grep -E "(.address=|.download_address=)" | cut -d "'" -f 2) node_servers=$(uci show "${CONFIG}" | grep -E "(.address=|.download_address=)" | cut -d "'" -f 2)
hosts_foreach "node_servers" host_from_url | grep '[a-zA-Z]$' | sort -u | grep -v "engage.cloudflareclient.com" > $TMP_ACL_PATH/vpslist hosts_foreach "node_servers" host_from_url | grep '[a-zA-Z]$' | sort -u | grep -v "engage.cloudflareclient.com" > $TMP_ACL_PATH/vpslist
} }
[ -n "${ipset}" ] && { [ -n "${ipset}" ] && {
set_names=$ipset set_names=$ipset
vps_set_names="psw2_vps,psw2_vps6" vps_set_names="psw2_vps,psw2_vps6"
@@ -213,7 +213,7 @@ function acl_app(l)
add_args(run_args, "config_file", config_file) add_args(run_args, "config_file", config_file)
add_args(run_args, "loglevel", v.loglevel) add_args(run_args, "loglevel", v.loglevel)
add_args(run_args, "log_file", log_file) add_args(run_args, "log_file", log_file)
local out = io.open(api.TMP_ACL_PATH .. "/acl_node_" .. flag , "a") local out = io.open(api.TMP_ACL_PATH .. "/acl_node_" .. flag , "a")
out:write(table.concat(run_args, " ")) out:write(table.concat(run_args, " "))
out:close() out:close()
@@ -120,9 +120,9 @@ function copy_instance(var)
local TMP_DNSMASQ_PATH = var["TMP_DNSMASQ_PATH"] local TMP_DNSMASQ_PATH = var["TMP_DNSMASQ_PATH"]
local conf_lines = {} local conf_lines = {}
local DEFAULT_DNSMASQ_CFGID = sys.exec("echo -n $(uci -q show dhcp.@dnsmasq[0] | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')") local DEFAULT_DNSMASQ_CFGID = sys.exec("echo -n $(uci -q show dhcp.@dnsmasq[0] | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')")
local conf_file = "/var/etc/dnsmasq.conf." .. DEFAULT_DNSMASQ_CFGID local conf_file = "/var/etc/dnsmasq.conf." .. DEFAULT_DNSMASQ_CFGID
local retry = 5 local retry = 5
while not fs.access(conf_file) and retry > 0 do while not fs.access(conf_file) and retry > 0 do
api.nixio.nanosleep(1, 0) api.nixio.nanosleep(1, 0)
@@ -291,7 +291,7 @@ load_acl() {
} }
local comment_l="$(i18n "Local")" local comment_l="$(i18n "Local")"
if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then if [ -n "$node" ] && ([ -z "$no_tcp_local_proxy" ] || [ -z "$no_udp_local_proxy" ]); then
[ -n "$dns_redirect_port" ] && { [ -n "$dns_redirect_port" ] && {
#$ipt_m -A PSW2_OUTPUT $(comment "${comment_l}") -p udp --dport 53 -j ACCEPT #$ipt_m -A PSW2_OUTPUT $(comment "${comment_l}") -p udp --dport 53 -j ACCEPT
@@ -390,7 +390,7 @@ load_acl() {
$ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN $ipt_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN" insert_rule_before "$ipt_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
$ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN $ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW2") -o lo -j RETURN
insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN" insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW2) -m mark --mark ${FWMARK} -j RETURN"
@@ -463,7 +463,7 @@ load_acl() {
log 2 "${msg}$(i18n "not proxy all %s" "TCP")" log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi fi
} }
[ -n "$udp_no_redir_ports" ] && { [ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then if ! has_1_65535 "$udp_no_redir_ports"; then
[ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null [ "$_ipv4" != "1" ] && add_port_rules "$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp" $udp_no_redir_ports "-j RETURN" 2>/dev/null
@@ -475,7 +475,7 @@ load_acl() {
log 2 "${msg}$(i18n "not proxy all %s" "UDP")" log 2 "${msg}$(i18n "not proxy all %s" "UDP")"
fi fi
} }
if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then if ([ -z "$no_tcp_proxy" ] || [ -z "$no_udp_proxy" ]) && [ -n "$dns_redirect_port" ]; then
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j ACCEPT $ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j ACCEPT
$ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j ACCEPT $ipt_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j ACCEPT
@@ -508,7 +508,7 @@ load_acl() {
add_shunt_t_rule "${shunt_list4}" "$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source}" "$(REDIRECT)" add_shunt_t_rule "${shunt_list4}" "$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source}" "$(REDIRECT)"
$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT) $ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT)
} }
[ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && { [ "$accept_icmpv6" = "1" ] && [ "$PROXY_IPV6" == "1" ] && {
$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null $ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} -d $FAKE_IP_6 $(REDIRECT) 2>/dev/null
add_shunt_t_rule "${shunt_list6}" "$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source}" "$(REDIRECT)" 2>/dev/null add_shunt_t_rule "${shunt_list6}" "$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source}" "$(REDIRECT)" 2>/dev/null
@@ -650,12 +650,12 @@ update_wan_sets() {
add_firewall_rule() { add_firewall_rule() {
log_i18n 0 "Starting to load %s firewall rules..." "iptables" log_i18n 0 "Starting to load %s firewall rules..." "iptables"
ipset -! create $IPSET_LOCAL nethash maxelem 1048576 ipset -! create $IPSET_LOCAL nethash maxelem 1048576
ipset -! create $IPSET_DIRECT nethash maxelem 1048576 ipset -! create $IPSET_DIRECT nethash maxelem 1048576
ipset -! create $IPSET_VPS iphash maxelem 1048576 ipset -! create $IPSET_VPS iphash maxelem 1048576
ipset -! create $IPSET_WAN nethash maxelem 1048576 ipset -! create $IPSET_WAN nethash maxelem 1048576
ipset -! create $IPSET_LOCAL6 nethash family inet6 maxelem 1048576 ipset -! create $IPSET_LOCAL6 nethash family inet6 maxelem 1048576
ipset -! create $IPSET_DIRECT6 nethash family inet6 maxelem 1048576 ipset -! create $IPSET_DIRECT6 nethash family inet6 maxelem 1048576
ipset -! create $IPSET_VPS6 iphash family inet6 maxelem 1048576 ipset -! create $IPSET_VPS6 iphash family inet6 maxelem 1048576
@@ -734,7 +734,7 @@ add_firewall_rule() {
$ipt_n -N PSW2 $ipt_n -N PSW2
$ipt_n -A PSW2 $(dst $IPSET_VPS) -j RETURN $ipt_n -A PSW2 $(dst $IPSET_VPS) -j RETURN
$ipt_n -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN $ipt_n -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
[ "$accept_icmp" = "1" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p icmp -j PSW2" [ "$accept_icmp" = "1" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p icmp -j PSW2"
[ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p tcp -j PSW2" [ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "$(dst $IPSET_DIRECT !) -p tcp -j PSW2"
@@ -784,7 +784,7 @@ add_firewall_rule() {
$ip6t_n -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN $ip6t_n -A PSW2_OUTPUT $(dst $IPSET_VPS6) -j RETURN
$ip6t_n -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN $ip6t_n -A PSW2_OUTPUT -m mark --mark 0xff/0xff -j RETURN
} }
$ip6t_n -N PSW2_DNS $ip6t_n -N PSW2_DNS
if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then if [ $(config_n_get @global[0] dns_redirect "1") = "0" ]; then
#Only hijack when dest address is local IP #Only hijack when dest address is local IP
@@ -945,7 +945,7 @@ gen_include() {
${__ipt} ${__ipt}
${__ip6t} ${__ip6t}
return 0 return 0
EOF EOF
return 0 return 0
@@ -26,7 +26,7 @@ while [ "$ENABLED" -eq 1 ]; do
fi fi
done done
} }
rm -f $LOCK_FILE rm -f $LOCK_FILE
sleep 58s sleep 58s
done done
@@ -157,20 +157,20 @@ insert_nftset() {
RS = "[ \t\n\r]+" RS = "[ \t\n\r]+"
ORS = "" ORS = ""
} }
$0 != "" { $0 != "" {
if (!first) { if (!first) {
printf "add element %s %s { \n", t, n printf "add element %s %s { \n", t, n
first = 1 first = 1
} else { } else {
print ",\n" print ",\n"
} }
printf " %s", $0 printf " %s", $0
} }
END { END {
if (first) { if (first) {
print "\n }\n" print "\n }\n"
} }
}' | nft -f - }' | nft -f -
} }
gen_nftset() { gen_nftset() {
@@ -455,7 +455,7 @@ load_acl() {
continue continue
fi fi
msg="${msg1}${msg}" msg="${msg1}${msg}"
[ -n "$tcp_no_redir_ports" ] && { [ -n "$tcp_no_redir_ports" ] && {
if ! has_1_65535 "$tcp_no_redir_ports"; then if ! has_1_65535 "$tcp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\"" nft "add rule $NFTABLE_NAME $nft_prerouting_chain ${_ipt_source} ip protocol tcp $(factor $tcp_no_redir_ports "tcp dport") counter return comment \"$remarks\""
@@ -467,7 +467,7 @@ load_acl() {
log 2 "${msg}$(i18n "not proxy all %s" "TCP")" log 2 "${msg}$(i18n "not proxy all %s" "TCP")"
fi fi
} }
[ -n "$udp_no_redir_ports" ] && { [ -n "$udp_no_redir_ports" ] && {
if ! has_1_65535 "$udp_no_redir_ports"; then if ! has_1_65535 "$udp_no_redir_ports"; then
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ${_ipt_source} $(factor $udp_no_redir_ports "udp dport") counter return comment \"$remarks\""
@@ -958,7 +958,7 @@ gen_include() {
cat <<-EOF >> $FWI cat <<-EOF >> $FWI
${__nft} ${__nft}
return 0 return 0
EOF EOF
return 0 return 0
@@ -155,7 +155,7 @@ do
if true then if true then
local szType = "@global[0]" local szType = "@global[0]"
local option = "node" local option = "node"
local node_id = uci_get(szType, option) local node_id = uci_get(szType, option)
CONFIG[#CONFIG + 1] = { CONFIG[#CONFIG + 1] = {
log = true, log = true,
@@ -651,7 +651,7 @@ local function parseClashNode(node, add_mode, group, sub_cfg)
end end
end end
result.transport = node.network and string.lower(node.network) or "tcp" result.transport = node.network and string.lower(node.network) or "tcp"
if result.type == "sing-box" and result.transport == "raw" then if result.type == "sing-box" and result.transport == "raw" then
result.transport = "tcp" result.transport = "tcp"
elseif result.type == "Xray" and result.transport == "tcp" then elseif result.type == "Xray" and result.transport == "tcp" then
result.transport = "raw" result.transport = "raw"
@@ -723,7 +723,7 @@ local function parseClashNode(node, add_mode, group, sub_cfg)
result.reality_shortId = (node["reality-opts"] and node["reality-opts"]["short-id"]) or nil result.reality_shortId = (node["reality-opts"] and node["reality-opts"]["short-id"]) or nil
end end
result.transport = node.network and string.lower(node.network) or "tcp" result.transport = node.network and string.lower(node.network) or "tcp"
if result.type == "sing-box" and result.transport == "raw" then if result.type == "sing-box" and result.transport == "raw" then
result.transport = "tcp" result.transport = "tcp"
elseif result.type == "Xray" and result.transport == "tcp" then elseif result.type == "Xray" and result.transport == "tcp" then
result.transport = "raw" result.transport = "raw"
@@ -914,7 +914,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
result.protocol = hostInfo[#hostInfo-3] result.protocol = hostInfo[#hostInfo-3]
result.method = hostInfo[#hostInfo-2] result.method = hostInfo[#hostInfo-2]
result.obfs = hostInfo[#hostInfo-1] result.obfs = hostInfo[#hostInfo-1]
result.password = base64Decode(hostInfo[#hostInfo]) result.password = base64Decode(hostInfo[#hostInfo])
local params = {} local params = {}
for _, v in pairs(split(dat[2], '&')) do for _, v in pairs(split(dat[2], '&')) do
local s = v:find("=", 1, true) local s = v:find("=", 1, true)
@@ -1001,7 +1001,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if not info.net then info.net = "tcp" end if not info.net then info.net = "tcp" end
info.net = string.lower(info.net) info.net = string.lower(info.net)
if result.type == "sing-box" and info.net == "raw" then if result.type == "sing-box" and info.net == "raw" then
info.net = "tcp" info.net = "tcp"
elseif result.type == "Xray" and info.net == "tcp" then elseif result.type == "Xray" and info.net == "tcp" then
info.net = "raw" info.net = "raw"
@@ -1282,7 +1282,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if params.type then if params.type then
params.type = string.lower(params.type) params.type = string.lower(params.type)
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -1447,7 +1447,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "Trojan", "Trojan")) log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "Trojan", "Trojan"))
return nil return nil
end end
local alias = "" local alias = ""
if content:find("#") then if content:find("#") then
local idx_sp = content:find("#") local idx_sp = content:find("#")
@@ -1511,7 +1511,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if not params.type then params.type = "tcp" end if not params.type then params.type = "tcp" end
params.type = string.lower(params.type) params.type = string.lower(params.type)
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -1652,7 +1652,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
if ({ xhttp=true, kcp=true, mkcp=true })[params.type] and result.type ~= "Xray" and has_xray then if ({ xhttp=true, kcp=true, mkcp=true })[params.type] and result.type ~= "Xray" and has_xray then
result.type = "Xray" result.type = "Xray"
end end
if result.type == "sing-box" and params.type == "raw" then if result.type == "sing-box" and params.type == "raw" then
params.type = "tcp" params.type = "tcp"
elseif result.type == "Xray" and params.type == "tcp" then elseif result.type == "Xray" and params.type == "tcp" then
params.type = "raw" params.type = "raw"
@@ -1791,7 +1791,7 @@ local function processData(szType, content, add_mode, group, sub_cfg)
content = content:sub(0, idx_sp - 1) content = content:sub(0, idx_sp - 1)
end end
result.remarks = UrlDecode(alias) result.remarks = UrlDecode(alias)
local query = split(content:gsub("/%?", "?"), '%?') local query = split(content:gsub("/%?", "?"), '%?')
local host_port = query[1] local host_port = query[1]
local params = {} local params = {}
@@ -2508,7 +2508,7 @@ local function update_node(manual)
uci_set(cfgid, "chain_proxy", "3") uci_set(cfgid, "chain_proxy", "3")
uci_set(cfgid, "outbound_iface", outbound_iface_group) uci_set(cfgid, "outbound_iface", outbound_iface_group)
end end
end end
end end
end end
end end