update 2026-07-16 14:12:35
No files matched your search
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 640 KiB |
|
After Width: | Height: | Size: 550 KiB |
|
After Width: | Height: | Size: 547 KiB |
|
After Width: | Height: | Size: 659 KiB |
|
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
|
||||||
@@ -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"]');
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||