问题出现得很突然,日志倒是留得挺全。给站点换了新证书后,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 顺序反了同样报错,别只盯着文件在不在。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
