一行 curl 看懂 HTTPS:证书链、SNI 与常见握手失败排查
排查 HTTPS 问题时,浏览器报错往往语焉不详,一行 curl -v 反而能把证书链、SNI、协议版本的问题暴露得一清二楚。这篇短文整理几个我常用的 curl 排查姿势。
一、看证书链:curl -v 输出里藏着什么
curl -v https://example.com -o /dev/null
关注 * 开头的调试行:"SSL connection using TLSv1.3" 告诉你协商出的协议版本;"Server certificate:" 段落会依次列出证书链的每一级——subject、有效期、签发者。如果这里只显示一张证书,说明服务器没下发中间证书,桌面浏览器可能因为缓存侥幸通过,但手机端或 Java/Python 客户端会直接报 unable to get local issuer certificate。
补全证书链可以用:
openssl s_client -connect example.com:443 -servername example.com -showcerts
数一下 BEGIN CERTIFICATE 出现的次数,正常至少是 2(站点证书 + 中间证书)。
二、SNI:一台服务器多个站点的分水岭
现代 HTTPS 依赖 SNI(Server Name Indication)在握手阶段告诉服务器"我要访问哪个域名"。curl 默认把 URL 里的主机名作为 SNI 发出去,但排查虚机 IP 或 CDN 回源时经常要手动指定:
curl -v --resolve example.com:443:1.2.3.4 https://example.com
这条命令把 DNS 解析强制指向 1.2.3.4,SNI 和 Host 头仍然是 example.com。如果返回的证书不对,说明这台服务器上的默认站点配置有问题,而不是 DNS 的问题——一步就能划清责任边界。
反过来,用 curl -k https://1.2.3.4 访问裸 IP 时,SNI 为空,服务器只能返回默认证书,此时报证书域名不匹配是正常现象,不是故障。
三、常见握手失败与对应的 curl 现象
1. 证书过期/未生效:curl 报 certificate has expired 或 certificate is not yet valid。用 -v 看 expire date 一眼确认。
2. 中间证书缺失:报 unable to get local issuer certificate。本机 CA 齐全也报,基本就是服务端链没配全。
3. 协议版本不匹配:报 alert protocol version 或直接 handshake failure。可以加 --tlsv1.2 或 --tls-max 1.2 复现老客户端的行为。
4. 加密套件不匹配:报 no ciphers available。老网关常见,用 --ciphers DEFAULT@SECLEVEL=1 测试是否是安全等级过严导致。
5. 域名不对但想继续:-k 只是跳过校验,仅用于临时验证,千万不要写进脚本。
四、一步定位:模拟客户端看协商结果
curl -vso /dev/null --ciphers DEFAULT@SECLEVEL=1 https://example.com 2>&1 | grep -E "SSL|subject|expire"
一行命令同时拿到协商出的 TLS 版本、证书主体和有效期,贴进工单里,对方运维基本不用再追问。
小结
HTTPS 排查的关键是把「网络通不通」「证书对不对」「协议配没配」三个问题拆开,curl -v 加上 --resolve、--tlsv1.2 这几个参数,就能在终端里完成浏览器开发者工具要做的事,而且输出可以直接复制进工单。下次遇到"微信里打不开、浏览器能打开"这类问题,先用 curl 模拟一遍,多半能少走很多弯路。
- 点赞
- 收藏
- 关注作者
评论(0)