README — Documentation for rack-attack (5.0.1) (2024)

Rack middleware for blocking & throttling abusive requests

Rack::Attack is a rack middleware to protect your web app from bad clients.It allows safelisting, blocklisting, throttling, and tracking based on arbitrary properties of the request.

Throttle and fail2ban state is stored in a configurable cache (e.g. Rails.cache), presumably backed by memcached or redis (at least gem v3.0.0).

See the Backing & Hacking blog post introducing Rack::Attack.

README — Documentation for rack-attack (5.0.1) (1)README — Documentation for rack-attack (5.0.1) (2)README — Documentation for rack-attack (5.0.1) (3)

Getting started

Install the rack-attack gem; or add it to your Gemfile with bundler:

# In your Gemfilegem 'rack-attack'

Tell your app to use the Rack::Attack middleware.For Rails 3+ apps:

# In config/application.rbconfig.middleware.use Rack::Attack

Or for Rackup files:

# In config.ruuse Rack::Attack

Add a rack-attack.rb file to config/initializers/:

# In config/initializers/rack-attack.rbclass Rack::Attack # your custom configuration...end

Tip: The example in the wiki is a great way to get started:Example Configuration

Optionally configure the cache store for throttling or fail2ban filtering:

Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache

Note that Rack::Attack.cache is only used for throttling and fail2ban filtering; not blocklisting & safelisting. Your cache store must implement increment and write like ActiveSupport::Cache::Store.

How it works

The Rack::Attack middleware compares each request against safelists, blocklists, throttles, and tracks that you define. There are none by default.

  • If the request matches any safelist, it is allowed.
  • Otherwise, if the request matches any blocklist, it is blocked.
  • Otherwise, if the request matches any throttle, a counter is incremented in the Rack::Attack.cache. If any throttle's limit is exceeded, the request is blocked.
  • Otherwise, all tracks are checked, and the request is allowed.

The algorithm is actually more concise in code: See Rack::Attack.call:

def call(env) req = Rack::Attack::Request.new(env) if safelisted?(req) @app.call(env) elsif blocklisted?(req) self.class.blocklisted_response.call(env) elsif throttled?(req) self.class.throttled_response.call(env) else tracked?(req) @app.call(env) endend

Note: Rack::Attack::Request is just a subclass of Rack::Request so that youcan cleanly monkey patch helper methods onto therequest object.

About Tracks

Rack::Attack.track doesn't affect request processing. Tracks are an easy way to log and measure requests matching arbitrary attributes.

Usage

Define safelists, blocklists, throttles, and tracks as blocks that return truthy values if matched, falsy otherwise. In a Rails appthese go in an initializer in config/initializers/.A Rack::Request object is passed to the block (named 'req' in the examples).

Safelists

# Always allow requests from localhost# (blocklist & throttles are skipped)Rack::Attack.safelist('allow from localhost') do |req| # Requests are allowed if the return value is truthy '127.0.0.1' == req.ip || '::1' == req.ipend

Blocklists

# Block requests from 1.2.3.4Rack::Attack.blocklist('block 1.2.3.4') do |req| # Requests are blocked if the return value is truthy '1.2.3.4' == req.ipend# Block logins from a bad user agentRack::Attack.blocklist('block bad UA logins') do |req| req.path == '/login' && req.post? && req.user_agent == 'BadUA'end

Fail2Ban

Fail2Ban.filter can be used within a blocklist to block all requests from misbehaving clients.This pattern is inspired by fail2ban.See the fail2ban documentation for more details onhow the parameters work. For multiple filters, be sure to put each filter in a separate blocklist and use a unique discriminator for each fail2ban filter.

# Block suspicious requests for '/etc/password' or wordpress specific paths.# After 3 blocked requests in 10 minutes, block all requests from that IP for 5 minutes.Rack::Attack.blocklist('fail2ban pentesters') do |req| # `filter` returns truthy value if request fails, or if it's from a previously banned IP # so the request is blocked Rack::Attack::Fail2Ban.filter("pentesters-#{req.ip}", :maxretry => 3, :findtime => 10.minutes, :bantime => 5.minutes) do # The count for the IP is incremented if the return value is truthy CGI.unescape(req.query_string) =~ %r{/etc/passwd} || req.path.include?('/etc/passwd') || req.path.include?('wp-admin') || req.path.include?('wp-login') endend

Note that Fail2Ban filters are not automatically scoped to the blocklist, so when using multiple filters in an application the scoping must be added to the discriminator e.g. "pentest:#{req.ip}".

