-
Notifications
You must be signed in to change notification settings - Fork 337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement exponential backoff #106
Comments
Hmm, exponential backoff would require a really tricky re-work of how the key naming arithmetic works. You can still block 90% of abusive clients by throttling on specific actions. The example configuration will already slow dictionary attacks down to 5 requests/20 seconds, which would make an attack using the entire Oxford English Dictionary take almost 8 days (http://blog.codinghorror.com/dictionary-attacks-101/) After some brainstorming, I realized you can actually write a pseudo-exponential backoff using the standard Rack::Attack throttles by doing something like this: # Allows 20 requests in 8 seconds
# 40 requests in 64 seconds
# ...
# 100 requests in 0.38 days (~250 requests/day)
(1..5).each do |level|
throttle("logins/ip/#{level}", :limit => (20 * level), :period => (8 ** level).seconds) do |req|
if req.path == '/login' && req.post?
req.ip
end
end
end |
(note that the above solution throttles on all login requests for a single ip, not just failed ones) |
@reedloden - does the Advanced Configuration page solve your issue? |
I haven't had time to test. I could close this out if it's a problem... I hope to pick this up later this month. |
Haha, not a problem at all. Just wanted to check in since it had been a while 😃 |
Closing this since it's covered in the advanced config docs. Happy throttling! 🌻 |
@reedloden - Was this ever tested? |
@ACPK Not sure if we ever implemented it in this fashion. I will check and see. |
@reedloden Thanks! |
Can anyone confirm this approach actually works? To me, it seems like only the last rule is active. In my example below, I only have a limit after the 10th request ( (1..5).each do |level|
throttle('req/ip', limit: (2 * level), period: (8 ** level).seconds) do |req|
req.ip
end
end Thank you! |
@em4nue1 You need to have unique names for each throttle. So, use |
It would be really awesome if Rack::Attack supported exponential backoff so as people continue to misbehave, their ban times increase (maybe up to some max time).
This article has some useful thoughts and tables about it:
https://devcentral.f5.com/articles/implementing-the-exponential-backoff-algorithm-to-thwart-dictionary-attacks
The text was updated successfully, but these errors were encountered: