nginx可通过正则匹配$request_uri和$query_string等变量实时拦截含单引号、尖括号、union select、%3c等恶意字符的请求,作为轻量前置过滤网,不替代应用层防护。

通过 Nginx 限制请求中恶意字符的注入,核心思路是在请求到达后端前,利用内置变量和正则匹配对 URI、查询参数、请求头等关键字段做实时检测,命中即拦截。这不是替代应用层防护的方案,而是轻量、前置、高效的首道过滤网。
拦截 URL 和查询参数中的高危字符
SQL 注入、XSS、文件路径遍历等攻击常把恶意内容藏在 $request_uri 或 $query_string 中。例如单引号、尖括号、union select、<script></script>、%3C(URL 编码的
- 在
server或location块中添加如下判断:
if ($query_string ~* "[;'%3C%3E]|(union|select|insert|drop|script|alert|eval|javascript)") { return 403; }
if ($request_uri ~* "../|..\\|/etc/passwd|/phpmyadmin|/wp-admin") { return 403; }
注意:避免在 location 外大量使用 if;更推荐用 map 提前标记风险再统一拦截,减少运行时开销。
过滤请求头里的恶意内容
攻击者可能通过 User-Agent、Referer、Cookie 等头部注入脚本或扫描特征。Nginx 可直接读取这些变量进行匹配。
- 封禁含 XSS 关键字的 UA:
if ($http_user_agent ~* "(|%3C|%3E|script|alert|document.cookie|onerror|onload)") { return 403; }
- 拒绝空 UA 或已知扫描工具 UA:
if ($http_user_agent = "") { return 403; }
if ($http_user_agent ~* "(curl|wget|python-requests|nmap|sqlmap|nikto)") { return 403; }
控制请求体与头部大小防绕过
大请求体可能携带未被 $args 捕获的 POST 数据,过长的请求头也可能用于绕过规则或耗尽资源。
- 限制请求体最大为 10MB(根据业务调整):
client_max_body_size 10m;
- 限制请求头缓冲区大小,防长头攻击:
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
若需检测 POST 内容中的恶意字符(如表单提交的 SQL 片段),单纯靠 $args 不够,必须启用 SecRequestBodyAccess On 配合 Naxsi 模块,或用 Lua 脚本解析 $request_body。
配合限流与日志增强实效性
仅靠字符拦截容易被高频试探绕过。建议叠加行为维度控制:
- 对触发过 2 次拦截的 IP 自动限速或封禁(可用
geo+map+limit_req实现) - 记录所有被拦截请求的完整信息到独立日志,便于溯源分析:
log_format blocked '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time';
access_log /var/log/nginx/blocked.log blocked if=$block_flag;











