[拒绝服务攻击] 【系统安全】DDoS攻击

676 1
Honkers 2026-2-7 01:58:55 来自手机 | 显示全部楼层 |阅读模式

【一】什么是DDoS攻击

【1】DDoS攻击的概念

DDoS​ 的全称是 ​Distributed Denial-of-Service,即 ​分布式拒绝服务攻击。
(1)拒绝服务(DoS)​​:
目标​:攻击者的目的不是窃取数据或入侵系统,而是让正常的用户无法访问目标服务,也就是“拒绝”提供“服务”。

​比喻​:这就像你开了一家商店,攻击者不是来偷东西,而是雇了成百上千人堵在你的店门口。真正的顾客根本无法进门,你的生意也就瘫痪了。

(2)​分布式(D)​​:
​手段​:攻击不是来自一个源头,而是来自分布在全世界成千上万台被黑客控制的设备(如电脑、服务器、物联网摄像头、智能家居设备等)。这些设备组成了一个“僵尸网络”。

比喻​:堵门的不是一伙人,而是从全国各地雇来的人,让你根本无法通过拦住一两个人来解决问题。

(3)简单总结
DDoS攻击就是攻击者指挥一个由大量计算机组成的“僵尸网络”,向一个特定的目标(如网站、服务器、网络设备)发动洪水般的垃圾请求,耗尽其所有资源(如网络带宽、系统CPU/内存、应用处理能力),从而导致合法用户无法获得服务的攻击方式。

【2】DDoS攻击的主要类型

(1)流量型攻击​
网络层/传输层
用巨大的垃圾数据流堵塞目标服务器的网络管道(带宽)。

(2)协议型攻击​
网络层/传输层
利用网络协议(如TCP三次握手)的缺陷,耗尽服务器的连接资源。

(3)应用层攻击​
应用层
模仿正常用户行为,向消耗大的网页(如搜索、登录)发起频繁请求,耗尽CPU/内存资源。

【3】DDoS攻击的常见表现

(1)网络和系统层面表现

(1)网络严重拥塞,带宽耗尽​:
表现​:服务器的入口带宽使用率突然飙升到95%甚至100%,而出站带宽可能正常。监控图表会显示一个极高的峰值。

结果​:服务器与外部网络的连接变得极慢或完全中断,SSH远程连接都可能卡顿或断开。

(2)服务器资源耗尽​:
1-CPU使用率100%​​:尤其是应用层攻击,大量请求需要服务器进行业务逻辑处理,导致CPU不堪重负。
2-内存耗尽​:每个请求都会占用一定的内存,海量并发请求会快速吃光所有可用内存。
3-连接数耗尽​:服务器操作系统或Web容器(如Tomcat、Nginx)的最大连接数被占满,无法再建立新的连接。查看网络连接会看到成千上万的ESTABLISHED、SYN_RECV状态的连接(尤其是协议攻击)。

(2)应用和服务层面表现

(1)​服务响应极其缓慢或完全无响应​:
1-表现​:网站、API接口的响应时间从几十毫秒飙升到几秒、几十秒,甚至直接超时。
2-结果​:前端页面一直处于“加载中”,移动App无法刷新内容,用户体验极差。
(2)大量错误和异常​:
1-5xx错误激增​:如 502 Bad Gateway(网关后端服务无响应)、503 Service Unavailable(服务不可用)、504 Gateway Timeout(网关超时)。
2-4xx错误激增​:在网关层或防护设备启动防护后,会返回大量 429 Too Many Requests(请求过快)或 403 Forbidden(IP被禁止)。
(3)​微服务架构中的连锁反应​:
1-​表现​:在Spring Cloud微服务体系中,一个服务(如网关或用户服务)被攻击瘫痪,可能通过依赖关系引发雪崩效应。
2-​示例​:网关被压垮 → 所有服务不可用;用户服务被压垮 → 依赖用户认证的订单、支付等服务全部报错;数据库连接池被占满 → 所有需要数据库的服务全部瘫痪。
(4)日志中出现异常模式​:
1-来自少量IP的海量请求​:在应用日志中,你会发现同一个IP地址在极短时间内对同一个接口(特别是耗时的接口,如搜索、导出)发起成千上万次请求。
2-User-Agent异常​:大量请求使用奇怪或统一的恶意User-Agent。
3-无Referer或异常Referer​:请求缺乏来源页信息或来源页是伪造的。

(3)监控告警系统的表现

一个健全的监控系统会在攻击发生时发出明确的警报:
(1)​流量告警​:网络流量超过预设阈值。
(2)QPS(每秒查询率)告警​:API请求量异常飙升。
(3)错误率告警​:HTTP 5xx/4xx错误率大幅上升。
(4)资源告警​:CPU、内存、磁盘I/O使用率告警。
(5)健康检查失败​:服务注册中心(如Eureka、Nacos)连续收到某个服务下线的心跳,导致该服务从服务列表中剔除。

【4】总结

DDoS攻击的核心表现可以概括为:在没有任何明显业务增长的情况下,系统各项资源指标(带宽、CPU、内存、连接数)突然达到极限,导致服务对正常用户变得极慢或完全不可用,并伴随大量错误日志和监控告警。

