springboot tomcat 嵌入式 解决Slow HTTP DOS问题解决

Slow HTTP DOS是一种应用层拒绝服务攻击,主要针对HTTP协议,攻击的成本很低,并且能够消耗服务器端资源,占用客户端连接数,导致正常用户无法连接服务器。

SpringBoot 2.7.18 默认使用嵌入式 Tomcat 9.0.x,针对 Slow HTTP DOS 攻击(慢请求头、慢请求体、慢读取等类型),核心解决思路是通过配置 Tomcat 连接 / 请求超时、限制连接数 / 请求体大小、优化连接器参数,从源头阻断慢请求占用服务器连接资源,以下是可直接落地的全套配置方案,包含核心配置、进阶优化、监控告警三部分,适配嵌入式 Tomcat 的特性。

一、核心配置(application.yml/application.properties)

这是最基础、最核心的配置,直接在 SpringBoot 的配置文件中添加,无需编写 Java 代码,即可覆盖 Tomcat 默认的宽松参数,精准防御 Slow HTTP DOS 攻击。
推荐 YAML 格式(application.yml)

yaml 复制代码
server:
  # Tomcat 连接器核心配置(针对HTTP/1.1,嵌入式Tomcat默认连接器)
  tomcat:
    # 1. 限制最大连接数(总连接数,包含活跃+等待,根据服务器性能调整:4核8G建议200-500)
    max-connections: 200
    # 2. 限制最大工作线程数(处理请求的核心线程,4核8G建议200-400)
    max-threads: 200
    # 3. 最小空闲线程数(避免线程频繁创建销毁,建议为max-threads的1/4)
    min-spare-threads: 50
    # 4. 连接超时时间(TCP握手超时,默认60000ms,建议缩短至3000ms)
    connection-timeout: 3000
    # 5. 禁用TCP延迟(开启Nagle算法,提升传输效率,间接减少慢连接)
    tcp-no-delay: true
    # 6. 限制请求体最大大小(防止超大慢请求体,单位MB,根据业务调整,默认无限制)
    max-http-post-size: 10MB
    # 7. 等待队列大小(连接数达max-connections时,排队请求数,建议100-200)
    accept-count: 100
    # 8. 慢请求相关核心:连接器超时(Tomcat 9关键参数,覆盖慢读/慢写)
    connection-linger: -1
    # 9. 关闭无效连接(自动清理空闲超时的连接,默认开启,显式配置更稳妥)
    disable-aborted-upload-cleanup: false
  # HTTP协议基础配置
  port: 8080
  http:
    encoding:
      enabled: true
      charset: UTF-8
      force: true
  # 10. 关键:设置请求头读取超时(Tomcat 9通过connector的属性配置,核心防御Slow Headers)
  tomcat:
    connector:
      # 读取请求头的超时时间(ms),超时则关闭连接,建议5000ms(5秒)
      connectionTimeout: 5000
      # 读取请求体的超时时间(ms),针对Slow Body,与请求头超时一致即可
      async-timeout: 5000

兼容 Properties 格式(application.properties)

properties 复制代码
# Tomcat核心连接限制
server.tomcat.max-connections=200
server.tomcat.max-threads=200
server.tomcat.min-spare-threads=50
server.tomcat.connection-timeout=3000
server.tomcat.tcp-no-delay=true
server.tomcat.max-http-post-size=10485760
server.tomcat.accept-count=100
# 慢请求超时核心配置
server.tomcat.connector.connectionTimeout=5000
server.tomcat.connector.async-timeout=5000
# 基础配置
server.port=8080
server.http.encoding.enabled=true
server.http.encoding.charset=UTF-8
server.http.encoding.force=true

核心参数说明(防御 Slow HTTP DOS 的关键)

