Skip to content

Metadata retention mechanism when limit/period procs are used on throttles #600

@Nowaker

Description

@Nowaker

Example from README:

limit_proc = proc { |req| req.env["REMOTE_USER"] == "admin" ? 100 : 1 }
period_proc = proc { |req| req.env["REMOTE_USER"] == "admin" ? 1 : 60 }

Rack::Attack.throttle('request per ip', limit: limit_proc, period: period_proc) do |request|
  request.ip
end

In my specific case, I have a dynamic limit that's based on whether an IP is recognized as VPN, DC, Tor, specific country, etc. Presence of each indicator increases the penalty. For example: VPN x3, Russia 2x, DC x3, and VPN+Russia would be x5. To simplify it for this issue description, consider it something like this:

limit_proc = proc do |req|
  factors = {}

  if Geocoder.country(req.remote_ip) == 'us'
    factors[:country] = 2
  end

  if SecurityChecker.vpn?(req.remote_ip)
    factors[:vpn] = 3
  end

  penalty = factors.values.sum

  (60.0 / penalty).ceil
end

Rack::Attack.throttle('request per ip', limit: limit_proc, period: 60) do |request|
  request.ip
end

When a throttle trips, all I'll know is that the limit was 60, or 30, or 20, or 10.. It can be any number that comes out. Wouldn't it be great to retain the value of factors variable somehow, so notifications and throttle request handler can access it in env['rack.attack.match_data'] or alike?

For example:

limit_proc = proc do |req|
  factors = {}

  if Geocoder.country(req.remote_ip) == 'us'
    factors[:country] = 2
  end

  if SecurityChecker.vpn?(req.remote_ip)
    factors[:vpn] = 3
  end

  penalty = factors.values.sum
  limit = (60.0 / penalty).ceil

  [limit, factors]
  # will return: [5, {country: 2, vpn: 3}
  #               ^ throttle uses this as the limit
  #.                 ^ this contextual information lands in rack.attack.match_data if this throttle trips
end

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions