Tomcat and flood protection - java

We are using Tomcat 7 for our web application. We provide an XML based API so that our customers can communicate with our server in a machine-to-machine way (no web browser needed). The requests are processed by a servlet.
We need to prevent users from sending too many requests in a row. Some of the services we provide involve polling for results and users may make requests in a loop without any pauses, making dozens of requests per second for nothing.
How can we protect ourselves from being flooded with useless requests? Is there a simple way to block requests at the servlet entry level when there are too many requests originating from the same IP? Is there something built-in Tomcat to deal with this problem?

Assuming that you are using an apache reverse-proxy in front of tomcat (if you aren't you should be), use mod_cband on the apache layer.

You could code your own.
Starting points for looking at this would be the Servlet API, in particular the Filter interface and the getRemoteHost() method of the SerlvetRequest interface.
Should be easy enough to write a Filter implementation which stores a count of requests from each host and takes action if a limit exceeded.

Spring Security has a lot of the features of Apache httpd's mod_security if you want a Java-only solution.

Apache's mod_evasive
or mod_security
could cover for your need here. You may consider Cloudflare for more complexly serious attacks that will require hardware protection.

Related

AngularJS: Server Side Architecture

Within our corporate intranet, we have a few end-point service platforms like BPM, document management system, etc. These end-point services expose REST API. We develop web applications using AngularJS as front end.
There are two options on how we can make calls from AngualJS to these end-point services.
Option 1: Given these end-point services expose REST, call these REST API directly from AngualrJS.
Option 2: Introduce a middle layer (on an application server like WebLogic or Tomcat). Build a Java application layer that calls into the end-point REST API; and host it on this millde layer. The AngularJS calls into REST provided by this middle layer; this middle layer inturn calls into the end-point REST.
I personally prefer the Option 1; however I invite your openion on this matter. I have listed the pros and cons of Option 1 as I see them.
Pros of Option 1:
Better performance (throughput) given one less hop for HTTP requests.
Lesser development/deployment efforts due to one less component.
Lesser number of points of failure. If there is an issue, we know its either in AngualrJs or the end service.
Cons of Option 1:
Security issues? Not sure of this - would like expert comments on this.
CORS: the end services will need to enable Access-Control-Allow-Origin to appropriate domains.
Poor logging? If something goes wrong, the logs will be available only on user machines (IE/Chrome development tool) or on the end service.
Too much processing in AngualJS layer? This processing is mainly parsing the result from end service. This also depends on the kind of end service that is being used.
option 2 in my opinion is a better option in long run. There are few reasons for that.
Security is first and foremost, If you have a middleware in between, you can have inherent security, which means you can expose only those REST APIs which your angular webapp needs. You can also include a security mechanism like oAuth since you control the middleware.
Logging is another one. for sure any application nowadays do need some sort of auditing. both security and logging are layers before your actual REST calls.
You would be able to add some aspects on any key REST API, such that in case if that API is called trigger a mail, it's always handy to have those flexibility even we don't need at the moment.
You can include response transformation and error handling efficiently. Once you get the response from service, in your middleware you can transform the response, remove unnecessary or critical fields, conjure some values etc. This all can be done with angular also but then the real response or error is exposed to the client.
On the downside you rightly mentioned performance is one but imo keeping your REST middlware in sync with services REST is more bane. any new API added by services, needs to be included in middleware, recompiled and redeployed. But it also depends what are the likelihood and frequency of those changes? for any those changes you anyhow might need to change in angular webapp to include it.
You mention "Within our corporate intranet". Depending on how the end-points are secured, option 1 could be challenging.
Angular will run in a web-browser so if those services are only accessible via VPN / intranet, the web-app will only work if your computer is connected to that intranet (i.e. it won't work if you run it from home).
Another security challenge with option 1 is that if the end-points require special authentication "secrets" (API tokens, passwords, certificates, etc.), those secrets will be exposed and visible to anyone who uses the web-app since anyone can see the traffic between their browser and the server. With option 2, those secrets can stay hidden behind your middle layer.
Lastly, even if Angular talks to those end-points directly, you will still need to have the HTML / JS / CSS hosted on some web-server. You may not need a full blown application server but you'll need something to point your web browser at.
If those concerns don't apply to your case, then it's really up to you to pick whichever option you and your team are the most comfortable with.
Thanks for such a nice article.
If you are concern with security and your project requirement is focused on Security. One must go with Option 2.
If Security is not a big concern. Options 2 is better.

Moving from Spring HTTP invoker to load balanced solution

Our application currently uses Spring's HttpInvokerProxyFactoryBean to expose a Java service interface, with POJO requests and responses handled by our single Tomcat server. This solution allows us to have a pure Java client and server, sharing the same Java interface. Due to increased load, we are now looking into the possibility of load balancing across multiple Tomcat instances.
It would be nice if we could make this transition while retaining the same Java interface, as this would minimise the additional development required. Googling seems to suggest that the most common solution for Tomcat load balancing is to use Apache http server together with mod_jk, but I presume this would mean using some communication mechanism other than Spring's HTTP invoker? Is there a better solution which would allow us to retain more of our current code? If not, what would be involved in transitioning between what we have now and Apache/mod_jk?
Any help would be greatly appreciated as I don't have any experience in this matter.

How to implement rate limiting based on a client token in Spring?

I am developing a simple REST API using Spring 3 + Spring MVC. Authentication will be done through OAuth 2.0 or basic auth with a client token using Spring Security. This is still under debate. All connections will be forced through an SSL connection.
I have been looking for information on how to implement rate limiting, but it does not seem like there is a lot of information out there. The implementation needs to be distributed, in that it works across multiple web servers.
Eg if there are three api servers A, B, C and clients are limited to 5 requests a second, then a client that makes 6 requests like so will find the request to C rejected with an error.
A recieves 3 requests \
B receives 2 requests | Executed in order, all requests from one client.
C receives 1 request /
It needs to work based on a token included in the request, as one client may be making requests on behalf of many users, and each user should be rate limited rather than the server IP address.
The set up will be multiple (2-5) web servers behind an HAProxy load balancer. There is a Cassandra backed, and memcached is used. The web servers will be running on Jetty.
One potential solution might be to write a custom Spring Security filter that extracts the token and checks how many requests have been made with it in the last X seconds. This would allow us to do some things like different rate limits for different clients.
Any suggestions on how it can be done? Is there an existing solution or will I have to write my own solution? I haven't done a lot of web site infrastructure before.
It needs to work based on a token included in the request, as one client may be making requests on behalf of many users, and each user should be rate limited rather than the server IP address.
The set up will be multiple (2-5) web servers behind an HAProxy load balancer. There is a Cassandra backed, and memcached is used. The web servers will be running on Jetty.
I think the project is request/response http(s) protocol. And you use HAProxy as fronted.
Maybe the HAProxy can load balancing with token, you can check from here.
Then the same token requests will reach same webserver, and webserver can just use memory cache to implement rate limiter.
I would avoid modifying application level code to meet this requirement if at all possible.
I had a look through the HAProxy LB documentation nothing too obvious there, but the requirement may warrant a full investigation of ACLs.
Putting HAProxy to one side, a possible architecture is to put an Apache WebServer out front and use an Apache plugin to do the rate limiting. Over-the-limit requests are refused out front and the application servers in the tier behind Apache are then separated from rate limit concerns making them simpler. You could also consider serving static content from the Web Server.
See the answer to this question How can I implement rate limiting with Apache? (requests per second)
I hope this helps.
Rob
You could put rate limits at various points in the flow (generally the higher up the better) and the general approach you have makes a lot of sense. One option for the implementation is to use 3scale to do it (http://www.3scale.net) - it does rate limits, analytics, key managed etc. and works either with a code plugin (the Java plugin is here: https://github.com/3scale/3scale_ws_api_for_java) which pushes or by putting something like Varnish (http://www.varnish-cache.org) in the pipeline and having that apply rate limits.
I was also thinking of the similar solutions a couple of day's ago. Basically, I prefer the "central-controlled" solution to save the state of the client request in the distributed environment.
In my application, I use a "session_id" to identify the request client. Then create a servlet filter or spring HandlerInterceptorAdapter to filter the request, then check the "session_id" with the central-controlled data repository, which could be memcached, redis, cassandra or zookeeper.
We use redis as leaky bucket backend
Add a controller as entrance
google cache that token as key with expired time
then filter every request
It is best if you implement ratelimit using REDIS. For more info please look this Rate limiting js Example.

How to avoid network call when REST client and server are on the same server

I have a web application in which two of the major components are the website (implemented in Groovy and Grails) and a backend RESTful web service (implemented using JAX-RS (Jersey) and Spring). Both of these will be running in Glassfish. The website will make calls to the RESTful web service. In many cases, these components will reside on separate servers, so the website will make calls over the network to the RESTful web service. If, however, I run both applications in the same Glassfish server, are there any optimizations that can be made to avoid the network call? In other words, I'm looking for some equivalent of EJB's remote/local interfaces for REST. Thanks!
Don't sweat the network call. Your traffic will generally never leave the local interface so you won't be consuming any bandwidth. You lose a bit of performance from serialization/deserialization, but you'll need to ask yourself if reducing the impact of this is worth developing a complicated proxy architecture. I think it most cases you'll find the answer to be no.
Not sure you will find any trivial solutions: you could of course add your own additional proxy layer, but I really wouldn't worry about it. Local network I/O (localhost or 127.0.0.1) is so heavily optimized anyway that you really won't notice.
Depending on your implementation Spring does support a number of remoting technologies (an old list is at http://static.springsource.org/spring/docs/2.0.x/reference/remoting.html), but you will find that key to all of these is the network transfer: they wrap it up in a variety of different ways but ultimately almost all turnkey remoting technologies drop into the network at some point in time. You may gain SOME efficiency by not having to use HTTP, but you will probably lose some of the loose coupling you gained by using Jersey.
If you are not too afraid to tightly couple maybe you can put the actual objects you are exposing via Jersey into a Glassfish-wide Spring context and invoke the methods directly: much tighter coupling though, so I'd say stick with the HTTP calls.
Yes, you can avoid a network call if your server and client both reside in the same JVM. You should be able to use Jersey Client API to create your own implementation of Connector to override default HTTP calls and handle request/response. Here is the blog that can get you started - http://www.theotherian.com/2013/08/jersey-2.0-server-side-client-in-memory-connector.html
IMHO, an unnecessary network overhead should be avoided at all cost. Even though this overhead would be only a few milliseconds, but while building features for your web application, you would increase such services call and all these milliseconds will add up to a good amount of latency on your application.

Servlet filters for abuse prevention? (DoS, spam, etc)

I'm looking for a servlet filter library that helps me secure our web service against unauthorized usage and DDoS.
We have "authorized clients" for our web service, so ideally the filter would help detect clients that aren't authorized or behave improperly, or detect multiple people using the same account. Also we need a way to prevent DoS'ing of our various services since we have an open-account policy -- limiting the number of simultaneous connections for a user, etc.
We've looked at the Tomcat LockOutFilter and such but those are fairly primitive and only prevent against one sort of attack.
Of course there are many application-specific components of the solution, but I was wondering if someone had written up a general solution as a starting point.
Apache Shiro is an interesting security solution (it was called jSecurity before joining Apache.org). I find their source code much easier to understand and tweak for my needs, and also to integrate it.
iTransformers DDOS servlet filter is a good example for a servlet filter able to apply Remotely Triggered Black holing https://www.rfc-editor.org/rfc/rfc5635 which is the only real/good and scalable way to defend yourself from a DDOS attacks.
If you are using Spring then Acegi security is pretty complete.
Here is a series of tutorial articles.
It looks like you might be able to run this without needing Spring everywhere, See here.
Acegi has become Spring Security since this was posted.
Also looks like www.acegisecurity.org has been hacked.

Categories