这个坑值得记一笔。网关要求双向 TLS,客户端带 client.crt 与 client.key 请求报 SSL: unable to verify the first certificate,用 openssl s_client 看服务端只下发了叶子证书,没有中级 CA。
刚开始盯着「证书链拼接顺序写反」,折腾了半个多小时,排掉了。
真正麻烦的地方在于,几个原因的现象几乎一样。服务端没有下发中级证书,链不完整;客户端没配 CA bundle 或 bundle 里缺根证书;证书与私钥不是一对。
上来先把服务端证书链打印出来看
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts < NUL
接着核对证书与私钥是否匹配
openssl x509 -noout -modulus -in client.crt | openssl md5; openssl rsa -noout -modulus -in client.key | openssl md5
随后把中级证书拼进服务端证书文件后重启
cat server.crt intermediate.crt > fullchain.crt && nginx -s reload
等前面都确认过,再用完整链再发起一次请求
curl -s -o /dev/null -w '%{http_code}\n' --cert client.crt --key client.key --cacert ca.crt https://api.example.com/health
那几天正好在做别的变更,先把时间线对齐才敢动手。
怎么算真的好了,看的是同一批现象。握手成功返回 200,openssl 输出里能看到叶子加中级两张证书,客户端不再报 unable to verify。
缺中级证书在浏览器里经常被自动补链掩盖,服务间调用没有这个兜底,部署时就把 fullchain 一起发。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
