-
Notifications
You must be signed in to change notification settings - Fork 343
Description
Gem Versions:
- rack-attack: 6.7.0
- ruby: 3.3.4
- rails: 7.0.8.4
- redis 4.8.1
Context
I encountered an issue with the rack-attack gem when applied to a Rails application. I noticed that the TTL (Time-to-Live) values for Redis keys are inconsistently applied, causing problems with request rate limiting.
Problem Description
When blocking requests based on actions taken on an endpoint, the filters apply a TTL in Redis that does not align with the expected duration. This inconsistency happens randomly. For instance, if a 3-minute window is supposed to validate more than 20 hits, the Redis key should have a TTL of approximately 180 seconds. However, in some cases, it only applies a TTL of 80 seconds, making it impossible to validate the conditions because the data persists incorrectly.
This issue is not noticeable with smaller numbers of hits in a shorter time frame (e.g., 10 hits in one minute) because the TTL mismatch is less obvious. For example, the expected TTL might be 60 seconds, but it sometimes applies 30 seconds, thus obscuring the error.
Example code for implementation
RA_REDIS_CONF = {
url: ENV.fetch("REDIS_URL"),
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
}
rack_attack = Rack::Attack
rack_attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(**RA_REDIS_CONF)
API_ENDPOINT = "/api/endpoint"
rack_attack.blocklist("filter 1") do |req|
rack_attack::Allow2Ban.filter("filter_1:#{req.ip}", maxretry: 20, findtime: 180, bantime: 1.hour) do
req.path == API_ENDPOINT && req.post?
end
end
rack_attack.blocklist("filter 2") do |req|
rack_attack::Allow2Ban.filter("filter_2:#{req.ip}", maxretry: 10, findtime: 60, bantime: 3.minutes) do
req.path == API_ENDPOINT && req.post?
end
end
rack_attack.blocklisted_responder = lambda do |request_env|
[403, { "Content-Type" => "application/json" }, [{ error: "Too many requests. Please try again later." }.to_json]]
endLogs of TTLs wrongly applied when I start the counters
TTL for rack::attack:95485:allow2ban:count:filter_1:14.0.4.4: --> 68 # (should be approx 180)
TTL for rack::attack:25841:allow2ban:count:filter_2:14.0.4.4: --> 33 # (should be approx 60)
Please, any possible solution related to this?
Thanks.