当前位置:网站首页 >  攻略

十分钟搞定Nginx异常请求过滤与流量清洗实战

时间:2026年06月15日 15:51:50 来源:易频IT社区

一、基础设施层拦截:Nginx 全量配置实战

在流量到达应用服务器之前,利用 Nginx 进行清洗是性价比最高的方案。以下配置涵盖了恶意扫描器拦截、SQL注入/XSS防御以及高频访问限制。请根据实际路径调整配置文件位置,通常为 /etc/nginx/nginx.conf

1. 恶意 User-Agent 与扫描器清洗

使用 map 模块可以高效地识别并阻断恶意爬虫和扫描工具。请在 http 块的起始位置添加以下配置:

http {
定义恶意UA映射,如果匹配成功则变量值为1
map $http_user_agent $blocked_ua {
default 0;
~malicious 1;
~bot 1;
~spider 1;
~crawler 1;
~scraper 1;
~Nmap 1;
~Sqlmap 1;
~Wget 1;
~curl 1;   生产环境可根据需求决定是否拦截curl
}
... 其他 http 配置
}

配置完成后,需要在 server 块中添加判断逻辑,如果变量值为 1 则直接返回 403:

server {
listen 80;
server_name example.com;
如果UA在黑名单中,直接拒绝
if ($blocked_ua) {
return 403;
}
location / {
proxy_pass http://backend_server;
}
}

2. 接口访问频率限制(防CC攻击)

通过 limit_req_zone 定义限流区域,限制单个 IP 的请求速率。在 http 块中添加如下配置:

http {
定义限流区域:以二进制远程地址为key,区域名为my_limit,大小10M,速率为每秒1次请求
limit_req_zone $binary_remote_addr zone=my_limit:10m rate=1r/s;
server {
listen 80;
server_name example.com;
location / {
应用限流规则,允许5个请求的突发缓冲区(burst),不延迟处理(nodelay)
limit_req zone=my_limit burst=5 nodelay;
超过限制返回 503
limit_req_status 503;
proxy_pass http://backend_server;
}
}
}

3. SQL注入与XSS攻击正则匹配

server 块中,利用正则表达式对 URL 参数进行深度检测。如果匹配到敏感词,直接返回 403。这种方式能有效过滤常见的 Web 攻击载荷。

server {
... 其他配置
使用正则匹配 $args (查询参数) 和 $uri
if ($args ~ "union.select|insert.into|delete.from|drop.table|script|alert|eval|expression") {
return 403;
}
针对URI的检测
if ($uri ~ "\.(php|jsp|asp|aspx)") {
如果您的站点是纯静态或纯接口,且不包含这些后缀,建议直接拦截
return 403;
}
}

注意:配置修改完成后,必须执行 nginx -t 检查语法,确认无误后执行 nginx -s reload 重载配置。

二、应用层拦截:Spring Boot 动态过滤器

当业务逻辑需要根据用户状态或动态黑名单进行拦截时,Nginx 的静态配置就显得力不从心。以下是基于 Spring Boot 的实操代码,实现包含 IP 黑名单和参数清洗的过滤器。

1. 核心过滤器代码实现

创建一个名为 SecurityFilter 的类,实现 javax.servlet.Filter 接口。该过滤器会拦截所有请求,检查 IP 并清洗参数。

package com.example.demo.config;
import javax.servlet.;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
@WebFilter(urlPatterns = "/", filterName = "securityFilter")
public class SecurityFilter implements Filter {
// 模拟本地黑名单,实际生产中建议替换为 Redis 查询
private static final Set BLACKLIST_IP = new HashSet<>(Arrays.asList("192.168.1.100", "10.0.0.50"));
// SQL注入和XSS检测正则
private static final Pattern ATTACK_PATTERN = Pattern.compile(
".(union\\s+select|insert\\s+into|delete\\s+from|drop\\s+table|script|alert\\(|eval\\(|expression\\().",
Pattern.CASE_INSENSITIVE
);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化逻辑
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String clientIp = getClientIp(req);
// 1. IP 黑名单检查
if (BLACKLIST_IP.contains(clientIp)) {
res.setStatus(403);
res.getWriter().write("Access Denied: IP is blocked");
return;
}
// 2. 参数攻击特征检查
if (containsAttackPattern(req)) {
res.setStatus(403);
res.getWriter().write("Access Denied: Illegal parameters detected");
return;
}
// 放行请求
chain.doFilter(request, response);
}
@Override
public void destroy() {
// 销毁逻辑
}
private String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 处理多级代理的情况,取第一个IP
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
private boolean containsAttackPattern(HttpServletRequest request) {
// 检查 URI
if (ATTACK_PATTERN.matcher(request.getRequestURI()).matches()) {
return true;
}
// 检查 Query String
if (ATTACK_PATTERN.matcher(request.getQueryString() != null ? request.getQueryString() : "").matches()) {
return true;
}
return false;
}
}

关键点说明:

  • @WebFilter 注解确保 Spring Boot 启动时自动注册该过滤器。
  • getClientIp 方法考虑了 Nginx 反向代理的情况,优先获取 X-Forwarded-For 头部中的真实 IP。
  • containsAttackPattern 方法对 URI 和 QueryString 进行正则匹配,拦截恶意 SQL 关键字和脚本标签。

2. 启用过滤器组件

十分钟搞定Nginx异常请求过滤与流量清洗实战

确保您的 Spring Boot 主启动类带有 @ServletComponentScan 注解,否则 @WebFilter 将不会生效。

package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan // 必须添加此注解
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

三、效果验证与测试命令

配置完成后,使用 curl 命令模拟异常请求进行验证。以下测试命令假设您的服务运行在本地 8080 端口。

1. 测试 User-Agent 过滤(Nginx层)

模拟一个恶意扫描器的 UA,预期返回 403 Forbidden:

curl -I -A "Sqlmap/1.0" http://localhost/

如果配置正确,响应头中应包含 HTTP/1.1 403 Forbidden

2. 测试 IP 黑名单(应用层)

模拟黑名单 IP 发起请求。修改上述 Java 代码中的 BLACKLIST_IP,将您的本机 IP(或局域网 IP)加入重启服务后访问:

curl -v http://localhost:8080/api/test

预期响应内容为:Access Denied: IP is blocked

3. 测试 SQL 注入过滤(应用层)

在 URL 参数中注入 SQL 语句:

curl -v "http://localhost:8080/api/user?id=1%20union%20select%201,2,3"

由于参数中包含 union select,应用层过滤器应拦截并返回:Access Denied: Illegal parameters detected

4. 测试频率限制(Nginx层)

使用循环命令快速发送 10 个请求:

for i in {1..10}; do curl -I http://localhost/; done

根据 Nginx 配置(rate=1r/s, burst=5),前几个请求可能成功(200 OK),后续请求将收到 503 Service Temporarily Unavailable

相关推荐

最新

热门

推荐

精选

标签

易频IT社区是综合性互联网IT技术门户网站,专注分享网络技术、服务器运维、网络安全、编程开发、系统架构、云计算、大数据等行业干货,实时更新IT行业资讯、零基础教程、实战案例,为IT从业者、技术爱好者提供专业的学习交流平台。

Copyright © 2021-2026 易频IT社区. All Rights Reserved. 备案号:闽ICP备2023013482号 网站地图