DevKitLab Logo DevKitLab
SSL / TLS / 证书 / HTTPS / 安全

为什么 SSL 证书无效?从报错到根因的排查方法

浏览器报证书错误,并不等于证书文件本身坏了。按有效期、域名覆盖、信任链、中间证书、SNI、TLS 协商和 DNS 的顺序核对,才能找到真正出问题的一层。

浏览器提示「连接不是私密连接」,或者监控报出证书无效时,最容易做的事是重新申请证书。可很多时候,重新申请之后问题还在。

因为 HTTPS 不是只有一张证书文件:对外服务必须在正确的域名上送出正确的证书,证书要处在有效期内,还要把足够的中间证书一并送出,让客户端能够建立信任链,并协商出兼容的 TLS 连接。服务器磁盘里的证书看起来没问题,不代表公网用户实际拿到的也是它。

先用 SSL 证书检测工具 检查公网域名。它会把有效期、域名匹配、信任链、服务端是否送全证书链,以及 TLS 版本分开显示。把这些结果混成一句「证书有问题」,往往就是排查绕路的开始。

客户端实际连到的端点

输入公网域名,而不是服务器上的证书文件路径。服务不在 443 端口时,要填真实端口;若你直连某个 IP、但想测试某个虚拟主机,就把那个域名填进 SNI。

先记下四项结果,再改配置:

检查项它回答的问题失败通常意味着什么
有效期今天能不能使用?已过期、尚未生效,或客户端时钟不对
域名匹配证书覆盖这次请求的名字吗?SAN 没写对,或返回了错误的虚拟主机
信任链公共客户端能否连到受信任根证书?缺中间证书、私有 CA、拦截,或签发者不受信任
服务端证书链服务端是否把中间证书送全?可能是漏了中间证书,也可能是链上别处不受信任或已过期,导致无法建链

它们不是同一件事。过期证书也可能域名完全匹配;有效证书也可能属于别的域名;浏览器能打开,也可能只是本机缓存过某张中间证书。

把浏览器报错归到正确一层

不同浏览器的错误名不完全一样,但常见的对应关系很有用:

看到的报错优先怀疑先查什么
NET::ERR_CERT_DATE_INVALID有效期或客户端时间notBeforenotAfter 和设备时间
NET::ERR_CERT_COMMON_NAME_INVALID域名覆盖或 SNISAN 列表和请求的域名
NET::ERR_CERT_AUTHORITY_INVALID信任链或本地拦截签发者、中间证书,以及是否只在一个网络失败
NET::ERR_CERT_REVOKED吊销状态向 CA 核对序列号的吊销状态,再确认线上是否已换证书
ERR_SSL_VERSION_OR_CIPHER_MISMATCHTLS 协商支持的 TLS 版本、代理和服务端配置

这只是排查起点,不是结论。例如 ERR_CERT_AUTHORITY_INVALID 既可能是漏装中间证书,也可能是公司 HTTPS 解密代理、防病毒软件或酒店 Wi‑Fi 门户在中间替换了证书。先换一个独立网络复现,再判断是否是服务端事故。

另外,混合内容警告不是证书问题:它表示 HTTPS 页面加载了 HTTP 资源,换证书不会解决。

证书过期,不一定是续期失败

如果公网端点确实送出了过期证书,先看精确的 notAfter,再把它的序列号或 SHA‑256 指纹与自己准备部署的证书比较。CA 那边续期成功,线上仍然送旧证书,是非常常见的情况。

常见原因包括:

  • TLS 实际由 CDN、负载均衡、Ingress 或反向代理终止,而不是应用服务器;
  • 一组机器里有节点没有重新加载,导致问题时好时坏;
  • 续期任务写入了新文件,却没有重载 Web 服务;
  • 域名仍解析到旧 IP、预发环境,或者 IPv4 已更新而 IPv6 没更新。

从检测结果记下解析到的 IP,再用 DNS 查询工具 看 A、AAAA 记录和 TTL。两种地址族都要查。「我这里正常」可能只是你的网络优先走到了已更新的 IPv4,其他用户却走向旧的 IPv6。

吊销和过期是两种不同的失效

还在有效期内的证书也可能已被吊销。NET::ERR_CERT_REVOKED 表示客户端依据它获得的吊销信息不再信任该证书;它不等于 notAfter 写错。SSL 检测工具能显示是否提供 OCSP stapling,但不验证吊销状态;不同客户端使用的吊销数据与缓存策略也不相同。

先按证书序列号向 CA 核对状态。如果 CA 确认已经吊销,应立即重新签发并在实际 TLS 终止点部署新证书,同时查明私钥泄露、误签发或域名控制权变更等原因。只有 CA 并未确认吊销、而特定客户端仍报错时,才继续检查该客户端环境和 OCSP stapling 配置。

证书是否覆盖域名,看 SAN,不看文件名

