必须配置default_server拦截所有未授权Host请求,即在80和443端口分别设置listen default_server的server块,server_name设为_,统一return 444关闭连接;HTTPS需配有效证书,推荐Nginx 1.19.4+启用ssl_reject_handshake on实现TLS握手阶段拦截。

直接通过主机名(如 Host: evil.com)访问,本质是绕过你配置的合法域名,利用 Nginx 默认匹配逻辑发起扫描或探测。这类请求不走业务 server 块,而是落入 default_server,必须在配置层主动拦截,不能依赖后端或日志事后处理。
用 default_server 拦截所有未授权 Host 请求
这是最核心、最可靠的防线。Nginx 会把所有 Host 头不匹配任一 server_name 的请求,交给标记为 default_server 的块处理。你需要把它设为“拒绝专用块”:
- 新建一个以
00-开头的配置文件(如/etc/nginx/conf.d/00-block-illegal-host.conf),确保它最先加载 - HTTP 和 HTTPS 各配一个
default_server,server_name分别写__(HTTP)和_(HTTPS),这是 Nginx 官方推荐的占位写法 - 统一返回
444:直接关闭 TCP 连接,不发任何响应,比 403 更隐蔽、更节省资源
禁止含下划线或非法字符的 Host 头
Nginx 默认不解析含下划线的域名(如 admin_internal.example.com),但这类请求仍可能落到 default_server。你可以在 default_server 内加一层校验:
- 用
if ($host ~ "_") { return 444; }主动拦截带下划线的 Host - 同理可扩展匹配空格、控制字符、非 ASCII 字符等:
if ($host ~ "[[:space:]\x00-\x1f]") { return 444; } - 注意:该
if必须放在server块内,不能放在http块顶层
配合 Host 白名单做精确控制
如果你的站点只服务几个固定域名,建议显式声明白名单,而非依赖 default_server 被动拦截:
- 每个合法
server块中,server_name写全称,例如server_name example.com www.example.com; - 禁用泛域名(如
*.example.com),防止被滥用 - 对于 HTTPS,Nginx 1.19.4+ 可启用
ssl_reject_handshake on;,在 TLS 握手阶段就拒掉非法 SNI,连证书都不暴露
验证拦截是否生效
配完别急着上线,先本地测试:
- 用 curl 模拟非法 Host:
curl -H "Host: fake.com" http://your-server-ip/,应无响应或连接被重置 - HTTPS 测试:
openssl s_client -connect your.ip:443 -servername bad.test.com,应看到unrecognized_name或连接中断 - 检查 Nginx error 日志,确认没有因 Host 匹配失败而产生的 warning


