参数 作用 为什么能防御 Slow HTTP DOS
connectionTimeout 请求头 / 请求体读取超时(ms) 针对Slow Headers/Slow Body,攻击者缓慢发送请求头 / 体时,超时直接断开连接,释放资源
max-connections Tomcat 最大总连接数 限制服务器同时处理的连接数,防止攻击者占满所有连接,导致正常用户无法连接
max-threads 最大工作线程数 避免慢请求占用所有处理线程,保证正常请求有线程可用
max-http-post-size 最大请求体大小 防止攻击者发送超大慢请求体,持续消耗服务器 IO 和内存
accept-count 连接等待队列 避免连接数满时直接拒绝所有请求,同时限制排队的慢请求数
tcp-no-delay 开启 TCP 即时传输 关闭 Nagle 算法,避免 Tomcat 为拼接数据而缓存慢请求的字节,减少资源占用

二、进阶优化:自定义 Tomcat 连接器(Java 代码配置)

如果基础配置无法满足精细化需求(比如区分 HTTP/HTTPS 配置、自定义超时规则),可通过实现 WebServerFactoryCustomizer 接口自定义 Tomcat 连接器,直接操控 Tomcat 底层参数,适配更复杂的业务场景。
编写自定义配置类(无需 @ComponentScan,SpringBoot 自动扫描)

java 复制代码
import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;

/**
 * SpringBoot 2.7.18 嵌入式Tomcat 自定义配置,防御Slow HTTP DOS
 */
@Configuration
public class TomcatSlowHttpDosConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        // 自定义Tomcat连接器(NIO模式,Tomcat 9默认,性能最优)
        factory.addConnectorCustomizers((Connector connector) -> {
            // 强转为HTTP/1.1 NIO协议配置,获取底层参数
            Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
            
            // 1. 核心:请求读取超时(覆盖Slow Headers/Slow Body,优先级高于配置文件)
            protocol.setConnectionTimeout(5000); // 5秒
            // 2. 响应读取超时(针对Slow Read,攻击者缓慢读取响应,超时断开)
            protocol.setSoTimeout(3000); // 3秒
            // 3. 最大连接数(总连接数限制)
            protocol.setMaxConnections(200);
            // 4. 最大工作线程数
            protocol.setMaxThreads(200);
            // 5. 最小空闲线程数
            protocol.setMinSpareThreads(50);
            // 6. 等待队列大小
            protocol.setAcceptCount(100);
            // 7. 禁用无效连接缓存,及时清理慢连接
            protocol.setDisableUploadTimeout(false);
            // 8. 请求体最大大小(10MB,单位:字节)
            connector.setMaxPostSize(10 * 1024 * 1024);
            // 9. 请求头最大大小(防止超大慢请求头,8KB,单位:字节)
            connector.setMaxHeaderCount(100);
            connector.setMaxHttpHeaderSize(8 * 1024);
            // 10. 开启TCP保活,检测死连接/慢连接
            protocol.setSoKeepAlive(true);
        });

        // 可选:设置Tomcat启动端口(与配置文件一致即可)
        factory.setPort(8080);
        // 可选:设置上下文路径
        factory.setContextPath("/");
    }
}

代码配置的优势

  1. 可直接操作 Tomcat 底层的Http11NioProtocol协议参数,比配置文件更精细化;
  2. 支持多连接器配置(比如同时配置 HTTP 和 HTTPS,分别设置不同的超时规则);
  3. 可添加自定义过滤器、阀门(Valve),对慢请求做更灵活的拦截。

三、补充防御:添加请求拦截过滤器(针对慢请求特征)

针对 Slow HTTP DOS 的典型特征(请求发送速率极低、单请求耗时过长),可自定义拦截过滤器,在请求到达业务层前做前置拦截,进一步过滤可疑慢请求。
自定义慢请求拦截过滤器

java 复制代码
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;

/**
 * 慢请求前置拦截过滤器,过滤可疑Slow HTTP DOS请求
 * Order(1) 表示优先级最高,最先执行
 */
@Component
@Order(1)
public class SlowHttpDosFilter implements Filter {

