You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Actix-web中无响应直接关闭连接以应对类DDoS请求

解决方案:在Actix Web中直接关闭连接不返回响应

要实现直接关闭连接、不向客户端发送任何响应的需求,你可以通过Actix Web的底层连接控制API来实现,核心是获取当前请求的底层HTTP连接并主动关闭,同时避免返回任何有效响应内容。

方法1:在路由处理函数中直接关闭连接

修改你的defaultentry函数,通过HttpRequest的扩展信息拿到底层连接并关闭,同时消费请求payload防止连接挂起:

use actix_web::{web, HttpRequest, HttpResponse, Error, http::StatusCode};
use actix_web::dev::HttpConnection;

async fn defaultentry(req: HttpRequest, payload: web::Payload) -> Result<impl Responder, Error> {
    // 获取底层HTTP连接并执行关闭操作
    if let Some(conn) = req.extensions().get::<HttpConnection>() {
        conn.close();
    }

    // 消费请求payload,避免未处理的数据导致连接无法正常关闭
    while let Some(_chunk) = payload.next().await {}

    // 返回空的无内容响应(实际客户端不会收到,因为连接已提前关闭)
    Ok(HttpResponse::new(StatusCode::NO_CONTENT).finish())
}

方法2:用中间件提前拦截恶意请求

如果需要在请求进入路由处理前就拦截并关闭连接,推荐用中间件实现,性能更高,能避免不必要的请求解析开销:

use actix_web::{
    dev::{Service, ServiceRequest, ServiceResponse, Transform},
    Error, HttpResponse, http::StatusCode,
};
use futures::future::{ready, Ready};
use std::task::{Context, Poll};

// 定义中间件结构体
struct MaliciousRequestBlocker;

impl<S, B> Transform<S, ServiceRequest> for MaliciousRequestBlocker
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Transform = BlockerService<S>;
    type InitError = ();
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ready(Ok(BlockerService { service }))
    }
}

// 中间件服务逻辑实现
struct BlockerService<S> {
    service: S,
}

impl<S, B> Service<ServiceRequest> for BlockerService<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = Ready<Result<Self::Response, Self::Error>>;

    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.service.poll_ready(cx)
    }

    fn call(&self, req: ServiceRequest) -> Self::Future {
        // 替换成你的恶意请求判断逻辑,比如IP黑名单、请求特征匹配等
        let is_malicious = true;

        if is_malicious {
            // 关闭当前连接
            if let Some(conn) = req.extensions().get::<actix_web::dev::HttpConnection>() {
                conn.close();
            }
            // 返回空响应(连接已关闭,客户端不会收到任何内容)
            ready(Ok(req.into_response(HttpResponse::new(StatusCode::NO_CONTENT).finish())))
        } else {
            // 正常转发请求到后续服务或路由
            ready(self.service.call(req).await)
        }
    }
}

然后在main函数中注册该中间件:

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || {
        App::new()
            .wrap(MaliciousRequestBlocker) // 注册恶意请求拦截中间件
            .default_service(web::get().to(defaultentry))
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}

关键说明

  • 直接关闭连接后,客户端会收到TCP连接断开/重置信号,不会获取到任何HTTP响应,以此迫使发起方的TIME-WAIT连接堆积。
  • 消费请求payload是必要步骤,否则未处理的请求数据可能导致连接无法正常关闭。
  • 中间件方式更适合批量拦截恶意请求,因为它在请求解析的早期阶段就介入,性能优于路由内处理。

内容的提问来源于stack exchange,提问作者Agathe_DVY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:01:15