update 2026-07-16 14:12:35

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

BIN
doc/taskplan1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

BIN
doc/taskplan2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

BIN
doc/taskplan3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

BIN
doc/view.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 KiB

BIN
doc/view2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

View File

@ -1075,10 +1075,20 @@ function fetch_certsha256()
local port = (id ~= "") and uci:get(appname, id, "port") or 0
local sni = (id ~= "") and uci:get(appname, id, "tls_serverName") or ""
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
http_write_json_error()
return
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 })
end

View File

@ -1673,18 +1673,29 @@ function cleanEmptyTables(t)
return next(t) and t or nil
end
function fetch_cert_sha256(host, port, sni, timeout)
function fetch_cert_sha256(host, port, sni, timeout, http3)
if not host then return "" end
port = tonumber(port) or 443
sni = sni or host
timeout = tonumber(timeout) or 5
local 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
)
local cmd
if http3 then
cmd = string.format(
"timeout %d curl --http3 -k -w '%%{certs}' -o /dev/null https://%s:%d 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
)
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 fp = out:match("^([0-9a-fA-F]+)")
if not fp or fp:lower():match("^e3b0c44298fc1c149afbf4c8996fb924") then

View File

@ -153,8 +153,8 @@ function gen_outbound(flag, node, tag, proxy_table)
tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName,
fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil,
pinnedPeerCertSha256 = node.tls_pinSHA256,
verifyPeerCertByName = node.tls_CertByName,
pinnedPeerCertSha256 = node.tls_pinSHA256 or "",
verifyPeerCertByName = node.tls_CertByName or "",
echConfigList = (node.ech == "1") and node.ech_config or nil,
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
certificate = api.split(node.tls_certificate_pem, "\n"),

View File

@ -67,7 +67,10 @@ local api = self.api
return;
}
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;
}
const inputs = document.querySelectorAll('input[id$=".xray_tls_pinSHA256"]');

View File

@ -1820,8 +1820,14 @@ msgstr "TLS 用于验证 leaf 证书的 name。"
msgid "Fetch Manually"
msgstr "手动获取"
msgid "Fetch Failed"
msgstr "获取失败"
msgid "Fetch Failed!"
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)"
msgstr "TLS 证书PEM"

View File

@ -177,8 +177,8 @@ function gen_outbound(flag, node, tag, proxy_table)
tlsSettings = (node.stream_security == "tls") and {
serverName = node.tls_serverName,
fingerprint = (node.type == "Xray" and node.utls == "1" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil,
pinnedPeerCertSha256 = node.tls_pinSHA256,
verifyPeerCertByName = node.tls_CertByName,
pinnedPeerCertSha256 = node.tls_pinSHA256 or "",
verifyPeerCertByName = node.tls_CertByName or "",
echConfigList = (node.ech == "1") and node.ech_config or nil,
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
certificate = api.split(node.tls_certificate_pem, "\n"),