【二】DDoS 攻击类型与防护架构

【1】攻击类型识别

【2】防护体系架构

【三】基础设施层防护

【1】云服务商防护配置

  1. # 阿里云DDoS高防配置示例
  2. aliyun:
  3. ddos:
  4. basic:
  5. enable: true
  6. threshold: 5000 # 5Gbps触发清洗
  7. bgp:
  8. enable: true # 启用BGP高防IP
  9. waf:
  10. enable: true
  11. rules:
  12. cc-protection:
  13. enable: true
  14. threshold: 1000 # 单IP每秒请求阈值
复制代码

【2】CDN 动态加速配置

  1. @Configuration
  2. public class CdnConfig {
  3. @Bean
  4. public FilterRegistrationBean<CdnFilter> cdnFilter() {
  5. FilterRegistrationBean<CdnFilter> registration = new FilterRegistrationBean<>();
  6. registration.setFilter(new CdnFilter());
  7. registration.addUrlPatterns("/*");
  8. registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
  9. return registration;
  10. }
  11. }
  12. // CDN头验证过滤器
  13. public class CdnFilter implements Filter {
  14. private final Set<String> cdnIps = Set.of("1.1.1.1", "2.2.2.2"); // CDN IP段
  15. @Override
  16. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
  17. HttpServletRequest httpRequest = (HttpServletRequest) request;
  18. String clientIp = getRealClientIp(httpRequest);
  19. // 验证CDN头部
  20. if (!isFromCdn(httpRequest, clientIp)) {
  21. ((HttpServletResponse) response).setStatus(403);
  22. return;
  23. }
  24. chain.doFilter(request, response);
  25. }
  26. private String getRealClientIp(HttpServletRequest request) {
  27. String ip = request.getHeader("X-Forwarded-For");
  28. if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
  29. ip = request.getHeader("X-Real-IP");
  30. }
  31. return ip != null ? ip : request.getRemoteAddr();
  32. }
  33. private boolean isFromCdn(HttpServletRequest request, String clientIp) {
  34. // 验证CDN特定头部
  35. String cdnSecret = request.getHeader("X-CDN-Secret");
  36. return "valid-secret".equals(cdnSecret) && cdnIps.contains(clientIp);
  37. }
  38. }
复制代码

【四】Nginx流量网关

【五】API 网关层防护(Spring Cloud Gateway)

【1】限流配置:对服务限流

