白月光

sing-box Hysteria2 证书解析失败怎么排查?

更新于 2026-10-25 · bygcloud.store

简答:先看报错发生在哪一层:failed to parse certificate 通常是本地 certificate 或 certificate_path 读到的内容不是可解析的 PEM/X.509 证书;failed to verify certificate 则多发生在连接服务端时的证书链、server_name、SAN、时间或信任校验。普通 Hysteria2 出站不需要随意填写 certificate_path,更不能把私钥或公钥文件当作服务器证书使用。

定义:sing-box Hysteria2 证书解析失败,是客户端读取 TLS 的 certificate 或 certificate_path 后,无法把文件内容解析为有效的 PEM 编码 X.509 证书链。

先试这一步:按报错文字判断排查方向

本文是白月光站点整理的第三方使用指南,不代表 sing-box 或任何节点服务的官方页面。先备份配置,再只保留一个 Hysteria2 出站进行检查。sing-box 的 Hysteria2 出站要求 TLS 配置,具体结构以Hysteria2 出站配置页为准。

报错或现象更可能的阶段先检查什么
failed to parse certificate本地读取或解析证书失败certificate 内容、certificate_path 路径、PEM 头尾、文件是否真的是证书
panic: unknown value某些版本在无效证书错误路径中触发异常先修复证书内容,不要把 panic 当成服务端故障
failed to verify certificate已读到证书,但验证服务端身份失败server_name、SAN、系统时间、信任链、insecure 和证书固定字段
配置检查通过但连接仍失败运行时握手或协议兼容问题服务端实际发送的证书、ALPN、证书算法和客户端版本

如果错误在执行 sing-box check 时已经出现,优先处理本地配置;如果只有连接节点时出现,才继续核对远端证书和域名。

先分清 outbound、inbound 和双向 TLS 的证书字段

这是最容易修错的地方。Hysteria2 outbound 是客户端连接服务端;Hysteria2 inbound 是本机作为服务端接收连接。两者的 TLS 字段用途不同,不能把服务端配置原样复制到客户端。

场景字段含义常见误用
客户端 outboundcertificate / certificate_path用于指定服务端证书链或自定义信任证书,格式为 PEM;不是服务端私钥,也不是客户端公钥把 public_key.pem、private_key.pem 或普通文本放进去
客户端 outboundclient_certificate / client_key只有服务端要求双向 TLS 客户端认证时才使用普通 Hysteria2 节点也随意填写
服务端 inboundcertificate / certificate_path 与 key / key_path服务端对外提供的证书和私钥把 inbound 的证书私钥字段复制到 outbound
客户端 outboundserver_name用于校验服务端证书的名称,并参与 TLS 握手只填服务器 IP,却没有确认证书 SAN 是否包含该 IP

当前 TLS 配置页明确区分了 outbound 的服务端证书链字段、客户端证书字段,以及 inbound 的服务端证书和私钥字段;需要双向 TLS 时,应使用 client_certificate、client_certificate_path、client_key 或 client_key_path,而不是把服务端证书放进客户端认证字段。可直接对照sing-box TLS 字段说明。

按顺序执行:本地配置、证书文件与域名校验

  1. 用最小配置执行 sing-box check。在配置文件所在目录运行 sing-box check -c config.json。如果此处就出现 failed to parse certificate,不需要先测试节点,先处理 certificate 或 certificate_path。Issue #4347 记录了无效 X.509 内容在检查阶段即可触发该错误路径,某些版本还可能显示 panic: unknown value;该 issue 页面给出的复现不需要远端服务器,说明这类问题首先是本地证书内容问题。可查看sing-box Issue #4347 的复现记录。
  2. 确认文件不是公钥、私钥或目录。证书文件通常应包含 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE-----,中间是 Base64 编码内容。不要把 -----BEGIN PUBLIC KEY-----、-----BEGIN PRIVATE KEY----- 或只含一段公钥的文件改名为证书。Issue #4658 的示例把由 openssl pkey -pubout 生成的 public_key.pem 放入 certificate_path,随后出现 failed to parse certificate;这是该案例配置中的直接线索,不应扩展成所有证书报错都由同一原因导致。详见sing-box Issue #4658 的配置与讨论。
  3. 用 OpenSSL 验证证书是否能被解析。macOS/Linux 使用:openssl x509 -in ./certificate.pem -text -noout。Windows PowerShell 或命令提示符使用:openssl x509 -in D:\sing-box\certificate.pem -text -noout。如果命令提示 unable to load certificate、no start line 或类似解析失败,先重新导出有效的 PEM/X.509 证书;不要只修改 JSON 字段名。
  4. 检查路径和运行环境。相对路径是相对于 sing-box 进程的工作目录,不一定是配置文件所在目录。Windows 示例使用 D:\sing-box\certificate.pem,macOS/Linux 示例使用 /etc/sing-box/certificate.pem。如果 sing-box 在容器内运行,宿主机路径必须已经挂载到容器内,并且进程需要读取权限。
  5. 确认 JSON 中的换行是正确的。内嵌证书必须使用字面量转义换行,例如 "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----"。不要在 JSON 字符串中直接插入未转义的真实换行,也不要把代码块中的 \n误删成普通文字。若证书较长,优先使用 certificate_path,减少转义和复制错误。
  6. 本地解析通过后,再检查 server_name 与 SAN。sing-box TLS 文档说明,server_name用于校验返回证书中的主机名;如果填的是 IP,证书的 SAN 必须包含该 IP,否则即使证书文件格式正确,也可能进入校验失败。用 openssl x509 -in ./certificate.pem -text -noout查看 Subject Alternative Name,不要只看旧式 Common Name。
  7. 区分信任证书、自签证书和跳过校验。公共 CA 证书通常可以先不填写 outbound 的 certificate 或 certificate_path,让系统或运行时信任链处理。自签证书或私有 CA 场景,才考虑提供正确的服务端证书链。insecure: true表示接受任意服务端证书,只适合短时定位校验问题,不应作为长期修复方案;TLS 页面明确说明该字段会接受任意服务端证书。
  8. 最后才检查证书固定和算法兼容性。certificate_public_key_sha256是固定服务端证书公钥的字段,配置页标注为 sing-box 1.13.0 起提供;certificate_sha256则标注为 1.15.0 起提供。这里仅按文档的字段版本标注,不据此判断你当前安装包是否已经包含该字段。若启用了 Chrome QUIC 指纹,文档提示 Ed25519 服务端证书会导致握手失败,应核对服务端证书算法是否为 ECDSA 或 RSA。

