🌴 Sync 2026-04-20 08:30:53

This commit is contained in:
github-actions[bot] committed 2026-04-20 08:30:53 +08:00
1 parent 90adc6da11
commit f994078db9
24 files changed
+1811 -709

No files matched your search

@@ -933,8 +933,8 @@ start_haproxy() {
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
haproxy_path=$TMP_PATH/haproxy
haproxy_conf="config.cfg"
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf} -dns ${LOCAL_DNS:-${AUTO_DNS}}
ln_run ${QUEUE_RUN} "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}"
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf}
ln_run 0 "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}"
}
run_copy_dnsmasq() {
@@ -1,7 +1,7 @@
#!/usr/bin/lua
local api = require ("luci.passwall2.api")
local appname = "passwall2"
local appname = api.appname
local fs = api.fs
local jsonc = api.jsonc
local uci = api.uci
@@ -18,11 +18,12 @@ end
local var = api.get_args(arg)
local haproxy_path = var["-path"]
local haproxy_conf = var["-conf"]
local haproxy_dns = var["-dns"] or "119.29.29.29:53,223.5.5.5:53"
local haproxy_dns = "127.0.0.1"
local cpu_thread = sys.exec('echo -n $(cat /proc/cpuinfo | grep "processor" | wc -l)') or "1"
local health_check_type = uci:get(appname, "@global_haproxy[0]", "health_check_type") or "tcp"
local health_check_inter = uci:get(appname, "@global_haproxy[0]", "health_check_inter") or "10"
local health_check_inter = uci:get(appname, "@global_haproxy[0]", "health_check_inter") or "20"
local balancingStrategy = uci:get(appname, "@global_haproxy[0]", "balancingStrategy") or "roundrobin"
local console_port = uci:get(appname, "@global_haproxy[0]", "console_port")
local bind_local = uci:get(appname, "@global_haproxy[0]", "bind_local") or "0"
local bind_address = "0.0.0.0"
@@ -38,35 +39,37 @@ local f_out = io.open(haproxy_file, "a")
local haproxy_config = [[
global
daemon
log 127.0.0.1 local2
maxconn 60000
stats socket {{path}}/haproxy.sock
log 127.0.0.1 local2
maxconn 60000
stats socket {{path}}/haproxy.sock
nbthread {{nbthread}}
external-check
insecure-fork-wanted
spread-checks 50
tune.max-checks-per-thread 5
defaults
mode tcp
log global
option tcplog
option dontlognull
mode tcp
log global
option tcplog
option dontlognull
option http-server-close
#option forwardfor except 127.0.0.0/8
option redispatch
retries 2
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
#option forwardfor except 127.0.0.0/8
option redispatch
retries 2
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
timeout check 10s
maxconn 3000
resolvers mydns
resolve_retries 1
timeout resolve 5s
hold valid 600s
resolve_retries 1
timeout resolve 5s
hold valid 600s
{{dns}}
]]
@@ -97,10 +100,12 @@ uci:foreach(appname, "haproxy_config", function(t)
local lbss = t.lbss
local listen_port = tonumber(t.haproxy_port) or 0
local server_node = uci:get_all(appname, lbss)
if server_node and server_node.address and server_node.port then
server_remark = server_node.address .. ":" .. server_node.port
local hop = (health_check_type == "passwall_logic") and (server_node.hysteria_hop or server_node.hysteria2_hop) or nil
hop = hop and hop:gsub(":", "-") or nil
if server_node and server_node.address and (server_node.port or hop) then
server_remark = server_node.address .. ":" .. (server_node.port or hop)
server_address = server_node.address
server_port = server_node.port
server_port = server_node.port or hop
t.origin_address = server_address
t.origin_port = server_port
if health_check_type == "passwall_logic" then
@@ -143,6 +148,10 @@ uci:foreach(appname, "haproxy_config", function(t)
end
end)
local inter = tonumber((health_check_inter or "20"):match("^%d+"))
inter = (inter and inter >= 20) and inter or 20
local inter_arg = "inter " .. inter .. "s fastinter " .. inter / 2 .. "s downinter " .. inter * 1.5 .. "s"
local sortTable = {}
for i in pairs(listens) do
if i ~= nil then
@@ -158,14 +167,14 @@ for i, port in pairs(sortTable) do
listen %s
bind %s:%s
mode tcp
balance roundrobin
]], port, bind_address, port))
balance %s
]], port, bind_address, port, balancingStrategy))
if health_check_type == "passwall_logic" then
f_out:write(string.format([[
option external-check
external-check command "/usr/share/passwall2/haproxy_check.sh"
]], port, port))
external-check command "/usr/share/%s/haproxy_check.sh"
]], appname))
end
local count_M, count_B = 1, 1
@@ -180,7 +189,7 @@ listen %s
count_B = count_B + 1
end
local server = o.server_address .. ":" .. o.server_port
local server_conf = "server {{remark}} {{server}} weight {{weight}} {{resolvers}} check inter {{inter}} rise 1 fall 3 {{backup}}"
local server_conf = "server {{remark}} {{server}} weight {{weight}} {{resolvers}} check {{inter_arg}} rise 2 fall 2 {{backup}}"
server_conf = server_conf:gsub("{{remark}}", remark)
server_conf = server_conf:gsub("{{server}}", server)
server_conf = server_conf:gsub("{{weight}}", o.lbweight)
@@ -189,13 +198,13 @@ listen %s
resolvers = ""
end
server_conf = server_conf:gsub("{{resolvers}}", resolvers)
server_conf = server_conf:gsub("{{inter}}", tonumber(health_check_inter) .. "s")
server_conf = server_conf:gsub("{{inter_arg}}", inter_arg)
server_conf = server_conf:gsub("{{backup}}", tostring(o.backup) == "1" and "backup" or "")
f_out:write(" " .. server_conf .. "\n")
f_out:write(" " .. api.trim(server_conf) .. "\n")
if o.export ~= "0" then
sys.call(string.format(". /usr/share/passwall2/utils.sh ; add_ip2route %s %s", o.origin_address, o.export))
sys.call(string.format(". /usr/share/%s/utils.sh ; add_ip2route %s %s", appname, o.origin_address, o.export))
end
log(2, string.format(api.i18n.translatef("Node: %s:%s, Weight: %s", o.origin_address, o.origin_port, o.lbweight)))
@@ -24,7 +24,7 @@ if /usr/bin/curl --help all | grep -q "\-\-retry-all-errors"; then
extra_params="${extra_params} --retry-all-errors"
fi
status=$(/usr/bin/curl -I -o /dev/null -skL ${extra_params} --connect-timeout 3 --retry 2 --max-time 10 -w "%{http_code}" "${probeUrl}")
status=$(/usr/bin/curl -I -o /dev/null -skL ${extra_params} --connect-timeout 3 --retry 1 --max-time 6 -w "%{http_code}" "${probeUrl}")
case "$status" in
200|204)
@@ -617,6 +617,24 @@ filter_direct_node_list() {
done
}
update_wan_sets() {
local WAN_IP=$(get_wan_ips ip4)
[ -n "$WAN_IP" ] && {
ipset -F "$IPSET_WAN"
for wan_ip in $WAN_IP; do
ipset -! add "$IPSET_WAN" "$wan_ip"
done
}
local WAN6_IP=$(get_wan_ips ip6)
[ -n "$WAN6_IP" ] && {
ipset -F "$IPSET_WAN6"
for wan6_ip in $WAN6_IP; do
ipset -! add "$IPSET_WAN6" "$wan6_ip"
done
}
}
add_firewall_rule() {
log_i18n 0 "Starting to load %s firewall rules..." "iptables"
@@ -665,6 +683,8 @@ add_firewall_rule() {
EOF
}
update_wan_sets
[ -n "$ISP_DNS" ] && {
for ispip in $ISP_DNS; do
ipset -! add $IPSET_LAN $ispip
@@ -716,6 +736,7 @@ add_firewall_rule() {
$ipt_n -N PSW2
$ipt_n -A PSW2 $(dst $IPSET_LAN) -j RETURN
$ipt_n -A PSW2 $(dst $IPSET_VPS) -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" "-p icmp -j PSW2"
[ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p tcp -j PSW2"
@@ -747,19 +768,9 @@ add_firewall_rule() {
$ipt_m -N PSW2
$ipt_m -A PSW2 $(dst $IPSET_LAN) -j RETURN
$ipt_m -A PSW2 $(dst $IPSET_VPS) -j RETURN
$ipt_m -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
$ipt_m -A PSW2 -m conntrack --ctdir REPLY -j RETURN
WAN_IP=$(get_wan_ips ip4)
[ -n "${WAN_IP}" ] && {
ipset -F $IPSET_WAN
for wan_ip in $WAN_IP; do
ipset -! add $IPSET_WAN ${wan_ip}
done
$ipt_n -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
$ipt_m -A PSW2 $(comment "WAN_IP_RETURN") $(dst $IPSET_WAN) -j RETURN
}
unset WAN_IP wan_ip
insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "-j PSW2"
# Only TCP, UDP Invalid.
insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT"
@@ -807,17 +818,8 @@ add_firewall_rule() {
$ip6t_m -N PSW2
$ip6t_m -A PSW2 $(dst $IPSET_LAN6) -j RETURN
$ip6t_m -A PSW2 $(dst $IPSET_VPS6) -j RETURN
$ip6t_m -A PSW2 $(comment "WAN6_IP_RETURN") $(dst $IPSET_WAN6) -j RETURN
$ip6t_m -A PSW2 -m conntrack --ctdir REPLY -j RETURN
WAN6_IP=$(get_wan_ips ip6)
[ -n "${WAN6_IP}" ] && {
ipset -F $IPSET_WAN6
for wan6_ip in $WAN6_IP; do
ipset -! add $IPSET_WAN6 ${wan6_ip}
done
$ip6t_m -A PSW2 $(comment "WAN6_IP_RETURN") $(dst $IPSET_WAN6) -j RETURN
}
unset WAN6_IP wan6_ip
insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2"
# Only TCP, UDP Invalid.
@@ -835,7 +837,7 @@ add_firewall_rule() {
local dns_port=$(echo $auto_dns | awk -F '#' '{print $2}')
if [[ "$dns_address" == *::* ]]; then
$ip6t_m -I PSW2_OUTPUT -p udp -d ${dns_address} --dport ${dns_port:-53} -j RETURN
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "ip6tables" "${dns_address}:${dns_port:-53}")"
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "ip6tables" "[${dns_address}]:${dns_port:-53}")"
else
$ipt_m -I PSW2_OUTPUT -p udp -d ${dns_address} --dport ${dns_port:-53} -j RETURN
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "iptables" "${dns_address}:${dns_port:-53}")"
@@ -1050,7 +1052,7 @@ gen_include() {
local __ipt=""
[ -n "${ipt}" ] && {
__ipt=$(cat <<- EOF
. $UTILS_PATH
${MY_PATH} update_wan_sets
$ipt-save -c | grep -v "PSW2" | $ipt-restore -c
$ipt-restore -n <<-EOT
$(extract_rules 4 nat)
@@ -1062,21 +1064,13 @@ gen_include() {
\$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "mwan3" "-j PSW2")
\$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
WAN_IP=\$(get_wan_ips ip4)
[ ! -z "\${WAN_IP}" ] && {
ipset -F $IPSET_WAN
for wan_ip in \$WAN_IP; do
ipset -! add $IPSET_WAN \${wan_ip}
done
}
EOF
)
}
local __ip6t=""
[ -n "${ip6t}" ] && {
__ip6t=$(cat <<- EOF
. $UTILS_PATH
${MY_PATH} update_wan_sets
$ip6t-save -c | grep -v "PSW2" | $ip6t-restore -c
$ip6t-restore -n <<-EOT
$(extract_rules 6 nat)
@@ -1087,20 +1081,12 @@ gen_include() {
\$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2")
\$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
WAN6_IP=\$(get_wan_ips ip6)
[ ! -z "\${WAN6_IP}" ] && {
ipset -F $IPSET_WAN6
for wan6_ip in \$WAN6_IP; do
ipset -! add $IPSET_WAN6 \${wan6_ip}
done
}
EOF
)
}
cat <<-EOF >> $FWI
${__ipt}
${__ip6t}
return 0
@@ -1158,6 +1144,9 @@ get_ip6t_bin)
filter_direct_node_list)
filter_direct_node_list
;;
update_wan_sets)
update_wan_sets "$@"
;;
stop)
stop
;;
@@ -680,6 +680,20 @@ mwan3_start() {
nft list chain ip mangle mwan3_hook >/dev/null 2>&1 && nft insert rule ip mangle mwan3_hook ct mark ${FWMARK} counter return >/dev/null 2>&1
}
update_wan_sets() {
local WAN_IP=$(get_wan_ips ip4)
[ -n "$WAN_IP" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN
echo "$WAN_IP" | insert_nftset $NFTSET_WAN "-1"
}
local WAN6_IP=$(get_wan_ips ip6)
[ -n "${WAN6_IP}" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN6
echo "$WAN6_IP" | insert_nftset $NFTSET_WAN6 "-1"
}
}
add_firewall_rule() {
log_i18n 0 "Starting to load %s firewall rules..." "nftables"
gen_nft_tables
@@ -714,6 +728,8 @@ add_firewall_rule() {
[ -n "$lan_ip6" ] && echo $lan_ip6 | insert_nftset $NFTSET_LAN6 "-1"
}
update_wan_sets
[ -n "$ISP_DNS" ] && {
echo "$ISP_DNS" | insert_nftset $NFTSET_LAN 0
for ispip in $ISP_DNS; do
@@ -835,14 +851,9 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME nat_output meta l4proto {icmp,icmpv6} counter jump PSW2_ICMP_REDIRECT"
fi
WAN_IP=$(get_wan_ips ip4)
[ -n "${WAN_IP}" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN
echo $WAN_IP | insert_nftset $NFTSET_WAN "-1"
[ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_NAT ip daddr @$NFTSET_WAN counter return comment \"WAN_IP_RETURN\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip daddr @$NFTSET_WAN counter return comment \"WAN_IP_RETURN\""
}
unset WAN_IP
#ipv4 wan_ip
[ -z "${is_tproxy}" ] && nft "add rule $NFTABLE_NAME PSW2_NAT ip daddr @$NFTSET_WAN counter return comment \"WAN_IP_RETURN\""
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip daddr @$NFTSET_WAN counter return comment \"WAN_IP_RETURN\""
ip rule add fwmark ${FWMARK} table 999 priority 999
ip route add local 0.0.0.0/0 dev lo table 999
@@ -867,10 +878,11 @@ add_firewall_rule() {
local dns_port=$(echo $auto_dns | awk -F '#' '{print $2}')
if [[ "$dns_address" == *::* ]]; then
nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp ip6 daddr ${dns_address} $(factor ${dns_port:-53} "udp dport") counter return"
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "nftables" "[${dns_address}]:${dns_port:-53}")"
else
nft "insert rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr ${dns_address} $(factor ${dns_port:-53} "udp dport") counter return"
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "nftables" "${dns_address}:${dns_port:-53}")"
fi
log_i18n 1 "$(i18n "Add direct DNS to %s: %s" "nftables" "${dns_address}:${dns_port:-53}")"
done
}
@@ -879,13 +891,7 @@ add_firewall_rule() {
nft "add rule $NFTABLE_NAME mangle_prerouting meta nfproto {ipv6} counter jump PSW2_MANGLE_V6"
nft "add rule $NFTABLE_NAME mangle_output meta nfproto {ipv6} counter jump PSW2_OUTPUT_MANGLE_V6 comment \"PSW2_OUTPUT_MANGLE\""
WAN6_IP=$(get_wan_ips ip6)
[ -n "${WAN6_IP}" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN6
echo $WAN6_IP | insert_nftset $NFTSET_WAN6 "-1"
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ip6 daddr @$NFTSET_WAN6 counter return comment \"WAN6_IP_RETURN\""
}
unset WAN6_IP
nft "add rule $NFTABLE_NAME PSW2_MANGLE_V6 ip6 daddr @$NFTSET_WAN6 counter return comment \"WAN6_IP_RETURN\""
ip -6 rule add fwmark ${FWMARK} table 999 priority 999
ip -6 route add local ::/0 dev lo table 999
@@ -894,7 +900,7 @@ add_firewall_rule() {
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
TCP_LOCALHOST_PROXY=$LOCALHOST_PROXY
UDP_LOCALHOST_PROXY=$LOCALHOST_PROXY
msg="$(i18n "[Local],")"
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME $nft_output_chain ip protocol tcp $(factor $TCP_NO_REDIR_PORTS "tcp dport") counter return"
@@ -906,7 +912,7 @@ add_firewall_rule() {
log 1 "${msg}$(i18n "not proxy all %s" "TCP")"
fi
}
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE_V6 meta l4proto udp $(factor $UDP_NO_REDIR_PORTS "udp dport") counter return"
@@ -1088,20 +1094,9 @@ gen_include() {
local __nft=" "
__nft=$(cat <<- EOF
. $UTILS_PATH
[ -z "\$(nft list chain $NFTABLE_NAME mangle_prerouting | grep PSW2)" ] && nft -f ${nft_chain_file}
WAN_IP=\$(get_wan_ips ip4)
[ ! -z "\${WAN_IP}" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN
echo "\${WAN_IP}" | sh ${MY_PATH} insert_nftset $NFTSET_WAN "-1"
}
[ "$PROXY_IPV6" == "1" ] && {
WAN6_IP=\$(get_wan_ips ip6)
[ ! -z "\${WAN6_IP}" ] && {
nft flush set $NFTABLE_NAME $NFTSET_WAN6
echo "\${WAN6_IP}" | sh ${MY_PATH} insert_nftset $NFTSET_WAN6 "-1"
}
}
${MY_PATH} update_wan_sets
EOF
)
@@ -1150,6 +1145,9 @@ mwan3_start)
mwan3_stop)
mwan3_stop
;;
update_wan_sets)
update_wan_sets "$@"
;;
stop)
stop
;;
@@ -31,59 +31,60 @@ local has_ssr = api.is_finded("ssr-local") and api.is_finded("ssr-redir")
local has_singbox = api.finded_com("sing-box")
local has_xray = api.finded_com("xray")
local has_hysteria2 = api.finded_com("hysteria")
local allowInsecure_default = true
local DEFAULT_ALLOWINSECURE = true
local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
-- Nodes should be retrieved using the core type (if not set on the node subscription page, the default type will be used automatically).
local ss_type_default = api.get_core("ss_type", {{has_ss,"shadowsocks-libev"},{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}})
local trojan_type_default = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
local vmess_type_default = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
local vless_type_default = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
local hysteria2_type_default = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"},{has_xray,"xray"}})
local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss,"shadowsocks-libev"},{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}})
local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}})
local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_hysteria2,"hysteria2"},{has_singbox,"sing-box"},{has_xray,"xray"}})
local core_has = {
["xray"] = has_xray, ["sing-box"] = has_singbox, ["shadowsocks-libev"] = has_ss,["shadowsocks-rust"] = has_ss_rust,
["xray"] = has_xray,
["sing-box"] = has_singbox,
["shadowsocks-libev"] = has_ss,
["shadowsocks-rust"] = has_ss_rust,
["hysteria2"] = has_hysteria2
}
local domain_resolver, domain_resolver_dns, domain_resolver_dns_https, domain_strategy
local preproxy_node_group, to_node_group, chain_node_type = "", "", ""
-- Determine whether to filter node keywords
local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
local filter_keyword_keep_list_default = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
local function is_filter_keyword(value)
if filter_keyword_mode_default == "1" then
for k,v in ipairs(filter_keyword_discard_list_default) do
local function is_filter_keyword(mode, discard_list, keep_list, value)
if mode == "1" then
for k,v in ipairs(discard_list) do
if value:find(v, 1, true) then
return true
end
end
elseif filter_keyword_mode_default == "2" then
elseif mode == "2" then
local result = true
for k,v in ipairs(filter_keyword_keep_list_default) do
for k,v in ipairs(keep_list) do
if value:find(v, 1, true) then
result = false
end
end
return result
elseif filter_keyword_mode_default == "3" then
elseif mode == "3" then
local result = false
for k,v in ipairs(filter_keyword_discard_list_default) do
for k,v in ipairs(discard_list) do
if value:find(v, 1, true) then
result = true
end
end
for k,v in ipairs(filter_keyword_keep_list_default) do
for k,v in ipairs(keep_list) do
if value:find(v, 1, true) then
result = false
end
end
return result
elseif filter_keyword_mode_default == "4" then
elseif mode == "4" then
local result = true
for k,v in ipairs(filter_keyword_keep_list_default) do
for k,v in ipairs(keep_list) do
if value:find(v, 1, true) then
result = false
end
end
for k,v in ipairs(filter_keyword_discard_list_default) do
for k,v in ipairs(discard_list) do
if value:find(v, 1, true) then
result = true
end
@@ -425,16 +426,16 @@ local function get_subscribe_info(cfgid, value)
end
-- Configure the SS protocol implementation type
local function set_ss_implementation(result)
if ss_type_default == "shadowsocks-libev" and has_ss then
local function set_ss_implementation(ss_type, result)
if ss_type == "shadowsocks-libev" and has_ss then
result.type = "SS"
elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then
elseif ss_type == "shadowsocks-rust" and has_ss_rust then
result.type = 'SS-Rust'
elseif ss_type_default == "xray" and has_xray then
elseif ss_type == "xray" and has_xray then
result.type = 'Xray'
result.protocol = 'shadowsocks'
result.transport = 'raw'
elseif ss_type_default == "sing-box" and has_singbox then
elseif ss_type == "sing-box" and has_singbox then
result.type = 'sing-box'
result.protocol = 'shadowsocks'
else
@@ -445,8 +446,60 @@ local function set_ss_implementation(result)
end
-- Processing data
local function processData(szType, content, add_mode, group)
local function processData(szType, content, add_mode, group, sub_cfg)
--log(2, content, add_mode, group)
local default_allowinsecure = DEFAULT_ALLOWINSECURE
local default_filter_keyword_mode = DEFAULT_FILTER_KEYWORD_MODE
local default_filter_keyword_discard_list = DEFAULT_FILTER_KEYWORD_DISCARD_LIST
local default_filter_keyword_keep_list = DEFAULT_FILTER_KEYWORD_KEEP_LIST
local default_ss_type = DEFAULT_SS_TYPE
local default_trojan_type = DEFAULT_TROJAN_TYPE
local default_vmess_type = DEFAULT_VMESS_TYPE
local default_vless_type = DEFAULT_VLESS_TYPE
local default_hysteria2_type = DEFAULT_HYSTERIA2_TYPE
if sub_cfg then
if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then
default_allowinsecure = nil
end
local filter_keyword_mode = sub_cfg.filter_keyword_mode or "5" -- 5 is global
if filter_keyword_mode == "0" then
default_filter_keyword_mode = "0"
elseif filter_keyword_mode == "1" then
default_filter_keyword_mode = "1"
default_filter_keyword_discard_list = sub_cfg.filter_discard_list or {}
elseif filter_keyword_mode == "2" then
default_filter_keyword_mode = "2"
default_filter_keyword_keep_list = sub_cfg.filter_keep_list or {}
elseif filter_keyword_mode == "3" then
default_filter_keyword_mode = "3"
default_filter_keyword_keep_list = sub_cfg.filter_keep_list or {}
default_filter_keyword_discard_list = sub_cfg.filter_discard_list or {}
elseif filter_keyword_mode == "4" then
default_filter_keyword_mode = "4"
default_filter_keyword_keep_list = sub_cfg.filter_keep_list or {}
default_filter_keyword_discard_list = sub_cfg.filter_discard_list or {}
end
local ss_type = sub_cfg.ss_type or "global"
if ss_type ~= "global" and core_has[ss_type] then
default_ss_type = ss_type
end
local trojan_type = sub_cfg.trojan_type or "global"
if trojan_type ~= "global" and core_has[trojan_type] then
default_trojan_type = trojan_type
end
local vmess_type = sub_cfg.vmess_type or "global"
if vmess_type ~= "global" and core_has[vmess_type] then
default_vmess_type = vmess_type
end
local vless_type = sub_cfg.vless_type or "global"
if vless_type ~= "global" and core_has[vless_type] then
default_vless_type = vless_type
end
local hysteria2_type = sub_cfg.hysteria2_type or "global"
if hysteria2_type ~= "global" and core_has[hysteria2_type] then
default_hysteria2_type = hysteria2_type
end
end
local result = {
timeout = 60,
add_mode = add_mode, -- `0` for manual configuration, `1` for import, `2` for subscription
@@ -486,9 +539,9 @@ local function processData(szType, content, add_mode, group)
result.remarks = base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = jsonParse(content)
if vmess_type_default == "sing-box" and has_singbox then
if default_vmess_type == "sing-box" and has_singbox then
result.type = 'sing-box'
elseif vmess_type_default == "xray" and has_xray then
elseif default_vmess_type == "xray" and has_xray then
result.type = "Xray"
else
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "VMess", "VMess"))
@@ -559,12 +612,7 @@ local function processData(szType, content, add_mode, group)
if info.net == 'kcp' or info.net == 'mkcp' then
info.net = "mkcp"
result.mkcp_guise = info.type
result.mkcp_mtu = 1350
result.mkcp_tti = 50
result.mkcp_uplinkCapacity = 5
result.mkcp_downlinkCapacity = 20
result.mkcp_readBufferSize = 2
result.mkcp_writeBufferSize = 2
result.mkcp_seed = info.seed
end
if info.net == 'quic' then
result.quic_guise = info.type
@@ -599,7 +647,7 @@ local function processData(szType, content, add_mode, group)
result.tls_CertSha = info.pcs
result.tls_CertByName = info.vcn
local insecure = info.allowinsecure or info.allowInsecure or info.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
else
result.tls = "0"
end
@@ -615,7 +663,7 @@ local function processData(szType, content, add_mode, group)
return nil
end
elseif szType == "ss" then
result = set_ss_implementation(result)
result = set_ss_implementation(default_ss_type, result)
if not result then return nil end
--SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ]
@@ -825,12 +873,6 @@ local function processData(szType, content, add_mode, group)
if params.type == 'kcp' or params.type == 'mkcp' then
result.transport = "mkcp"
result.mkcp_guise = params.headerType or "none"
result.mkcp_mtu = 1350
result.mkcp_tti = 50
result.mkcp_uplinkCapacity = 5
result.mkcp_downlinkCapacity = 20
result.mkcp_readBufferSize = 2
result.mkcp_writeBufferSize = 2
result.mkcp_seed = params.seed
end
if params.type == 'quic' then
@@ -884,7 +926,7 @@ local function processData(szType, content, add_mode, group)
end
end
local insecure = params.allowinsecure or params.allowInsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
result.uot = params.udp
elseif (params.type ~= "tcp" and params.type ~= "raw") and (params.headerType and params.headerType ~= "none") then
result.error_msg = i18n.translatef("Please replace Xray or Sing-Box to support more transmission methods in Shadowsocks.")
@@ -893,7 +935,7 @@ local function processData(szType, content, add_mode, group)
if params["shadow-tls"] then
if result.type ~= "sing-box" and result.type ~= "SS-Rust" then
result.error_msg = ss_type_default .. " " .. i18n.translatef("unsupport %s plugin.", "shadow-tls")
result.error_msg = default_ss_type .. " " .. i18n.translatef("unsupport %s plugin.", "shadow-tls")
else
-- Parsing SS Shadow-TLS plugin parameters
local function parseShadowTLSParams(b64str, out)
@@ -935,10 +977,10 @@ local function processData(szType, content, add_mode, group)
end
end
elseif szType == "trojan" then
if trojan_type_default == "sing-box" and has_singbox then
if default_trojan_type == "sing-box" and has_singbox then
result.type = 'sing-box'
result.protocol = 'trojan'
elseif trojan_type_default == "xray" and has_xray then
elseif default_trojan_type == "xray" and has_xray then
result.type = 'Xray'
result.protocol = 'trojan'
else
@@ -988,7 +1030,7 @@ local function processData(szType, content, add_mode, group)
result.tls_CertSha = params.pcs
result.tls_CertByName = params.vcn
local insecure = params.allowinsecure or params.allowInsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
if not params.type then params.type = "tcp" end
params.type = string.lower(params.type)
@@ -1042,12 +1084,6 @@ local function processData(szType, content, add_mode, group)
if params.type == 'kcp' or params.type == 'mkcp' then
result.transport = "mkcp"
result.mkcp_guise = params.headerType or "none"
result.mkcp_mtu = 1350
result.mkcp_tti = 50
result.mkcp_uplinkCapacity = 5
result.mkcp_downlinkCapacity = 20
result.mkcp_readBufferSize = 2
result.mkcp_writeBufferSize = 2
result.mkcp_seed = params.seed
end
if params.type == 'quic' then
@@ -1079,7 +1115,7 @@ local function processData(szType, content, add_mode, group)
end
end
elseif szType == "ssd" then
result = set_ss_implementation(result)
result = set_ss_implementation(default_ss_type, result)
if not result then return nil end
result.address = content.server
result.port = content.port
@@ -1090,9 +1126,9 @@ local function processData(szType, content, add_mode, group)
result.group = content.airport
result.remarks = content.remarks
elseif szType == "vless" then
if vless_type_default == "sing-box" and has_singbox then
if default_vless_type == "sing-box" and has_singbox then
result.type = 'sing-box'
elseif vless_type_default == "xray" and has_xray then
elseif default_vless_type == "xray" and has_xray then
result.type = "Xray"
else
log(2, i18n.translatef("Skipping the %s node is due to incompatibility with the %s core program or incorrect node usage type settings.", "VLESS", "VLESS"))
@@ -1189,12 +1225,7 @@ local function processData(szType, content, add_mode, group)
if params.type == 'kcp' or params.type == 'mkcp' then
result.transport = "mkcp"
result.mkcp_guise = params.headerType or "none"
result.mkcp_mtu = 1350
result.mkcp_tti = 50
result.mkcp_uplinkCapacity = 5
result.mkcp_downlinkCapacity = 20
result.mkcp_readBufferSize = 2
result.mkcp_writeBufferSize = 2
result.mkcp_seed = params.seed
end
if params.type == 'quic' then
result.quic_guise = params.headerType or "none"
@@ -1250,7 +1281,7 @@ local function processData(szType, content, add_mode, group)
result.reality_mldsa65Verify = params.pqv or nil
end
local insecure = params.allowinsecure or params.allowInsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
end
result.port = port
@@ -1307,7 +1338,7 @@ local function processData(szType, content, add_mode, group)
result.hysteria_auth_password = params.auth
result.tls_serverName = params.peer or params.sni or ""
local insecure = params.allowinsecure or params.allowInsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
result.alpn = params.alpn
result.hysteria_up_mbps = params.upmbps
result.hysteria_down_mbps = params.downmbps
@@ -1353,12 +1384,12 @@ local function processData(szType, content, add_mode, group)
result.tls_CertSha = params.pcs
result.tls_CertByName = params.vcn
local insecure = params.allowinsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
result.hysteria2_tls_pinSHA256 = params.pinSHA256
result.hysteria2_hop = params.mport
if (hysteria2_type_default == "sing-box" and has_singbox) or (hysteria2_type_default == "xray" and has_xray) then
local is_singbox = hysteria2_type_default == "sing-box" and has_singbox
if (default_hysteria2_type == "sing-box" and has_singbox) or (default_hysteria2_type == "xray" and has_xray) then
local is_singbox = default_hysteria2_type == "sing-box" and has_singbox
result.type = is_singbox and 'sing-box' or 'Xray'
result.protocol = "hysteria2"
if params["obfs-password"] or params["obfs_password"] then
@@ -1433,7 +1464,7 @@ local function processData(szType, content, add_mode, group)
result.tuic_congestion_control = params.congestion_control or "cubic"
result.tuic_udp_relay_mode = params.udp_relay_mode or "native"
local insecure = params.allowinsecure or params.insecure or params.allow_insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
elseif szType == "anytls" then
if has_singbox then
result.type = 'sing-box'
@@ -1497,7 +1528,7 @@ local function processData(szType, content, add_mode, group)
end
result.port = port
local insecure = params.allowinsecure or params.insecure
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0")
result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (default_allowinsecure and "1" or "0")
end
elseif szType == 'naive+https' or szType == 'naive+quic' then
if has_singbox then
@@ -1840,6 +1871,29 @@ local function update_node(manual)
for _, v in ipairs(nodeResult) do
local remark = v["remark"]
local list = v["list"]
local sub_cfg = v["sub_cfg"]
local domain_resolver, domain_resolver_dns, domain_resolver_dns_https, domain_strategy
local preproxy_node_group, to_node_group, chain_node_type = "", "", ""
-- Subscription Group Chain Agent
local function valid_chain_node(node)
if not node then return "" end
local cp = uci:get(appname, node, "chain_proxy") or ""
local am = uci:get(appname, node, "add_mode") or "0"
chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or ""
if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then
chain_node_type = ""
return ""
end
return node
end
if sub_cfg then
domain_resolver = sub_cfg.domain_resolver
domain_resolver_dns = sub_cfg.domain_resolver_dns
domain_resolver_dns_https = sub_cfg.domain_resolver_dns_https
domain_strategy = (sub_cfg.domain_strategy == "UseIPv4" or sub_cfg.domain_strategy == "UseIPv6") and sub_cfg.domain_strategy or nil
preproxy_node_group = (sub_cfg.chain_proxy == "1") and valid_chain_node(sub_cfg.preproxy_node) or ""
to_node_group = (sub_cfg.chain_proxy == "2") and valid_chain_node(sub_cfg.to_node) or ""
end
for _, vv in ipairs(list) do
local cfgid = uci:section(appname, "nodes", api.gen_short_uuid())
for kkk, vvv in pairs(vv) do
@@ -1929,8 +1983,12 @@ local function update_node(manual)
end
end
local function parse_link(raw, add_mode, group, cfgid)
local function parse_link(raw, add_mode, group, sub_cfg)
if raw and #raw > 0 then
local cfgid
if sub_cfg then
cfgid = sub_cfg[".name"]
end
local nodes, szType
local node_list = {}
-- ssd appear to be in this format, starting with ssd://.
@@ -1965,17 +2023,17 @@ local function parse_link(raw, add_mode, group, cfgid)
xpcall(function ()
local result
if szType == 'ssd' then
result = processData(szType, v, add_mode, group)
result = processData(szType, v, add_mode, group, sub_cfg)
elseif not szType then
local node = api.trim(v)
local dat = split(node, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'vmess' or dat[1] == 'ssr' then
local link = api.trim(dat[2]:gsub("#.*$", ""))
result = processData(dat[1], base64Decode(link), add_mode, group)
result = processData(dat[1], base64Decode(link), add_mode, group, sub_cfg)
else
local link = dat[2]:gsub("&amp;", "&"):gsub("%s*#%s*", "#") -- Some odd links use "&" as "&", and include spaces before and after "#".
result = processData(dat[1], link, add_mode, group)
result = processData(dat[1], link, add_mode, group, sub_cfg)
end
end
else
@@ -1987,7 +2045,7 @@ local function parse_link(raw, add_mode, group, cfgid)
log(2, i18n.translatef("Discard node: %s, Reason:", result.remarks) .. " " .. result.error_msg)
elseif not result.type then
log(2, i18n.translatef("Discard node: %s, Reason:", result.remarks) .. " " .. i18n.translatef("No usable binary was found."))
elseif (add_mode == "2" and is_filter_keyword(result.remarks)) or not result.address or result.remarks == "NULL" or result.address == "127.0.0.1" or
elseif (add_mode == "2" and is_filter_keyword(default_filter_keyword_mode, default_filter_keyword_discard_list, default_filter_keyword_keep_list, result.remarks)) or not result.address or result.remarks == "NULL" or result.address == "127.0.0.1" or
(not datatypes.hostname(result.address) and not (api.is_ip(result.address))) then
log(2, i18n.translatef("Discard filter nodes: %s type node %s", result.type, result.remarks))
else
@@ -2007,7 +2065,8 @@ local function parse_link(raw, add_mode, group, cfgid)
if #node_list > 0 then
nodeResult[#nodeResult + 1] = {
remark = group,
list = node_list
list = node_list,
sub_cfg = sub_cfg
}
end
log(2, i18n.translatef("Successfully resolved the [%s] node, number: %s", group, #node_list))
@@ -2038,77 +2097,26 @@ local execute = function()
local cfgid = value[".name"]
local remark = value.remark or ""
local url = value.url or ""
if value.allowInsecure and value.allowInsecure ~= "1" then
allowInsecure_default = nil
end
local filter_keyword_mode = value.filter_keyword_mode or "5"
if filter_keyword_mode == "0" then
filter_keyword_mode_default = "0"
elseif filter_keyword_mode == "1" then
filter_keyword_mode_default = "1"
filter_keyword_discard_list_default = value.filter_discard_list or {}
elseif filter_keyword_mode == "2" then
filter_keyword_mode_default = "2"
filter_keyword_keep_list_default = value.filter_keep_list or {}
elseif filter_keyword_mode == "3" then
filter_keyword_mode_default = "3"
filter_keyword_keep_list_default = value.filter_keep_list or {}
filter_keyword_discard_list_default = value.filter_discard_list or {}
elseif filter_keyword_mode == "4" then
filter_keyword_mode_default = "4"
filter_keyword_keep_list_default = value.filter_keep_list or {}
filter_keyword_discard_list_default = value.filter_discard_list or {}
end
local ss_type = value.ss_type or "global"
if ss_type ~= "global" and core_has[ss_type] then
ss_type_default = ss_type
end
local trojan_type = value.trojan_type or "global"
if trojan_type ~= "global" and core_has[trojan_type] then
trojan_type_default = trojan_type
end
local vmess_type = value.vmess_type or "global"
if vmess_type ~= "global" and core_has[vmess_type] then
vmess_type_default = vmess_type
end
local vless_type = value.vless_type or "global"
if vless_type ~= "global" and core_has[vless_type] then
vless_type_default = vless_type
end
local hysteria2_type = value.hysteria2_type or "global"
if hysteria2_type ~= "global" and core_has[hysteria2_type] then
hysteria2_type_default = hysteria2_type
end
domain_resolver = value.domain_resolver
domain_resolver_dns = value.domain_resolver_dns
domain_resolver_dns_https = value.domain_resolver_dns_https
domain_strategy = (value.domain_strategy == "UseIPv4" or value.domain_strategy == "UseIPv6") and value.domain_strategy or nil
-- Subscription Group Chain Agent
local function valid_chain_node(node)
if not node then return "" end
local cp = uci:get(appname, node, "chain_proxy") or ""
local am = uci:get(appname, node, "add_mode") or "0"
chain_node_type = (cp == "" and am ~= "2") and (uci:get(appname, node, "type") or "") or ""
if chain_node_type ~= "Xray" and chain_node_type ~= "sing-box" then
chain_node_type = ""
return ""
end
return node
end
preproxy_node_group = (value.chain_proxy == "1") and valid_chain_node(value.preproxy_node) or ""
to_node_group = (value.chain_proxy == "2") and valid_chain_node(value.to_node) or ""
local ua = value.user_agent
local access_mode = value.access_mode
local result = (not access_mode) and i18n.translatef("Auto") or (access_mode == "direct" and i18n.translatef("Direct") or (access_mode == "proxy" and i18n.translatef("Proxy") or i18n.translatef("Auto")))
log(1, i18n.translatef("Start subscribing: %s", '【' .. remark .. '】' .. url .. ' [' .. result .. ']'))
local tmp_file = "/tmp/" .. cfgid
value.http_code = curl(url, tmp_file, ua, access_mode)
if value.http_code ~= 200 then
fail_list[#fail_list + 1] = value
local url_is_local
if fs.access(url) then
-- debug, reads local files.
log(1, i18n.translatef("Start subscribing: %s", '【' .. remark .. '】' .. url))
url_is_local = true
tmp_file = url
else
local ua = value.user_agent
local access_mode = value.access_mode
local result = (not access_mode) and i18n.translatef("Auto") or (access_mode == "direct" and i18n.translatef("Direct") or (access_mode == "proxy" and i18n.translatef("Proxy") or i18n.translatef("Auto")))
log(1, i18n.translatef("Start subscribing: %s", '【' .. remark .. '】' .. url .. ' [' .. result .. ']'))
tmp_file = "/tmp/" .. cfgid
value.http_code = curl(url, tmp_file, ua, access_mode)
if value.http_code ~= 200 then
fail_list[#fail_list + 1] = value
luci.sys.call("rm -f " .. tmp_file)
end
end
if fs.access(tmp_file) then
if luci.sys.call("[ -f " .. tmp_file .. " ] && sed -i -e '/^[ \t]*$/d' -e '/^[ \t]*\r$/d' " .. tmp_file) == 0 then
local f = io.open(tmp_file, "r")
local stdout = f:read("*all")
@@ -2119,33 +2127,18 @@ local execute = function()
if not manual_sub and old_md5 == new_md5 then
log(1, i18n.translatef("Subscription: [%s] No changes, no update required.", remark))
else
parse_link(raw_data, "2", remark, cfgid)
parse_link(raw_data, "2", remark, value)
uci:set(appname, cfgid, "md5", new_md5)
end
else
fail_list[#fail_list + 1] = value
end
if url_is_local then
value.http_code = 0
else
luci.sys.call("rm -f " .. tmp_file)
end
end
allowInsecure_default = true
luci.sys.call("rm -f " .. tmp_file)
filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
filter_keyword_keep_list_default = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
ss_type = uci:get(appname, "@global_subscribe[0]", "ss_type") or ""
ss_type_default = core_has[ss_type] and ss_type or ss_type_default
trojan_type = uci:get(appname, "@global_subscribe[0]", "trojan_type") or ""
trojan_type_default = core_has[trojan_type] and trojan_type or trojan_type_default
vmess_type = uci:get(appname, "@global_subscribe[0]", "vmess_type") or ""
vmess_type_default = core_has[vmess_type] and vmess_type or vmess_type_default
vless_type = uci:get(appname, "@global_subscribe[0]", "vless_type") or ""
vless_type_default = core_has[vless_type] and vless_type or vless_type_default
hysteria2_type = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or ""
hysteria2_type_default = core_has[hysteria2_type] and hysteria2_type or hysteria2_type_default
end
if #fail_list > 0 then