    // 最大请求头数量(超过则判定为可疑请求)
    private static final int MAX_HEADER_COUNT = 100;
    // 单个请求头值最大长度(超过则判定为可疑请求,单位:字符)
    private static final int MAX_HEADER_VALUE_LENGTH = 1024;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        // 1. 检查请求头数量,防止攻击者发送大量慢请求头
        Enumeration<String> headerNames = httpRequest.getHeaderNames();
        int headerCount = 0;
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = httpRequest.getHeader(headerName);
            headerCount++;
            // 检查请求头数量超限
            if (headerCount > MAX_HEADER_COUNT) {
                response.setStatus(400); // Bad Request
                response.getWriter().write("Invalid request: too many headers");
                return;
            }
            // 检查单个请求头值过长
            if (headerValue != null && headerValue.length() > MAX_HEADER_VALUE_LENGTH) {
                response.setStatus(400);
                response.getWriter().write("Invalid request: header value too large");
                return;
            }
        }

        // 2. 可选:检查请求方法(仅允许业务需要的方法,屏蔽无用方法)
        String method = httpRequest.getMethod();
        if (!"GET".equals(method) && !"POST".equals(method) && !"PUT".equals(method) && !"DELETE".equals(method)) {
            response.setStatus(405); // Method Not Allowed
            response.getWriter().write("Method not allowed");
            return;
        }

        // 正常请求,继续执行过滤器链
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

四、关键补充:Tomcat 9 针对 Slow Read 的防御

Slow Read 攻击(攻击者建立连接后缓慢读取响应)是容易被忽略的类型,针对这种攻击,除了上述setSoTimeout(Socket 读取超时),还需注意:

  1. 配置protocol.setDisableUploadTimeout(false):开启上传超时检测,针对 POST 请求的慢读取;
  2. 启用 Tomcat 的ConnectionTimeout:对所有连接的读写操作做统一超时限制,避免连接长时间处于 "挂起" 状态;
  3. 结合服务器内核参数优化(Linux):限制 TCP 连接的空闲时间,从操作系统层面清理慢连接,示例:
bash 复制代码
# 编辑sysctl配置
vi /etc/sysctl.conf
# 添加以下参数(针对TCP空闲连接)
net.ipv4.tcp_keepalive_time = 600  # 连接空闲10分钟后发送保活包
net.ipv4.tcp_keepalive_intvl = 30  # 保活包发送间隔30秒
net.ipv4.tcp_keepalive_probes = 3  # 连续3次未收到响应则关闭连接
net.ipv4.tcp_fin_timeout = 30      # TCP关闭握手超时30秒
# 生效配置
sysctl -p

五、监控告警:及时发现 Slow HTTP DOS 攻击

防御的同时需做好监控,及时发现攻击并调整参数,SpringBoot 2.7.18 可通过Actuator监控 Tomcat 核心指标,步骤如下:
1. 引入 Actuator 依赖(pom.xml)

xml 复制代码
<!-- SpringBoot 监控核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 可选:引入micrometer,适配Prometheus/Grafana可视化 -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

2. 开启 Actuator 监控端点(application.yml)

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: tomcat,metrics,health,info  # 暴露tomcat监控端点
  endpoint:
    tomcat:
      enabled: true  # 开启Tomcat详细监控
    metrics:
      enabled: true
    health:
      show-details: always

