curl 报证书错误而浏览器正常:证书链不完整、SNI 与本地 CA 库的三步排查

举报
yd_291384559 发表于 2026/11/12 06:10:33 2026/11/12
【摘要】 浏览器能正常打开的 HTTPS 地址,curl 却报 unable to get local issuer certificate。本文按证书链、SNI 与本地 CA 信任库三步排查,讲清浏览器为何能自动补链、服务端如何下发 fullchain,以及 -k 为什么不能进生产脚本。

同样的 HTTPS 地址,浏览器打开是绿锁,脚本里 curl 却直接失败:curl: (60) SSL certificate problem: unable to get local issuer certificate。这不是网络问题,而是两端补全证书链的能力不同。下面按「看链 → 看握手 → 看信任库」的顺序排查。

一、第一步:把服务器发出来的证书链打出来

openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null

输出里的 s: 与 i: 行就是证书主题与签发者,数一下出现几段 -----BEGIN CERTIFICATE-----。只出现一段、且签发者是中间 CA 的名字,说明服务器只发了叶子证书。浏览器会顺着证书里的 AIA 扩展自己去下载中间证书补齐链,curl、Java、Go 默认都不会这么做,所以同一个站点两端结论不一致。

把链存成 fullchain.pem 后验证:openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt fullchain.pem,链完整时返回 OK,缺中间证书时会明确提示 unable to get local issuer certificate,和 curl 的报错一一对应。

二、第二步:确认 SNI 与访问的虚拟主机一致

一个 IP 上挂多个域名时,服务器按 SNI 选证书。直接用 IP 访问,或在 openssl s_client 里漏掉 -servername,拿到的是默认站点的证书,域名对不上就报 certificate subject name does not match。curl 想验证真实链路又要保留 SNI,用 --resolve 把域名钉到目标 IP:

curl -v --resolve example.com:443:203.0.113.10 https://example.com/

看输出里 subjectAltName 是否包含访问的域名。不包含就是服务端证书配置问题,改客户端没有意义。

三、第三步:本地 CA 信任库是否过期

链完整、SNI 正确却仍报错,多半是客户端信任库太旧。容器镜像里最常见:/etc/ssl/certs 是构建时的快照,新换的 CA(尤其国产 CA 与 Let's Encrypt 新根)不在里面。确认办法是把完整链存下来,用 curl --cacert fullchain.pem 指定后重试,能过就是信任库的问题。修复方式:Debian 系 apt-get install --reinstall ca-certificates,RHEL 系 update-ca-trust;Go 静态编译的程序需要额外设置 SSL_CERT_FILE 指向证书文件。

四、修复与两个提醒

服务端的标准做法是下发 fullchain:Nginx 的 ssl_certificate 指向「叶子证书 + 中间证书」拼接的文件,顺序不能颠倒;Apache 2.4.8 之前用 SSLCertificateChainFile。改完用 nginx -t 校验再 reload。

提醒一:curl -k 只适合用来判断「是不是证书问题」,不要写进脚本和流水线,它会让中间人攻击彻底失效。提醒二:证书没过期、链也完整却偶发失败,检查负载均衡前后端证书是否一致、以及是否只部署了 RSA 证书而客户端优先走 ECDSA。

顺序记住:先 s_client 看链,再看 SNI 与 SAN,最后才动本地信任库。多数「浏览器正常、脚本报错」的案子在前两步就能定案,不用去改代码里的超时和重试。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。