问题出现得很突然,日志倒是留得挺全。给站点换了新证书后,Chrome 打开正常,Android 7 上的 WebView 报证书链不完整,openssl s_client 输出最后一行是 unable to get local issuer certificate。

刚开始盯着「证书和私钥不是同一对,握手时给出的是另一张证书的链」,折腾了半个多小时,排掉了。

真正麻烦的地方在于,几个原因的现象几乎一样。只配了站点证书没配中间证书,桌面浏览器会自动补齐,老系统不会。另一种情况是fullchain 文件拼接顺序错,中间证书放在了站点证书前面。

另外,服务端开了 ssl_stapling 但没配 stapling_verify,OCSP 拿不到影响链校验。

上来先看服务端到底发了哪些证书

openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts </dev/null 2>/dev/null | grep -E 's:|i:'

随后按站点证书在前的顺序拼 fullchain

cat www.crt intermediate.crt > fullchain.crt && nginx -t

接着核对证书与私钥是否匹配

openssl x509 -noout -modulus -in fullchain.crt | md5sum && openssl rsa -noout -modulus -in www.key | md5sum

等前面都确认过,再重载后用 verify 检查整条链

openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt fullchain.crt

怎么算真的好了,看的是同一批现象。openssl s_client 不再打印 unable to get local issuer,verify 返回 OK,Android 与老版本 iOS 上页面能正常加载。

补一句。桌面上能开不代表链是完整的,兼容性测试要看 s_client 的输出;fullchain 顺序反了同样报错,别只盯着文件在不在。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189