对服务配置限流

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: user_service
  6. uri: lb://user-service
  7. predicates:
  8. - Path=/api/users/**
  9. filters:
  10. - name: RequestRateLimiter
  11. args:
  12. redis-rate-limiter.replenishRate: 100 # 每秒令牌数
  13. redis-rate-limiter.burstCapacity: 200 # 令牌桶容量
  14. key-resolver: "#{@ipKeyResolver}"
  15. - name: RequestSize
  16. args:
  17. maxSize: 10MB
  18. - StripPrefix=1
  19. redis:
  20. host: localhost
  21. port: 6379
复制代码

【2】自定义限流策略

  1. @Configuration
  2. public class RateLimitConfig {
  3. @Bean
  4. public KeyResolver ipKeyResolver() {
  5. return exchange -> {
  6. String ip = Objects.requireNonNull(exchange.getRequest()
  7. .getRemoteAddress()).getAddress().getHostAddress();
  8. return Mono.just(ip);
  9. };
  10. }
  11. @Bean
  12. public KeyResolver apiKeyResolver() {
  13. return exchange -> {
  14. String apiKey = exchange.getRequest()
  15. .getHeaders().getFirst("X-API-Key");
  16. return Mono.just(apiKey != null ? apiKey : "anonymous");
  17. };
  18. }
  19. @Bean
  20. public KeyResolver userKeyResolver() {
  21. return exchange -> {
  22. String token = exchange.getRequest()
  23. .getHeaders().getFirst("Authorization");
  24. if (token != null && token.startsWith("Bearer ")) {
  25. String username = JwtUtil.extractUsername(token.substring(7));
  26. return Mono.just(username != null ? username : "anonymous");
  27. }
  28. return Mono.just("anonymous");
  29. };
  30. }
  31. }
复制代码

【3】全局过滤器防护:DDoS保护过滤器

(1)限制全局QPS,登录接口限制10,普通接口限制100,其他静态资源限制1000
(2)检查全局请求速率
(3)检查IP黑白名单
(4)用户代理检查
(5)路径防护,判断是否敏感路径,判断是否是无效请求
(6)请求频率检查

  1. @Component
  2. public class DdosProtectionFilter implements GlobalFilter, Ordered {
  3. private final RedisTemplate<String, String> redisTemplate;
  4. private final RateLimiter rateLimiter = RateLimiter.create(1000); // 全局QPS限制
  5. @Override
  6. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  7. ServerHttpRequest request = exchange.getRequest();
  8. String clientIp = getClientIp(request);
  9. String path = request.getPath().value();
  10. // 1. 全局速率限制
  11. if (!rateLimiter.tryAcquire()) {
  12. return tooManyRequests(exchange);
  13. }
  14. // 2. IP黑白名单检查
  15. if (isBlacklistedIp(clientIp)) {
  16. return forbidden(exchange);
  17. }
  18. // 3. 用户代理检查
  19. if (isSuspiciousUserAgent(request)) {
  20. return forbidden(exchange);
  21. }
  22. // 4. 路径防护
  23. if (isSensitivePath(path) && !isValidRequest(request)) {
  24. return forbidden(exchange);
  25. }
  26. // 5. 请求频率检查
  27. if (exceedsRateLimit(clientIp, path)) {
  28. return tooManyRequests(exchange);
  29. }
  30. return chain.filter(exchange);
  31. }
  32. private boolean exceedsRateLimit(String clientIp, String path) {
  33. String key = "rate_limit:" + clientIp + ":" + path;
  34. Long count = redisTemplate.opsForValue().increment(key);
  35. redisTemplate.expire(key, 1, TimeUnit.SECONDS);
  36. return count != null && count > getPathLimit(path);
  37. }
  38. private int getPathLimit(String path) {
  39. if (path.contains("/api/login")) return 10; // 登录接口严格限制
  40. if (path.contains("/api/")) return 100; // 普通API
  41. return 1000; // 静态资源
  42. }
  43. }
复制代码

【4】Gateway的配置案例

(1)HTTPS强制跳转与证书配置

  1. spring:
  2. cloud:
  3. gateway:
  4. httpclient:
  5. ssl:
  6. use-insecure-trust-manager: false # 禁用不安全证书
  7. trustedX509Certificates:
  8. - classpath:server.crt
  9. routes:
  10. - id: https_redirect
  11. uri: https://example.com
  12. predicates:
  13. - Path=/**
  14. filters:
  15. - RedirectTo=302, https://${host}:${server.port}${path} # HTTP自动跳HTTPS
  16. server:
  17. ssl:
  18. key-store: classpath:keystore.p12
  19. key-store-password: changeit
  20. key-store-type: PKCS12
  21. key-alias: gateway
复制代码

(2)CORS跨域安全配置

(1)跨域安全问题​
跨域安全问题​(Cross-Origin Resource Sharing Security)源于浏览器的同源策略​(Same-Origin Policy),这是浏览器最基本的安全机制。当网页尝试访问与其自身源(协议+域名+端口)不同的资源时,浏览器会阻止这种跨域请求。

(2)跨域攻击场景一:CSRF(跨站请求伪造)
攻击者诱导用户访问恶意网站,该网站自动向目标网站发起请求(携带用户凭证Cookie),执行用户不知情的操作(转账、修改密码等)

(3)跨域攻击场景二:XSSI(跨站脚本包含)​​
通过

(4)配置的逻辑
1-config.addAllowedOrigin(“https://trusted-domain.com”);
精确指定可信域名,不允许任意源访问
2-config.setExposedHeaders(“Authorization”);
仅暴露必要头信息,用来传token令牌
3-config.addAllowedHeader(List.of(“Content-Type”,“Accept”));

  1. @Bean
  2. public CorsWebFilter corsFilter() {
  3. return new CorsWebFilter(source -> {
  4. CorsConfiguration config = new CorsConfiguration();
  5. config.setAllowCredentials(true);// 允许凭证
  6. config.addAllowedOrigin("https://trusted-domain.com");// 允许的源
  7. config.addAllowedMethod("*");// 允许所有HTTP方法
  8. config.addAllowedHeader("*");// 允许所有头
  9. config.setExposedHeaders(List.of("Authorization"));// 暴露的响应头
  10. config.setMaxAge(3600L);// 预检缓存时间(秒)
  11. return config;
  12. });
  13. }
复制代码

(3)请求限流防护(Redis令牌桶)

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: api_route
  6. uri: lb://user-service
  7. predicates:
  8. - Path=/api/**
  9. filters:
  10. - name: RequestRateLimiter
  11. args:
  12. redis-rate-limiter.replenishRate: 100 # 每秒令牌数
  13. redis-rate-limiter.burstCapacity: 200 # 突发容量
  14. key-resolver: "#{@ipKeyResolver}"
复制代码
  1. @Bean
  2. public KeyResolver ipKeyResolver() {
  3. return exchange ->
  4. Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
  5. }
复制代码

(4)JWT认证过滤器

【一】执行流程
(1)拦截所有需要认证的请求
跳过不需要认证的路径(如登录、公开API)
(2)验证JWT令牌的签名、有效期和结构
1-从Authorization头提取Bearer Token
2-使用公钥验证令牌签名
3-验证exp声明,判断是否过期
4-验证令牌是否已被撤销
(3)将认证信息传递给下游服务
1-解析令牌中的用户信息(如用户ID、角色)
2-将用户信息添加到请求头,传递给下游服务
(4)处理无效令牌的请求
无效令牌:返回401 Unauthorizen
过期令牌:返回403 Forbidden
缺失令牌:返回400 Bad Request

【二】配置重点
(1)密钥管理
使用非对称加密(RS256)
使用强密钥,定期轮换密钥(通过JWKS端点)

(2)令牌撤销
实现令牌黑名单(Redis存储)
短期令牌+刷新令牌机制

(3)防御措施
防止令牌泄露:强制HTTPS,设置HttpOnly Cookie
限制令牌有效期:设置合理的exp时间(通常30分钟-2小时)
敏感操作要求重新认证
添加必要的安全头Authorization
结合API网关的限流功能防止暴力破解

【三】RS256算法优点
(1)非对称加密,性能相对较差
(2)公钥和私钥是分离的,用公钥加密,用私钥解密,保证私钥安全即可,前端可以用公钥验证而无需接触私钥,私钥可以集中保管在安全环境,即使公钥泄露也不影响整体安全
(3)秘钥长度256字节,保密性更高
(4)适用于多租户和开放平台

【四】token生成的原理
JWT由Header(头信息),PayLoad (用户信息),Signature(签名)三个部分组成
(1)Header:头信息
Header头信息主要声明加密算法
HS256:对称加密
RS256:非对称加密
(2)PayLoad:用户信息
指定了七个默认字段供选择
也可以自定义私有字段,但是不建议在此存放密码之类的敏感信息,因为此部分可以解码还原出原始内容。虽然它可以解码,但是也不能修改这个内容。

  1. iss:发行人
  2. exp:到期时间
  3. sub:主体
  4. aud:用户
  5. nbf:在此之前不可用
  6. iat:发布时间
  7. jti:JWT ID用于标识该JWT
复制代码

对其进行base64加密,得到Jwt的第二部分

(3)Signature:签名
此部分用于防止jwt内容被篡改。这个签证信息由三部分组成(由加密后的Header,加密后的PayLoad,加密后的签名三部分组成)。base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐加密,然后就构成了jwt的第三部分,每个部分直接使用"."来进行拼接

【五】token校验的原理
通过秘钥解析token,得到用户信息、头信息等,根据用户信息查询到对应库里的用户信息,然后用同样的加密算法加密,然后判断加密后的信息是否一致

  1. @Component
  2. public class JwtAuthFilter implements GlobalFilter {
  3. @Override
  4. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  5. // 从头信息获取token令牌
  6. String token = exchange.getRequest()
  7. .getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
  8. // 缺失令牌
  9. if (token == null || !token.startsWith("Bearer ")) {
  10. return unauthorized(exchange, "Missing token");
  11. }
  12. try {
  13. //
  14. Claims claims = Jwts.parserBuilder()
  15. .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
  16. .build()
  17. .parseClaimsJws(token.substring(7))
  18. .getBody();
  19. exchange.getAttributes().put("user", claims.getSubject());
  20. return chain.filter(exchange);
  21. } catch (JwtException e) {
  22. return unauthorized(exchange, "Invalid token");
  23. }
  24. }
  25. private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
  26. exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
  27. return exchange.getResponse().writeWith(
  28. Mono.just(exchange.getResponse().bufferFactory().wrap(msg.getBytes()))
  29. );
  30. }
  31. }
复制代码

(5)IP黑白名单控制

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: secure_route
  6. uri: lb://core-service
  7. predicates:
  8. - Path=/v1/**
  9. filters:
  10. - name: RemoteAddr
  11. args:
  12. sources:
  13. - 192.168.1.0/24
  14. - 10.0.0.1
  15. deny: 0.0.0.0/0 # 默认拒绝所有
复制代码

(6)敏感头信息过滤

  1. spring:
  2. cloud:
  3. gateway:
  4. default-filters:
  5. - RemoveRequestHeader=Cookie,Set-Cookie # 移除敏感头
  6. - AddResponseHeader=X-Content-Type-Options, nosniff
  7. - AddResponseHeader=X-Frame-Options, DENY
  8. routes:
  9. - id: proxy_route
  10. uri: lb://internal-service
  11. filters:
  12. - StripPrefix=1
  13. - RemoveRequestHeader=Authorization # 特定路由移除
复制代码

(7)请求大小限制

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: upload_route
  6. uri: lb://file-service
  7. predicates:
  8. - Path=/upload
  9. filters:
  10. - name: RequestSize
  11. args:
  12. maxSize: 10MB # 最大请求体限制
复制代码

(8)WAF集成(Web应用防火墙)

【一】sql注入检查
攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而欺骗数据库执行非法的SQL命令。这可能导致数据泄露、数据篡改、甚至数据库服务器被完全控制。
(1)检查请求参数(包括查询参数、请求体、路径变量等)中是否包含可疑的SQL关键字或特殊字符。
(2)使用正则表达式或字符串匹配来检测常见的SQL注入模式。

复杂的SQL注入攻击可能使用编码、注释等方式绕过简单的关键字匹配。因此,网关层的SQL注入防护通常作为一道基础防线,更深入的防护应该在应用层(如使用预编译语句、ORM框架等)实现。

【二】检查XSS攻击
XSS(跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本,当其他用户浏览该网页时,脚本执行,从而窃取用户信息、会话令牌或进行其他恶意操作。
(1)检查输入中是否包含可疑的HTML标签(如

  1. @Component
  2. public class WafFilter implements GlobalFilter {
  3. private final WafClient wafClient;
  4. @Override
  5. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  6. ServerHttpRequest request = exchange.getRequest();
  7. // 1. 检查SQL注入
  8. if (wafClient.detectSqlInjection(request.getQueryParams().toString())) {
  9. return blockRequest(exchange, "SQLi detected");
  10. }
  11. // 2. 检查XSS攻击
  12. if (request.getHeaders().values().stream()
  13. .anyMatch(header -> wafClient.detectXss(header.toString()))) {
  14. return blockRequest(exchange, "XSS detected");
  15. }
  16. return chain.filter(exchange);
  17. }
  18. }
复制代码

(9)OAuth2资源服务器配置

  1. spring:
  2. security:
  3. oauth2:
  4. resourceserver:
  5. jwt:
  6. issuer-uri: https://auth-server.com
  7. jwk-set-uri: https://auth-server.com/.well-known/jwks.json
复制代码
  1. @Bean
  2. public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
  3. return http
  4. .authorizeExchange(exchanges -> exchanges
  5. .pathMatchers("/public/**").permitAll()
  6. .pathMatchers("/admin/**").hasAuthority("ROLE_ADMIN")
  7. .anyExchange().authenticated()
  8. )
  9. .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt)
  10. .csrf().disable() // 在网关层禁用CSRF
  11. .build();
  12. }
复制代码

【六】应用层防护(Spring Boot)

【1】自定义限流注解:对接口限流

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface RateLimit {
  4. int value() default 100; // 请求次数
  5. int time() default 60; // 时间窗口(秒)
  6. RateLimitType type() default RateLimitType.IP;
  7. }
  8. public enum RateLimitType {
  9. IP, // 按IP限制
  10. USER, // 按用户限制
  11. METHOD, // 按方法限制
  12. GLOBAL // 全局限制
  13. }
  14. // AOP限流实现
  15. @Aspect
  16. @Component
  17. public class RateLimitAspect {
  18. private final RedisTemplate<String, Object> redisTemplate;
  19. @Around("@annotation(rateLimit)")
  20. public Object around(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {
  21. String key = generateKey(joinPoint, rateLimit);
  22. if (!tryAcquire(key, rateLimit)) {
  23. throw new RateLimitExceededException("请求过于频繁");
  24. }
  25. try {
  26. return joinPoint.proceed();
  27. } finally {
  28. // 清理资源
  29. }
  30. }
  31. private boolean tryAcquire(String key, RateLimit rateLimit) {
  32. String redisKey = "rate_limit:" + key;
  33. Long count = redisTemplate.opsForValue().increment(redisKey);
  34. if (count == 1) {
  35. redisTemplate.expire(redisKey, rateLimit.time(), TimeUnit.SECONDS);
  36. }
  37. return count <= rateLimit.value();
  38. }
  39. }
复制代码

【2】请求指纹识别

  1. @Component
  2. public class RequestFingerprint {
  3. public String generate(HttpServletRequest request) {
  4. String fingerprint = String.join("|",
  5. request.getRemoteAddr(),
  6. request.getHeader("User-Agent"),
  7. getBrowserFingerprint(request),
  8. getDeviceFingerprint(request)
  9. );
  10. return DigestUtils.md5DigestAsHex(fingerprint.getBytes());
  11. }
  12. private String getBrowserFingerprint(HttpServletRequest request) {
  13. // 基于浏览器特性生成指纹
  14. return String.join(",",
  15. request.getHeader("Accept-Language"),
  16. request.getHeader("Accept-Encoding"),
  17. request.getHeader("Accept")
  18. );
  19. }
  20. }
复制代码

【3】人机验证集成

  1. @Service
  2. public class CaptchaService {
  3. public boolean verifyCaptcha(String captcha, String clientIp) {
  4. // 1. 基础验证
  5. if (StringUtils.isEmpty(captcha)) {
  6. return false;
  7. }
  8. // 2. 验证码服务调用
  9. CaptchaResult result = captchaClient.verify(captcha, clientIp);
  10. // 3. 风险评估
  11. RiskAssessment risk = assessRisk(clientIp, result.getScore());
  12. return risk.isAllowed();
  13. }
  14. @RateLimit(value = 5, time = 300, type = RateLimitType.IP)
  15. public String generateCaptcha(String clientIp) {
  16. // 生成验证码逻辑
  17. return captchaClient.generate(clientIp);
  18. }
  19. }
复制代码

【4】使用Spring Security

  1. @Configuration
  2. @EnableWebSecurity
  3. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Override
  5. protected void configure(HttpSecurity http) throws Exception {
  6. http
  7. .authorizeRequests()
  8. .antMatchers("/public/**").permitAll()
  9. .anyRequest().authenticated()
  10. .and()
  11. .addFilterBefore(new RateLimitFilter(), UsernamePasswordAuthenticationFilter.class);
  12. }
  13. }
  14. public class RateLimitFilter extends OncePerRequestFilter {
  15. private final RateLimiter rateLimiter = RateLimiter.create(100); // 每秒100个请求
  16. @Override
  17. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  18. if (!rateLimiter.tryAcquire()) {
  19. response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
  20. response.getWriter().write("Too many requests");
  21. return;
  22. }
  23. filterChain.doFilter(request, response);
  24. }
  25. }
复制代码

【5】数据脱敏

【七】微服务间防护

【1】Feign 客户端防护

  1. @FeignClient(name = "user-service",
  2. configuration = FeignSecurityConfig.class,
  3. fallbackFactory = UserServiceFallbackFactory.class)
  4. public interface UserServiceClient {
  5. @RateLimit(value = 50, time = 60)
  6. @GetMapping("/users/{id}")
  7. ResponseEntity<User> getUser(@PathVariable Long id);
  8. @PostMapping("/users")
  9. ResponseEntity<User> createUser(@RequestBody User user);
  10. }
  11. // Feign配置
  12. @Configuration
  13. public class FeignSecurityConfig {
  14. @Bean
  15. public RequestInterceptor rateLimitInterceptor() {
  16. return template -> {
  17. // 添加限流头信息
  18. template.header("X-RateLimit-Service", "user-service");
  19. };
  20. }
  21. @Bean
  22. public Retryer feignRetryer() {
  23. // 防止重放攻击,限制重试次数
  24. return new Retryer.Default(100, 1000, 3);
  25. }
  26. }
  27. // 降级处理
  28. @Component
  29. public class UserServiceFallbackFactory implements FallbackFactory<UserServiceClient> {
  30. @Override
  31. public UserServiceClient create(Throwable cause) {
  32. return new UserServiceClient() {
  33. @Override
  34. public ResponseEntity<User> getUser(Long id) {
  35. // 记录攻击日志
  36. log.warn("User service fallback triggered by: {}", cause.getMessage());
  37. return ResponseEntity.status(503).build();
  38. }
  39. };
  40. }
  41. }
复制代码

【八】缓存层防护

【1】Redis 缓存击穿防护

  1. @Service
  2. public class CacheProtectionService {
  3. public <T> T getWithProtection(String key, Class<T> type,
  4. Supplier<T> loader, Duration timeout) {
  5. // 1. 布隆过滤器检查
  6. if (!bloomFilter.mightContain(key)) {
  7. return null;
  8. }
  9. // 2. 缓存获取
  10. T value = redisTemplate.opsForValue().get(key);
  11. if (value != null) {
  12. return value;
  13. }
  14. // 3. 分布式锁防止缓存击穿
  15. String lockKey = "lock:" + key;
  16. boolean locked = tryLock(lockKey, timeout);
  17. if (!locked) {
  18. // 等待其他线程加载
  19. return waitForCache(key, type, timeout);
  20. }
  21. try {
  22. // 双重检查
  23. value = redisTemplate.opsForValue().get(key);
  24. if (value != null) {
  25. return value;
  26. }
  27. // 加载数据
  28. value = loader.get();
  29. if (value != null) {
  30. redisTemplate.opsForValue().set(key, value, timeout);
  31. bloomFilter.put(key); // 更新布隆过滤器
  32. }
  33. return value;
  34. } finally {
  35. releaseLock(lockKey);
  36. }
  37. }
  38. }
复制代码

【2】热点数据保护

  1. @Component
  2. public class HotKeyProtection {
  3. private final Map<String, AtomicLong> accessCounters = new ConcurrentHashMap<>();
  4. private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
  5. @PostConstruct
  6. public void init() {
  7. // 定期清理计数器
  8. scheduler.scheduleAtFixedRate(this::cleanupCounters, 1, 1, TimeUnit.MINUTES);
  9. }
  10. public boolean isHotKey(String key) {
  11. AtomicLong counter = accessCounters.computeIfAbsent(key, k -> new AtomicLong());
  12. long count = counter.incrementAndGet();
  13. // 阈值判断
  14. return count > 1000; // 每分钟超过1000次访问
  15. }
  16. public void handleHotKey(String key, Runnable fallback) {
  17. if (isHotKey(key)) {
  18. // 热点Key降级处理
  19. fallback.run();
  20. log.warn("Hot key detected: {}", key);
  21. }
  22. }
  23. }
复制代码

【八】监控与告警体系

【1】Micrometer 监控指标

  1. @Component
  2. public class DdosMetrics {
  3. private final MeterRegistry meterRegistry;
  4. private final Counter requestCounter;
  5. private final DistributionSummary requestSizeSummary;
  6. public DdosMetrics(MeterRegistry meterRegistry) {
  7. this.meterRegistry = meterRegistry;
  8. this.requestCounter = Counter.builder("http.requests")
  9. .tag("type", "ddos_protection")
  10. .register(meterRegistry);
  11. this.requestSizeSummary = DistributionSummary.builder("http.request.size")
  12. .register(meterRegistry);
  13. }
  14. public void recordRequest(HttpServletRequest request, boolean blocked) {
  15. requestCounter.increment();
  16. if (blocked) {
  17. meterRegistry.counter("http.requests.blocked").increment();
  18. }
  19. // 记录请求大小
  20. int contentLength = request.getContentLength();
  21. if (contentLength > 0) {
  22. requestSizeSummary.record(contentLength);
  23. }
  24. // 记录IP频率
  25. String ip = request.getRemoteAddr();
  26. meterRegistry.counter("ip.requests", "ip", ip).increment();
  27. }
  28. }
复制代码

【2】自定义健康检查

  1. @Component
  2. public class DdosHealthIndicator implements HealthIndicator {
  3. private final RedisTemplate<String, String> redisTemplate;
  4. @Override
  5. public Health health() {
  6. Map<String, Object> details = new HashMap<>();
  7. // 检查请求频率
  8. long totalRequests = getTotalRequestsLastMinute();
  9. details.put("totalRequestsLastMinute", totalRequests);
  10. // 检查阻塞请求数
  11. long blockedRequests = getBlockedRequestsLastMinute();
  12. details.put("blockedRequestsLastMinute", blockedRequests);
  13. // 风险评估
  14. if (totalRequests > 10000 || blockedRequests > 1000) {
  15. return Health.down()
  16. .withDetails(details)
  17. .withDetail("error", "Possible DDoS attack detected")
  18. .build();
  19. }
  20. return Health.up().withDetails(details).build();
  21. }
  22. }
复制代码

【3】告警规则配置

  1. # Prometheus告警规则
  2. groups:
  3. - name: ddos_alerts
  4. rules:
  5. - alert: HighRequestRate
  6. expr: rate(http_requests_total[5m]) > 1000
  7. for: 2m
  8. labels:
  9. severity: critical
  10. annotations:
  11. summary: "高请求率告警"
  12. description: "当前请求率: {{ $value }} req/s"
  13. - alert: ManyBlockedRequests
  14. expr: rate(http_requests_blocked_total[5m]) > 100
  15. for: 5m
  16. labels:
  17. severity: warning
  18. annotations:
  19. summary: "大量请求被拦截"
  20. - alert: SuspiciousIP
  21. expr: sum by (ip) (rate(ip_requests_total[1m])) > 500
  22. for: 1m
  23. labels:
  24. severity: critical
复制代码

【4】使用Spring Boot Actuator

(1)应用健康检查​
实时暴露应用健康状态(数据库、磁盘、服务依赖等)

  1. // 访问 /actuator/health 返回示例
  2. {
  3. "status": "UP",
  4. "components": {
  5. "db": { "status": "UP", "details": { "database": "H2" } },
  6. "diskSpace": { "status": "UP", "details": { "free": 100GB } }
  7. }
  8. }
复制代码

(2)指标监控​
集成 Micrometer 收集 JVM/HTTP/缓存等 500+ 指标

(3)运行时洞察​
动态查看日志级别、线程堆栈、环境变量等
(4)审计跟踪​
记录用户操作事件(登录、数据修改等)

  1. @Bean
  2. public AuditEventRepository auditEventRepository() {
  3. return new InMemoryAuditEventRepository(); // 可替换为JDBC实现
  4. }
复制代码

(5)优雅停机
确保服务关闭时不中断进行中的请求

  1. server:
  2. shutdown: graceful # 开启优雅停机
  3. spring:
  4. lifecycle:
  5. timeout-per-shutdown-phase: 30s # 最长等待时间
复制代码

【九】应急响应机制

【1】自动封禁策略

  1. @Service
  2. public class AutoBlockService {
  3. @Scheduled(fixedRate = 60000) // 每分钟检查
  4. public void autoBlockMaliciousIps() {
  5. Map<String, Long> ipStats = getIpRequestStats();
  6. ipStats.entrySet().stream()
  7. .filter(entry -> entry.getValue() > 1000) // 每分钟超过1000次
  8. .forEach(entry -> {
  9. String ip = entry.getKey();
  10. blockIp(ip, Duration.ofHours(1)); // 封禁1小时
  11. log.warn("Auto blocked IP: {} for excessive requests: {}", ip, entry.getValue());
  12. // 发送告警
  13. alertService.sendAlert("IP自动封禁",
  14. "IP: " + ip + " 请求数: " + entry.getValue());
  15. });
  16. }
  17. public void blockIp(String ip, Duration duration) {
  18. String key = "blocked_ip:" + ip;
  19. redisTemplate.opsForValue().set(key, "1", duration);
  20. }
  21. }
复制代码

【2】降级策略

  1. @Component
  2. public class DegradationStrategy {
  3. public void activateEmergencyMode() {
  4. // 1. 关闭非核心服务
  5. feignConfig.disableNonCriticalServices();
  6. // 2. 启用静态降级页面
  7. staticModeService.enable();
  8. // 3. 限制API速率
  9. rateLimitConfig.setStrictMode(true);
  10. // 4. 发送通知
  11. notificationService.sendEmergencyAlert("DDoS攻击防护已激活");
  12. }
  13. @EventListener
  14. public void handleDdosEvent(DdosDetectedEvent event) {
  15. if (event.getSeverity() == Severity.CRITICAL) {
  16. activateEmergencyMode();
  17. }
  18. }
  19. }
复制代码

【十】测试与演练

【1】压力测试配置

  1. @SpringBootTest
  2. @TestPropertySource(properties = {
  3. "spring.redis.embedded=true",
  4. "resilience4j.ratelimiter.enabled=true"
  5. })
  6. public class DdosProtectionTest {
  7. @Autowired
  8. private TestRestTemplate restTemplate;
  9. @Test
  10. public void testRateLimiting() {
  11. // 模拟高并发请求
  12. List<CompletableFuture<ResponseEntity<String>>> futures = new ArrayList<>();
  13. for (int i = 0; i < 1000; i++) {
  14. futures.add(CompletableFuture.supplyAsync(() ->
  15. restTemplate.getForEntity("/api/users/1", String.class)
  16. ));
  17. }
  18. // 统计429响应数量
  19. long blockedCount = futures.stream()
  20. .map(CompletableFuture::join)
  21. .filter(response -> response.getStatusCode() == HttpStatus.TOO_MANY_REQUESTS)
  22. .count();
  23. assertThat(blockedCount).isGreaterThan(800); // 80%请求应被限流
  24. }
  25. }
复制代码

【2】混沌工程测试

  1. @Component
  2. public class ChaosTestService {
  3. public void simulateDdosAttack() {
  4. // 1. 生成大量请求
  5. IntStream.range(0, 10000).parallel().forEach(i -> {
  6. restTemplate.getForObject("/api/data", String.class);
  7. });
  8. // 2. 验证防护效果
  9. Health health = healthEndpoint.health();
  10. assertThat(health.getStatus()).isEqualTo(Status.UP);
  11. }
  12. }
复制代码

【十一】总结

【1】网络层

云防护、防火墙进行DDoS清洗、IP封禁

【2】Nginx流量网管层

【3】Gateway业务网关层

(1)https强制跳转和证书配置

(2)全局过滤器请求限流防护(对服务)
令牌桶限流,例如100-1000,根据业务需求来配置

(3)CORS跨域安全过滤器
1-config.addAllowedOrigin(“https://trusted-domain.com”);
精确指定可信域名,不允许任意源访问
2-config.setExposedHeaders(“Authorization”);
仅暴露必要头信息,用来传token令牌
3-config.addAllowedHeader(List.of(“Content-Type”,“Accept”));

(4)sql注入检查和XSS攻击过滤器
sql注入检查
攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而欺骗数据库执行非法的SQL命令。这可能导致数据泄露、数据篡改、甚至数据库服务器被完全控制。
1-检查请求参数(包括查询参数、请求体、路径变量等)中是否包含可疑的SQL关键字或特殊字符。
2-使用正则表达式或字符串匹配来检测常见的SQL注入模式。

复杂的SQL注入攻击可能使用编码、注释等方式绕过简单的关键字匹配。因此,网关层的SQL注入防护通常作为一道基础防线,更深入的防护应该在应用层(如使用预编译语句、ORM框架等)实现。

检查XSS攻击
XSS(跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意脚本,当其他用户浏览该网页时,脚本执行,从而窃取用户信息、会话令牌或进行其他恶意操作。
1-检查输入中是否包含可疑的HTML标签(如

(5)JWT认证过滤器
1-使用非对称加密(RS256),秘钥公钥分离,秘钥做好安全存放
2-使用强密钥,定期轮换密钥(通过JWKS端点)
3-防止令牌泄露:强制HTTPS,设置HttpOnly Cookie
4-限制令牌有效期:设置合理的exp时间(通常30分钟-2小时)
5-敏感操作要求重新认证
6-添加必要的安全头Authorization
7-结合API网关的限流功能防止暴力破解
8-令牌token里不要放敏感信息

(6)IP黑白名单控制
(7)敏感头信息过滤
(8)请求大小限制
(9)OAuth2资源服务器配置
1-有些高密的接口配置高级访问权限的限制

【4】应用层

(1)人机验证
1-登录或者注册接口,使用输入编码或点击图片等实现人机验证和机器人过滤
(2)token令牌
1-登录成功后,通过秘钥生成token令牌,设置令牌的过期时间,返回给前端放进cookie,下次请求带token
2-请求达到gateway会经过SpringSecurity的过滤器,对token进行解密和校验,如果token不存在或者已过期,则跳转到登录页面
(3)业务限流
1-根据业务的实际情况对某些接口进行限流,例如登录注册接口和其他业务接口,使用不同的限流配置
(4)服务监控报警
1-自定义健康检查
(5)自动封禁和降级
1-对于访问频率异常的ip可以放进redis黑名单缓存里1小时,gateway黑名单过滤的时候进行过滤
(6)人工干预降级
(7)数据脱敏存储

【5】服务层

(1)Hystrix熔断降级
(2)Feign容错
(3)传递token校验

【6】Redis、布隆过滤器

热点保护、击穿防护

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
198382 2026-2-7 16:10:18 来自手机 | 显示全部楼层
《讨论:当DDoS瞄准你的Spring Cloud网关,除了限流和封IP,我们还能做什么?》
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行