From 155d0be12b67dec5660b96bc45683a79561e69d8 Mon Sep 17 00:00:00 2001 From: gitea-action Date: Wed, 26 Feb 2025 20:30:22 +0800 Subject: [PATCH] luci-app-passwall: sync upstream last commit: https://github.com/xiaorouji/openwrt-passwall/commit/8d36e3079b0b7034d8496b7e805768ed035cec32 --- .../model/cbi/passwall/client/global.lua | 15 ++++- .../model/cbi/passwall/client/node_list.lua | 2 + .../cbi/passwall/client/type/sing-box.lua | 55 +++++++++++++++++++ luci-app-passwall/luasrc/passwall/api.lua | 6 +- .../luasrc/passwall/util_sing-box.lua | 54 ++++++++++++++++++ luci-app-passwall/po/zh-cn/passwall.po | 42 ++++++++++++-- .../root/usr/share/passwall/app.sh | 2 +- .../root/usr/share/passwall/subscribe.lua | 32 ++++++++++- .../root/usr/share/passwall/test.sh | 2 +- patch-luci-app-passwall.patch | 6 +- 10 files changed, 200 insertions(+), 16 deletions(-) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 174df8b2e..d33a67969 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -19,6 +19,7 @@ end local normal_list = {} local balancing_list = {} +local urltest_list = {} local shunt_list = {} local iface_list = {} for k, v in pairs(nodes_table) do @@ -28,6 +29,9 @@ for k, v in pairs(nodes_table) do if v.protocol and v.protocol == "_balancing" then balancing_list[#balancing_list + 1] = v end + if v.protocol and v.protocol == "_urltest" then + urltest_list[#urltest_list + 1] = v + end if v.protocol and v.protocol == "_shunt" then shunt_list[#shunt_list + 1] = v end @@ -185,6 +189,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -226,6 +233,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -250,6 +260,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then for k1, v1 in pairs(balancing_list) do o:value(v1.id, v1.remark) end + for k1, v1 in pairs(urltest_list) do + o:value(v1.id, v1.remark) + end for k1, v1 in pairs(iface_list) do o:value(v1.id, v1.remark) end @@ -265,7 +278,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then o:value("", translate("Close")) o:value("main", translate("Preproxy Node")) for k1, v1 in pairs(normal_list) do - if v1.protocol ~= "_balancing" then + if v1.protocol ~= "_balancing" and v1.protocol ~= "_urltest" then o:depends({ [vid .. "-default_node"] = v1.id, [vid .. "-preproxy_enabled"] = "1" }) end end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua index cdde9ba3d..33587b183 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua @@ -103,6 +103,8 @@ o.cfgvalue = function(t, n) local protocol = m:get(n, "protocol") if protocol == "_balancing" then protocol = translate("Balancing") + elseif protocol == "_urltest" then + protocol = "URLTest" elseif protocol == "_shunt" then protocol = translate("Shunt") elseif protocol == "vmess" then diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua index 7e5ee34a6..d826f3360 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua @@ -56,6 +56,7 @@ end if singbox_tags:find("with_quic") then o:value("hysteria2", "Hysteria2") end +o:value("_urltest", translate("URLTest")) o:value("_shunt", translate("Shunt")) o:value("_iface", translate("Custom Interface")) @@ -65,6 +66,7 @@ o:depends({ [_n("protocol")] = "_iface" }) local nodes_table = {} local iface_table = {} +local urltest_table = {} for k, e in ipairs(api.get_valid_nodes()) do if e.node_type == "normal" then nodes_table[#nodes_table + 1] = { @@ -79,6 +81,12 @@ for k, e in ipairs(api.get_valid_nodes()) do remark = e["remark"] } end + if e.protocol == "_urltest" then + urltest_table[#urltest_table + 1] = { + id = e[".name"], + remark = e["remark"] + } + end end local socks_list = {} @@ -91,6 +99,44 @@ m.uci:foreach(appname, "socks", function(s) end end) +--[[ URLTest ]] +o = s:option(DynamicList, _n("urltest_node"), translate("URLTest node list"), translate("List of nodes to test, document")) +o:depends({ [_n("protocol")] = "_urltest" }) +for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end + +o = s:option(Value, _n("urltest_url"), translate("Probe URL")) +o:depends({ [_n("protocol")] = "_urltest" }) +o:value("https://cp.cloudflare.com/", "Cloudflare") +o:value("https://www.gstatic.com/generate_204", "Gstatic") +o:value("https://www.google.com/generate_204", "Google") +o:value("https://www.youtube.com/generate_204", "YouTube") +o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)") +o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)") +o.default = "https://www.gstatic.com/generate_204" +o.description = translate("The URL used to detect the connection status.") + +o = s:option(Value, _n("urltest_interval"), translate("Test interval")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "180" +o.description = translate("The test interval in seconds.") .. "
" .. + translate("Test interval must be less or equal than idle timeout.") + +o = s:option(Value, _n("urltest_tolerance"), translate("Test tolerance"), translate("The test tolerance in milliseconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "50" + +o = s:option(Value, _n("urltest_idle_timeout"), translate("Idle timeout"), translate("The idle timeout in seconds.")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.datatype = "uinteger" +o.default = "1800" + +o = s:option(Flag, _n("urltest_interrupt_exist_connections"), translate("Interrupt existing connections")) +o:depends({ [_n("protocol")] = "_urltest" }) +o.default = "0" +o.description = translate("Interrupt existing connections when the selected outbound has changed.") + -- [[ 分流模块 ]] if #nodes_table > 0 then o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy")) @@ -101,6 +147,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -121,6 +170,9 @@ m.uci:foreach(appname, "shunt_rules", function(e) for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end @@ -152,6 +204,9 @@ if #nodes_table > 0 then for k, v in pairs(socks_list) do o:value(v.id, v.remark) end + for k, v in pairs(urltest_table) do + o:value(v.id, v.remark) + end for k, v in pairs(iface_table) do o:value(v.id, v.remark) end diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index ca3611cdd..f08c7019c 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -384,7 +384,7 @@ function strToTable(str) end function is_normal_node(e) - if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then return false end return true @@ -494,7 +494,7 @@ function get_valid_nodes() uci:foreach(appname, "nodes", function(e) e.id = e[".name"] if e.type and e.remarks then - if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface" or e.protocol == "_urltest") then local type = e.type if type == "sing-box" then type = "Sing-Box" end e["remark"] = "%s:[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks} @@ -544,7 +544,7 @@ end function get_node_remarks(n) local remarks = "" if n then - if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then + if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface" or n.protocol == "_urltest") then remarks = "%s:[%s] " % {n.type .. " " .. i18n.translatef(n.protocol), n.remarks} else local type2 = n.type diff --git a/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/luci-app-passwall/luasrc/passwall/util_sing-box.lua index 671974548..bd3a2688c 100644 --- a/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -901,6 +901,54 @@ function gen_config(var) table.insert(inbounds, inbound) end + local function gen_urltest(_node) + local urltest_id = _node[".name"] + local urltest_tag = "urltest-" .. urltest_id + -- existing urltest + for _, v in ipairs(outbounds) do + if v.tag == urltest_tag then + return urltest_tag + end + end + -- new urltest + local ut_nodes = _node.urltest_node + local valid_nodes = {} + for i = 1, #ut_nodes do + local ut_node_id = ut_nodes[i] + local ut_node_tag = "ut-" .. ut_node_id + local is_new_ut_node = true + for _, outbound in ipairs(outbounds) do + if string.sub(outbound.tag, 1, #ut_node_tag) == ut_node_tag then + is_new_ut_node = false + valid_nodes[#valid_nodes + 1] = outbound.tag + break + end + end + if is_new_ut_node then + local ut_node = uci:get_all(appname, ut_node_id) + local outbound = gen_outbound(flag, ut_node, ut_node_tag) + if outbound then + outbound.tag = outbound.tag .. ":" .. ut_node.remarks + table.insert(outbounds, outbound) + valid_nodes[#valid_nodes + 1] = outbound.tag + end + end + end + if #valid_nodes == 0 then return nil end + local outbound = { + type = "urltest", + tag = urltest_tag, + outbounds = valid_nodes, + url = _node.urltest_url or "https://www.gstatic.com/generate_204", + interval = _node.urltest_interval and tonumber(_node.urltest_interval) and string.format("%dm", tonumber(_node.urltest_interval) / 60) or "3m", + tolerance = _node.urltest_tolerance and tonumber(_node.urltest_tolerance) and tonumber(_node.urltest_tolerance) or 50, + idle_timeout = _node.urltest_idle_timeout and tonumber(_node.urltest_idle_timeout) and string.format("%dm", tonumber(_node.urltest_idle_timeout) / 60) or "30m", + interrupt_exist_connections = (_node.urltest_interrupt_exist_connections == "true" or _node.urltest_interrupt_exist_connections == "1") and true or false + } + table.insert(outbounds, outbound) + return urltest_tag + end + local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name) if not node or not outbound or not outbounds_table then return nil end local default_outTag = outbound.tag @@ -1055,6 +1103,8 @@ function gen_config(var) end end end + elseif _node.protocol == "_urltest" then + rule_outboundTag = gen_urltest(_node) elseif _node.protocol == "_iface" then if _node.iface then local _outbound = { @@ -1231,6 +1281,10 @@ function gen_config(var) for index, value in ipairs(rules) do table.insert(route.rules, rules[index]) end + elseif node.protocol == "_urltest" then + if node.urltest_node then + COMMON.default_outbound_tag = gen_urltest(node) + end elseif node.protocol == "_iface" then if node.iface then local outbound = { diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 29998faf8..4c93e477c 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -1579,9 +1579,6 @@ msgstr "最大并发连接数" msgid "XUDP Mux concurrency" msgstr "XUDP 最大并发连接数" -msgid "Mux idle timeout" -msgstr "最大闲置时间" - msgid "Padding" msgstr "填充" @@ -1600,9 +1597,6 @@ msgstr "推荐值:Sec-WebSocket-Protocol" msgid "Health check" msgstr "健康检查" -msgid "Idle timeout" -msgstr "闲置时间" - msgid "Health check timeout" msgstr "检查超时时间" @@ -1803,3 +1797,39 @@ msgstr "是否真的要恢复客户端默认配置?" msgid "Settings have been successfully saved and applied!" msgstr "设置已成功保存并应用!" + +msgid "_urltest" +msgstr "URLTest" + +msgid "URLTest node list" +msgstr "URLTest 节点列表" + +msgid "List of nodes to test, document" +msgstr "要测试的节点列表,文档原理" + +msgid "Test interval" +msgstr "测试间隔" + +msgid "The test interval in seconds." +msgstr "测试间隔时间(单位:秒)。" + +msgid "Test interval must be less or equal than idle timeout." +msgstr "测试间隔时间必须小于或等于空闲超时时间。" + +msgid "Test tolerance" +msgstr "测试容差" + +msgid "The test tolerance in milliseconds." +msgstr "测试容差时间(单位:毫秒)。" + +msgid "Idle timeout" +msgstr "空闲超时" + +msgid "The idle timeout in seconds." +msgstr "空闲超时时间(单位:秒)。" + +msgid "Interrupt existing connections" +msgstr "中断现有连接" + +msgid "Interrupt existing connections when the selected outbound has changed." +msgstr "当选择的出站发生变化时中断现有连接。" diff --git a/luci-app-passwall/root/usr/share/passwall/app.sh b/luci-app-passwall/root/usr/share/passwall/app.sh index c7f3346c9..aea09e627 100755 --- a/luci-app-passwall/root/usr/share/passwall/app.sh +++ b/luci-app-passwall/root/usr/share/passwall/app.sh @@ -621,7 +621,7 @@ run_socks() { if [ "$type" == "sing-box" ] || [ "$type" == "xray" ]; then local protocol=$(config_n_get $node protocol) - if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then + if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ] || [ "$protocol" == "_urltest" ]; then unset error_msg fi fi diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index f89ab7ba7..7533743d0 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -318,6 +318,36 @@ do end } end + elseif node.protocol and node.protocol == '_urltest' then + local flag = "Sing-Box URLTest节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} + if node.urltest_node then + for k, node in pairs(node.urltest_node) do + currentNodes[#currentNodes + 1] = { + log = false, + node = node, + currentNode = node and uci:get_all(appname, node) or nil, + remarks = node, + set = function(o, server) + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "urltest_node", newNodes or {}) + end + end + } else --前置代理节点 local currentNode = uci:get_all(appname, node_id) or nil @@ -1691,7 +1721,7 @@ local execute = function() f:close() raw = trim(stdout) local old_md5 = value.md5 or "" - local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0") + local new_md5 = luci.sys.exec("[ -f " .. tmp_file .. " ] && md5sum " .. tmp_file .. " | awk '{print $1}' || echo 0"):gsub("\n", "") os.remove(tmp_file) if old_md5 == new_md5 then log('订阅:【' .. remark .. '】没有变化,无需更新。') diff --git a/luci-app-passwall/root/usr/share/passwall/test.sh b/luci-app-passwall/root/usr/share/passwall/test.sh index 83335b80e..2da810894 100755 --- a/luci-app-passwall/root/usr/share/passwall/test.sh +++ b/luci-app-passwall/root/usr/share/passwall/test.sh @@ -95,7 +95,7 @@ url_test_node() { [ "${chn_list}" = "proxy" ] && probeUrl="www.baidu.com" result=$(${_curl} --max-time 5 -o /dev/null -I -skL -x ${curlx} ${curl_arg}${probeUrl}) pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}.json" + rm -rf "/tmp/etc/${CONFIG}/url_test_${node_id}"*.json } echo $result } diff --git a/patch-luci-app-passwall.patch b/patch-luci-app-passwall.patch index 6243de609..06fb4fa96 100644 --- a/patch-luci-app-passwall.patch +++ b/patch-luci-app-passwall.patch @@ -20,10 +20,10 @@ index af6e04a..709fba2 100644 define Package/$(PKG_NAME)/postrm diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua -index 5687101..174df8b 100644 +index 908dc46..d33a679 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua -@@ -493,6 +493,12 @@ o:value("9.9.9.9", "9.9.9.9 (Quad9)") +@@ -506,6 +506,12 @@ o:value("9.9.9.9", "9.9.9.9 (Quad9)") o:value("149.112.112.112", "149.112.112.112 (Quad9)") o:value("208.67.220.220", "208.67.220.220 (OpenDNS)") o:value("208.67.222.222", "208.67.222.222 (OpenDNS)") @@ -36,7 +36,7 @@ index 5687101..174df8b 100644 o:depends({dns_mode = "dns2socks"}) o:depends({dns_mode = "tcp"}) o:depends({dns_mode = "udp"}) -@@ -592,7 +598,7 @@ if api.is_finded("smartdns") then +@@ -605,7 +611,7 @@ if api.is_finded("smartdns") then end o = s:taboption("DNS", Flag, "dns_redirect", translate("DNS Redirect"), translate("Force special DNS server to need proxy devices."))