update 2026-07-16 14:12:35

This commit is contained in:
action committed 2026-07-16 14:12:35 +08:00
1 parent 151daa8c75
commit ba1b0b5cf2
14 files changed
+46 -16

No files matched your search

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

@@ -1075,10 +1075,20 @@ function fetch_certsha256()
local port = (id ~= "") and uci:get(appname, id, "port") or 0 local port = (id ~= "") and uci:get(appname, id, "port") or 0
local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or "" local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or ""
sni = (sni ~= "") and sni or address sni = (sni ~= "") and sni or address
local protocol = uci:get(appname, id, "protocol")
local h3, timeout = false, 10
if protocol == "hysteria2" then
h3 = true
timeout = 60
if port == 0 then
local hop = uci:get(appname, id, "hysteria2_hop") or "0"
port = tonumber(hop:match("^%s*(%d+)"))
end
end
if address == "" or port == 0 then if address == "" or port == 0 then
http_write_json_error() http_write_json_error()
return return
end end
local data = api.fetch_cert_sha256(address, port, sni, 5) local data = api.fetch_cert_sha256(address, port, sni, timeout, h3)
http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 }) http_write_json(data ~= "" and { code = 1, data = data } or { code = 0 })
end end
+19 -8
View File
@@ -1673,18 +1673,29 @@ function cleanEmptyTables(t)
return next(t) and t or nil return next(t) and t or nil
end end
function fetch_cert_sha256(host, port, sni, timeout) function fetch_cert_sha256(host, port, sni, timeout, http3)
if not host then return "" end if not host then return "" end
port = tonumber(port) or 443 port = tonumber(port) or 443
sni = sni or host sni = sni or host
timeout = tonumber(timeout) or 5 timeout = tonumber(timeout) or 5
local cmd = string.format( local cmd
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " .. if http3 then
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " .. cmd = string.format(
"| openssl x509 -outform der 2>/dev/null " .. "timeout %d curl --http3 -k -w '%%{certs}' -o /dev/null https://%s:%d 2>/dev/null " ..
"| sha256sum 2>/dev/null", "| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
timeout, host, port, sni "| openssl x509 -outform der 2>/dev/null " ..
) "| sha256sum 2>/dev/null",
timeout, host, port
)
else
cmd = string.format(
"timeout %d openssl s_client -connect %s:%d -servername %s -showcerts </dev/null 2>/dev/null " ..
"| awk 'BEGIN{c=0}/BEGIN CERT/{c++} c==1{print} /END CERT/{if(c==1)exit}' " ..
"| openssl x509 -outform der 2>/dev/null " ..
"| sha256sum 2>/dev/null",
timeout, host, port, sni
)
end
local out = trim(sys.exec(cmd)) local out = trim(sys.exec(cmd))
local fp = out:match("^([0-9a-fA-F]+)") local fp = out:match("^([0-9a-fA-F]+)")
if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then
@@ -153,8 +153,8 @@ function gen_outbound(flag, node, tag, proxy_table)
tlsSettings = (node.stream_security == "tls") and { tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil, fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil,
pinnedPeerCertSha256 = node.tls_pinSHA256, pinnedPeerCertSha256 = node.tls_pinSHA256 or "",
verifyPeerCertByName = node.tls_CertByName, verifyPeerCertByName = node.tls_CertByName or "",
echConfigList = (node.ech == "1") and node.ech_config or nil, echConfigList = (node.ech == "1") and node.ech_config or nil,
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and { certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
certificate = api.split(node.tls_certificate_pem, "\n"), certificate = api.split(node.tls_certificate_pem, "\n"),
@@ -67,7 +67,10 @@ local api = self.api
return; return;
} }
if (!res || res.code !== 1 || !res.data) { if (!res || res.code !== 1 || !res.data) {
alert(res && res.msg ? res.msg : "<%:Fetch Failed%> !"); alert(res && res.msg ? res.msg : "<%:Fetch Failed!%>\n" +
"<%:Requires OpenSSL to retrieve the TLS certificate chain fingerprint.%>\n" +
"<%:QUIC protocols such as HY2 also require curl with http3 support.%>"
);
return; return;
} }
const inputs = document.querySelectorAll('input[id$=".xray_tls_pinSHA256"]'); const inputs = document.querySelectorAll('input[id$=".xray_tls_pinSHA256"]');
+8 -2
View File
@@ -1820,8 +1820,14 @@ msgstr "TLS 用于验证 leaf 证书的 name。"
msgid "Fetch Manually" msgid "Fetch Manually"
msgstr "手动获取" msgstr "手动获取"
msgid "Fetch Failed" msgid "Fetch Failed!"
msgstr "获取失败" msgstr "获取失败!"
msgid "Requires OpenSSL to retrieve the TLS certificate chain fingerprint."
msgstr "获取 TLS 证书链指纹需要 OpenSSL 支持。"
msgid "QUIC protocols such as HY2 also require curl with http3 support."
msgstr "HY2 等 QUIC 协议还需要 curl 支持 http3。"
msgid "TLS Certificate (PEM)" msgid "TLS Certificate (PEM)"
msgstr "TLS 证书(PEM)" msgstr "TLS 证书(PEM)"
@@ -177,8 +177,8 @@ function gen_outbound(flag, node, tag, proxy_table)
tlsSettings = (node.stream_security == "tls") and { tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName, serverName = node.tls_serverName,
fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil, fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil,
pinnedPeerCertSha256 = node.tls_pinSHA256, pinnedPeerCertSha256 = node.tls_pinSHA256 or "",
verifyPeerCertByName = node.tls_CertByName, verifyPeerCertByName = node.tls_CertByName or "",
echConfigList = (node.ech == "1") and node.ech_config or nil, echConfigList = (node.ech == "1") and node.ech_config or nil,
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and { certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
certificate = api.split(node.tls_certificate_pem, "\n"), certificate = api.split(node.tls_certificate_pem, "\n"),