Skip to content

Commit fe06c61

Browse files
ClearlyClairehiyuki2578
authored andcommitted
Improve rate limiting (mastodon#10860)
* Rate limit based on remote address IP, not on potential reverse proxy * Limit rate of unauthenticated API requests further * Rate-limit paging requests to one every 3 seconds
1 parent 77b1d3a commit fe06c61

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

config/initializers/rack_attack.rb

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ def authenticated_token
1313
)
1414
end
1515

16+
def remote_ip
17+
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
18+
end
19+
1620
def authenticated_user_id
1721
authenticated_token&.resource_owner_id
1822
end
@@ -28,6 +32,10 @@ def api_request?
2832
def web_request?
2933
!api_request?
3034
end
35+
36+
def paging_request?
37+
params['page'].present? || params['min_id'].present? || params['max_id'].present? || params['since_id'].present?
38+
end
3139
end
3240

3341
PROTECTED_PATHS = %w(
@@ -42,27 +50,36 @@ def web_request?
4250
# (blocklist & throttles are skipped)
4351
Rack::Attack.safelist('allow from localhost') do |req|
4452
# Requests are allowed if the return value is truthy
45-
req.ip == '127.0.0.1' || req.ip == '::1'
53+
req.remote_ip == '127.0.0.1' || req.remote_ip == '::1'
4654
end
4755

4856
throttle('throttle_authenticated_api', limit: 300, period: 5.minutes) do |req|
4957
req.authenticated_user_id if req.api_request?
5058
end
5159

52-
throttle('throttle_unauthenticated_api', limit: 7_500, period: 5.minutes) do |req|
53-
req.ip if req.api_request?
60+
throttle('throttle_unauthenticated_api', limit: 300, period: 5.minutes) do |req|
61+
req.remote_ip if req.api_request? && !req.authenticated?
5462
end
5563

5664
throttle('throttle_api_media', limit: 30, period: 30.minutes) do |req|
5765
req.authenticated_user_id if req.post? && req.path.start_with?('/api/v1/media')
5866
end
5967

6068
throttle('throttle_media_proxy', limit: 30, period: 30.minutes) do |req|
61-
req.ip if req.path.start_with?('/media_proxy')
69+
req.remote_ip if req.path.start_with?('/media_proxy')
6270
end
6371

6472
throttle('throttle_api_sign_up', limit: 5, period: 30.minutes) do |req|
65-
req.ip if req.post? && req.path == '/api/v1/accounts'
73+
req.remote_ip if req.post? && req.path == '/api/v1/accounts'
74+
end
75+
76+
# Throttle paging, as it is mainly used for public pages and AP collections
77+
throttle('throttle_authenticated_paging', limit: 300, period: 15.minutes) do |req|
78+
req.authenticated_user_id if req.paging_request?
79+
end
80+
81+
throttle('throttle_unauthenticated_paging', limit: 300, period: 15.minutes) do |req|
82+
req.remote_ip if req.paging_request? && !req.authenticated?
6683
end
6784

6885
API_DELETE_REBLOG_REGEX = /\A\/api\/v1\/statuses\/[\d]+\/unreblog/.freeze
@@ -73,7 +90,7 @@ def web_request?
7390
end
7491

7592
throttle('protected_paths', limit: 25, period: 5.minutes) do |req|
76-
req.ip if req.post? && req.path =~ PROTECTED_PATHS_REGEX
93+
req.remote_ip if req.post? && req.path =~ PROTECTED_PATHS_REGEX
7794
end
7895

7996
self.throttled_response = lambda do |env|

0 commit comments

Comments
 (0)