mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 03:37:56 +01:00
Add DDoS protection (#308)
* Add and configure rack-attack gem * Limit number of tenant registrations with same email address * Limit requests to tenants#create by IP
This commit is contained in:
committed by
GitHub
parent
e34e3f1aba
commit
336adb9bfd
3
Gemfile
3
Gemfile
@@ -41,6 +41,9 @@ gem 'react-rails', '2.6.2'
|
|||||||
# Pagination
|
# Pagination
|
||||||
gem 'kaminari', '1.2.2'
|
gem 'kaminari', '1.2.2'
|
||||||
|
|
||||||
|
# DDoS protection
|
||||||
|
gem 'rack-attack', '6.7.0'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ GEM
|
|||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
racc (1.7.3)
|
racc (1.7.3)
|
||||||
rack (2.2.8.1)
|
rack (2.2.8.1)
|
||||||
|
rack-attack (6.7.0)
|
||||||
|
rack (>= 1.0, < 4)
|
||||||
rack-test (2.1.0)
|
rack-test (2.1.0)
|
||||||
rack (>= 1.3)
|
rack (>= 1.3)
|
||||||
rails (6.1.7.7)
|
rails (6.1.7.7)
|
||||||
@@ -293,6 +295,7 @@ DEPENDENCIES
|
|||||||
pg (= 1.3.5)
|
pg (= 1.3.5)
|
||||||
puma (= 5.6.8)
|
puma (= 5.6.8)
|
||||||
pundit (= 2.2.0)
|
pundit (= 2.2.0)
|
||||||
|
rack-attack (= 6.7.0)
|
||||||
rails (= 6.1.7.7)
|
rails (= 6.1.7.7)
|
||||||
rake (= 12.3.3)
|
rake (= 12.3.3)
|
||||||
react-rails (= 2.6.2)
|
react-rails (= 2.6.2)
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ class TenantsController < ApplicationController
|
|||||||
@tenant.status = "active" # no need to verify email address if logged in with oauth
|
@tenant.status = "active" # no need to verify email address if logged in with oauth
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Check how many times this email registered a tenant
|
||||||
|
already_registered_tenants = User.unscoped.where(email: params[:user][:email], role: User.roles[:owner]).count
|
||||||
|
raise "Too many tenants registered by email" unless already_registered_tenants < 3
|
||||||
|
|
||||||
@tenant.save!
|
@tenant.save!
|
||||||
Current.tenant = @tenant
|
Current.tenant = @tenant
|
||||||
|
|
||||||
|
|||||||
73
config/initializers/rack_attack.rb
Normal file
73
config/initializers/rack_attack.rb
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
class Rack::Attack
|
||||||
|
### Throttle Spammy Clients ###
|
||||||
|
|
||||||
|
# If any single client IP is making tons of requests, then they're
|
||||||
|
# probably malicious or a poorly-configured scraper. Either way, they
|
||||||
|
# don't deserve to hog all of the app server's CPU. Cut them off!
|
||||||
|
#
|
||||||
|
# Note: If you're serving assets through rack, those requests may be
|
||||||
|
# counted by rack-attack and this throttle may be activated too
|
||||||
|
# quickly. If so, enable the condition to exclude them from tracking.
|
||||||
|
|
||||||
|
# Throttle all requests by IP (60rpm)
|
||||||
|
#
|
||||||
|
# Key: "rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}"
|
||||||
|
throttle('req/ip', limit: 300, period: 5.minutes) do |req|
|
||||||
|
req.ip # unless req.path.start_with?('/assets')
|
||||||
|
end
|
||||||
|
|
||||||
|
### Prevent Brute-Force Login Attacks ###
|
||||||
|
|
||||||
|
# The most common brute-force login attack is a brute-force password
|
||||||
|
# attack where an attacker simply tries a large number of emails and
|
||||||
|
# passwords to see if any credentials match.
|
||||||
|
#
|
||||||
|
# Another common method of attack is to use a swarm of computers with
|
||||||
|
# different IPs to try brute-forcing a password for a specific account.
|
||||||
|
|
||||||
|
# Throttle POST requests to /users/sign_in by IP address
|
||||||
|
#
|
||||||
|
# Key: "rack::attack:#{Time.now.to_i/:period}:logins/ip:#{req.ip}"
|
||||||
|
throttle('logins/ip', limit: 5, period: 20.seconds) do |req|
|
||||||
|
if req.path == '/users/sign_in' && req.post?
|
||||||
|
req.ip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Throttle POST requests to /users/sign_in by email param
|
||||||
|
#
|
||||||
|
# Key: "rack::attack:#{Time.now.to_i/:period}:logins/email:#{normalized_email}"
|
||||||
|
#
|
||||||
|
# Note: This creates a problem where a malicious user could intentionally
|
||||||
|
# throttle logins for another user and force their login requests to be
|
||||||
|
# denied, but that's not very common and shouldn't happen to you. (Knock
|
||||||
|
# on wood!)
|
||||||
|
throttle('logins/email', limit: 5, period: 20.seconds) do |req|
|
||||||
|
if req.path == '/users/sign_in' && req.post?
|
||||||
|
# Normalize the email, using the same logic as your authentication process, to
|
||||||
|
# protect against rate limit bypasses. Return the normalized email if present, nil otherwise.
|
||||||
|
req.params['email'].to_s.downcase.gsub(/\s+/, "").presence
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Throttle POST requests to /tenants by IP address
|
||||||
|
throttle('tenant_signups/ip', limit: 5, period: 20.seconds) do |req|
|
||||||
|
if req.path == '/tenants' && req.post?
|
||||||
|
req.ip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
### Custom Throttle Response ###
|
||||||
|
|
||||||
|
# By default, Rack::Attack returns an HTTP 429 for throttled responses,
|
||||||
|
# which is just fine.
|
||||||
|
#
|
||||||
|
# If you want to return 503 so that the attacker might be fooled into
|
||||||
|
# believing that they've successfully broken your app (or you just want to
|
||||||
|
# customize the response), then uncomment these lines.
|
||||||
|
# self.throttled_response = lambda do |env|
|
||||||
|
# [ 503, # status
|
||||||
|
# {}, # headers
|
||||||
|
# ['']] # body
|
||||||
|
# end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user