「服务端没问题」的排障:请求根本没到 nginx
线上出现一个很迷惑的现象:页面偶尔能打开,多数时候浏览器直接报连接失败;同一时刻,服务器本机 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。服务端没有任何可修的地方。
得到的教训
- 「服务端没问题」要先被证明,而不是当结论用
- 排障顺序从下往上:TCP → TLS → HTTP → 应用
- 对照实验是切变量最快的工具:换域名、换网络、换端口,一次只动一个
- 业务侧的解法往往是换入口,而不是修服务器
后来备案生效,阻断自然消失。但那次排查留下的方法比结论更有价值:先定位边界,再谈修复。