现代客户端用 Subject Alternative Name(SAN)扩展来验证域名。Common Name 可能仍会显示,但不能靠它判断覆盖范围。

把公网拿到的叶子证书放进 证书解码工具,逐项核对 DNS SAN 和用户请求的名字:

  • example.comwww.example.com 是两个不同的名字;
  • *.example.com 能覆盖 api.example.com,却不覆盖 example.com,也不覆盖 v2.api.example.com
  • 用 IP 访问时,证书里必须有对应的 IP SAN,DNS SAN 不算;
  • 内部域名的证书不能自动拿来服务公网域名。

SAN 明明正确却仍不匹配,通常该查路由。直连 IP、没有带正确 SNI 时,服务端可能返回默认站点的证书;代理按主机名分流时,也可能收到与你预期不同的 SNI。

缺中间证书,不等于根证书不受信任

服务端通常应发送叶子证书和一到多张中间证书,不应发送根证书。客户端用这些中间证书一路连到自己信任库中的根证书。

部署时只装了 cert.pem、没装 CA 给出的 fullchain.pem,是最常见的错误之一。某些浏览器会通过 Authority Information Access 下载中间证书,或命中本地缓存,所以看起来正常;命令行客户端、移动应用、旧设备和受限的企业环境却未必会补救。因此才会出现「我能打开,客户打不开」。

SSL 检测工具会分别显示信任结果和服务端是否送全证书链。后一项失败最常见是漏中间证书,但链上其他证书过期或不受信任时也可能一并失败。安装前先检查每一张已送出的证书;若叶子证书有效、只是缺少中间证书,再到真正终止 TLS 的位置安装 CA 提供的完整链,不要随手把根证书拼进配置里。

别把 SNI 漏在证书前面

同一个 IP 可以服务很多 HTTPS 域名。TLS 握手里的 SNI 告诉服务端客户端想访问哪个名字。没有正确的 SNI,服务端可能合法地返回自己的默认证书——只是它不属于你要访问的域名。

这类问题常出现在迁移到 CDN、反向代理、Kubernetes Ingress 或共享负载均衡之后;监控如果只连 IP、不带 SNI,测到的请求也和浏览器不同。

想确认时,可以对同一个 IP 做两次检查:一次不填 SNI,一次填生产域名。两次证书不同,说明证书选择会随请求或命中的节点变化;虚拟主机很常见,但负载均衡也可能造成这个差异。只有带 SNI 才返回错误证书,则应回头检查该域名的代理或路由规则。

DNS 会把用户带到错误的 TLS 入口

DNS 不验证证书,却决定客户端去问哪台机器要证书。迁移后应检查 A、AAAA、CNAME,并顺着 CNAME 看清前面是否还有 CDN 或托管平台。TTL 很低也不会立刻让全网旧记录消失;它只限制缓存从拿到答案那一刻起还能保存多久。

CAA 记录影响的是签发和续期,不参与浏览器对现有证书的验证。续期申请失败时查 CAA;用户看到域名不匹配时,优先查 A、AAAA、CNAME、CDN 映射和 SNI。

别忽略只发生在一台设备上的原因

如果独立网络上的检测结果正常,只有某个人仍然看到警告,应把问题收窄到客户端:

  • 检查设备时间和时区;严重偏差会让有效证书看起来过期或尚未生效;
  • 换一个网络;门户网络、企业 HTTPS 解密和安全软件都可能送出自己的证书;
  • 极旧系统或嵌入式设备的根证书库可能不认识较新的链;
  • 确认用户输入的不是 IP、旧域名或内部别名。

登录、付款和管理页面出现证书警告时,不要建议用户「继续访问」。先确认为什么这个客户端看到了不同或不受信任的证书。

一套不容易走偏的排查顺序

  1. SSL 证书检测工具 检查公网域名;必要时带上真实端口和 SNI。
  2. 确认失败的是日期、域名、信任链、服务端证书链,还是 TLS 协商;吊销只能结合浏览器报错与 CA 状态判断,SSL 检测工具不作这个结论。
  3. 证书解码工具 解码公网返回的整条证书链,比较 SAN、签发者、日期、序列号和指纹是否符合计划部署的证书。
  4. 涉及迁移或续期时,用 DNS 查询工具 看 A、AAAA、CNAME 和 CAA。
  5. 在实际送出错误证书的 TLS 终止点修复配置,再重载或重新部署。
  6. 从公网重新检查;多节点服务要确认每个地址都已送出预期证书。

按这个顺序,证书事故会小很多。你不再靠反复换证书碰运气,而是先分清问题出在证书、链、域名、路由,还是某个客户端看到的环境。

如果公网检查指向证书链问题,可接着看为什么证书链不完整;如果证书可信、却不覆盖请求的域名,则看为什么 SSL 证书与域名不匹配