应显式配置 default_server 拦截无 Host 头请求:在 http 块顶部添加带 default_server 标识的 server 块,监听 80/443 并 return 444;HTTPS 需配有效证书;可配合 map 模块校验 Host 合法性。
当客户端发起 HTTP 请求但未携带
头时(常见于 HTTP/1.0 请求、恶意扫描、构造的畸形请求),Nginx 默认会将其路由到配置中第一个
块——这往往不是你期望的行为,可能造成信息泄露、日志污染甚至安全风险。关键在于:**不能依赖“默认 server”被动承接,而要主动拦截或明确响应**。
为什么没有 Host 头的请求会落到第一个 server?
Nginx 在匹配虚拟主机时,优先依据
和
请求头。若请求不含
头,且未启用
等特殊配置,Nginx 就无法做域名匹配,只能退回到“默认 server”——即按配置文件顺序出现的第一个
块(除非显式标记
)。这个行为不是 bug,而是设计逻辑,但极易被忽略。
用 default_server 主动接管并拒绝非法请求
最稳妥的做法是:**显式定义一个带
标识的 server 块,专用于处理所有无法匹配 Host 的请求,并统一返回 444(关闭连接)或 400(错误请求)**。这样既避免误入业务站点,又减少无效日志。
在
块内顶部(确保最先加载)添加:
}
注意:HTTPS 的
必须提供有效证书,否则 TLS 握手失败前无法识别 Host,浏览器会报证书错误;若仅需拦截 HTTP 流量,可只配
。
配合 map 模块实现 Host 头合法性校验
对于已知合法域名,还可进一步增强防护:用
提前判断
是否在白名单中,不在则直接拒绝。这种方式适合多租户或 SaaS 场景。
在
块中定义映射:
在每个业务
块中加入校验:
⚠️ 注意:
在
上下文中可用,但在
中慎用;该方案是对
的补充,而非替代。
验证与排查技巧
测试是否生效,别只靠浏览器(浏览器自动加 Host)——用
手动构造无 Host 请求:
→ 应收到空响应或连接重置
→ HTTP/1.0 默认无 Host,也应被拦截
检查 Nginx 错误日志:
,确认无 “no resolver defined” 或 “no host in request” 类警告
用
验证配置后,务必
,避免旧进程残留
Hostserverserver_nameHostHostunderscores_in_headers onserverdefault_serverdefault_serverhttpserver {
listen 80 default_server;
listen 443 ssl default_server;
ssl_certificate /path/to/default.crt;
ssl_certificate_key /path/to/default.key;
return 444; # 立即关闭连接,不发响应体(比 400 更静默)
# 或用 return 400; 如果需兼容某些严格要求返回 HTTP 状态的场景
default_serverlisten 80 default_servermap$hosthttpmap $host $invalid_host {
default 1;
example.com 0;
api.example.com 0;
~^www\..+\.com$ 0;
}serverif ($invalid_host) {
return 444;
}ifserverlocationdefault_servercurlcurl -v http://your-ip/ --header "Host:"curl -v http://your-ip/ --http1.0tail -f /var/log/nginx/error.lognginx -tnginx -s reload