Skip to content

Throttle and then Fail2Ban #210

Closed
Closed

Description

@acegilz

I want to first throttle abusers but then if they continue issue a ban, I am not being successful as everything is getting "forbidden"

class Rack::Attack

  ##LETS GIVE A FIRST THROTTLE
  throttle('req/ip', :limit => 50, :period => 1.minutes) do |req|
    req.ip
  end

  ##IF IT CONTINUES BAN FOR 24H
  Rack::Attack.blocklist('fail2ban pentesters') do |req|
    Rack::Attack::Fail2Ban.filter("pentesters-#{req.ip}", :maxretry => 100, :findtime => 5.minutes, :bantime => 1.days) do
      true ## I want to consider all requests, including legits
    end
  end
end

Activity

  1. acegilz commented on Jan 10, 2017

    @acegilz
    Author

    up..

  2. courtenay commented on Mar 26, 2017

    @courtenay

    in your fail2ban.filter code, check for the throttle key in Rails.cache.read("rack::attack:#{Time.now.to_i / 1.minute}:req/ip:127.0.0.1") - if the count is over a certain amount return true and it'll ban.

  3. feliperaul commented on Jan 16, 2018

    @feliperaul

    @courtenay I like your suggestion, but in this case we should set maxretry to 0 in the Fail2Ban filter, right?

  4. kruglyjmax commented on Apr 19, 2020

    @kruglyjmax

    Solved with using throttled?(req) in Rack::Attack::Fail2Ban.filter with maxretry: 0

    Rack::Attack.throttle('xhr/ip', limit: 10, period: 1.minute) do |req|
      req.path.include?('/api/')
    end
    
    Rack::Attack.blocklist('fail2ban') do |req|
      Rack::Attack::Fail2Ban.filter("xhr/#{req.ip}", maxretry: 0, findtime: 1.minute, bantime: 1.day) do
        throttled?(req) # Counts repeatedly
      end
    end
    
  5. dvandersluis commented on Feb 26, 2021

    @dvandersluis

    @kruglyjmax using throttled? seems to doubly increment the throttle (ie. the counter in redis is updated both by the throttle and by the fail2ban). Have you gotten around this?

  6. dvandersluis commented on Feb 26, 2021

    @dvandersluis

    I solved my issue by adding a method to Rack::Attack::Throttle:

    def exceeded?(request)
      discriminator = discriminator_for(request)
      return false unless discriminator
    
      current_period = period_for(request)
      current_limit = limit_for(request)
    
      key = [Time.now.to_i / current_period, name, discriminator].join(':')
      count = cache.read(key).to_i
    
      count > current_limit
    end

    And then I can use:

    Rack::Attack::Fail2Ban.filter("throttled/#{req.ip}", maxretry: 10, findtime: 1.minute, bantime: 1.hour) do
      configuration.throttles.any? { |_name, throttle| throttle.exceeded?(req) }
    end
  7. locked and limited conversation to collaborators on Mar 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions