Nginx 利用 server_name 不支持下划线的特性,结合 default_server 实现非法 Host 拦截:所有含下划线或未匹配白名单的请求均落入兜底 server,返回 444 或 403。

在 Nginx 中,server_name 本身**不支持下划线(_)作为合法域名字符**,这是由 RFC 标准决定的。但正因如此,利用这一限制可实现一种轻量、有效的“拦截恶意域名解析”的手段——即配置一个带下划线的 server_name,让 Nginx 主动拒绝(或跳转/返回错误)所有非法、非预期的 Host 请求。
为什么下划线能用于拦截?
Nginx 在匹配 server_name 时,若发现请求头中的 Host 值包含下划线,而当前 server 块中又没有完全匹配的 server_name(包括含下划线的),则会落入默认 server(通常是第一个或标记为 default_server 的块)。但关键在于:如果你显式写一个含下划线的 server_name,Nginx 会直接忽略该配置项(启动时警告),不会用它做匹配。所以真正起作用的是:利用 Nginx 对下划线 Host 的“天然不兼容” + 显式兜底 server 的组合策略。
实战配置:用 default_server 拦截非法 Host
核心思路是:不依赖下划线匹配,而是让所有未被明确 server_name 覆盖的请求(包括含下划线的 Host)都进入一个专用的“拒绝 server”。操作如下:
- 确保你的主业务 server 块只写合法域名,例如:
server_name example.com www.example.com; - 单独定义一个
server块,监听相同端口,加上default_server标志,并设置严格响应 - 该块不写
server_name,或仅写一个无效值(如server_name "_";,虽无效但可作语义提示)
示例配置:
server {
listen 80 default_server;
server_name _; # 或留空,或写任意非法值,仅作占位
<pre class="brush:php;toolbar:false;">return 444; # 直接关闭连接(无声丢弃)
# 或返回 403 + 自定义页面:
# return 403;
# root /usr/share/nginx/html;
# error_page 403 /403.html;
}
常见恶意场景与拦截效果
攻击者常通过 DNS 解析将任意子域(如 xxx.恶意IP.com、123_abc.attacker.net)指向你的服务器 IP,试图绕过 CDN、触发 SSRF、探测内网服务等。只要这些域名含下划线、或根本不在你白名单中,就会被 default_server 拦截:
-
curl -H "Host: test_user.example.com" http://your-ip/→ 匹配失败,进入 default_server → 返回 444 -
curl -H "Host: _admin.internal" http://your-ip/→ Host 含下划线,Nginx 不匹配任何合法 server_name → 进入 default_server - 未配置
server_name的裸 IP 访问、随机字符串 Host → 同样落入 default_server
注意事项与增强建议
这个方法简单有效,但需注意几点:
-
default_server必须和主 server 使用相同listen指令(如都是listen 443 ssl),否则不生效 - 避免多个
default_server冲突;生产环境建议只保留一个明确的兜底块 - 配合日志记录可进一步分析恶意请求:
log_format blocked '$remote_addr - $request_time "$request" $status'; - 对 HTTPS 站点,还需确保 SNI 匹配逻辑正常——若使用泛域名证书,仍需靠
server_name白名单控制,不能仅依赖 Host 头
不复杂但容易忽略。










