跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

实战讲解Nginx中虚拟主机如何处理没有Host头的非法请求

应显式配置 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;
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
,避免旧进程残留

相关文章