1
0

Add rate limit conf to user directory endpoint (#19291)

The goal is to avoid that an user could scrape the user directory too
quickly.
This commit is contained in:
Mathieu Velten
2026-01-05 20:35:11 +01:00
committed by GitHub
parent 6b755f964b
commit 444bc56cda
7 changed files with 55 additions and 0 deletions

1
changelog.d/19291.misc Normal file
View File

@@ -0,0 +1 @@
Add a config to be able to rate limit search in the user directory.

View File

@@ -145,6 +145,12 @@ for port in 8080 8081 8082; do
rc_delayed_event_mgmt:
per_second: 1000
burst_count: 1000
rc_room_creation:
per_second: 1000
burst_count: 1000
rc_user_directory:
per_second: 1000
burst_count: 1000
RC
)
echo "${ratelimiting}" >> "$port.config"

View File

@@ -102,6 +102,10 @@ rc_room_creation:
per_second: 9999
burst_count: 9999
rc_user_directory:
per_second: 9999
burst_count: 9999
federation_rr_transactions_per_room_per_second: 9999
allow_device_name_lookup_over_federation: true

View File

@@ -2041,6 +2041,25 @@ rc_room_creation:
burst_count: 5.0
```
---
### `rc_user_directory`
*(object)* This option allows admins to ratelimit searches in the user directory.
_Added in Synapse 1.145.0._
This setting has the following sub-options:
* `per_second` (number): Maximum number of requests a client can send per second.
* `burst_count` (number): Maximum number of requests a client can send before being throttled.
Default configuration:
```yaml
rc_user_directory:
per_second: 0.016
burst_count: 200.0
```
---
### `federation_rr_transactions_per_room_per_second`
*(integer)* Sets outgoing federation transaction frequency for sending read-receipts, per-room.

View File

@@ -2274,6 +2274,16 @@ properties:
examples:
- per_second: 1.0
burst_count: 5.0
rc_user_directory:
$ref: "#/$defs/rc"
description: >-
This option allows admins to ratelimit searches in the user directory.
_Added in Synapse 1.145.0._
default:
per_second: 0.016
burst_count: 200.0
federation_rr_transactions_per_room_per_second:
type: integer
description: >-

View File

@@ -252,3 +252,9 @@ class RatelimitConfig(Config):
"rc_reports",
defaults={"per_second": 1, "burst_count": 5},
)
self.rc_user_directory = RatelimitSettings.parse(
config,
"rc_user_directory",
defaults={"per_second": 0.016, "burst_count": 200},
)

View File

@@ -23,6 +23,7 @@ import logging
from typing import TYPE_CHECKING
from synapse.api.errors import SynapseError
from synapse.api.ratelimiting import Ratelimiter
from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_json_object_from_request
from synapse.http.site import SynapseRequest
@@ -46,6 +47,12 @@ class UserDirectorySearchRestServlet(RestServlet):
self.auth = hs.get_auth()
self.user_directory_handler = hs.get_user_directory_handler()
self._per_user_limiter = Ratelimiter(
store=hs.get_datastores().main,
clock=hs.get_clock(),
cfg=hs.config.ratelimiting.rc_user_directory,
)
async def on_POST(self, request: SynapseRequest) -> tuple[int, JsonMapping]:
"""Searches for users in directory
@@ -69,6 +76,8 @@ class UserDirectorySearchRestServlet(RestServlet):
if not self.hs.config.userdirectory.user_directory_search_enabled:
return 200, {"limited": False, "results": []}
await self._per_user_limiter.ratelimit(requester)
body = parse_json_object_from_request(request)
limit = int(body.get("limit", 10))