mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-26 18:12:51 +08:00
1 parent
54d5be6086
commit
7ae707aaa6
8 files changed
+112
-64
No files matched your search
@@ -381,35 +381,36 @@ function connect_status()
|
||||
local e = {}
|
||||
e.use_time = ""
|
||||
local url = http.formvalue("url")
|
||||
if not url or url == "" then
|
||||
http_write_json(e)
|
||||
return
|
||||
end
|
||||
local aliyun = string.find(url, "aliyun")
|
||||
local chn_list = uci_get("@global[0]", "chn_list") or "direct"
|
||||
local gfw_list = uci_get("@global[0]", "use_gfw_list") or "1"
|
||||
local proxy_mode = uci_get("@global[0]", "tcp_proxy_mode") or "proxy"
|
||||
local localhost_proxy = uci_get("@global[0]", "localhost_proxy") or "1"
|
||||
local socks_server = (localhost_proxy == "0") and api.get_cache_var("GLOBAL_SOCKS_server") or ""
|
||||
url = "-w %{http_code}:%{time_pretransfer} " .. url
|
||||
local curl_args = "-w '%{http_code}:%{time_pretransfer}:%{time_starttransfer}' " .. util.shellquote(url)
|
||||
if socks_server and socks_server ~= "" then
|
||||
if (chn_list == "proxy" and gfw_list == "0" and proxy_mode ~= "proxy" and aliyun ~= nil) or (chn_list == "0" and gfw_list == "0" and proxy_mode == "proxy") then
|
||||
-- 中国列表+阿里 or 全局
|
||||
url = "-x socks5h://" .. socks_server .. " " .. url
|
||||
curl_args = "-x " .. util.shellquote("socks5h://" .. socks_server) .. " " .. curl_args
|
||||
elseif aliyun == nil then
|
||||
-- 其他代理模式+阿里以外网站
|
||||
url = "-x socks5h://" .. socks_server .. " " .. url
|
||||
curl_args = "-x " .. util.shellquote("socks5h://" .. socks_server) .. " " .. curl_args
|
||||
end
|
||||
end
|
||||
local result = luci.sys.exec('/usr/bin/curl --connect-timeout 3 --max-time 5 -o /dev/null -I -sk ' .. url)
|
||||
local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0")
|
||||
if code ~= 0 then
|
||||
local use_time_str = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'")
|
||||
local use_time = tonumber(use_time_str)
|
||||
if use_time then
|
||||
if use_time_str:find("%.") then
|
||||
e.use_time = string.format("%.2f", use_time * 1000)
|
||||
else
|
||||
e.use_time = string.format("%.2f", use_time / 1000)
|
||||
end
|
||||
e.ping_type = "curl"
|
||||
end
|
||||
local result = luci.sys.exec('curl_result=$(/usr/bin/curl --connect-timeout 3 --max-time 5 -o /dev/null -I -sk ' .. curl_args .. '); [ $? -eq 0 ] && printf "%s" "$curl_result"')
|
||||
local code, pretransfer, starttransfer = result:match("^%s*(%d+):([%d%.]+):([%d%.]+)%s*$")
|
||||
code, pretransfer, starttransfer = tonumber(code), tonumber(pretransfer), tonumber(starttransfer)
|
||||
if code and code > 0 then e.http_code = code end
|
||||
-- A completed HTTP response, including 4xx/5xx, confirms homepage connectivity.
|
||||
if code and code >= 200 and code < 600 and pretransfer and pretransfer >= 0 and starttransfer and starttransfer > 0 and starttransfer >= pretransfer then
|
||||
-- HTTP request latency excludes connection and TLS handshakes.
|
||||
e.use_time = string.format("%.2f", (starttransfer - pretransfer) * 1000)
|
||||
e.handshake_time = string.format("%.2f", pretransfer * 1000)
|
||||
e.ping_type = "curl"
|
||||
end
|
||||
http_write_json(e)
|
||||
end
|
||||
@@ -438,17 +439,13 @@ function urltest_node()
|
||||
local e = {}
|
||||
e.index = index
|
||||
local result = luci.sys.exec("/usr/share/passwall/test.sh url_test_node " .. util.shellquote(id or ""))
|
||||
local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0")
|
||||
if code ~= 0 then
|
||||
local use_time_str = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'")
|
||||
local use_time = tonumber(use_time_str)
|
||||
if use_time then
|
||||
if use_time_str:find("%.") then
|
||||
e.use_time = string.format("%.2f", use_time * 1000)
|
||||
else
|
||||
e.use_time = string.format("%.2f", use_time / 1000)
|
||||
end
|
||||
end
|
||||
local code, pretransfer, starttransfer = result:match("^%s*(%d+):([%d%.]+):([%d%.]+)%s*$")
|
||||
code, pretransfer, starttransfer = tonumber(code), tonumber(pretransfer), tonumber(starttransfer)
|
||||
if code and code > 0 then e.http_code = code end
|
||||
if code and code >= 200 and code < 600 and pretransfer and pretransfer >= 0 and starttransfer and starttransfer > 0 and starttransfer >= pretransfer then
|
||||
-- Keep node test parsing independent from the homepage test.
|
||||
e.use_time = string.format("%.2f", (starttransfer - pretransfer) * 1000)
|
||||
e.handshake_time = string.format("%.2f", pretransfer * 1000)
|
||||
end
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
@@ -169,7 +169,7 @@ function del_cache_var(key)
|
||||
end
|
||||
|
||||
function set_cache_var(key, val)
|
||||
sys.call(string.format('. /usr/share/passwall/utils.sh ; set_cache_var "%s" "%s"', key, val))
|
||||
sys.call(string.format('. /usr/share/passwall/utils.sh ; set_cache_var %s %s', util.shellquote(tostring(key)), util.shellquote(tostring(val))))
|
||||
end
|
||||
|
||||
function get_cache_var(key)
|
||||
|
||||
@@ -139,7 +139,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('aliyun', 'https://www.aliyun.com')" title="<%:TLS handshake test, latency for reference only%>">
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('aliyun', 'https://www.aliyun.com')" title="<%:HTTP request latency, for reference only%>">
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
@@ -151,7 +151,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('google', 'https://www.google.com/generate_204')" title="<%:TLS handshake test, latency for reference only%>">
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('google', 'https://www.google.com/generate_204')" title="<%:HTTP request latency, for reference only%>">
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
@@ -163,7 +163,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('github', 'https://github.com')" title="<%:TLS handshake test, latency for reference only%>">
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('github', 'https://github.com')" title="<%:HTTP request latency, for reference only%>">
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
@@ -175,7 +175,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('youtube', 'https://www.youtube.com')" title="<%:TLS handshake test, latency for reference only%>">
|
||||
<div class="pure-u-1-4 check" onclick="check_connect('youtube', 'https://www.youtube.com/generate_204')" title="<%:HTTP request latency, for reference only%>">
|
||||
<div class="block pure-g">
|
||||
<div class="pure-u-1-3">
|
||||
<div class="img-con">
|
||||
@@ -246,6 +246,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
if (s) {
|
||||
var div = s.parentNode.parentNode.parentNode.parentNode;
|
||||
div.removeAttribute('onclick');
|
||||
div.title = "<%:HTTP request latency, for reference only%>";
|
||||
s.innerHTML = '<%:Check...%>';
|
||||
var sendDate = (new Date()).getTime();
|
||||
XHR.get('<%=api.url("connect_status")%>', {
|
||||
@@ -263,6 +264,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||
s.className="red";
|
||||
}
|
||||
s.innerHTML = use_time + " ms";
|
||||
div.title += "\n<%:Initial handshake time%>: " + rv.handshake_time + " ms";
|
||||
} else if (rv.status) {
|
||||
s.className="green";
|
||||
s.innerHTML = "<%:Working...%>";
|
||||
|
||||
@@ -710,6 +710,7 @@ table td, .table .td {
|
||||
function urltest_node(cbi_id, dom) {
|
||||
if (dom.dataset.busy == "1" || !cbi_id) return;
|
||||
dom.dataset.busy = "1";
|
||||
dom.title = "<%:HTTP request latency, for reference only%>";
|
||||
dom.style.color = "";
|
||||
dom.innerText = "<%:Check...%>";
|
||||
XHR.get('<%=api.url("urltest_node")%>', {
|
||||
@@ -720,7 +721,7 @@ table td, .table .td {
|
||||
let text = "<%:Error%>";
|
||||
if (x && x.status == 200) {
|
||||
if (result.use_time == null || result.use_time.trim() == "") {
|
||||
text = "<%:Timeout%>";
|
||||
text = result.http_code >= 400 ? "HTTP " + result.http_code : "<%:Timeout%>";
|
||||
} else {
|
||||
let use_time = parseInt(result.use_time);
|
||||
if (use_time < 1000)
|
||||
@@ -728,6 +729,7 @@ table td, .table .td {
|
||||
else if (use_time < 2000)
|
||||
color = "#fb9a05";
|
||||
text = use_time + " ms";
|
||||
dom.title += "\n<%:Initial handshake time%>: " + result.handshake_time + " ms";
|
||||
}
|
||||
}
|
||||
dom.innerText = text;
|
||||
@@ -1417,7 +1419,7 @@ table td, .table .td {
|
||||
innerHTML = innerHTML.split("{{tcping}}").join('<span class="tcping_value" cbiid="{{id}}"><a href="javascript:void(0)" style="color:inherit">---</a></span>');
|
||||
}
|
||||
if (o["address"] && _port) {
|
||||
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping"><a href="javascript:void(0)" onclick="javascript:urltest_node(\'{{id}}\', this)" title="<%:TLS handshake test, latency for reference only%>"><%:Test%></a></span>');
|
||||
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping"><a href="javascript:void(0)" onclick="javascript:urltest_node(\'{{id}}\', this)" title="<%:HTTP request latency, for reference only%>"><%:Test%></a></span>');
|
||||
} else {
|
||||
innerHTML = innerHTML.split("{{url_test}}").join('<span class="ping" cbiid="{{id}}">---</span>');
|
||||
}
|
||||
|
||||
@@ -22,8 +22,11 @@ msgstr "连接失败"
|
||||
msgid "Touch Check"
|
||||
msgstr "点我检测"
|
||||
|
||||
msgid "TLS handshake test, latency for reference only"
|
||||
msgstr "TLS握手测试,延时仅供参考"
|
||||
msgid "HTTP request latency, for reference only"
|
||||
msgstr "HTTP 请求延迟,仅供参考"
|
||||
|
||||
msgid "Initial handshake time"
|
||||
msgstr "首次握手耗时"
|
||||
|
||||
msgid "Kernel Unsupported"
|
||||
msgstr "内核不支持"
|
||||
|
||||
@@ -21,7 +21,7 @@ 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 = api.uci_get_c("@global_haproxy[0]", "health_check_type") or "tcp"
|
||||
local health_check_inter = api.uci_get_c("@global_haproxy[0]", "health_check_inter") or "20"
|
||||
local health_check_inter = api.uci_get_c("@global_haproxy[0]", "health_check_inter") or "60"
|
||||
local balancingStrategy = api.uci_get_c("@global_haproxy[0]", "balancingStrategy") or "roundrobin"
|
||||
local console_port = api.uci_get_c("@global_haproxy[0]", "console_port") or "1188"
|
||||
local bind_local = api.uci_get_c("@global_haproxy[0]", "bind_local") or "0"
|
||||
@@ -44,7 +44,7 @@ global
|
||||
nbthread {{nbthread}}
|
||||
external-check
|
||||
insecure-fork-wanted
|
||||
spread-checks 50
|
||||
spread-checks 20
|
||||
tune.max-checks-per-thread 5
|
||||
|
||||
defaults
|
||||
@@ -99,7 +99,7 @@ api.uci_foreach_c("haproxy_config", function(t)
|
||||
local lbss = t.lbss
|
||||
local listen_port = tonumber(t.haproxy_port) or 0
|
||||
local server_node = api.uci_get_c(lbss)
|
||||
local hop = (health_check_type == "script_logic") and (server_node.hysteria_hop or server_node.hysteria2_hop) or nil
|
||||
local hop = (health_check_type == "script_logic") and server_node 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)
|
||||
@@ -153,9 +153,12 @@ api.uci_foreach_c("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 inter = tonumber(health_check_inter:match("^%d+")) or 60
|
||||
inter = math.max(inter, 20)
|
||||
-- 限制过渡状态的确认间隔,避免正常检测间隔较长时摘除或恢复过慢。
|
||||
local fastinter = math.max(10, math.min(15, math.floor(inter / 2)))
|
||||
local downinter = math.ceil(inter * 1.5)
|
||||
local inter_arg = string.format("inter %ds fastinter %ds downinter %ds", inter, fastinter, downinter)
|
||||
|
||||
local sortTable = {}
|
||||
for i in pairs(listens) do
|
||||
@@ -165,7 +168,28 @@ for i in pairs(listens) do
|
||||
end
|
||||
table.sort(sortTable, function(a,b) return (a < b) end)
|
||||
|
||||
for i, port in pairs(sortTable) do
|
||||
local function server_endpoint(o)
|
||||
local address = o.server_address:gsub("^%[(.*)%]$", "%1")
|
||||
if address:find(":", 1, true) then address = "[" .. address .. "]" end
|
||||
return address .. ":" .. o.server_port
|
||||
end
|
||||
|
||||
local check_counts = {}
|
||||
if health_check_type == "script_logic" then
|
||||
for _, port in ipairs(sortTable) do
|
||||
for _, o in ipairs(listens[port]) do
|
||||
-- 域名可能解析到不同 IP,仅对相同的实际代理端点共享检测。
|
||||
if api.is_ip(o.server_address) then
|
||||
local endpoint = server_endpoint(o)
|
||||
check_counts[endpoint] = (check_counts[endpoint] or 0) + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local shared_checks = {}
|
||||
local shared_check_names = {}
|
||||
|
||||
for i, port in ipairs(sortTable) do
|
||||
log(" + 入口 %s:%s" % {bind_address, port})
|
||||
|
||||
f_out:write("\n" .. string.format([[
|
||||
@@ -184,7 +208,7 @@ listen %s
|
||||
|
||||
local count_M, count_B = 1, 1
|
||||
for i, o in ipairs(listens[port]) do
|
||||
local remark = o.server_remark or ""
|
||||
local remark = (o.server_remark or ""):gsub("[%[%]]", "")
|
||||
-- 防止重名导致无法运行
|
||||
if tostring(o.backup) ~= "1" then
|
||||
remark = "M" .. count_M .. "-" .. remark
|
||||
@@ -193,8 +217,18 @@ listen %s
|
||||
remark = "B" .. count_B .. "-" .. remark
|
||||
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_arg}} rise 2 fall 2 {{backup}}"
|
||||
local server = server_endpoint(o)
|
||||
local check_arg = "check " .. inter_arg .. " rise 2 fall 2"
|
||||
if (check_counts[server] or 0) > 1 then
|
||||
local name = shared_check_names[server]
|
||||
if not name then
|
||||
name = "check_" .. (#shared_checks + 1)
|
||||
shared_check_names[server] = name
|
||||
table.insert(shared_checks, {name = name, server = server})
|
||||
end
|
||||
check_arg = "track " .. appname .. "_health_checks/" .. name
|
||||
end
|
||||
local server_conf = "server {{remark}} {{server}} weight {{weight}} {{resolvers}} {{check_arg}} {{backup}}"
|
||||
server_conf = server_conf:gsub("{{remark}}", remark)
|
||||
server_conf = server_conf:gsub("{{server}}", server)
|
||||
server_conf = server_conf:gsub("{{weight}}", o.lbweight)
|
||||
@@ -203,7 +237,7 @@ listen %s
|
||||
resolvers = ""
|
||||
end
|
||||
server_conf = server_conf:gsub("{{resolvers}}", resolvers)
|
||||
server_conf = server_conf:gsub("{{inter_arg}}", inter_arg)
|
||||
server_conf = server_conf:gsub("{{check_arg}}", check_arg)
|
||||
server_conf = server_conf:gsub("{{backup}}", tostring(o.backup) == "1" and "backup" or "")
|
||||
|
||||
f_out:write(" " .. api.trim(server_conf) .. "\n")
|
||||
@@ -216,6 +250,20 @@ listen %s
|
||||
end
|
||||
end
|
||||
|
||||
-- 独立检测 backend,避免入口服务器的手动维护状态传播到其他入口。
|
||||
if #shared_checks > 0 then
|
||||
f_out:write(string.format([[
|
||||
|
||||
backend %s_health_checks
|
||||
mode tcp
|
||||
option external-check
|
||||
external-check command "/usr/share/%s/haproxy_check.sh"
|
||||
]], appname, appname))
|
||||
for _, check in ipairs(shared_checks) do
|
||||
f_out:write(string.format("\tserver %s %s check %s rise 2 fall 2\n", check.name, check.server, inter_arg))
|
||||
end
|
||||
end
|
||||
|
||||
--控制台配置
|
||||
local console_user = api.uci_get_c("@global_haproxy[0]", "console_user")
|
||||
local console_password = api.uci_get_c("@global_haproxy[0]", "console_password")
|
||||
@@ -234,8 +282,7 @@ f_out:close()
|
||||
|
||||
--passwall内置健康检查URL
|
||||
if health_check_type == "script_logic" then
|
||||
local probeUrl = api.uci_get_c("@global_haproxy[0]", "health_probe_url") or "https://www.google.com/generate_204"
|
||||
local f_url = io.open(haproxy_path .. "/Probe_URL", "w")
|
||||
f_url:write(probeUrl)
|
||||
f_url:close()
|
||||
local probeUrl = api.trim(api.uci_get_c("@global_haproxy[0]", "health_probe_url") or "")
|
||||
if probeUrl == "" then probeUrl = "https://www.google.com/generate_204" end
|
||||
api.set_cache_var("HAPROXY_PROBE_URL", probeUrl)
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
export PATH=/usr/sbin:/usr/bin:/sbin:/bin:/root/bin
|
||||
CONFIG=passwall
|
||||
. /usr/share/passwall/utils.sh
|
||||
|
||||
listen_address=$1
|
||||
listen_port=$2
|
||||
@@ -13,19 +13,16 @@ busybox pgrep -af "${CONFIG}/" | grep -E 'app\.sh.*(start|stop)|nftables\.sh|ipt
|
||||
exit 0
|
||||
}
|
||||
|
||||
probe_file="/tmp/etc/passwall/haproxy/Probe_URL"
|
||||
probeUrl="https://www.google.com/generate_204"
|
||||
if [ -f "$probe_file" ]; then
|
||||
firstLine=$(head -n 1 "$probe_file" | tr -d ' \t\n')
|
||||
[ -n "$firstLine" ] && probeUrl="$firstLine"
|
||||
fi
|
||||
probeUrl=$(get_cache_var "HAPROXY_PROBE_URL")
|
||||
probeUrl="${probeUrl:-https://www.google.com/generate_204}"
|
||||
|
||||
extra_params="-x socks5h://${server_address}:${server_port}"
|
||||
if /usr/bin/curl --help all | grep -q "\-\-retry-all-errors"; then
|
||||
extra_params="${extra_params} --retry-all-errors"
|
||||
fi
|
||||
case "$server_address" in
|
||||
\[*\]) ;;
|
||||
*:*) server_address="[$server_address]" ;;
|
||||
esac
|
||||
|
||||
status=$(/usr/bin/curl -I -o /dev/null -skL ${extra_params} --connect-timeout 3 --retry 1 --max-time 6 -w "%{http_code}" "${probeUrl}")
|
||||
# 每轮只探测一次,连续成功/失败由 HAProxy 的 rise/fall 判定。
|
||||
status=$(/usr/bin/curl -q -I -o /dev/null -sk --noproxy "" -x "socks5h://${server_address}:${server_port}" --connect-timeout 3 --max-time 6 -w "%{http_code}" "$probeUrl") || exit 1
|
||||
|
||||
case "$status" in
|
||||
200|204)
|
||||
|
||||
@@ -73,7 +73,7 @@ url_test_node() {
|
||||
fi
|
||||
sleep 2s
|
||||
probeUrl=$(config_n_get @global_other[0] url_test_url https://www.google.com/generate_204)
|
||||
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" "$@" -x "$curlx" "${probeUrl}")
|
||||
result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -sk -w "%{http_code}:%{time_pretransfer}:%{time_starttransfer}" "$@" -x "$curlx" "${probeUrl}") || result=0
|
||||
# 结束 SS 插件进程
|
||||
if [ "$_type" != "socks" ]; then
|
||||
pid_file="${TMP_PATH}/${test_flag}_plugin.pid"
|
||||
|
||||
Reference in new issue
Block a user