Configure Rack::Attack to block misbehaving clients
This commit is contained in:
parent
6f141ada87
commit
b8d91ca3c3
1
Gemfile
1
Gemfile
|
@ -46,6 +46,7 @@ gem "ruumba" # tests views
|
|||
gem "sitemap_generator" # for better search engine indexing
|
||||
gem "svg-graph", require: 'SVG/Graph/TimeSeries' # for charting, note workaround in lib/time_series.rb
|
||||
gem 'transaction_retry' # mitigate https://github.com/lobsters/lobsters-ansible/issues/39
|
||||
gem 'rack-attack' # rate-limiting
|
||||
|
||||
group :test, :development do
|
||||
gem 'capybara'
|
||||
|
|
|
@ -150,6 +150,8 @@ GEM
|
|||
nio4r (~> 2.0)
|
||||
racc (1.5.2)
|
||||
rack (2.2.3)
|
||||
rack-attack (6.5.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-mini-profiler (2.0.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-test (1.1.0)
|
||||
|
@ -304,6 +306,7 @@ DEPENDENCIES
|
|||
oauth
|
||||
pdf-reader
|
||||
puma
|
||||
rack-attack
|
||||
rack-mini-profiler
|
||||
rails (~> 6.0.3.3)
|
||||
rb-readline
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
Rack::Attack.safelist('localhost') do |req|
|
||||
'127.0.0.1' == req.ip || '::1' == req.ip
|
||||
end
|
||||
|
||||
# this will kick in way too early if serving assets via rack
|
||||
Rack::Attack.throttle("5 requests per second", limit: 5, period: 1, &:ip)
|
||||
|
||||
# we ask scrapers to sleep 1s between hits
|
||||
Rack::Attack.throttle("60 requests per minute", limit: 60, period: 60, &:ip)
|
||||
|
||||
# there's an attacker enumeratng usernames via Tor
|
||||
Rack::Attack.throttle("user enumerator", limit: 30, period: 300) do |request|
|
||||
request.ip if request.path.startswith? '/u/'
|
||||
end
|
||||
# at some point they'll proceed to testing credentials
|
||||
Rack::Attack.throttle("login", limit: 4, period: 60) do |request|
|
||||
request.ip if request.post? && request.path == '/login'
|
||||
end
|
||||
|
||||
# explain the throttle
|
||||
Rack::Attack.throttled_response_retry_after_header = true
|
||||
Rack::Attack.throttled_response = lambda do |env|
|
||||
match_data = env['rack.attack.match_data']
|
||||
now = match_data[:epoch_time]
|
||||
|
||||
headers = {
|
||||
'RateLimit-Limit' => match_data[:limit].to_s,
|
||||
'RateLimit-Remaining' => '0',
|
||||
'RateLimit-Reset' => (now + (match_data[:period] - now % match_data[:period])).to_s,
|
||||
}
|
||||
|
||||
[429, headers, ["Throttled, sleep(1) between hits; more in config/initializers/rack_attack.rb\n"]]
|
||||
end
|
Loading…
Reference in New Issue