{"id":18103973,"url":"https://github.com/svoop/rack-dedos","last_synced_at":"2025-04-06T05:48:11.107Z","repository":{"id":65615857,"uuid":"595783668","full_name":"svoop/rack-dedos","owner":"svoop","description":"Drastic filters to counter DoS attacks","archived":false,"fork":false,"pushed_at":"2024-03-26T19:47:22.000Z","size":131,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-04-27T05:20:46.131Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/svoop.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"svoop","custom":"https://donorbox.org/bitcetera"}},"created_at":"2023-01-31T19:58:21.000Z","updated_at":"2024-04-27T05:20:46.132Z","dependencies_parsed_at":"2024-11-07T00:15:43.143Z","dependency_job_id":"9ba29ef4-6a1d-4aee-b06e-4be84344d8f4","html_url":"https://github.com/svoop/rack-dedos","commit_stats":{"total_commits":2,"total_committers":1,"mean_commits":2.0,"dds":0.0,"last_synced_commit":"656986a21ba1c9ed632fbffc52e4edb336822f00"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Frack-dedos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Frack-dedos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Frack-dedos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svoop%2Frack-dedos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/svoop","download_url":"https://codeload.github.com/svoop/rack-dedos/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441006,"owners_count":20939235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-31T22:13:39.772Z","updated_at":"2025-04-06T05:48:11.080Z","avatar_url":"https://github.com/svoop.png","language":"Ruby","funding_links":["https://github.com/sponsors/svoop","https://donorbox.org/bitcetera"],"categories":[],"sub_categories":[],"readme":"[![Version](https://img.shields.io/gem/v/rack-dedos.svg?style=flat)](https://rubygems.org/gems/rack-dedos)\n[![Tests](https://img.shields.io/github/actions/workflow/status/svoop/rack-dedos/test.yml?style=flat\u0026label=tests)](https://github.com/svoop/rack-dedos/actions?workflow=Test)\n[![Code Climate](https://img.shields.io/codeclimate/maintainability/svoop/rack-dedos.svg?style=flat)](https://codeclimate.com/github/svoop/rack-dedos/)\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/svoop.svg)](https://github.com/sponsors/svoop)\n\n\u003cimg src=\"https://github.com/svoop/rack-dedos/raw/main/doc/chop-chop.png\" alt=\"chop-chop\" align=\"right\"\u003e\n\n# Rack::Dedos\n\nSomewhat more radical filters designed to decimate malicious requests during a [denial-of-service (DoS) attack](https://en.wikipedia.org/wiki/Denial-of-service_attack) by chopping their connection well before your Rack app wastes any significant resources on them – ouch!\n\nThe 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.\n\n* [Homepage](https://github.com/svoop/rack-dedos)\n* [API](https://www.rubydoc.info/gems/rack-dedos)\n* Author: [Sven Schwyn - Bitcetera](https://bitcetera.com)\n\nThank you for supporting free and open-source software by sponsoring on [GitHub](https://github.com/sponsors/svoop) or on [Donorbox](https://donorbox.com/bitcetera). Any gesture is appreciated, from a single Euro for a ☕️ cup of coffee to 🍹 early retirement.\n\n## Install\n\n### Security\n\nThis gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) 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:\n\n```\ngem cert --add \u003c(curl -Ls https://raw.github.com/svoop/rack-dedos/main/certs/svoop.pem)\n```\n\n### Bundler\n\nAdd the following to the \u003ctt\u003eGemfile\u003c/tt\u003e or \u003ctt\u003egems.rb\u003c/tt\u003e of your [Bundler](https://bundler.io) powered Ruby project:\n\n```ruby\ngem 'rack-dedos'\n```\n\nAnd then install the bundle:\n\n```\nbundle install --trust-policy MediumSecurity\n```\n\n## Configuration\n\nGiven 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.\n\n### Rails\n\n```ruby\n# config/application.rb\nclass Application \u003c Rails::Application\n  if Rails.env.production? \u0026\u0026 ActiveModel::Type::Boolean.new.cast(ENV['UNDER_ATTACK'])\n    config.middleware.use Rack::Dedos\n  end\nend\n```\n\n### Rackup\n\n```ruby\n#!/usr/bin/env rackup\nrequire 'rack/dedos'\n\nif %w(true t on 1).include? ENV['UNDER_ATTACK']\n  use Rack::Dedos\nend\n\nrun lambda { |env| [200, {'Content-Type' =\u003e 'text/plain'}, \"Hello, world!\\n\"] }\n```\n\n### Response\n\nIf a request is classified as malicious by at least one filter, the middleware responds with:\n\n\u003e 403 Forbidden (Temporarily Blocked by Rules)\n\nThis is the most appropriate response, however, feel free to trick the requester by tweaking this:\n\n```ruby\nuse Rack::Dedos,\n  status: 503,\n  text: \"Temporary Server Error\"\n```\n\n## Filters\n\nBy default, all filters described below are applied. You can exclude certain filters:\n\n```ruby\nuse Rack::Dedos,\n  except: [:user_agent]\n```\n\nTo only apply one specific filter, use the corresponding class as shown below.\n\n### User Agent Filter\n\n```ruby\nuse Rack::Dedos::Filters::UserAgent,\n  cache_url: 'redis://redis.example.com:6379/12',   # db 12 on default port\n  cache_key_prefix: 'dedos',   # key prefix for shared caches (default: nil)\n  cache_period: 1800   # seconds (default: 900)\n```\n\nRequests 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.\n\nThe following cache backends are supported:\n\n* `redis://...` – ⚠️ The [redis gem](https://rubygems.org/gems/redis) has to be installed.\n* `hash` – Only for testing, don't use this in production.\n\n### Country Filter\n\n```ruby\nuse Rack::Dedos::Filters::Country,\n  maxmind_db_file: '/var/db/maxmind/GeoLite2-Country.mmdb',\n  allowed_countries: %i(AT CH DE),\n  denied_countries: %i(RU)\n```\n\nEither allow or deny requests by probable country of origin. If both are set, the `denied_countries` option is ignored.\n\n⚠️ The [maxmind-db gem](https://rubygems.org/gems/maxmind-db) has to be installed.\n\nThe MaxMind GeoLite2 database is free, however, you have to create an account on [maxmind.com](https://www.maxmind.com) and then download the country database.\n\nFor automatic updates, create a `geoipupdate.conf` file and then use the [geoipupdate tool for your arch](https://github.com/maxmind/geoipupdate/releases) to fetch the latest country database.\n\nThe bundled `geoipget` executable does all this in one swipe:\n\n```\ngeoipget --help\ngeoipget --dir . --arch linux_amd64 /etc/geoipupdate.conf\n```\n\n## Real Client IP\n\nA 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:\n\n\u003e request.ip = 172.71.135.17\u003cbr\u003e\n\u003e request.forwarded_for = [\"81.XXX.XXX.XXX\", \"172.71.135.17\", \"10.201.229.136\"]\n\nObviously, the reported IP 172.71.135.17 is not the real client IP, the correct one is the (redacted) 81.XXX.XXX.XXX.\n\nDue to this flaw, Rack::Dedos determines the real client IP as follows in order of priority:\n\n1. [`Cf-Connecting-Ip` header](https://developers.cloudflare.com/fundamentals/get-started/reference/http-request-headers/#cf-connecting-ip)\n2. First entry of the [`X-Forwarded-For` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)\n3. [`ip` reported by Rack](https://github.com/rack/rack/blob/main/lib/rack/request.rb)\n\n## Development\n\nFor all required test fixtures to be present, you have to check out the repo\nwith all of its submodules:\n\n```\ngit clone git@github.com:svoop/rack-dedos.git\ncd rack-dedos\ngit submodule update --init\n```\n\nTo install the development dependencies and then run the test suite:\n\n```\nbundle install\nbundle exec rake    # run tests once\nbundle exec guard   # run tests whenever files are modified\n```\n\nYou're welcome to [submit issues](https://github.com/svoop/rack-dedos/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvoop%2Frack-dedos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvoop%2Frack-dedos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvoop%2Frack-dedos/lists"}