证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置

服务器只部署了叶子证书而漏掉中间证书,桌面浏览器靠缓存和 AIA 抓取悄悄补上,命令行客户端却直接握手失败。本文解释这一现象的成因、排查方法和部署时的正确做法。

本文目录
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置

线上有个挺折磨人的现象:运维同事说证书明明刚换好,自己浏览器打开一切正常,结果监控告警和移动端的报错刷屏——certificate verify failed。两边都没说谎,问题出在证书链缺了中间证书,而浏览器替你"补考及格"了。

为什么浏览器能打开

TLS 握手时,服务器应把叶子证书和中间证书一起发给客户端。很多签发流程里,运维只拿到 domain.crt 这一个文件,直接配上去了,中间证书没发。

证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 1
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 1查看原图

桌面浏览器对此很宽容:一是它会缓存中间证书——只要你访问过同一家 CA 签发的其他站点,中间证书已经在本地了;二是现代证书里带 AIA(Authority Information Access)扩展,里面写了中间证书的下载地址,Chrome 会自己去抓。抓到了,链就补上了,地址栏一片祥和。

但 OpenSSL、curl、Java 的默认 truststore、很多移动端 HTTP 库不做 AIA 抓取,也不一定有那份缓存。它们拿到一条断掉的链,只能报错。于是同一个站点,浏览器是绿的,脚本全线飘红。

排查方法

最直接的验证:

证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 2
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 2查看原图
openssl s_client -connect example.com:443 -servername example.com

看输出里的 Verify return code。如果是 21 (unable to verify the first certificate),基本就是缺中间证书。也可以在返回的证书列表里数一下:只返回了一张证书(叶子),中间证书缺席。

注意 -servername 别省。一个 IP 上挂多个站时,不带 SNI 测到的可能是默认证书,查错了对象更浪费时间。

证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 3
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 3查看原图

另外有个坑:某些 CDN 或负载均衡后面有多台节点,如果只有部分节点配置正确,用 openssl 抽查一次可能刚好命中好的那台。出问题时间歇性发作的,多测几次,或者逐节点测。

正确的部署姿势

多数 CA 会提供 fullchain.pem(叶子 + 中间),或者让你自己拼接。拼接顺序是从叶子到根方向的中间证书,叶子在前:

cat domain.crt intermediate.crt > fullchain.pem
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 4
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 4查看原图

根证书不用放进去,客户端信任库里本来就有,发了也是白占握手流量。

在 CertbotX 中实践:自动签发流程拿到的就是完整的 fullchain,重新签发后自动部署到 Agent、EdgeOne 或 CDN 时也是整条链一起推,不存在"只传了叶子证书"这种半成品状态。部署记录里能看到每次推送的目标和结果,排查"哪个节点没更新"这类问题时不用挨个登录机器翻文件。

顺手要查的两件事

证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 5
证书链缺了中间证书:浏览器能开、API 调用却大面积报错的原因和处置 illustration 5查看原图

修链的同时值得顺带看一眼:

  1. 中间证书本身也会过期。Let's Encrypt 这类 CA 偶尔会轮换中间证书。如果你的部署脚本里硬编码了某张中间证书文件,签发方换链后你还在发旧的,又会断。每次签发都用新下发的链,别复用。
  2. 交叉签名的兼容性。有些 CA 提供多条链(比如同时兼容老 Android 的交叉签名链)。如果你的客户端里有老旧设备,确认发的是哪条链,必要时按 CA 文档选择。

证书链这事的小坑在于:它不报错的时候你根本不知道它断了。上线新证书后,别只用浏览器点一下就算验收——拿 openssl s_client 或者 SSL Labs 的检测跑一遍,把"运气"从验收流程里剔除。

← 返回资讯中心