diff --git a/doc/lucky1.png b/doc/lucky1.png deleted file mode 100644 index a5b41b6e..00000000 Binary files a/doc/lucky1.png and /dev/null differ diff --git a/doc/lucky2.png b/doc/lucky2.png deleted file mode 100644 index ba4c026f..00000000 Binary files a/doc/lucky2.png and /dev/null differ diff --git a/doc/lucky3.png b/doc/lucky3.png deleted file mode 100644 index 6fa7982f..00000000 Binary files a/doc/lucky3.png and /dev/null differ diff --git a/doc/taskplan1.png b/doc/taskplan1.png new file mode 100644 index 00000000..1f8db7be Binary files /dev/null and b/doc/taskplan1.png differ diff --git a/doc/taskplan2.png b/doc/taskplan2.png new file mode 100644 index 00000000..edb45d6d Binary files /dev/null and b/doc/taskplan2.png differ diff --git a/doc/taskplan3.png b/doc/taskplan3.png new file mode 100644 index 00000000..d4794702 Binary files /dev/null and b/doc/taskplan3.png differ diff --git a/doc/view.png b/doc/view.png new file mode 100644 index 00000000..169e112f Binary files /dev/null and b/doc/view.png differ diff --git a/doc/view2.png b/doc/view2.png new file mode 100644 index 00000000..9058c632 Binary files /dev/null and b/doc/view2.png differ diff --git a/luci-app-passwall/luasrc/controller/passwall.lua b/luci-app-passwall/luasrc/controller/passwall.lua index d6ba203b..aa5ef485 100644 --- a/luci-app-passwall/luasrc/controller/passwall.lua +++ b/luci-app-passwall/luasrc/controller/passwall.lua @@ -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 diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index 111f34cc..3755ea3a 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -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 " .. - "| 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 " .. + "| 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 diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 2ed73aea..a6454928 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -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"), diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/header.htm b/luci-app-passwall/luasrc/view/passwall/node_config/header.htm index 7d7fda07..b8591bc6 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/header.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/header.htm @@ -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"]'); diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 95068ce1..63222c62 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -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)" diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 914320be..e8ba1589 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -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"),