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:
parent
0db5d247f8
commit
aed1b1e05a
4 changed files with 40 additions and 2 deletions
1
changelog.d/18000.bugfix
Normal file
1
changelog.d/18000.bugfix
Normal file
|
@ -0,0 +1 @@
|
|||
Add ratelimit `rc_set_presence.per_user` to prevent load from excessive presence updates sent by clients. Contributed by @rda0.
|
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
)
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Add table
Reference in a new issue