3. 关键监控指标(访问:http://ip:8080/actuator/tomcat)

通过该端点可查看 Tomcat 实时连接状态,以下指标异常则大概率是 Slow HTTP DOS 攻击:

  • connections.active:活跃连接数(持续接近max-connections,异常);
  • connections.pending:等待队列连接数(持续大于 0,且居高不下,异常);
  • requestCount:请求总数(短时间内激增,且请求耗时过长,异常);
  • errorCount:错误请求数(400/405/503 错误激增,异常)。

4. 告警阈值建议

  • 活跃连接数 > max-connections * 80%,触发告警;
  • 等待队列连接数 > accept-count * 50%,触发告警;
  • 单请求平均耗时 > 3 秒(根据业务调整),且持续 5 分钟,触发告警。

六、配置验证与测试

配置完成后,可通过以下方式验证是否生效,确保防御规则正常运行:

  1. 启动 SpringBoot 应用,查看日志,确认 Tomcat 连接器参数已加载:
plaintext 复制代码
Tomcat initialized with port(s): 8080 (http)
Initializing ProtocolHandler ["http-nio-8080"]
Starting ProtocolHandler ["http-nio-8080"]
  1. 使用 curl 模拟慢请求头攻击,验证超时是否生效:
bash 复制代码
# 分批次缓慢发送请求头,模拟Slow Headers
curl -v --limit-rate 1b/s http://localhost:8080/your-api

预期结果:curl 连接 5 秒后被断开(与connectionTimeout=5000一致),应用日志无报错,连接资源被释放。

  1. 查看 Actuator 监控:访问http://localhost:8080/actuator/tomcat,确认maxConnections、connectionTimeout等参数与配置一致。

七、版本适配说明(SpringBoot 2.7.18 + Tomcat 9)

  1. SpringBoot 2.7.18 内置 Tomcat 9.0.80,上述所有配置均基于 Tomcat 9 的 API,无版本兼容问题;
  2. 避免使用 Tomcat 8 的过时参数(如maxHttpHeaderSize在 Tomcat 9 中仍可用,无需替换);
  3. 若项目启用 HTTPS,只需在自定义连接器中添加 SSL 配置,上述超时 / 连接限制参数可直接复用。

总结

SpringBoot 2.7.18 嵌入式 Tomcat 防御 Slow HTTP DOS 的核心思路是 "限制 + 超时 + 监控"

  1. 基础限制:通过max-connections/max-threads限制连接和线程数,防止资源被占满;
  2. 核心超时:通过connectionTimeout/soTimeout设置请求读写超时,直接断开慢请求;
  3. 精细化控制:通过自定义连接器和过滤器,拦截可疑请求头 / 请求体,过滤攻击特征;
  4. 底层保障:结合 Linux 内核参数,从操作系统层面清理空闲慢连接;
  5. 实时监控:通过 Actuator 监控 Tomcat 指标,及时发现攻击并调整参数。

以上配置可直接在生产环境使用,根据服务器性能(CPU / 内存)和业务量,微调max-connections、max-threads等数值即可(4 核 8G 服务器推荐上述默认值,8 核 16G 可翻倍)。

相关推荐
洛阳纸贵2 小时前
JAVA高级工程师--Springboot集成ES、MySQL同步ES的方案、ES分片副本、文档及分片规划
java·spring boot·elasticsearch
我是一只小小鱼~2 小时前
JAVA 使用spring boot 搭建WebAPI项目
java·数据库·spring boot
小信丶2 小时前
@EnableMethodCache 注解详解:原理、应用场景与示例代码
java·spring boot·后端·spring
Jason_wu862 小时前
Mac OS 上charles抓包配置,支持Https访问
网络协议·http·https
有代理ip5 小时前
详解 HTTP 代理 8080 与 3128 的端口特性及用途
网络·网络协议·http
我不是程序员yy5 小时前
HTTP与HTTPS的区别:不只是多了一个S那么简单
网络协议·http·https
qq_2975746710 小时前
【实战教程】SpringBoot 集成阿里云短信服务实现验证码发送
spring boot·后端·阿里云
RANCE_atttackkk11 小时前
[Java]实现使用邮箱找回密码的功能
java·开发语言·前端·spring boot·intellij-idea·idea
韩立学长12 小时前
【开题答辩实录分享】以《智能大学宿舍管理系统的设计与实现》为例进行选题答辩实录分享
数据库·spring boot·后端