A gem we use in some of our apps to add rate-limiting capabilities is rack-ratelimit. This gem is not too complex and quite flexible but lacks a feature that could be useful for people using it: the possiblity of banning a client completely for a period of time when they expose some undesirable behaviour.
The idea is that users of this gem could specify a number of requests after which a particular client would get banned for a given time interval, for all requests, rather than just rate-limited for a particular kind of requests. A new config option, ban, could be introduced to support this, working as follows:
ban: an array of [max requests, period in seconds, ban time]: [500, 5.minutes, 3.hours]
ban could be provided instead of rate, so this one wouldn't be required anymore (but one of them would be always necessary). Here is an example of how it could be used:
# Ban IPs that are hammering our sign in page with login requests for 24 hours
use(Rack::Ratelimit, name: 'login_brute_force',
conditions: ->(env) { env['REQUEST_METHOD'] == 'POST' && env['PATH_INFO'] =~ /\A\/sessions/ },
ban: [10, 5.minutes, 24.hours],
cache: Dalli::Client.new,
logger: Rails.logger) { |env| Rack::Request.new(env).ip }That is: if we see over 10 POST requests to /sessions in 5 minutes, we want that IP address to be banned completely for 24 hours, for all requests.
- The described way
bancould be used and configured is just a suggestion that can be changed if you decide so, no problem about that! - The change should be backwards-compatible with existing usages of
Rack::Ratelimit. - Tests and updating the
READMEto describe this feature are expected.
- Don't fork the
rack-ratelimitrepository on Github or submit a pull request directly there, as that would make your solution public for others to see. Instead, just clone the repository and work locally on it. - When you're done, squash your work into a single commit and use
git format-patchto generate a patch file. Email the patch file to us as your work sample submission. If you prefer to provide a GitHub's private gist or even do your work in a private repo and add us to it, that's also totally fine.