必须用default_server显式兜底,否则ip直连或未备案域名解析必然落到业务块;其正确写法是listen 80 default_server与listen 443 ssl default_server分别配置,server_name设为_,并配有效证书,返回444终止连接。

必须用 default_server 显式兜底,否则 IP 直连或未备案域名解析仍会落到业务块里——这不是“可能”,而是 Nginx 路由机制决定的必然结果。
为什么 if ($host != "xxx") 在 server 块里完全不可靠
Nginx 官方明确不推荐在 server 级别使用 if,尤其搭配 return 时:
- 多数版本中 if 在 server 块内不支持 return,配置静默失效,nginx -t 也不报错
- $host 可被恶意构造(如 Host: example.com:8080、Host: \texample.com),绕过字符串比对
- HTTPS 场景下,若没配 listen 443 ssl default_server,IP 直连会跳过所有 if 判断,直接进入业务 server 块
- 即使生效,也发生在 SSL 握手之后、请求解析阶段,晚于路由决策,属于“补救”而非“拦截”
default_server 的正确写法和位置
这个兜底块必须独立存在,且满足三个硬性条件:
- listen 80 default_server 和 listen 443 ssl default_server 必须分开写,不能合并
- server_name _ 是必须项,下划线是 Nginx 官方认可的无效主机名占位符,不是随便写的符号
- 必须确保整个 http{} 块中,仅有一个 listen 80 default_server(同理 443),否则 nginx -t 报 conflicting server name 错误
- 推荐放在所有业务 server 块之前,避免因配置顺序引发歧义
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
<p>server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server<em>name </em>;
ssl_certificate /etc/nginx/ssl/placeholder.crt;
ssl_certificate_key /etc/nginx/ssl/placeholder.key;
return 444;
}</p>
HTTPS 配置容易漏掉的关键点
很多人只配了 HTTP 的 default_server,却忘了 HTTPS 同样需要:
- ssl_certificate 和 ssl_certificate_key 路径不能留空,Nginx 启动会失败
- 可用自签名证书临时占位(openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout placeholder.key -out placeholder.crt),但不能省略
- 不要用 rewrite ^(.*) https://example.com permanent 替代 return 444,这会让恶意解析获得有效响应,等于白设
- 若业务 server 块里已有 default_server,新增兜底块前务必先删掉旧的,否则冲突
验证是否真正生效的两个动作
配置 reload 后,别只信 nginx -t:
- 用 curl -H "Host:" http://your-server-ip 测试空 Host 头
- 用 curl -k https://your-server-ip 测试 HTTPS IP 直连(-k 跳过证书校验)
- 两者都应立即断连(无响应体、无状态码),而不是返回 403、500 或跳转到某个域名
- 如果返回了业务站点内容,说明兜底块没生效,大概率是 default_server 冲突或 HTTPS 块缺失











