Nginx 过滤恶意请求头的核心是在入口层拦截、重写或剥离,而非后端清洗;推荐按优先级采用 map+if 高性能匹配、if+正则直接拦截、proxy_set_header 主动覆盖/清空、client_header_buffer_size 防大头攻击四种方式。

Nginx 本身不解析请求头参数(如 X-Forwarded-For、User-Agent、Referer 等)的语义,但它能高效匹配、校验、覆盖或丢弃这些头部。真正的“过滤恶意请求头参数”,关键不是在后端做清洗,而是在 Nginx 入口层识别、拦截、重写或剥离——把风险挡在第一道门。
以下几种方式是生产环境验证有效的核心做法,按优先级和实用性排序:
用 map + if 实现高性能头部匹配拦截
适合批量规则、高并发场景,比 if 直接正则更安全高效(map 在配置加载时预编译):
# 在 http 块中定义
map $http_user_agent $bad_ua {
default 0;
~*(sqlmap|nikto|dirbuster|wvs|masscan) 1;
~*CVE-2023-.* 1;
}
map $http_referer $bad_referer {
default 0;
~*evil\.site|\.xyz 1;
}
# 在 server 或 location 中应用
if ($bad_ua) { return 444; }
if ($bad_referer) { return 403; }✅ 优势:无运行时编译开销,支持大小写不敏感(
~*),可扩展性强;
⚠️ 注意:map只支持字符串匹配,不支持复杂逻辑(如 AND/OR),需拆解为多个变量。
用 if + 正则直接拦截高危头部值
适用于明确、少量、强特征的攻击模式(如扫描器 UA、伪造 Host):
# 拦截非法 Host 头(防虚拟主机探测/缓存污染)
if ($host !~ ^(example\.com|www\.example\.com|api\.example\.com)$) {
return 444;
}
# 拦截含恶意字符的 Referer(防 CSRF 探测或盗链绕过)
if ($http_referer ~* "(phpmyadmin|shell|webshell|\.asp\.net)") {
return 403;
}
# 拦截超长或畸形 User-Agent(防 DoS 或解析溢出)
if ($http_user_agent = "") { return 403; }
if ($http_user_agent ~* "^[a-zA-Z0-9\s\.\-\,]{1,200}$" = "") { return 400; }✅ 适用场景:规则少、特征明显、需快速响应;
⚠️ 注意:避免在location /中堆叠多个if,建议集中到server块顶部;if在 Nginx 中有执行顺序限制,不能嵌套。
用 proxy_set_header 主动覆盖/清空高风险头(代理场景必做)
如果你用 Nginx 做反向代理,绝不能透传客户端任意头部。这是最常被忽视却最有效的“过滤”:
# ✅ 安全做法:固定或可信来源覆盖 Host proxy_set_header Host $proxy_host; # 推荐,来自 proxy_pass 地址 # 或 proxy_set_header Host api.example.com; # ✅ 规范 X-Forwarded-*,杜绝 IP 伪造 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; # 不用 $http_x_forwarded_for! proxy_set_header X-Forwarded-Proto $scheme; # ✅ 禁用下划线头解析(防 X_User_ID → X-User-ID 绕过) underscores_in_headers off; # ✅ 清空或剥离无业务价值但易被滥用的头 proxy_set_header User-Agent ""; proxy_set_header Referer ""; proxy_set_header Origin ""; # ✅ 隐藏后端指纹(非请求头过滤,但属同源加固) proxy_hide_header Server; proxy_hide_header X-Powered-By;
✅ 核心逻辑:不是“过滤内容”,而是“拒绝信任输入”;
⚠️ 关键点:$remote_addr是真实客户端 IP(经set_real_ip_from校准后),永远比$http_x_forwarded_for可信。
用 client_header_buffer_size 和 large_client_header_buffers 防大头攻击
针对超长请求头(如数 MB 的 Cookie 或自定义头)引发的内存耗尽或缓冲区溢出:
# 单个请求头最大缓冲区(默认 1k,太小易误杀,太大易被利用) client_header_buffer_size 2k; # 最多允许 4 个大头,每个最多 8k large_client_header_buffers 4 8k; # 超出即返回 400 Bad Request(Nginx 自动触发,无需手动 return)
✅ 效果:直接阻断超长头,不进业务逻辑;
⚠️ 建议:根据实际业务头部长度测试调整(如 JWT Token 较长,可设为16k)。
不复杂但容易忽略。


















