From 43101fb3a05fa50c8b768d21bca482a35057183b Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 16:32:17 +0000 Subject: [PATCH 1/9] Create adjustable ratelimiter for 3pid invites --- synapse/config/ratelimiting.py | 7 +++++++ synapse/handlers/room_member.py | 14 ++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/synapse/config/ratelimiting.py b/synapse/config/ratelimiting.py index 5a9adac480..67f96c9344 100644 --- a/synapse/config/ratelimiting.py +++ b/synapse/config/ratelimiting.py @@ -68,6 +68,7 @@ def read_config(self, config): ) self.rc_registration = RateLimitConfig(config.get("rc_registration", {})) + self.rc_third_party_invite = RateLimitConfig(config.get("rc_third_party_invite", {})) rc_login_config = config.get("rc_login", {}) self.rc_login_address = RateLimitConfig(rc_login_config.get("address", {})) @@ -102,6 +103,8 @@ def default_config(self, **kwargs): # - one for login that ratelimits login requests based on the account the # client is attempting to log into, based on the amount of failed login # attempts for this account. + # - one that ratelimits third-party invites requests based on the account the + # that's making the requests. # # The defaults are as shown below. # @@ -123,6 +126,10 @@ def default_config(self, **kwargs): # failed_attempts: # per_second: 0.17 # burst_count: 3 + # + #rc_third_party_invite: + # per_second: 0.2 + # burst_count: 10 # Ratelimiting settings for incoming federation diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index e940e4183b..5f8b7c7940 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -29,6 +29,7 @@ from synapse.types import RoomID, UserID from synapse.util.async_helpers import Linearizer from synapse.util.distributor import user_joined_room, user_left_room +from synapse.api.ratelimiting import Ratelimiter from ._base import BaseHandler @@ -74,11 +75,7 @@ def __init__(self, hs): self.rewrite_identity_server_urls = self.config.rewrite_identity_server_urls self._enable_lookup = hs.config.enable_3pid_lookup self.allow_per_room_profiles = self.config.allow_per_room_profiles - - # This is only used to get at ratelimit function, and - # maybe_kick_guest_users. It's fine there are multiple of these as - # it doesn't store state. - self.base_handler = BaseHandler(hs) + self.ratelimiter = Ratelimiter() @abc.abstractmethod def _remote_join(self, requester, remote_room_hosts, room_id, user, content): @@ -773,7 +770,12 @@ def do_3pid_invite( # We need to rate limit *before* we send out any 3PID invites, so we # can't just rely on the standard ratelimiting of events. - yield self.base_handler.ratelimit(requester) + self.ratelimiter.ratelimit( + requester.user.to_string(), time_now_s=self.hs.clock.time(), + rate_hz=self.hs.config.rc_third_party_invite.per_second, + burst_count=self.hs.config.rc_third_party_invite.burst_count, + update=True, + ) can_invite = yield self.third_party_event_rules.check_threepid_can_be_invited( medium, address, room_id, From ba13cfee17c98dd2ad5c808cbea097f179a13bba Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 16:40:45 +0000 Subject: [PATCH 2/9] gen sample config --- docs/sample_config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 63051dd56f..822beedd66 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -568,6 +568,8 @@ log_config: "CONFDIR/SERVERNAME.log.config" # - one for login that ratelimits login requests based on the account the # client is attempting to log into, based on the amount of failed login # attempts for this account. +# - one that ratelimits third-party invites requests based on the account the +# that's making the requests. # # The defaults are as shown below. # @@ -589,6 +591,10 @@ log_config: "CONFDIR/SERVERNAME.log.config" # failed_attempts: # per_second: 0.17 # burst_count: 3 +# +#rc_third_party_invite: +# per_second: 0.2 +# burst_count: 10 # Ratelimiting settings for incoming federation From 8e6ea2a6af064442c14ddf556b18bfa67e45c40f Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 16:48:15 +0000 Subject: [PATCH 3/9] lint --- scripts/generate_signing_key.py | 2 +- synapse/config/ratelimiting.py | 4 +++- synapse/handlers/room_member.py | 4 +--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/generate_signing_key.py b/scripts/generate_signing_key.py index ba3ba97395..36e9140b50 100755 --- a/scripts/generate_signing_key.py +++ b/scripts/generate_signing_key.py @@ -16,7 +16,7 @@ import argparse import sys -from signedjson.key import write_signing_keys, generate_signing_key +from signedjson.key import generate_signing_key, write_signing_keys from synapse.util.stringutils import random_string diff --git a/synapse/config/ratelimiting.py b/synapse/config/ratelimiting.py index 67f96c9344..5a05111c9b 100644 --- a/synapse/config/ratelimiting.py +++ b/synapse/config/ratelimiting.py @@ -68,7 +68,9 @@ def read_config(self, config): ) self.rc_registration = RateLimitConfig(config.get("rc_registration", {})) - self.rc_third_party_invite = RateLimitConfig(config.get("rc_third_party_invite", {})) + self.rc_third_party_invite = RateLimitConfig( + config.get("rc_third_party_invite", {}) + ) rc_login_config = config.get("rc_login", {}) self.rc_login_address = RateLimitConfig(rc_login_config.get("address", {})) diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index 5f8b7c7940..790aeba9f5 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -26,12 +26,10 @@ import synapse.types from synapse.api.constants import EventTypes, Membership from synapse.api.errors import AuthError, Codes, ProxiedRequestError, SynapseError +from synapse.api.ratelimiting import Ratelimiter from synapse.types import RoomID, UserID from synapse.util.async_helpers import Linearizer from synapse.util.distributor import user_joined_room, user_left_room -from synapse.api.ratelimiting import Ratelimiter - -from ._base import BaseHandler logger = logging.getLogger(__name__) From a68cd178143b91c43a9ea41b4eb3f07c314a0048 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 16:49:17 +0000 Subject: [PATCH 4/9] Add changelog --- changelog.d/11.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/11.feature diff --git a/changelog.d/11.feature b/changelog.d/11.feature new file mode 100644 index 0000000000..362e4b1efd --- /dev/null +++ b/changelog.d/11.feature @@ -0,0 +1 @@ +Allow server admins to configure a custom global rate-limiting for third party invites. \ No newline at end of file From d99ca431b3e392f90491194b5f377e0b7d1f515f Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 17:02:29 +0000 Subject: [PATCH 5/9] Disable 3pid ratelimit in test --- tests/rest/client/test_room_access_rules.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index 7d3ba0ee2a..db55a5bb55 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -326,6 +326,10 @@ def test_direct(self): expect_code=200, ) + # Disable the 3pid invite ratelimiter + self.hs.config.rc_third_party_invite.burst_count = 10 + self.hs.config.rc_third_party_invite.per_second = 0.1 + # We can't send a 3PID invite to a room that already has two members. self.send_threepid_invite( address="test@allowed_domain", From 58755e6cf1da9a90d923483f44c8c16c0243211c Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Wed, 6 Nov 2019 17:07:52 +0000 Subject: [PATCH 6/9] Don't override and forget the ratelimiter settings --- tests/rest/client/test_room_access_rules.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/rest/client/test_room_access_rules.py b/tests/rest/client/test_room_access_rules.py index db55a5bb55..13caea3b01 100644 --- a/tests/rest/client/test_room_access_rules.py +++ b/tests/rest/client/test_room_access_rules.py @@ -327,6 +327,8 @@ def test_direct(self): ) # Disable the 3pid invite ratelimiter + burst = self.hs.config.rc_third_party_invite.burst_count + per_second = self.hs.config.rc_third_party_invite.per_second self.hs.config.rc_third_party_invite.burst_count = 10 self.hs.config.rc_third_party_invite.per_second = 0.1 @@ -358,6 +360,9 @@ def test_direct(self): expected_code=403, ) + self.hs.config.rc_third_party_invite.burst_count = burst + self.hs.config.rc_third_party_invite.per_second = per_second + def test_unrestricted(self): """Tests that, in unrestricted mode, we can invite whoever we want, but we can only change the power level of users that wouldn't be forbidden in restricted From fa1f2d09e563219dd6f9e759426f8856b244ec28 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 7 Nov 2019 15:04:09 +0000 Subject: [PATCH 7/9] fix typo --- synapse/config/ratelimiting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synapse/config/ratelimiting.py b/synapse/config/ratelimiting.py index 5a05111c9b..2a4fe43406 100644 --- a/synapse/config/ratelimiting.py +++ b/synapse/config/ratelimiting.py @@ -105,7 +105,7 @@ def default_config(self, **kwargs): # - one for login that ratelimits login requests based on the account the # client is attempting to log into, based on the amount of failed login # attempts for this account. - # - one that ratelimits third-party invites requests based on the account the + # - one that ratelimits third-party invites requests based on the account # that's making the requests. # # The defaults are as shown below. From 940ce99c46346dc5476578cf7f51b84d2546b046 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 7 Nov 2019 15:42:05 +0000 Subject: [PATCH 8/9] Remove unnecessary linting change --- scripts/generate_signing_key.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_signing_key.py b/scripts/generate_signing_key.py index 36e9140b50..ba3ba97395 100755 --- a/scripts/generate_signing_key.py +++ b/scripts/generate_signing_key.py @@ -16,7 +16,7 @@ import argparse import sys -from signedjson.key import generate_signing_key, write_signing_keys +from signedjson.key import write_signing_keys, generate_signing_key from synapse.util.stringutils import random_string From 5631169586195761880a330c79df06cdffa7e0e6 Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Fri, 8 Nov 2019 16:36:45 +0000 Subject: [PATCH 9/9] sample config --- docs/sample_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sample_config.yaml b/docs/sample_config.yaml index 822beedd66..b4713b687e 100644 --- a/docs/sample_config.yaml +++ b/docs/sample_config.yaml @@ -568,7 +568,7 @@ log_config: "CONFDIR/SERVERNAME.log.config" # - one for login that ratelimits login requests based on the account the # client is attempting to log into, based on the amount of failed login # attempts for this account. -# - one that ratelimits third-party invites requests based on the account the +# - one that ratelimits third-party invites requests based on the account # that's making the requests. # # The defaults are as shown below.