Allow2Ban

Allow2Ban.filter works the same way as the Fail2Ban.filter except that it allows requests from misbehavingclients until such time as they reach maxretry at which they are cut off as per normal.

# Lockout IP addresses that are hammering your login page.# After 20 requests in 1 minute, block all requests from that IP for 1 hour.Rack::Attack.blocklist('allow2ban login scrapers') do |req| # `filter` returns false value if request is to your login page (but still # increments the count) so request below the limit are not blocked until # they hit the limit. At that point, filter will return true and block. Rack::Attack::Allow2Ban.filter(req.ip, :maxretry => 20, :findtime => 1.minute, :bantime => 1.hour) do # The count for the IP is incremented if the return value is truthy. req.path == '/login' and req.post? endend

Throttles

# Throttle requests to 5 requests per second per ipRack::Attack.throttle('req/ip', :limit => 5, :period => 1.second) do |req| # If the return value is truthy, the cache key for the return value # is incremented and compared with the limit. In this case: # "rack::attack:#{Time.now.to_i/1.second}:req/ip:#{req.ip}" # # If falsy, the cache key is neither incremented nor checked. req.ipend# Throttle login attempts for a given email parameter to 6 reqs/minute# Return the email as a discriminator on POST /login requestsRack::Attack.throttle('logins/email', :limit => 6, :period => 60.seconds) do |req| req.params['email'] if req.path == '/login' && req.post?end# You can also set a limit and period using a proc. For instance, after# Rack::Auth::Basic has authenticated the user:limit_proc = proc {|req| req.env["REMOTE_USER"] == "admin" ? 100 : 1}period_proc = proc {|req| req.env["REMOTE_USER"] == "admin" ? 1.second : 1.minute}Rack::Attack.throttle('req/ip', :limit => limit_proc, :period => period_proc) do |req| req.ipend

Tracks

# Track requests from a special user agent.Rack::Attack.track("special_agent") do |req| req.user_agent == "SpecialAgent"end# Supports optional limit and period, triggers the notification only when the limit is reached.Rack::Attack.track("special_agent", :limit => 6, :period => 60.seconds) do |req| req.user_agent == "SpecialAgent"end# Track it using ActiveSupport::NotificationActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, req| if req.env['rack.attack.matched'] == "special_agent" && req.env['rack.attack.match_type'] == :track Rails.logger.info "special_agent: #{req.path}" STATSD.increment("special_agent") endend

Responses

Customize the response of blocklisted and throttled requests using an object that adheres to the Rack app interface.

Rack::Attack.blocklisted_response = lambda do |env| # Using 503 because it may make attacker think that they have successfully # DOSed the site. Rack::Attack returns 403 for blocklists by default [ 503, {}, ['Blocked']]endRack::Attack.throttled_response = lambda do |env| # NB: you have access to the name and other data about the matched throttle # env['rack.attack.matched'], # env['rack.attack.match_type'], # env['rack.attack.match_data'] # Using 503 because it may make attacker think that they have successfully # DOSed the site. Rack::Attack returns 429 for throttling by default [ 503, {}, ["Server Error\n"]]end

X-RateLimit headers for well-behaved clients

While Rack::Attack's primary focus is minimizing harm from abusive clients, itcan also be used to return rate limit data that's helpful for well-behaved clients.

Here's an example response that includes conventional X-RateLimit-* headers:

Rack::Attack.throttled_response = lambda do |env| now = Time.now match_data = env['rack.attack.match_data'] headers = { 'X-RateLimit-Limit' => match_data[:limit].to_s, 'X-RateLimit-Remaining' => '0', 'X-RateLimit-Reset' => (now + (match_data[:period] - now.to_i % match_data[:period])).to_s } [ 429, headers, ["Throttled\n"]]end

For responses that did not exceed a throttle limit, Rack::Attack annotates the env with match data:

request.env['rack.attack.throttle_data'][name] # => { :count => n, :period => p, :limit => l }

Logging & Instrumentation

Rack::Attack uses the ActiveSupport::Notifications API if available.

You can subscribe to 'rack.attack' events and log it, graph it, etc:

ActiveSupport::Notifications.subscribe('rack.attack') do |name, start, finish, request_id, req| puts req.inspectend

Testing

A note on developing and testing apps using Rack::Attack - if you are using throttling in particular, you willneed to enable the cache in your development environment. See Caching with Railsfor more on how to do this.

Performance

