1
votes

I'm making a Java application which receives HTTP requests. For each request which comes in, I start a new thread, and in that thread I'm reading the request and performing the necessary actions. However, I want to prevent the users from performing a "Slow Loris Attack", so I was thinking about giving a thread a maxTime value. If the thread takes longer than the maxTime it will terminate no matter what. So it will also block slow connections, which is not a problem.

However, I don't know what the right way is to do this. I've tried the following code, but this code is blocking my main thread. I'm looking for a way to do something similar like this, without blocking the main thread.

Code:

/**
 * Executor which is used for threadpools.
 */
private ExecutorService executor;

/**
 * Constructor for the class RequestReceiver.
 * Initializes fields.
 */
public RequestReceiver() {
    this.executor = Executors.newFixedThreadPool(200);
}

@Override
public void run() {
    try {
        this.serverSocket = new ServerSocket(port);
    } catch (IOException ex) {
        Logger.getInstance().logText("Could not start server on port: " + port);
        return;
    }

    Logger.getInstance().logText("Server running at port: " + port);

    try {
        while (shouldContinue) {
            Socket client = serverSocket.accept();
            HTTPRequestHandler handler = new HTTPRequestHandler(client);
            Thread t = new Thread(handler);
            executor.submit(t).get(10, TimeUnit.SECONDS); //This line is blocking
        }
    } catch (IOException ex) {
        Logger.getInstance().logText("Server is shutdown");
    } catch (InterruptedException | ExecutionException | TimeoutException ex) {
        Logger.getInstance().logText("Thread took too long, it's shutdown");
    }
}
2
Can you add executor.shutdown(); immediately after blocking statement executor.submit(t).get(10, TimeUnit.SECONDS); and try?harshavmb
@harshavmb I don't see how this is going to solve my problem.. I did try it do, and like I predicted it crashed. Because when you send a 2nd HTTP request the pool won't accept it, because it's shutdown. java.util.concurrent.RejectedExecutionExceptionGuido
Why are you calling Future#get on your main thread? You don't even do anything with it. Plus, the TimeOutException will not stop the task.matt
@matt Because I found multiple answers on SO, indicating that you could use this. stackoverflow.com/a/2733370/4653908 (see comments).Guido
Answers, or comments? I don't follow what you linked to, the situation seems to be different. I provided an answer with an example so the .get() isn't blocking your main thread.matt

2 Answers

1
votes

The least change to your example that could get you something similar to what you want is to submit a new task.

Socket client = serverSocket.accept();
HTTPRequestHandler handler = new HTTPRequestHandler(client);
Future f = executor.submit(handler);
executor.submit(()->{
    try{
        f.get(10, TimeUnit.SECONDS);
    } catch(TimeoutException to){
        //timeout happened, this will cancel/interrupt the task.
        f.cancel(true);
    } catch(Exception e){
        throw new RuntimeException(e);
        //something else went wrong...
    }
});

This would work, but it will block an additional thread waiting on the get call. You'll also need to handle the interrupt in your HTTPRequestHandler code.

Another way could be to use a ScheduledExecutorService.

0
votes

There are a few problems with your approach:

I'm making a Java application which receives HTTP requests. For each request which comes in, I start a new thread, and in that thread I'm reading the request and performing the necessary actions.

This is a sure way to run out of memory or other resources. Instead, run your application within a servlet container (tomcat, jetty) and let it handle the multithreading for you. Just make sure that the code that handles the requests is "thread safe", because it will be called by multiple threads simultaneously.

If you HAVE to use a ServerSocket, then use a ExecutorService with a fixed number of threads. (never use an unlimited number of threads)

However, I want to prevent the users from performing a "Slow Loris Attack"

To prevent the slowloris attack, you should run your application behind a http server (Apache for example) and make sure to install the appropriate security modules. see for example: http://www.techrepublic.com/blog/smb-technologist/secure-your-apache-server-from-ddos-slowloris-and-dns-injection-attacks/

I was thinking about giving a thread a maxTime value. If the thread takes longer than the maxTime it will terminate no matter what.

This is not a good idea. In general, when you receive a HTTP request, the controller (the code that handles the request) must reply as fast as possible, but the way to do this is by optimizing the processing of the request (for example, don't do operations that take too long time when processing a http request). If your processing time is fast, but from the client perspective, the server is unresponsive, then you should consider distributing your application (putting many instances of your server behind a load balancer)