Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to leave client waiting for Java JAX-RS service to prevent DOS

Tags:

I'm having an issue with a web service with users trying to guess application IDs by looping over random IDs.

The bad requests are coming from random IPs, so I cannot just ban their IP (unless I do it dynamically, but I'm not looking into that yet).

Currently when I detect a client that has made 10 bad app ID attempts I put them on a block list in my app, and reject further requests from that IP for the day.

I want to minimize the amount of work my server needs to do, as the bad client will continue to send 1000s of requests even though they get rejected. I know there are dynamic Firewall solutions, but want something easy to implement in my app for now. Currently I am sleeping for 5 seconds to reduce the calls, but what I want to do is just not send a response to the client, so it has to timeout.

Anyone know how to do this in Java, in JAX-RS?

My service is like,

@Path("/api") public class MyServer {  @GET @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) @Path("/my-request") public String myRequest(String type,     @Context HttpServletRequest requestContext,     @Context HttpServletResponse response) { ... } 

See: How to stop hack/DOS attack on web API

like image 535
James Avatar asked Sep 30 '15 19:09

James


People also ask

Is it possible to make asynchronous requests in JAX-RS?

The JAX-RS 2.0 specification has added asynchronous HTTP support via two classes. The @Suspended annotation, and AsyncResponse interface.

What is JAX-RS Client API?

The JAX-RS client API is a Java based API used to access Web resources. It is not restricted to resources implemented using JAX-RS.

What is the purpose of using JAX-RS?

JAX-RS is a Java programming language API designed to make it easy to develop applications that use the REST architecture. The JAX-RS API uses Java programming language annotations to simplify the development of RESTful web services.


2 Answers

You are looking for asynchronous responses which are supported by JAX-RS. The tutorial for Jersey contains some examples of how to implement an asynchronous response to a request.

With asynchronous responses, the thread that is responsible for answering a request is freed for handling another request already before a request is completed. This feature is activated by adding a parameter with the @Suspended annotation. What you would need to do additionally, would be to register a dedicated scheduler that is responsible for waking up your requests after a given time-out like in this example:

@Path("/api") public class MyServer {    private ScheduledExecutorService scheduler = ...;    @GET   @Consumes(MediaType.APPLICATION_XML)   @Produces(MediaType.APPLICATION_XML)   @Path("/my-request")   public String myRequest(String type,                           @Context HttpServletRequest requestContext,                           @Context HttpServletResponse response,                           @Suspended AsyncResponse asyncResponse) {     scheduler.schedule(new Runnable() {       @Override       public void run() {         asyncResponse.resume(...)       }     }, 5, TimeUnit.SECOND);   } } 

This way, no thread is blocked for the waiting time of five seconds what gives an opportunity for handling other requests in the meantime.

JAX-RS does not offer a way of completely discarding a request without an answer. You will need to keep the connection open to produce a time out, if you terminate the connection, a user is notified of the termination. Best you could do would be to never answer an asynchronous request but this will still consume some ressources. If you wanted to avoid this, you would have to solve the problem outside of JAX-RS, for example by proxying the request by another server.

One way to do that would be to set up mod_proxy where you could answer the proxy with an error code for the mallicious requests and set up a very large retry limit for such requests.

like image 83
Rafael Winterhalter Avatar answered Oct 24 '22 09:10

Rafael Winterhalter


There are many possible solutions, with the restrictions you have given 2 possible solutions come to my mind:

1) Use a forward proxy that already has support for limiting requests. I personally have used Nginx and can recommend it partly because it is simple to set up. Relevant rate limiting config: Limit Req Module

2) Use Asynchronous JAX-RS to let timeout the malicious request that you detected. Sane request can be processed directly. But beware of the consequences, either way such an approach will consume resources on the server!

like image 32
Dainesch Avatar answered Oct 24 '22 10:10

Dainesch