nginx无法直接匹配$server_protocol限制协议,应通过强制host头校验、default_server兜底拦截、依赖内置协议解析返回400、限制http方法及ua黑名单等组合策略防御恶意扫描与畸形请求。

Nginx 本身不支持直接读取或拦截 $server_protocol(比如 HTTP/0.9、HTTP/3.0、HTTP/999),所以不能靠“匹配协议字符串”来限制。真正可行的做法,是识别并阻断那些因使用非法/过时/畸形协议而暴露恶意行为特征的请求——这类请求大多来自扫描器、爆破工具或僵尸网络客户端。
下面这些配置是生产环境验证过的组合策略,无需复杂模块或 Lua,开箱即用:
强制 Host 头校验,拦截无 Host 的 HTTP/1.0 请求
绝大多数恶意工具(如 Mirai、Gafgyt)仍用 HTTP/1.0 且省略 Host 头。Nginx 对 HTTP/1.1+ 强制要求 Host,而对缺失 Host 的请求会设 $host = "":
- 在 server 块中加入:
if ($host = "") { return 444; } - 配合
server_name _;使用,确保该规则生效 - 此方式对
curl -H "Host:"或 telnet 手动发包同样有效
设置 default_server 拦截所有非法 Host 和协议异常请求
把所有未命中合法 server_name 的请求(含 IP 直连、空 Host、伪造协议导致 SNI 不匹配等)统一交给一个拒绝专用 server:
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- HTTP 端:
server { listen 80 default_server; return 444; } - HTTPS 端必须配真实证书(否则 TLS 握手失败,用户看到的是浏览器证书错误,而非你可控的拦截)
- 这个兜底 server 实际上也捕获了大量因协议解析异常(如
GET / HTTP/3.0)被 Nginx 内部拒收后 fallback 过来的请求
依赖 Nginx 内置协议解析机制自动返回 400
Nginx 在解析请求行时,对非法协议标识有硬性校验。只要出现以下任意一种,就会记录 error log 并返回 400 Bad Request:
-
GET / HTTP/abc(非数字版本) -
POST / HTTP/3.0(HTTP/3 尚未启用,且 Nginx 不原生支持明文 HTTP/3) -
HEAD / HTTP/0.9(缺少路径和协议分隔) - 你无需额外配置,只需确保:
- 没用
error_page 400覆盖默认行为 - 开启详细日志:
error_log /var/log/nginx/error.log info; - 观察日志中是否频繁出现
client sent invalid request line—— 这就是僵尸工具在试错
- 没用
补充:限制高危方法 + 拦截典型工具 User-Agent
很多恶意请求还伴随危险 HTTP 方法或固定 UA 特征:
- 禁用非常规方法(除 GET、HEAD、POST 外):
limit_except GET HEAD POST { deny all; } - 创建 UA 黑名单文件
/etc/nginx/block-ua.map:map $http_user_agent $bad_ua { default 0; ~*malware 1; ~*sqlmap 1; ~*nuclei 1; ~*gobuster 1; ~*mozi 1; ~*mirai 1; } - 在 server 块中引用:
include /etc/nginx/block-ua.map; if ($bad_ua) { return 444; }
不复杂但容易忽略










