Virtual Host 流量错乱最常见根源是 server_name 重复或模糊;Nginx 不报错但请求静默进错块,需用 nginx -T 查所有 server 块的 listen 和 server_name,重点排查默认块、重复域名、通配符冲突、SNI 匹配、include 加载顺序及 debug 日志验证。

直接看 server_name 是否重复或模糊,这是 Virtual Host 流量错乱最常见、最隐蔽的根源。Nginx 不会报错启动失败(除非完全重复监听),但请求会静默进错块——比如用户访问 a.com,却进了本该服务 b.net 的配置,导致页面空白、接口 404 或证书告警。
查清所有生效的 server_name 定义
运行 nginx -T 2>/dev/null | grep -A2 "server {" | grep "server_name\|listen",把所有 server 块的监听端口和 server_name 全部列出来。重点关注:
- 是否有多个块监听相同端口(如都
listen 80)且server_name为空或写成""或_——这类“默认块”会抢走所有未匹配域名的请求 - 是否出现完全相同的
server_name example.com出现在不同文件中(比如app.conf和z-default.conf)——后加载的文件会覆盖前者 - 是否混用通配符与精确匹配:例如
server_name *.example.com;和server_name www.example.com;同时存在,而www请求可能被通配符块捕获(取决于匹配优先级)
验证 SNI 和实际匹配路径
HTTPS 场景下,仅看 server_name 不够,还要确认 TLS 握手阶段的 SNI 是否正确路由:
- 用
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>&1 | grep "subject="检查返回的证书 subject 是否匹配你预期的域名 - 在每个
server块里临时加一行return 200 "served by $server_name\n";,再用curl -H "Host: a.com" https://127.0.0.1直连测试,看返回值是否符合预期 - 注意:如果用了 CDN 或 LB,需绕过它们直连 Nginx,否则看到的是上游转发后的 Host,不是原始 SNI
检查 include 机制和文件加载顺序
/etc/nginx/conf.d/*.conf 是按字典序加载的,00-default.conf 会早于 99-app.conf 生效,但若两者都监听 80 且没设 server_name,后者可能因覆盖逻辑导致前者失效:
- 执行
ls -1 /etc/nginx/conf.d/看文件顺序,再逐个grep -l "listen.*80" /etc/nginx/conf.d/*找出所有监听 80 的文件 - 对每个含
server_name的块,补全default_server标识,例如:listen 80 default_server;,明确指定兜底行为 - 删掉无意义的
include /etc/nginx/conf.d/*.conf;重复语句(尤其在nginx.conf和子配置里都写了)
用 debug 日志确认真实匹配结果
启用 error_log debug 级别,触发一次请求,从日志里直接看到 Nginx 怎么选的 server 块:
- 确保编译含
--with-debug(nginx -V 2>&1 | grep -o with-debug) - 在
http块中加:error_log /var/log/nginx/vhost-debug.log debug; - 重启后请求,日志会出现类似:
"*1 client sent http request without \"Host\" header while reading client request headers, client: 127.0.0.1, server: _, request: \"GET / HTTP/1.1\""—— 这里的server: _就表示进了空server_name的块


















