要真正阻止通过服务器ip地址发起的恶意http请求,核心是让nginx拒绝为ip直连提供任何有效响应:http 80端口用default_server+return 444静默处理;https 443端口必须禁用default_server并启用ssl_reject_handshake,确保tls握手阶段即终止;辅以host头校验、日志监控、请求限流及网络层封禁。

要真正阻止通过服务器 IP 地址发起的恶意 HTTP 请求,核心不是“拦住请求”,而是让 Nginx 拒绝为 IP 直连提供任何有效响应——不返回页面、不跳转、不记录有效日志,从协议层切断意图。
HTTP 80 端口:用 default_server + return 444 彻底静默
在 HTTP 配置中,必须定义一个明确的兜底 server 块,且仅对未匹配任何合法 server_name 的请求生效:
- 添加 listen 80 default_server,确保它优先接管所有无 Host 匹配或 Host 为 IP 的请求
- server_name _(下划线)表示无效域名,这是 Nginx 官方推荐的占位写法
- 直接返回 return 444:Nginx 特有状态码,表示“关闭连接而不发任何响应体”,浏览器显示为空白或 ERR_EMPTY_RESPONSE,攻击者无法获取任何服务指纹
示例配置:
server {listen 80 default_server;
server_name _;
return 444;
}
HTTPS 443 端口:不能只靠 default_server,必须配合 ssl_reject_handshake
HTTPS 场景下,仅设 default_server 并返回 444 是无效的——因为 TLS 握手阶段已需选择证书,而 IP 直连通常不带 SNI 或 SNI 为 IP,Nginx 若配置了 ssl_certificate 就会 fallback 返回默认证书,等于暴露了服务存在性。
- 每个正式使用的 HTTPS server 块都必须显式声明 server_name example.com www.example.com(禁止留空、禁用通配符 *.example.com)
- 彻底移除或注释掉类似
listen 443 ssl default_server的配置,否则它会成为 SNI 不匹配时的“证书出口” - 在每个启用 SSL 的 server 块内启用 ssl_reject_handshake on:SNI 不匹配时,TLS 握手在 ServerHello 后立即终止,不发证书、不进 HTTP 流程
验证方式:openssl s_client -connect YOUR_IP:443 -servername YOUR_IP 应收到 SSL alert number 112 (unrecognized_name) 并断开。
补充加固:防止绕过与误判
单靠拒绝 IP 直连还不够,攻击者可能构造特殊 Host 头、滥用旧协议或高频探测消耗资源:
- 在 HTTP server 块中加 if ($host !~ ^(example\.com|www\.example\.com)$) { return 444; },双重校验 Host 头内容(注意:仅用于 HTTP,HTTPS 必须靠 SNI 匹配)
- 启用 log_format custom '$remote_addr - $host [$time_local] "$request" $status';,监控日志中高频出现的 IP 值或空 Host,快速识别扫描行为
- 结合 limit_req 对 / 路径限流,例如每秒最多 5 个请求,防 CC 类暴力探测
- 网络层同步封禁:对连续触发 444 的 IP,用
deny指令或防火墙(如 ufw/iptables)临时拉黑
常见误区提醒
以下做法看似合理,实则削弱防护效果:
- 用
rewrite ^ https://example.com$request_uri? permanent跳转 IP 请求 → 暴露域名、泄露重定向逻辑、增加握手开销 - 把
ssl_reject_handshake on放在 http 块或非 HTTPS server 块里 → 完全不生效 - 保留
server_name ""或server_name *→ 导致所有 IP/SNI 不匹配请求仍被接受 - 仅在 location 中 deny IP → 请求已进入 HTTP 流程,资源已被消耗,且无法拦截 TLS 握手阶段探测











