Rack::Dedos
Somewhat more radical filters designed to decimate malicious requests during a denial-of-service (DoS) attack by chopping their connection well before your Rack app wastes any significant resources on them – ouch!
The filters have been proven to work against certain DoS attacks, however, they might also block IPs behind proxies or VPNs. Make sure you have understood how the filters are triggered and consider this middleware a last resort only to be enabled during an attack.
- Homepage
- API
- Author: Sven Schwyn - Bitcetera
Thank you for supporting free and open-source software by sponsoring on GitHub or on Donorbox. Any gesture is appreciated, from a single Euro for a ☕️ cup of coffee to 🍹 early retirement.
Install
Security
This gem is cryptographically signed in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
gem cert --add <(curl -Ls https://raw.github.com/svoop/rack-dedos/main/certs/svoop.pem)
Bundler
Add the following to the Gemfile or gems.rb of your Bundler powered Ruby project:
gem 'rack-dedos'
And then install the bundle:
bundle install --trust-policy MediumSecurity
Configuration
Given the drastic nature of the filters, you should use this middleware for production environments only and/or if an environment variable like UNDER_ATTACK
is set to true.
Rails
# config/application.rb
class Application < Rails::Application
if Rails.env.production? && ActiveModel::Type::Boolean.new.cast(ENV['UNDER_ATTACK'])
config.middleware.use Rack::Dedos
end
end
Rackup
#!/usr/bin/env rackup
require 'rack/dedos'
if %w(true t on 1).include? ENV['UNDER_ATTACK']
use Rack::Dedos
end
run lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, world!\n"] }
Response
If a request is classified as malicious by at least one filter, the middleware responds with:
403 Forbidden (Temporarily Blocked by Rules)
This is the most appropriate response, however, feel free to trick the requester by tweaking this:
use Rack::Dedos,
status: 503,
text: "Temporary Server Error"
Filters
By default, all filters described below are applied. You can exclude certain filters:
use Rack::Dedos,
except: [:user_agent]
To only apply one specific filter, use the corresponding class as shown below.
User Agent Filter
use Rack::Dedos::Filters::UserAgent,
cache_url: 'redis://redis.example.com:6379/12', # db 12 on default port
cache_key_prefix: 'dedos', # key prefix for shared caches (default: nil)
cache_period: 1800 # seconds (default: 900)
Requests are blocked for cache_period
seconds in case another request has been made within cache_period
seconds from by same IP address but with a different user agent.
The following cache backends are supported:
redis://...
– ⚠️ The redis gem has to be installed.hash
– Only for testing, don't use this in production.
Country Filter
use Rack::Dedos::Filters::Country,
maxmind_db_file: '/var/db/maxmind/GeoLite2-Country.mmdb',
allowed_countries: %i(AT CH DE),
denied_countries: %i(RU)
Either allow or deny requests by probable country of origin. If both are set, the denied_countries
option is ignored.
⚠️ The maxmind-db gem has to be installed.
The MaxMind GeoLite2 database is free, however, you have to create an account on maxmind.com and then download the country database.
For automatic updates, create a geoipupdate.conf
file and then use the geoipupdate tool to fetch the latest country database:
version=4.10.0
arch=linux_amd64
conf=/etc/geoipupdate.conf
dir=/var/db/maxmind/
mkdir -p "${dir}"
wget --quiet -O /tmp/geoipupdate.tgz https://github.com/maxmind/geoipupdate/releases/download/v${version}/geoipupdate_${version}_${arch}.tar.gz
tar -xz -C /tmp -f /tmp/geoipupdate.tgz
/tmp/geoipupdate_${version}_${arch}/geoipupdate -f "${conf}" -d "${dir}"
Real Client IP
A word on how the real client IP is determined. Both Rack 2 and Rack 3 (up to 3.0.7 at the time of writing) may populate the request ip
incorrectly. Here's what a minimalistic Rack app deloyed to Render (behind Cloudflare) reports:
request.ip = 172.71.135.17
request.forwarded_for = ["81.XXX.XXX.XXX", "172.71.135.17", "10.201.229.136"]
Obviously, the reported IP 172.71.135.17 is not the real client IP, the correct one is the (redacted) 81.XXX.XXX.XXX.
Due to this flaw, Rack::Dedos determines the real client IP as follows in order of priority:
Cf-Connecting-Ip
header- First entry of the
X-Forwarded-For
header ip
reported by Rack
Development
For all required test fixtures to be present, you have to check out the repo with all of its submodules:
git clone git@github.com:svoop/rack-dedos.git
cd rack-dedos
git submodule update --init
To install the development dependencies and then run the test suite:
bundle install
bundle exec rake # run tests once
bundle exec guard # run tests whenever files are modified
You're welcome to submit issues and contribute code by forking the project and submitting pull requests.
License
The gem is available as open source under the terms of the MIT License.