应显式配置 default_server 拦截无 Host 头请求:在 http 块顶部添加带 default_server 标识的 server 块,监听 80/443 并 return 444;HTTPS 需配有效证书;可配合 map 模块校验 Host 合法性。

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

















