跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何利用 Nginx 拦截非法 Host 头部请求:防止 HTTP 主机头攻击(Host Injection)

最直接有效的方式是在Nginx层做Host头白名单校验,通过default_server拦截未匹配域名的请求并返回403,覆盖IP访问、伪造域名、含下划线域名、空或缺失Host头等非法请求。 最直接有效的方式,是在 Nginx 层做 Host 头白名单校验,所有不匹配预设域名的请求,在到达后端前就返回 403 或直接断连。这不需要改代码,也不依赖后端逻辑,是防御 Host 头攻击的第一道也是最关键的防线。 用 default_server 拦截未匹配的 Host 请求 这是最常用、最稳妥的方案。Nginx 会把所有 Host 头不匹配任何 server_name 的请求,交给标记为 default_server 的块处理。只要把它配成“拒绝专用 server”,就能覆盖绝大多数非法请求,包括: 直接用 IP 访问(如 http://192.168.1.100) 伪造的域名(如 Host: evil.com) 含下划线的域名(如 Host: admin_internal.example.com,Nginx 默认不认下划线) 空 Host 头或缺失 Host 头的请求 配置示例(放在独立 conf 文件中,建议以 00-block-host.conf 命名,确保最先加载):
server { listen 80 default_server; server_name _; return 403; }

server { listen 443 ssl default_server; servername ; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; return 403; }

注意:HTTPS 的 default_server 必须配有效证书,否则 TLS 握手阶段就会失败,用户看到的是证书错误,而不是 403。 主业务 server 显式声明合法域名 在 default_server 之后,再定义你真正提供服务的 server 块,并严格列出所有允许的域名:
server { listen 80; listen 443 ssl; server_name example.com www.example.com api.example.com;
ssl_certificate /path/to/main.pem;
ssl_certificate_key /path/to/main.key;

location / {
    proxy_pass http://backend;
    # 其他转发配置...
}
} 关键点: Nginx 在宝塔面板中轻松管理Nginx高性能Web服务器。提供可视化配置反向代理、负载均衡、SSL证书及HTTP缓存功能,一键优化高并发性能,助您高效搭建稳定、快速的网站运行环境。 下载 不要写 server_name * 或留空 —— 这会让 Nginx 接受任意 Host 多个域名用空格分隔,不支持通配符(如 *.example.com 需用正则或 map 模块) 如果需要泛域名支持,建议配合 map 模块做更灵活的白名单判断 用 set + if 实现精细控制(适合单域名场景) 当业务只跑一个主域名,且希望逻辑清晰、避免 default_server 语义模糊时,可用标志位方式校验:
server { listen 80; listen 443 ssl; server_name _; # 此处 server_name 只是占位,实际靠 if 判断
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

set $host_ok 0;
if ($host = "example.com") { set $host_ok 1; }
if ($host = "www.example.com") { set $host_ok 1; }
if ($host_ok = 0) { return 403; }

location / {
    proxy_pass http://backend;
}
} 优点是判断逻辑集中、可读性强;缺点是 if 在 location 外使用有局限,不适用于复杂多条件场景。生产环境推荐优先用 default_server 方式。 补充:拦截纯 IP 访问与 hosts 劫持 本地 hosts 文件篡改、或通过 IP 直连,常被用于绕过 WAF 或探测隐藏服务。Nginx 默认会把这类请求归入第一个或 default_server 块。因此上面的 default_server 配置已天然覆盖该风险。若想进一步加固,还可加一条:
if ($host ~ "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$") { return 403; }
这条规则能识别 IPv4 地址格式的 Host 头并拦截,对防止内网扫描和恶意解析有帮助。IPv6 可用更长正则匹配,按需启用。

相关文章