nginx在无default_server时默认选同一端口下第一个加载的server块作为兜底;可通过curl -h "host:"模拟请求、nginx -t查看加载顺序、添加return或独立access_log验证实际响应者。

测试多个 server_name 冲突时 Nginx 实际选中哪个默认虚拟主机,核心是绕过 DNS 和浏览器缓存,直击 Nginx 的匹配逻辑与加载顺序——它不报错,只静默路由,所以必须用可验证、可隔离的方式确认“谁真正响应”。
用 curl -H "Host:" 模拟任意域名请求
这是最直接的方法:不依赖 DNS 解析,强制构造 Host 头,看请求落到哪个 server 块。
- 执行
curl -H "Host: unknown.example.com" http://127.0.0.1,观察返回内容或状态码 - 若返回的是某个站点页面,说明该请求被某个未显式声明该域名的 server 块兜底处理了
- 配合
access_log查日志路径(如/var/log/nginx/access.log),确认哪条日志记录了这次请求
检查 default_server 和隐式兜底块
Nginx 不设 default_server 时,会把同一端口下第一个定义的 server 块当作默认入口——这个“第一个”由 include 展开顺序决定(通常按字母序)。
- 运行
nginx -T 2>/dev/null | grep "listen.*80" -A 5,找出所有监听 80 的块,并注意是否带default_server - 没有
default_server标记的,就看输出中第一个出现的server { ... }块——它就是实际兜底者 - 临时把疑似兜底的配置改名为
00-default.conf,重启后再次用curl -H测试,验证是否切换
在兜底块里加唯一标识或拦截动作
让“谁在兜底”变得肉眼可见,避免靠猜。
- 在你怀疑是默认入口的 server 块里加:
return 200 "I am the default server\n"; - 或者写入独立日志:
access_log /var/log/nginx/default-catch.log;,再发起 Host 不匹配的请求,查该日志是否有记录 - 若某次请求触发了这条日志或返回了该字符串,就确认了当前默认虚拟主机身份
对比 nginx -T 输出中的 server_name 实际加载情况
配置写了 ≠ 被加载 ≠ 被启用。重复的 server_name 会导致后加载者被静默忽略(Nginx 只警告不中断)。
- 执行
nginx -T 2>/dev/null | grep -A 10 "server_name.*your-domain",看该域名出现在几个块里、分别在哪个文件 - 再运行
nginx -T 2>/dev/null | grep "listen.*80" -A 3 | grep -E "(server_name|default_server)",对照顺序判断哪个块优先级更高 - 特别注意警告信息:启动时若有
conflicting server name "xxx" on 0.0.0.0:80, ignored,说明该行配置已失效











