Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Code exercise for SIP programmer opening July 2019

Support for ban in rack-ratelimit

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.

Notes about the implementation

  • The described way ban could 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 README to describe this feature are expected.

How to submit your solution

  • Don't fork the rack-ratelimit repository 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-patch to 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.