WaitAMinute
A simple, application level DOS (Denial-Of-Service) protection tool for small Rails applications.
How does it work?
Once WaitAMinute gem is installed and configured in a Rails application, it will run a before_filter on every call to any subclasses of ActionController.
The before hook checks if the IP is a ‘friendly’ one (eg. NewRelic monitoring), meaning it is allowed no matter what. For ‘non-friendly’ IP addresses, the before filter checks if the IP is not already banned within a minute (hence the name of the gem), if not, it checks the number of previous requests from the given address within a configurable floating timeframe and allows the request to be served only if the address did not exceed the allowed maximum requests within the timeframe. WaitAMinute then stores the request IP and the timestamp along with a bit indicating if the request was refused or not.
If the IP is banned, WaitAMinute renders a page with HTTP status 503 telling the server is too busy to handle the request and that the user should retry after a minute.
Installation
add the gem to your Gemfile then # bundle install
Configuration
in your application’s root directory,
run # rails g wait_a_minute:install
then # rake db:migrate
finally revise and tweak config/initializers/wait_a_minute.rb
WaitAMinute.lookback_interval - the floating timeframe size, eg. 2.minutes
WaitAMinute.maximum_requests - the max number of requests from a single IP within the timeframe, eg. 24 - along with the above it allows a request every 5 seconds from a single IP address
WaitAMinute.debug - set to true for having IP filtering logged
WaitAMinute.layout - if some layout is needed around the error page, specify it here /for best performance it is not recommended, we want banned IP’s to use the least resources/
WaitAMinute.allowed_ips - an array of strings with IP addresses that never should be banned, eg, [‘127.0.0.1’] (once tried that it works ok on the development box, likely want the local developer to pass through always)
Customization
create app/views/wait_a_minute/wait_a_minute.html.erb and customize to your liking to override the default error page for banned IP addresses.
Maintenance
from time to time WaitAMinute.cleanup should be called from a scheduled script to flush obsolete request logs in order to keep an optimal ActiveRecord performance in its filtering operations.
Further considerations
as the piece of software works with the REMOTE_ADDR of the request, it is only suitable in environments where it reflects the original request address. (eg. it won’t work in an environment where a load balancer replaces the REMOTE_ADDR address in the request)