The overhead of running Rack::Attack is typically negligible (a few milliseconds per request),but it depends on how many checks you've configured, and how long they take.Throttles usually require a network roundtrip to your cache server(s),so try to keep the number of throttle checks per request low.

If a request is blocklisted or throttled, the response is a very simple Rack response.A single typical ruby web server thread can block several hundred requests per second.

Rack::Attack complements tools like iptables and nginx's limit_conn_zone module.

Motivation

Abusive clients range from malicious login crackers to naively-written scrapers.They hinder the security, performance, & availability of web applications.

It is impractical if not impossible to block abusive clients completely.

Rack::Attack aims to let developers quickly mitigate abusive requests and relyless on short-term, one-off hacks to block a particular attack.

Contributing

Pull requests and issues are greatly appreciated. This project is intended to bea safe, welcoming space for collaboration, and contributors are expected toadhere to the Code of Conduct.

Mailing list

New releases of Rack::Attack are announced on[emailprotected]. To subscribe, just send an email to[emailprotected]. See thearchives.

License

Copyright Kickstarter, PBC.

Released under an MIT License.

README
  
    — Documentation for rack-attack (5.0.1) (2024)
Top Articles
Man in his 20s dies at Boomtown Festival 2024 after “medical incident” - Music news - NewsLocker
Novak Djokovic snubbed as greatest athlete of all-time by former tennis world No1 - The Mirror - Novak Djokovic news - NewsLocker
Victory Road Radical Red
Cars & Trucks - By Owner near Kissimmee, FL - craigslist
Immobiliare di Felice| Appartamento | Appartamento in vendita Porto San
Tj Nails Victoria Tx
Craigslist In South Carolina - Craigslist Near You
Aiken County government, school officials promote penny tax in North Augusta
Steve Strange - From Punk To New Romantic
Katie Boyle Dancer Biography
State Of Illinois Comptroller Salary Database
Garrick Joker'' Hastings Sentenced
Mawal Gameroom Download
Shuiby aslam - ForeverMissed.com Online Memorials
‘Accused: Guilty Or Innocent?’: A&E Delivering Up-Close Look At Lives Of Those Accused Of Brutal Crimes
Gwdonate Org
ocala cars & trucks - by owner - craigslist
Jc Post News
Sadie Proposal Ideas
bode - Bode frequency response of dynamic system
Caledonia - a simple love song to Scotland
Gentle Dental Northpointe
Kamzz Llc
Dcf Training Number
Yog-Sothoth
European city that's best to visit from the UK by train has amazing beer
Vernon Dursley To Harry Potter Nyt Crossword
Ficoforum
4 Methods to Fix “Vortex Mods Cannot Be Deployed” Issue - MiniTool Partition Wizard
Craigslist Rome Ny
Temu Seat Covers
Lcsc Skyward
Die wichtigsten E-Nummern
Greater Orangeburg
Redding Activity Partners
Alima Becker
Property Skipper Bermuda
Dollar Tree's 1,000 store closure tells the perils of poor acquisitions
The best bagels in NYC, according to a New Yorker
Craigslist Com Panama City Fl
Ezpawn Online Payment
Immobiliare di Felice| Appartamento | Appartamento in vendita Porto San
Craigslist Rooms For Rent In San Fernando Valley
Oakley Rae (Social Media Star) – Bio, Net Worth, Career, Age, Height, And More
How to Connect Jabra Earbuds to an iPhone | Decortweaks
bot .com Project by super soph
60 Days From August 16
Sam's Club Fountain Valley Gas Prices
28 Mm Zwart Spaanplaat Gemelamineerd (U999 ST9 Matte | RAL9005) Op Maat | Zagen Op Mm + ABS Kantenband
Deviantart Rwby
Pulpo Yonke Houston Tx
Salem witch trials - Hysteria, Accusations, Executions
Latest Posts
Article information

Author: Amb. Frankie Simonis

Last Updated:

Views: 6494

Rating: 4.6 / 5 (56 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Amb. Frankie Simonis

Birthday: 1998-02-19

Address: 64841 Delmar Isle, North Wiley, OR 74073

Phone: +17844167847676

Job: Forward IT Agent

Hobby: LARPing, Kitesurfing, Sewing, Digital arts, Sand art, Gardening, Dance

Introduction: My name is Amb. Frankie Simonis, I am a hilarious, enchanting, energetic, cooperative, innocent, cute, joyous person who loves writing and wants to share my knowledge and understanding with you.