1
0
Fork 0
mirror of https://github.com/element-hq/synapse.git synced 2025-03-05 07:26:52 +00:00

Ratelimit set_presence updates

This commit is contained in:
Sven Mäder 2024-12-04 20:18:53 +01:00
parent 0db5d247f8
commit aed1b1e05a
4 changed files with 40 additions and 2 deletions

1
changelog.d/18000.bugfix Normal file
View file

@ -0,0 +1 @@
Add ratelimit `rc_set_presence.per_user` to prevent load from excessive presence updates sent by clients. Contributed by @rda0.

View file

@ -1866,6 +1866,22 @@ rc_federation:
concurrent: 5
```
---
### `rc_set_presence`
This option sets ratelimiting for presence.
The `rc_set_presence.per_user` sets ratelimiting how often a specific users' presence
updates are evaluated. Ratelimited presence updates are ignored.
`per_user` defaults to `per_second: 0.1`, `burst_count: 1`.
Example configuration:
```yaml
rc_set_presence:
per_user:
per_second: 0.1
burst_count: 1
```
---
### `federation_rr_transactions_per_room_per_second`
Sets outgoing federation transaction frequency for sending read-receipts,

View file

@ -228,3 +228,9 @@ class RatelimitConfig(Config):
config.get("remote_media_download_burst_count", "500M")
),
)
self.rc_set_presence_per_user = RatelimitSettings.parse(
config,
"rc_set_presence.per_user",
defaults={"per_second": 0.1, "burst_count": 1},
)

View file

@ -24,9 +24,10 @@ from collections import defaultdict
from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, Union
from synapse.api.constants import AccountDataTypes, EduTypes, Membership, PresenceState
from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.api.errors import Codes, LimitExceededError, StoreError, SynapseError
from synapse.api.filtering import FilterCollection
from synapse.api.presence import UserPresenceState
from synapse.api.ratelimiting import Ratelimiter
from synapse.events.utils import (
SerializeEventConfig,
format_event_for_client_v2_without_room_id,
@ -126,6 +127,13 @@ class SyncRestServlet(RestServlet):
cache_name="sync_valid_filter",
)
# Ratelimiter for set_presence updates, keyed by requester.
self._set_presence_per_user_limiter = Ratelimiter(
store=self.store,
clock=self.clock,
cfg=hs.config.ratelimiting.rc_set_presence_per_user,
)
async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
# This will always be set by the time Twisted calls us.
assert request.args is not None
@ -239,7 +247,14 @@ class SyncRestServlet(RestServlet):
# send any outstanding server notices to the user.
await self._server_notices_sender.on_user_syncing(user.to_string())
affect_presence = set_presence != PresenceState.OFFLINE
# ignore the presence update if the ratelimit is exceeded
try:
await self._set_presence_per_user_limiter.ratelimit(requester)
except LimitExceededError:
affect_presence = False
logger.debug("User set_presence ratelimit exceeded; ignoring it.")
else:
affect_presence = set_presence != PresenceState.OFFLINE
context = await self.presence_handler.user_syncing(
user.to_string(),