三种修复方式怎么选

方式适合情况配置思路注意事项
删掉 certificate 字段服务端使用公共 CA,客户端只需正常校验保留 enabled、server_name 等必要 TLS 配置server_name 仍需和服务端证书 SAN 匹配
使用 certificate_path自签证书或私有 CA,需要指定信任证书链"certificate_path":"/etc/sing-box/ca.pem"文件必须是真正的 PEM/X.509 证书链,不是公钥或私钥
临时使用 insecure只为确认是否属于证书校验问题"insecure":true会接受任意服务端证书,定位完成后应撤回

一个普通客户端出站的最小结构可以写成:{"type":"hysteria2","server":"example.com","server_port":443,"password":"example-password","tls":{"enabled":true,"server_name":"example.com"}}。只有在确实使用自签或私有 CA 时,才增加 certificate_path;如果服务端要求双向 TLS,则另行配置客户端证书和私钥。字段定义以TLS 配置页和Hysteria2 出站页为准。

核对日期与结论边界

本文核对日期:2026-10-25。Issue #4658 页面显示该反馈于 2026-10-23 创建,页面中的配置使用了 public_key.pem 作为 certificate_path;这只能说明该案例的配置存在证书类型不匹配线索,不能据此断言所有 Hysteria2 证书解析失败都属于 sing-box 缺陷。Issue #4347 页面记录的是 sing-box 1.13.12 环境下的无效 X.509 证书错误路径,版本影响范围应以你正在使用的 sing-box 构建版本和后续变更为准。

如果 sing-box check 通过、OpenSSL 能读出证书、路径权限也正确,但仍出现 failed to verify certificate,下一步应获取服务端实际发送的证书,再比对 server_name、SAN、有效期、证书链和固定哈希;不要继续反复替换 certificate 文件。

常见问题

普通 Hysteria2 客户端一定要填写 certificate_path 吗?

不一定。若服务端证书由公共 CA 签发,普通 outbound 通常先保留必要 TLS 配置即可,不要为了“增强校验”随意把公钥、私钥或服务端配置文件放进 certificate_path。自签证书或私有 CA 场景,才需要根据实际证书链提供正确 PEM 文件。

certificate 和 client_certificate 有什么区别?

在 outbound 中,certificate/certificate_path用于服务端证书链或自定义信任证书;client_certificate/client_key用于客户端向服务端出示身份,通常只在双向 TLS 中使用。inbound 则由服务端使用 certificate 与 key 对外提供 TLS 身份,不能把两种方向混为一谈。

为什么 certificate_path 指向文件后出现 panic: unknown value?

如果文件内容不是可解析的 X.509 证书,某些版本可能在错误处理路径中显示 panic: unknown value。先用 OpenSSL 和 sing-box check验证文件,不要把 panic 直接判断为节点不可用;如果本地文件确实有效,再核对客户端版本和具体构建。

证书解析成功但仍然连不上,应该改成 insecure 吗?

可以短时把 insecure: true作为定位实验:如果开启后能连接,说明问题更可能在证书链、SAN、时间或信任校验;但它会接受任意服务端证书,不是长期修复方式。确认原因后,应恢复安全校验并修正 server_name 或证书链。

常见问题

普通 Hysteria2 客户端一定要填写 certificate_path 吗?

不一定。公共 CA 证书通常不需要额外填写;自签证书或私有 CA 场景才考虑使用正确的 PEM/X.509 证书链。

certificate 和 client_certificate 有什么区别?

outbound 中 certificate 用于服务端证书链或自定义信任证书,client_certificate 和 client_key 用于双向 TLS 的客户端身份认证;inbound 的 certificate 和 key 则是服务端身份配置。

为什么 certificate_path 会触发 panic: unknown value?

无效或无法解析的 X.509 内容可能触发某些版本的错误处理异常。先用 openssl x509 和 sing-box check 检查文件,不要把公钥或私钥当证书。

证书解析成功但仍连不上,可以一直使用 insecure 吗?

不建议。insecure 只适合短时确认是否为证书校验问题,定位完成后应恢复安全校验并修复 server_name、SAN、证书链或系统时间。

参考资料

  1. sing-box Hysteria2 出站配置、TLS、server_name 与证书算法说明
  2. sing-box Hysteria2 入站配置与服务端 TLS 结构
  3. sing-box TLS 字段定义、证书链、certificate_path、insecure 与证书固定
  4. sing-box Issue #4347:不可解析 X.509 证书与 panic: unknown value 复现