如何防止拒绝服务耗尽 Java 中套接字服务器上的线程池?

发布于 2024-12-09 12:05:04 字数 935 浏览 0 评论 0原文

为了工作,我编写了一个专门的 HTTP 服务器,它只对网站执行 301/302/Frame 重定向。最近,一些邪恶的客户端故意打开套接字并每 500 毫秒写入一个字符,以破坏我的 TCP 套接字超时。然后他们无限期地保持套接字打开,并让多个客户端在分布式拒绝服务中执行相同的操作。这最终会耗尽处理 TCP 连接的线程池。您将如何编写代码以使其不易受到此类不良行为的影响?这是我的套接字接受代码:

while (true) {
    // Blocks while waiting for a new connection
    log.debug("Blocking while waiting for a new connection.") ;
    try {
        Socket server = httpServer.accept() ; 

        // After receiving a new connection, set the SO_LINGER and SO_TIMEOUT options
        server.setReuseAddress(true) ;
        server.setSoTimeout(timeout) ;
        server.setSoLinger(true, socketTimeout) ;

        // Hand off the new socket connection to a worker thread
        threadPool.execute(new Worker(cache, server, requests, geoIp)) ;
    } catch (IOException e) {
        log.error("Unable to accept socket connection.", e) ;
        continue ;
    }
}

timeout 和 socketTimeout 当前设置为 500 毫秒。

For work I have written a specialized HTTP server which only performs 301/302/Frame redirections for web sites. Recently, some nefarious clients have been intentionally opening sockets and writing one character every 500 milliseconds in order to defeat my TCP socket timeout. Then they keep the socket open indefinitely and have multiple clients doing the same thing in a distributed denial of service. This eventually exhausts the thread pool which handles the TCP connections. How would you write your code to make it less susceptible to this sort of bad behavior? Here's my socket accept code:

while (true) {
    // Blocks while waiting for a new connection
    log.debug("Blocking while waiting for a new connection.") ;
    try {
        Socket server = httpServer.accept() ; 

        // After receiving a new connection, set the SO_LINGER and SO_TIMEOUT options
        server.setReuseAddress(true) ;
        server.setSoTimeout(timeout) ;
        server.setSoLinger(true, socketTimeout) ;

        // Hand off the new socket connection to a worker thread
        threadPool.execute(new Worker(cache, server, requests, geoIp)) ;
    } catch (IOException e) {
        log.error("Unable to accept socket connection.", e) ;
        continue ;
    }
}

timeout and socketTimeout are currently set to 500 milliseconds.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

魂ガ小子 2024-12-16 12:05:04

经过一定时间后开始关闭套接字。如果套接字保持打开状态太长时间,只需将其关闭即可。您可以通过两种方式执行此操作:

您还可以对客户端向您发送请求所需的时间设置时间限制。如果它们不能维持一定水平的吞吐量,则关闭它们。当线程正在读取请求时,通过在开始处添加 System.currentTimeInMillis() 并与循环时的位置进行比较,在读取循环中可以很容易地做到这一点。如果它超过了一定的限制,它们就会关闭并被丢弃。

这个想法的另一种想法可能不是拒绝它们,而是让你的线程返回到池中,但将套接字放在堆栈上进行监视。让字节堆积起来,当它们达到一定大小后,您可以将它们传递给池中的线程进行处理。这是切断它们的混合方法,也许它们还不错,但速度很慢。

处理这个问题的另一种方法是观察线程处理请求的时间,如果在时间限制内没有完成,则关闭底层套接字。然后线程将得到一个 SocketException 并且它可以关闭并清理。

以下是一些其他想法,主要涉及使用防火墙、负载平衡器等外部硬件。

https://security.stackexchange.com/questions/114/what-techniques-do-advanced-firewalls-use-to-protect-againt-dos-ddos/792#792

Start closing sockets after a certain time has passed. If a socket has stayed open too long just close it down. You could do this in two ways:

You could also put a time limit on how long the client takes to send you a request. If they don't sustain a certain level of throughput close em. That can be pretty easy to do in your read loop when your thread is reading the request by adding a System.currentTimeInMillis() at the start and compare to where you are as you loop. If it drifts past a certain limit they are shutdown and dropped.

An alternative idea to this idea is possibly not reject them but let your thread return to the pool, but put the socket on a stack to watch. Let the bytes pile up and after they reached a certain size you can them pass them to a thread in the pool to process. This the hybrid approach to cut em off vs. maybe they aren't bad but slow.

Another way to handle that is watch how long a thread has been working on a request, and if it's not finished within a time limit close the underlying socket. Then the thread will get a SocketException and it can shutdown and clean up.

Here are some other ideas that mostly involve using outside hardware like firewalls, load balancers, etc.

https://security.stackexchange.com/questions/114/what-techniques-do-advanced-firewalls-use-to-protect-againt-dos-ddos/792#792

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文