排查 HTTPS,我常用的几个 curl 和 openssl 姿势

HTTPS 的问题最烦的一点是层次多:DNS、TCP、TLS、证书、虚拟主机路由、应用,任何一层出错,浏览器给的都是同一种「打不开」。所以排查的顺序不是「试试这个试试那个」,而是从上往下切层。
一、让域名走指定的 IP:--resolve
DNS 还没生效、或者想验证「换台机器是不是就好了」,都要靠它:
curl -I --resolve hahaha.asia:443:127.0.0.1 https://hahaha.asia/
它把「域名 → IP」这一步固定住,剩下的链路照常走。测虚拟主机配置时几乎必用——因为 SNI 和 Host 都还是原域名,服务器的路由逻辑完全按真实访问来。
二、只想看连通性:-k 和 -o /dev/null
curl -sk -o /dev/null -w '%{http_code} %{time_total}s\n' -m 10 https://hahaha.asia/
-k 跳过证书校验,-w 打出状态码和耗时。这只用于排查:-k 能通、去掉 -k 就不通,说明问题在证书链而不在连通性——这一条判断能省掉很多时间。真要写进监控或脚本,就把证书校验打开。
三、看握手细节:-v
curl -sv -o /dev/null https://hahaha.asia/ 2>&1 | grep -Ei 'alpn|SSL connection|subject|issuer|expire'
能一次看到:TLS 版本、协商出的 ALPN(h2 还是 http/1.1)、证书的 subject/issuer/有效期。判断「是不是拿到了给正确域名的证书」,看这里最快。
四、证书本身:openssl s_client 必须带 SNI
echo | openssl s_client -connect hahaha.asia:443 -servername hahaha.asia 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
-servername 是关键。不加的话握手时不发 SNI,服务器只能给默认证书,你会看到一张「看起来完全不对」的证书,然后误判成证书配错了。同一台机器上放了多个站点时,这个误判特别常见。
-ext subjectAltName 也值得加上:现在的证书靠 SAN 匹配域名,CN 已经不作数了。
五、报错对照表
| 现象 | 大概率原因 |
|---|---|
Connection refused | 报文到了主机,但没有进程在监听这个端口 |
Connection timed out | 报文被静默丢弃:安全组/防火墙没放行 |
tlsv1 alert internal error | TLS 握手到了服务端,但服务端拿不出这个域名的证书 |
certificate verify failed | 证书链不完整、过期,或域名不匹配 |
curl: (60) SSL certificate problem | 根证书缺了,或中间证书没下发全 |
第三行那个报错很值得记住:它说明网络是通的、SNI 也到了,问题只在证书。反过来,这时候再去查安全组就是浪费时间。
六、别只在服务器上看
最后一条经验:「本机通」和「外网通」是两回事。从服务器访问自己的公网域名,流量可能走的是内部回环,不经过边界设备——该被拦的照样「通」,于是你在本机测一切正常,外面却全挂。
验证外部可达,用免费的多节点探测服务从外面打一圈:
curl -H 'Accept: application/json' \
'https://check-host.net/check-http?host=https%3A%2F%2Fhahaha.asia%2F'
# 拿 request_id,等十几秒再取结果
curl -H 'Accept: application/json' 'https://check-host.net/check-result/<request_id>'
「绝大多数节点通、个别节点超时」和「全部节点都不通」,指向的原因完全不同,前者往往是节点本身的问题。
小结
- 切层:DNS → TCP → TLS → 证书 → 路由,每一层都有对应的命令;
- 测路由用
--resolve,测证书用-servername,看细节用-v; - 本机的结果不足为凭,外部多节点才是真相。
把这几个姿势固定成肌肉记忆之后,HTTPS 的排查就从「玄学」变成了「按顺序排除」。