「服务端没问题」的排障:请求根本没到 nginx

#排障#网络#TLS

线上出现一个很迷惑的现象:页面偶尔能打开,多数时候浏览器直接报连接失败;同一时刻,服务器本机 curl 四个虚拟主机全部 200。

第一步:先证明服务端无辜

不要一上来就改配置。先在服务器上把每一层单独验证:

# 本机直连(绕过公网)
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: example.com' https://127.0.0.1:9443

# 走公网 IP + SNI
curl -sv --resolve example.com:443:203.0.113.10 https://example.com/ -o /dev/null

本机全绿、公网握手就断,说明问题在请求到达应用之前。

第二步:看日志有没有请求

tail -f /var/log/nginx/access.log

如果浏览器报错时 access log 一条都没有,那 nginx 连 TCP 都没建立,直接排除虚拟主机、证书、应用三层。

第三步:对照实验切变量

我当时的做法是三条独立网络分别测试同一个域名,结果一致失败;换一个域名指向同一台机器,立刻成功。变量只剩一个:域名字符串本身。

结论是链路中间设备按 SNI 精确匹配做了阻断——80 端口注入阻断页,443 直接 RST。服务端没有任何可修的地方。

得到的教训

  1. 「服务端没问题」要先被证明,而不是当结论用
  2. 排障顺序从下往上:TCP → TLS → HTTP → 应用
  3. 对照实验是切变量最快的工具:换域名、换网络、换端口,一次只动一个
  4. 业务侧的解法往往是换入口,而不是修服务器

后来备案生效,阻断自然消失。但那次排查留下的方法比结论更有价值:先定位边界,再谈修复。