Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 479fc9d

Browse files
committed
Merge commit '394be6a0e' into anoa/dinsic_release_1_21_x
* commit '394be6a0e': Newsfile Add ratelimiting on joins Add docs for undoing room shutdowns (#7998)
2 parents ed31392 + 394be6a commit 479fc9d

File tree

8 files changed

+97
-3
lines changed

8 files changed

+97
-3
lines changed

changelog.d/7998.doc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add documentation for how to undo a room shutdown.

changelog.d/8008.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add rate limiting to users joining rooms.

docs/admin_api/shutdown_room.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ You will need to authenticate with an access token for an admin user.
3333
* `message` - Optional. A string containing the first message that will be sent as
3434
`new_room_user_id` in the new room. Ideally this will clearly convey why the
3535
original room was shut down.
36-
36+
3737
If not specified, the default value of `room_name` is "Content Violation
3838
Notification". The default value of `message` is "Sharing illegal content on
3939
othis server is not permitted and rooms in violation will be blocked."
@@ -72,3 +72,23 @@ Response:
7272
"new_room_id": "!newroomid:example.com",
7373
},
7474
```
75+
76+
## Undoing room shutdowns
77+
78+
*Note*: This guide may be outdated by the time you read it. By nature of room shutdowns being performed at the database level,
79+
the structure can and does change without notice.
80+
81+
First, it's important to understand that a room shutdown is very destructive. Undoing a shutdown is not as simple as pretending it
82+
never happened - work has to be done to move forward instead of resetting the past.
83+
84+
1. For safety reasons, it is recommended to shut down Synapse prior to continuing.
85+
2. In the database, run `DELETE FROM blocked_rooms WHERE room_id = '!example:example.org';`
86+
* For caution: it's recommended to run this in a transaction: `BEGIN; DELETE ...;`, verify you got 1 result, then `COMMIT;`.
87+
* The room ID is the same one supplied to the shutdown room API, not the Content Violation room.
88+
3. Restart Synapse (required).
89+
90+
You will have to manually handle, if you so choose, the following:
91+
92+
* Aliases that would have been redirected to the Content Violation room.
93+
* Users that would have been booted from the room (and will have been force-joined to the Content Violation room).
94+
* Removal of the Content Violation room if desired.

docs/sample_config.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,10 @@ log_config: "CONFDIR/SERVERNAME.log.config"
746746
# - one for ratelimiting redactions by room admins. If this is not explicitly
747747
# set then it uses the same ratelimiting as per rc_message. This is useful
748748
# to allow room admins to deal with abuse quickly.
749+
# - two for ratelimiting number of rooms a user can join, "local" for when
750+
# users are joining rooms the server is already in (this is cheap) vs
751+
# "remote" for when users are trying to join rooms not on the server (which
752+
# can be more expensive)
749753
#
750754
# The defaults are as shown below.
751755
#
@@ -771,6 +775,14 @@ log_config: "CONFDIR/SERVERNAME.log.config"
771775
#rc_admin_redaction:
772776
# per_second: 1
773777
# burst_count: 50
778+
#
779+
#rc_joins:
780+
# local:
781+
# per_second: 0.1
782+
# burst_count: 3
783+
# remote:
784+
# per_second: 0.01
785+
# burst_count: 3
774786

775787

776788
# Ratelimiting settings for incoming federation

synapse/config/ratelimiting.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,15 @@ def read_config(self, config, **kwargs):
9696
if rc_admin_redaction:
9797
self.rc_admin_redaction = RateLimitConfig(rc_admin_redaction)
9898

99+
self.rc_joins_local = RateLimitConfig(
100+
config.get("rc_joins", {}).get("local", {}),
101+
defaults={"per_second": 0.1, "burst_count": 3},
102+
)
103+
self.rc_joins_remote = RateLimitConfig(
104+
config.get("rc_joins", {}).get("remote", {}),
105+
defaults={"per_second": 0.01, "burst_count": 3},
106+
)
107+
99108
def generate_config_section(self, **kwargs):
100109
return """\
101110
## Ratelimiting ##
@@ -123,6 +132,10 @@ def generate_config_section(self, **kwargs):
123132
# - one for ratelimiting redactions by room admins. If this is not explicitly
124133
# set then it uses the same ratelimiting as per rc_message. This is useful
125134
# to allow room admins to deal with abuse quickly.
135+
# - two for ratelimiting number of rooms a user can join, "local" for when
136+
# users are joining rooms the server is already in (this is cheap) vs
137+
# "remote" for when users are trying to join rooms not on the server (which
138+
# can be more expensive)
126139
#
127140
# The defaults are as shown below.
128141
#
@@ -152,6 +165,14 @@ def generate_config_section(self, **kwargs):
152165
#rc_admin_redaction:
153166
# per_second: 1
154167
# burst_count: 50
168+
#
169+
#rc_joins:
170+
# local:
171+
# per_second: 0.1
172+
# burst_count: 3
173+
# remote:
174+
# per_second: 0.01
175+
# burst_count: 3
155176
156177
157178
# Ratelimiting settings for incoming federation

synapse/handlers/room_member.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
from synapse import types
2424
from synapse.api.constants import MAX_DEPTH, EventTypes, Membership
25-
from synapse.api.errors import AuthError, Codes, SynapseError
25+
from synapse.api.errors import AuthError, Codes, LimitExceededError, SynapseError
26+
from synapse.api.ratelimiting import Ratelimiter
2627
from synapse.api.room_versions import EventFormatVersions
2728
from synapse.crypto.event_signing import compute_event_reference_hash
2829
from synapse.events import EventBase
@@ -78,6 +79,17 @@ def __init__(self, hs):
7879
if self._is_on_event_persistence_instance:
7980
self.persist_event_storage = hs.get_storage().persistence
8081

82+
self._join_rate_limiter_local = Ratelimiter(
83+
clock=self.clock,
84+
rate_hz=hs.config.ratelimiting.rc_joins_local.per_second,
85+
burst_count=hs.config.ratelimiting.rc_joins_local.burst_count,
86+
)
87+
self._join_rate_limiter_remote = Ratelimiter(
88+
clock=self.clock,
89+
rate_hz=hs.config.ratelimiting.rc_joins_remote.per_second,
90+
burst_count=hs.config.ratelimiting.rc_joins_remote.burst_count,
91+
)
92+
8193
# This is only used to get at ratelimit function, and
8294
# maybe_kick_guest_users. It's fine there are multiple of these as
8395
# it doesn't store state.
@@ -472,7 +484,28 @@ async def _update_membership(
472484
):
473485
raise SynapseError(403, "Not allowed to join this room")
474486

475-
if not is_host_in_room:
487+
if is_host_in_room:
488+
time_now_s = self.clock.time()
489+
allowed, time_allowed = self._join_rate_limiter_local.can_do_action(
490+
requester.user.to_string(),
491+
)
492+
493+
if not allowed:
494+
raise LimitExceededError(
495+
retry_after_ms=int(1000 * (time_allowed - time_now_s))
496+
)
497+
498+
else:
499+
time_now_s = self.clock.time()
500+
allowed, time_allowed = self._join_rate_limiter_remote.can_do_action(
501+
requester.user.to_string(),
502+
)
503+
504+
if not allowed:
505+
raise LimitExceededError(
506+
retry_after_ms=int(1000 * (time_allowed - time_now_s))
507+
)
508+
476509
inviter = await self._get_inviter(target.to_string(), room_id)
477510
if inviter and not self.hs.is_mine(inviter):
478511
remote_room_hosts.append(inviter.domain)

synapse/storage/data_stores/main/room.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
from canonicaljson import json
2525

26+
from twisted.internet import defer
27+
2628
from synapse.api.constants import EventTypes
2729
from synapse.api.errors import StoreError
2830
from synapse.api.room_versions import RoomVersion, RoomVersions

tests/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def default_config(name, parse=False):
154154
"account": {"per_second": 10000, "burst_count": 10000},
155155
"failed_attempts": {"per_second": 10000, "burst_count": 10000},
156156
},
157+
"rc_joins": {
158+
"local": {"per_second": 10000, "burst_count": 10000},
159+
"remote": {"per_second": 10000, "burst_count": 10000},
160+
},
157161
"saml2_enabled": False,
158162
"public_baseurl": None,
159163
"default_identity_server": None,

0 commit comments

Comments
 (0)