nginx rewrite指令不适合直接拦截恶意请求,应优先使用return、deny、map等指令在早期阶段终止响应;如用return 444拦截路径遍历,map预编译ua黑名单,deny封禁ip。

Nginx 的 rewrite 指令本身设计用于 URI 重写(如跳转、内部重定向),**并不适合直接做恶意请求拦截**。它不具备拒绝请求的能力——即使你用 rewrite ... break 或 last,请求仍会继续处理;而 rewrite ... redirect 只是返回 302,无法阻止攻击者反复发起请求。
真正安全、高效、推荐的拦截方式,是结合 return、deny、map 和 if(谨慎使用)等指令,在请求早期阶段直接终止响应。下面分场景给出实用方案:
用 return 快速拦截已知恶意特征
当 URL、参数或头部中存在明确攻击模式(如 SQL 注入关键字、路径遍历、扫描器 UA),优先用 return 403 或 return 444(Nginx 特有,关闭连接不发响应):
-
拦截含
../或etc/passwd的路径:if ($request_uri ~* "(?:\.\./|etc/passwd)") { return 444; } -
拦截常见 WebShell 参数(如
?cmd=、&act=exec):if ($args ~* "(cmd|exec|system)=|&act=exec") { return 403; } -
拦截扫描器 User-Agent(注意避免误伤爬虫):
if ($http_user_agent ~* "(sqlmap|nikto|dirbuster|wvs)") { return 444; }
用 map 实现高性能黑白名单匹配
map 在配置加载时预编译正则,比 if 更快更安全,适合管理大量规则:
-
定义恶意 UA 映射(在
http块中):map $http_user_agent $bad_ua {<br> default 0;<br> ~*(sqlmap|nikto) 1;<br> ~*CVE-2023-1234 1;<br>} -
在
server或location中应用:if ($bad_ua) { return 444; } - 同理可映射恶意 IP、Referer、请求头值等,支持大小写不敏感(
~*)和精确匹配(无修饰符)。
用 deny + allow 控制 IP 访问(基础但有效)
对已确认的恶意 IP 或网段,直接拒绝连接(比 return 更底层):
-
在
http、server或location块中配置:deny 192.168.1.100;<br>deny 203.0.113.0/24;<br>allow all;
- 注意顺序:
deny/allow按出现顺序逐条匹配,最后一条未匹配则按默认策略(默认为allow)。 - 配合
geo指令可实现基于国家/地区的粗粒度屏蔽(需 GeoIP 数据库)。
重要提醒:避开 if 的陷阱与性能误区
if 在 location 外使用有风险(如在 server 块中),且部分变量(如 $args、$request_uri)在 rewrite 后可能变化。务必注意:
- 避免在
if中使用rewrite+break试图“拦截”——这仍是重写,不是拒绝。 - 不要用
if判断文件是否存在(-f)、目录(-d)等,应改用try_files。 - 高并发下频繁正则匹配影响性能,建议用
map预处理,或结合 ModSecurity 等专业 WAF。
不复杂但容易忽略:拦截规则上线前,务必用 nginx -t 检查语法,并在测试环境验证是否误杀正常流量。真实攻击往往混合变形,单一规则效果有限,建议组合使用并定期更新规则库。











