我的学习 我的学习写字 · 记录 · 分享

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

· 约 2 分钟读完 #HTTPS#网络#建站

排查 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 errorTLS 握手到了服务端,但服务端拿不出这个域名的证书
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 的排查就从「玄学」变成了「按顺序排除」。