只写server_name _不起作用,是因为Nginx兜底逻辑依赖listen ... default_server标识,而非server_name是否为空;未设default_server时,请求会落入配置中第一个server块,无论其server_name为何值。

为什么只写 server_name _ 不起作用
很多人照着网上教程加了 server_name _,结果 IP 还能正常访问,甚至流量全打到某个业务 server 块里。根本原因是:Nginx 不靠 server_name 是否为空来判断“兜底”,而是按 listen 的 default_server 标识找第一个匹配的 server 块。没加 default_server,Nginx 就会退回到配置顺序匹配——通常落到第一个写的 server 里,哪怕它写了 server_name example.com。
常见错误配置:
server {
listen 80;
server_name _; # ❌ 没有 default_server,这行基本无效
return 444;
}正确做法是确保该块带 default_server,且整个 http 块中仅有一个 listen 80 default_server(HTTPS 同理)。
return 444 和 return 403 怎么选
return 444 是 Nginx 特有状态码,含义是“直接断开 TCP 连接”,不发任何响应头或响应体。这对封禁 IP 访问最干净:节省带宽、减少日志噪音、避免被扫描器识别出服务存在。
return 403 会返回完整 HTTP 响应(含 Content-Length: 0 等),适合需要返回自定义提示页的场景,但必须配合 error_page 才能生效:
server {
listen 80 default_server;
server_name _;
return 403;
error_page 403 /403.html;
}
location = /403.html {
root /usr/share/nginx/html;
}- 若只想快速切断连接,无条件用
return 444 - 若已配了全局
error_page 403,注意它不会自动继承到这个兜底块,必须显式声明 -
return 500或重定向(如rewrite ... permanent)都不推荐——前者暴露服务,后者可能给恶意解析导流
HTTPS 也要单独配一个兜底块
HTTP 和 HTTPS 是两个独立监听端口,listen 80 default_server 对 listen 443 完全无效。如果开了 HTTPS,必须额外加一个:
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /dev/null; # 占位用,实际不可用
ssl_certificate_key /dev/null;
return 444;
}关键点:
-
ssl_certificate和ssl_certificate_key必须存在且路径合法,否则nginx -t报错;用/dev/null是最小代价占位方案 - 不能复用已有业务块的证书——那会导致未备案域名通过 HTTPS 直接命中业务逻辑
- 若用 Let’s Encrypt 等自动签发工具,注意它可能覆盖或删除这个兜底块,部署后要人工校验
多个 server 块共存时怎么避免冲突
最容易被忽略的是:已有其他 server 块写了 listen 80 default_server,再新增兜底块就会导致 nginx -t 失败,报错类似:duplicate default_server for 0.0.0.0:80。
操作前务必检查:
- 执行
grep -r "default_server" /etc/nginx/conf.d/找出所有含该关键字的块 - 删掉旧的
default_server,或把它的default_server去掉,只保留你新建的那个兜底块 - 兜底块建议放在
http块最开头或最末尾,避免被 include 文件意外覆盖 - reload 前永远先跑
nginx -t,别信“改一行不用测”
真正生效的兜底逻辑只依赖两件事:唯一 default_server + 匹配不到任何 server_name。其余都是干扰项。


















