3

From a few sources (1 2 3), I'm getting the impression that whenever people wants to rate limit requests, the tendency seems to be "wrap Tomcat behind Apache, and rate-limit on Apache". There's also the iptables solution, but that won't answer HTTP 429 ("Too many requests").

Apache is fine, but sometimes it will be nice if we can improvise small-scale deployments of a small servlet we have, but we're still being asked to rate limit requests, and setting up an Apache layer seems like a bit of overkill (at least compared to cloning a web.xml file, which we're already doing anyway).

So I'm thinking of coding a small filter to do just that (as it seems like a significant amount of non-effort) and package it with the servlet, but the eerie absence of elaborate Tomcat rate limit filters out in the open suggests that this approach might be naive. I mean, this feels so generic and so much is Open-Source-available these days. So maybe there is a really good reason that justifies the Apache solution. Apache has so many options while Tomcat seems to have none.

(Jetty does seem to ship with one such filter though, despite being a servlet container.)

Why does Tomcat lack built-in rate-limit filters?

Community
  • 1
  • 1
Yd Ahhrk
  • 1,088
  • 12
  • 24

3 Answers3

3

Tomcat sure does have a rate-limit filter valve built-in. You just have to modify it to suit your needs.

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
  • Now I'm even more stumped. That is a valve, not a filter. Why was is not implemented as a filter? – Yd Ahhrk Nov 07 '16 at 16:57
  • 1
    Because you usually want to stop requests coming in before they get to any application, use-up authentication resources, etc. Valves always run before filters, but valves can be in any order. Making this a valve allows you to insert it at the very start of processing to make it fail as fast as possible. – Christopher Schultz Nov 07 '16 at 17:56
  • 2
    Rate limiting is a maximum number of requests that can be made over a moving window of time. The Semaphore Valve does not do that -- based on the valve's name and reading the documentation. – Andrew Gilmartin Jul 18 '18 at 16:53
  • @AndrewGilmartin The "semaphore valve" is certainly limited in what it can do. You can't really build `mod_security`-style DDOS protection out of it. But the class is mostly built as an extension point for your own logic, so you can implement a moving-window if you want it... sort-of. – Christopher Schultz Jan 22 '19 at 17:59
  • `SemaphoreValve` is not for rate limiting at all. You want to be able to control requests/IP/second, as well as bursts. See how nginx does this: https://www.nginx.com/blog/rate-limiting-nginx/ It's a shame Tomcat has nothing like this built-in. – Martynas Jusevičius Feb 01 '21 at 20:23
  • 1
    @MartynasJusevičius You can use SemaphoreValve to build your own rate-limiting which meets exactly your needs. Tomcat is an implementation of the Java Servlet and other related APIs. It is not intended to be a reverse-proxy, Web Application Firewall, or other similar device. If you like mod_security or nginx's rate-limiter, then use those products. You can mod this answer down, but you are really just complaining about Tomcat and not this answer. – Christopher Schultz Feb 02 '21 at 14:35
3

Tomcat is often used as application container behind another webserver (a.k.a. reverse-proxy) that implements some functions more efficiently, like TLS-offloading, serving static resources, or to spread load (like a loadbalancer) over multiple Java processes or multiple web applications, and it makes more sense to stop an attack as efficiently and early as possible. Also a servlet filter cannot be used for more than a single web application.

But Tomcat has a good mechanism called Valves that can be used to implement rate-limiting, see for a complete implementation:

https://github.com/ihbrune/Anti-DoS-Valve

On the downside, Valves remain Tomcat specific and Filters are portable to other web containers and depending on your application framework, e.g. Spring MVC the framework might offer similar options like Interceptors that you could combine with a library for rate-limiting like:

https://github.com/vladimir-bukhtoyarov/bucket4j

So you can write your own custom logic, e.g. checking the amount of failed login attempts, in case of credential stuffing attacks

JohannesB
  • 2,214
  • 1
  • 11
  • 18
2

Tomcat comes with RateLimitFilter since version 9.0.76 and 10.1.9.

The configuration is done in web.xml

Peter
  • 31
  • 4