mirror of
https://github.com/telemt/telemt.git
synced 2026-05-22 19:51:43 +03:00
Compare commits
13 Commits
4995e83236
...
658a565cb3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
658a565cb3 | ||
|
|
29fabcb199 | ||
|
|
efdf3bcc1b | ||
|
|
66c37ad6fd | ||
|
|
0fcf67ca34 | ||
|
|
df14762a12 | ||
|
|
b605b1ba7c | ||
|
|
b859fb95c3 | ||
|
|
8c303ab2b6 | ||
|
|
f70c2936c7 | ||
|
|
9ee341a94f | ||
|
|
f76c847c44 | ||
|
|
1aaa9c0bc6 |
@@ -178,6 +178,21 @@ Notes:
|
||||
| `data_quota_bytes` | `u64` | no | Per-user traffic quota. |
|
||||
| `max_unique_ips` | `usize` | no | Per-user unique source IP limit. |
|
||||
|
||||
### `access.user_source_deny` via API
|
||||
- In current API surface, per-user deny-list is **not** exposed as a dedicated field in `CreateUserRequest` / `PatchUserRequest`.
|
||||
- Configure it in `config.toml` under `[access.user_source_deny]` and apply via normal config reload path.
|
||||
- Runtime behavior after apply:
|
||||
- auth succeeds for username/secret
|
||||
- source IP is checked against `access.user_source_deny[username]`
|
||||
- on match, handshake is rejected with the same fail-closed outcome as invalid auth
|
||||
|
||||
Example config:
|
||||
```toml
|
||||
[access.user_source_deny]
|
||||
alice = ["203.0.113.0/24", "2001:db8:abcd::/48"]
|
||||
bob = ["198.51.100.42/32"]
|
||||
```
|
||||
|
||||
### `RotateSecretRequest`
|
||||
| Field | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
|
||||
@@ -162,6 +162,8 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||
| [`log_level`](#log_level) | `"debug"`, `"verbose"`, `"normal"`, or `"silent"` | `"normal"` |
|
||||
| [`disable_colors`](#disable_colors) | `bool` | `false` |
|
||||
| [`me_socks_kdf_policy`](#me_socks_kdf_policy) | `"strict"` or `"compat"` | `"strict"` |
|
||||
| [`me_route_backpressure_enabled`](#me_route_backpressure_enabled) | `bool` | `false` |
|
||||
| [`me_route_fairshare_enabled`](#me_route_fairshare_enabled) | `bool` | `false` |
|
||||
| [`me_route_backpressure_base_timeout_ms`](#me_route_backpressure_base_timeout_ms) | `u64` | `25` |
|
||||
| [`me_route_backpressure_high_timeout_ms`](#me_route_backpressure_high_timeout_ms) | `u64` | `120` |
|
||||
| [`me_route_backpressure_high_watermark_pct`](#me_route_backpressure_high_watermark_pct) | `u8` | `80` |
|
||||
@@ -975,6 +977,24 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||
[general]
|
||||
me_socks_kdf_policy = "strict"
|
||||
```
|
||||
## me_route_backpressure_enabled
|
||||
- **Constraints / validation**: `bool`.
|
||||
- **Description**: Enables channel-pressure-aware route send timeouts.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[general]
|
||||
me_route_backpressure_enabled = false
|
||||
```
|
||||
## me_route_fairshare_enabled
|
||||
- **Constraints / validation**: `bool`.
|
||||
- **Description**: Enables fair-share routing admission across writer workers.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[general]
|
||||
me_route_fairshare_enabled = false
|
||||
```
|
||||
## me_route_backpressure_base_timeout_ms
|
||||
- **Constraints / validation**: Must be within `1..=5000` (milliseconds).
|
||||
- **Description**: Base backpressure timeout in milliseconds for ME route-channel send.
|
||||
@@ -1753,6 +1773,7 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||
| [`metrics_whitelist`](#metrics_whitelist) | `IpNetwork[]` | `["127.0.0.1/32", "::1/128"]` |
|
||||
| [`max_connections`](#max_connections) | `u32` | `10000` |
|
||||
| [`accept_permit_timeout_ms`](#accept_permit_timeout_ms) | `u64` | `250` |
|
||||
| [`listen_backlog`](#listen_backlog) | `u32` | `1024` |
|
||||
|
||||
## port
|
||||
- **Constraints / validation**: `u16`.
|
||||
@@ -1763,6 +1784,15 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||
[server]
|
||||
port = 443
|
||||
```
|
||||
## listen_backlog
|
||||
- **Constraints / validation**: `u32`. `0` uses the OS default backlog behavior.
|
||||
- **Description**: Listen backlog passed to `listen(2)` for TCP sockets.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[server]
|
||||
listen_backlog = 1024
|
||||
```
|
||||
## listen_addr_ipv4
|
||||
- **Constraints / validation**: `String` (optional). When set, must be a valid IPv4 address string.
|
||||
- **Description**: IPv4 bind address for TCP listener (omit this key to disable IPv4 bind).
|
||||
@@ -2005,6 +2035,7 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
|
||||
| [`runtime_edge_top_n`](#runtime_edge_top_n) | `usize` | `10` |
|
||||
| [`runtime_edge_events_capacity`](#runtime_edge_events_capacity) | `usize` | `256` |
|
||||
| [`read_only`](#read_only) | `bool` | `false` |
|
||||
| [`gray_action`](#gray_action) | `"drop"`, `"api"`, or `"200"` | `"drop"` |
|
||||
|
||||
## enabled
|
||||
- **Constraints / validation**: `bool`.
|
||||
@@ -2015,6 +2046,15 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
|
||||
[server.api]
|
||||
enabled = true
|
||||
```
|
||||
## gray_action
|
||||
- **Constraints / validation**: `"drop"`, `"api"`, or `"200"`.
|
||||
- **Description**: API response policy for gray/limited states: drop request, serve normal API response, or force `200 OK`.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[server.api]
|
||||
gray_action = "drop"
|
||||
```
|
||||
## listen
|
||||
- **Constraints / validation**: `String`. Must be in `IP:PORT` format.
|
||||
- **Description**: API bind address in `IP:PORT` format.
|
||||
@@ -2207,6 +2247,15 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
|
||||
[timeouts]
|
||||
client_handshake = 30
|
||||
```
|
||||
## client_first_byte_idle_secs
|
||||
- **Constraints / validation**: `u64` (seconds). `0` disables first-byte idle enforcement.
|
||||
- **Description**: Maximum idle time to wait for the first client payload byte after session setup.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[timeouts]
|
||||
client_first_byte_idle_secs = 300
|
||||
```
|
||||
## relay_idle_policy_v2_enabled
|
||||
- **Constraints / validation**: `bool`.
|
||||
- **Description**: Enables soft/hard middle-relay client idle policy.
|
||||
@@ -2311,6 +2360,7 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
|
||||
| [`server_hello_delay_max_ms`](#server_hello_delay_max_ms) | `u64` | `0` |
|
||||
| [`tls_new_session_tickets`](#tls_new_session_tickets) | `u8` | `0` |
|
||||
| [`tls_full_cert_ttl_secs`](#tls_full_cert_ttl_secs) | `u64` | `90` |
|
||||
| [`serverhello_compact`](#serverhello_compact) | `bool` | `false` |
|
||||
| [`alpn_enforce`](#alpn_enforce) | `bool` | `true` |
|
||||
| [`mask_proxy_protocol`](#mask_proxy_protocol) | `u8` | `0` |
|
||||
| [`mask_shape_hardening`](#mask_shape_hardening) | `bool` | `true` |
|
||||
@@ -2488,6 +2538,15 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
|
||||
[censorship]
|
||||
tls_full_cert_ttl_secs = 90
|
||||
```
|
||||
## serverhello_compact
|
||||
- **Constraints / validation**: `bool`.
|
||||
- **Description**: Enables compact ServerHello/Fake-TLS profile to reduce response-size signature.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[censorship]
|
||||
serverhello_compact = false
|
||||
```
|
||||
## alpn_enforce
|
||||
- **Constraints / validation**: `bool`.
|
||||
- **Description**: Enforces ALPN echo behavior based on client preference.
|
||||
@@ -2827,9 +2886,12 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p
|
||||
| [`user_max_unique_ips_global_each`](#user_max_unique_ips_global_each) | `usize` | `0` |
|
||||
| [`user_max_unique_ips_mode`](#user_max_unique_ips_mode) | `"active_window"`, `"time_window"`, or `"combined"` | `"active_window"` |
|
||||
| [`user_max_unique_ips_window_secs`](#user_max_unique_ips_window_secs) | `u64` | `30` |
|
||||
| [`user_source_deny`](#user_source_deny) | `Map<String, IpNetwork[]>` | `{}` |
|
||||
| [`replay_check_len`](#replay_check_len) | `usize` | `65536` |
|
||||
| [`replay_window_secs`](#replay_window_secs) | `u64` | `120` |
|
||||
| [`ignore_time_skew`](#ignore_time_skew) | `bool` | `false` |
|
||||
| [`user_rate_limits`](#user_rate_limits) | `Map<String, RateLimitBps>` | `{}` |
|
||||
| [`cidr_rate_limits`](#cidr_rate_limits) | `Map<IpNetwork, RateLimitBps>` | `{}` |
|
||||
|
||||
## users
|
||||
- **Constraints / validation**: Must not be empty (at least one user must exist). Each value must be **exactly 32 hex characters**.
|
||||
@@ -2929,6 +2991,20 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p
|
||||
[access]
|
||||
user_max_unique_ips_window_secs = 30
|
||||
```
|
||||
## user_source_deny
|
||||
- **Constraints / validation**: Table `username -> IpNetwork[]`. Each network must parse as CIDR (for example `203.0.113.0/24` or `2001:db8::/32`).
|
||||
- **Description**: Per-user source IP/CIDR deny-list applied **after successful auth** in TLS and MTProto handshake paths. A matched source IP is rejected via the same fail-closed path as invalid auth.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[access.user_source_deny]
|
||||
alice = ["203.0.113.0/24", "2001:db8:abcd::/48"]
|
||||
bob = ["198.51.100.42/32"]
|
||||
```
|
||||
|
||||
- **How it works (quick check)**:
|
||||
- connection from user `alice` and source `203.0.113.55` -> rejected (matches `203.0.113.0/24`)
|
||||
- connection from user `alice` and source `198.51.100.10` -> allowed by this rule set (no match)
|
||||
## replay_check_len
|
||||
- **Constraints / validation**: `usize`.
|
||||
- **Description**: Replay-protection storage length (number of entries tracked for duplicate detection).
|
||||
@@ -2958,6 +3034,24 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p
|
||||
```
|
||||
|
||||
|
||||
## user_rate_limits
|
||||
- **Constraints / validation**: Table `username -> { up_bps, down_bps }`. At least one direction must be non-zero.
|
||||
- **Description**: Per-user bandwidth caps in bytes/sec for upload (`up_bps`) and download (`down_bps`).
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[access.user_rate_limits]
|
||||
alice = { up_bps = 1048576, down_bps = 2097152 }
|
||||
```
|
||||
## cidr_rate_limits
|
||||
- **Constraints / validation**: Table `CIDR -> { up_bps, down_bps }`. CIDR must parse as `IpNetwork`; at least one direction must be non-zero.
|
||||
- **Description**: Source-subnet bandwidth caps applied alongside per-user limits.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[access.cidr_rate_limits]
|
||||
"203.0.113.0/24" = { up_bps = 0, down_bps = 1048576 }
|
||||
```
|
||||
# [[upstreams]]
|
||||
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@
|
||||
| [`log_level`](#log_level) | `"debug"`, `"verbose"`, `"normal"`, or `"silent"` | `"normal"` |
|
||||
| [`disable_colors`](#disable_colors) | `bool` | `false` |
|
||||
| [`me_socks_kdf_policy`](#me_socks_kdf_policy) | `"strict"` or `"compat"` | `"strict"` |
|
||||
| [`me_route_backpressure_enabled`](#me_route_backpressure_enabled) | `bool` | `false` |
|
||||
| [`me_route_fairshare_enabled`](#me_route_fairshare_enabled) | `bool` | `false` |
|
||||
| [`me_route_backpressure_base_timeout_ms`](#me_route_backpressure_base_timeout_ms) | `u64` | `25` |
|
||||
| [`me_route_backpressure_high_timeout_ms`](#me_route_backpressure_high_timeout_ms) | `u64` | `120` |
|
||||
| [`me_route_backpressure_high_watermark_pct`](#me_route_backpressure_high_watermark_pct) | `u8` | `80` |
|
||||
@@ -975,6 +977,24 @@
|
||||
[general]
|
||||
me_socks_kdf_policy = "strict"
|
||||
```
|
||||
## me_route_backpressure_enabled
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
- **Описание**: Включает адаптивные таймауты записи маршрута в зависимости от заполнения канала.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[general]
|
||||
me_route_backpressure_enabled = false
|
||||
```
|
||||
## me_route_fairshare_enabled
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
- **Описание**: Включает справедливое распределение нагрузки маршрутизации между writer-потоками.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[general]
|
||||
me_route_fairshare_enabled = false
|
||||
```
|
||||
## me_route_backpressure_base_timeout_ms
|
||||
- **Ограничения / валидация**: Должно быть в пределах `1..=5000` (миллисекунд).
|
||||
- **Описание**: Базовый таймаут (в миллисекундах) ожидания при режиме **backpressure** (ситуация, при которой данные обрабатываются медленне, чем получаются) для отправки через ME route-channel.
|
||||
@@ -1755,6 +1775,7 @@
|
||||
| [`metrics_whitelist`](#metrics_whitelist) | `IpNetwork[]` | `["127.0.0.1/32", "::1/128"]` |
|
||||
| [`max_connections`](#max_connections) | `u32` | `10000` |
|
||||
| [`accept_permit_timeout_ms`](#accept_permit_timeout_ms) | `u64` | `250` |
|
||||
| [`listen_backlog`](#listen_backlog) | `u32` | `1024` |
|
||||
|
||||
## port
|
||||
- **Ограничения / валидация**: `u16`.
|
||||
@@ -1765,6 +1786,15 @@
|
||||
[server]
|
||||
port = 443
|
||||
```
|
||||
## listen_backlog
|
||||
- **Ограничения / валидация**: `u32`. `0` использует системный backlog по умолчанию.
|
||||
- **Описание**: Значение backlog, передаваемое в `listen(2)` для TCP-сокетов.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[server]
|
||||
listen_backlog = 1024
|
||||
```
|
||||
## listen_addr_ipv4
|
||||
- **Ограничения / валидация**: `String` (необязательный параметр). Если задан, должен содержать валидный IPv4-адрес в формате строки.
|
||||
- **Описание**: Прослушиваемый адрес в формате IPv4 (не задавайте этот параметр, если необходимо отключить прослушивание по IPv4).
|
||||
@@ -2011,6 +2041,7 @@
|
||||
| [`runtime_edge_top_n`](#runtime_edge_top_n) | `usize` | `10` |
|
||||
| [`runtime_edge_events_capacity`](#runtime_edge_events_capacity) | `usize` | `256` |
|
||||
| [`read_only`](#read_only) | `bool` | `false` |
|
||||
| [`gray_action`](#gray_action) | `"drop"`, `"api"`, or `"200"` | `"drop"` |
|
||||
|
||||
## enabled
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
@@ -2021,6 +2052,15 @@
|
||||
[server.api]
|
||||
enabled = true
|
||||
```
|
||||
## gray_action
|
||||
- **Ограничения / валидация**: `"drop"`, `"api"` или `"200"`.
|
||||
- **Описание**: Политика ответа API в «серых» (ограниченных) состояниях: сброс, обычный API-ответ, либо `200 OK`.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[server.api]
|
||||
gray_action = "drop"
|
||||
```
|
||||
## listen
|
||||
- **Ограничения / валидация**: `String`. Должно быть в формате `IP:PORT`.
|
||||
- **Описание**: Адрес биндинга API в формате `IP:PORT`.
|
||||
@@ -2213,6 +2253,15 @@
|
||||
[timeouts]
|
||||
client_handshake = 30
|
||||
```
|
||||
## client_first_byte_idle_secs
|
||||
- **Ограничения / валидация**: `u64` (секунды). `0` отключает проверку простоя до первого байта.
|
||||
- **Описание**: Максимальное время ожидания первого байта полезной нагрузки от клиента после установления сессии.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[timeouts]
|
||||
client_first_byte_idle_secs = 300
|
||||
```
|
||||
## relay_idle_policy_v2_enabled
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
- **Описание**: Включает политику простоя клиента для промежуточного узла.
|
||||
@@ -2317,6 +2366,7 @@
|
||||
| [`server_hello_delay_max_ms`](#server_hello_delay_max_ms) | `u64` | `0` |
|
||||
| [`tls_new_session_tickets`](#tls_new_session_tickets) | `u8` | `0` |
|
||||
| [`tls_full_cert_ttl_secs`](#tls_full_cert_ttl_secs) | `u64` | `90` |
|
||||
| [`serverhello_compact`](#serverhello_compact) | `bool` | `false` |
|
||||
| [`alpn_enforce`](#alpn_enforce) | `bool` | `true` |
|
||||
| [`mask_proxy_protocol`](#mask_proxy_protocol) | `u8` | `0` |
|
||||
| [`mask_shape_hardening`](#mask_shape_hardening) | `bool` | `true` |
|
||||
@@ -2493,6 +2543,15 @@
|
||||
[censorship]
|
||||
tls_full_cert_ttl_secs = 90
|
||||
```
|
||||
## serverhello_compact
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
- **Описание**: Включает компактный профиль ServerHello/Fake-TLS для снижения сигнатуры размера ответа.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[censorship]
|
||||
serverhello_compact = false
|
||||
```
|
||||
## alpn_enforce
|
||||
- **Ограничения / валидация**: `bool`.
|
||||
- **Описание**: Принудительно изменяет поведение возврата ALPN в соответствии с предпочтениями клиента.
|
||||
@@ -2837,6 +2896,8 @@
|
||||
| [`replay_check_len`](#replay_check_len) | `usize` | `65536` |
|
||||
| [`replay_window_secs`](#replay_window_secs) | `u64` | `120` |
|
||||
| [`ignore_time_skew`](#ignore_time_skew) | `bool` | `false` |
|
||||
| [`user_rate_limits`](#user_rate_limits) | `Map<String, RateLimitBps>` | `{}` |
|
||||
| [`cidr_rate_limits`](#cidr_rate_limits) | `Map<IpNetwork, RateLimitBps>` | `{}` |
|
||||
|
||||
## users
|
||||
- **Ограничения / валидация**: Не должно быть пустым (должен существовать хотя бы один пользователь). Каждое значение должно состоять **ровно из 32 шестнадцатеричных символов**.
|
||||
@@ -2965,6 +3026,24 @@
|
||||
```
|
||||
|
||||
|
||||
## user_rate_limits
|
||||
- **Ограничения / валидация**: Таблица `username -> { up_bps, down_bps }`. Должно быть ненулевое значение хотя бы в одном направлении.
|
||||
- **Описание**: Персональные лимиты скорости по пользователям в байтах/сек для отправки (`up_bps`) и получения (`down_bps`).
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[access.user_rate_limits]
|
||||
alice = { up_bps = 1048576, down_bps = 2097152 }
|
||||
```
|
||||
## cidr_rate_limits
|
||||
- **Ограничения / валидация**: Таблица `CIDR -> { up_bps, down_bps }`. CIDR должен корректно разбираться как `IpNetwork`; хотя бы одно направление должно быть ненулевым.
|
||||
- **Описание**: Лимиты скорости для подсетей источников, применяются поверх пользовательских ограничений.
|
||||
- **Example**:
|
||||
|
||||
```toml
|
||||
[access.cidr_rate_limits]
|
||||
"203.0.113.0/24" = { up_bps = 0, down_bps = 1048576 }
|
||||
```
|
||||
# [[upstreams]]
|
||||
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ tls_front_dir = "tlsfront" # Директория кэша для эмуляц
|
||||
hello = "00000000000000000000000000000000"
|
||||
```
|
||||
|
||||
Затем нажмите Ctrl+S -> Ctrl+X, чтобы сохранить
|
||||
Затем нажмите Ctrl+O -> Ctrl+X, чтобы сохранить
|
||||
|
||||
> [!WARNING]
|
||||
> Замените значение параметра `hello` на значение, которое вы получили в пункте 0.
|
||||
|
||||
@@ -102,6 +102,7 @@ set_language() {
|
||||
L_OUT_SUCC_H="УСТАНОВКА УСПЕШНО ЗАВЕРШЕНА"
|
||||
L_OUT_UNINST_H="УДАЛЕНИЕ ЗАВЕРШЕНО"
|
||||
L_OUT_LINK="Ваша ссылка для подключения к Telegram Proxy:\n"
|
||||
L_ERR_INCORR_ROOT_LOGIN="Используйте 'su -' или 'sudo -i' для входа под пользователем root"
|
||||
;;
|
||||
*)
|
||||
L_ERR_DOMAIN_REQ="requires a domain argument."
|
||||
@@ -176,6 +177,7 @@ set_language() {
|
||||
L_OUT_SUCC_H="INSTALLATION SUCCESS"
|
||||
L_OUT_UNINST_H="UNINSTALLATION COMPLETE"
|
||||
L_OUT_LINK="Your Telegram Proxy connection link:\n"
|
||||
L_ERR_INCORR_ROOT_LOGIN="Use 'su -' or 'sudo -i' to login under root"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -388,6 +390,9 @@ verify_common() {
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
SUDO=""
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
die "$L_ERR_INCORR_ROOT_LOGIN"
|
||||
fi
|
||||
else
|
||||
command -v sudo >/dev/null 2>&1 || die "$L_ERR_ROOT"
|
||||
SUDO="sudo"
|
||||
|
||||
@@ -1893,6 +1893,12 @@ pub struct AccessConfig {
|
||||
#[serde(default)]
|
||||
pub cidr_rate_limits: HashMap<IpNetwork, RateLimitBps>,
|
||||
|
||||
/// Per-username client source IP/CIDR deny list. Checked after successful
|
||||
/// authentication; matching IPs get the same rejection path as invalid auth
|
||||
/// (handshake fails closed for that connection).
|
||||
#[serde(default)]
|
||||
pub user_source_deny: HashMap<String, Vec<IpNetwork>>,
|
||||
|
||||
#[serde(default)]
|
||||
pub user_max_unique_ips: HashMap<String, usize>,
|
||||
|
||||
@@ -1928,6 +1934,7 @@ impl Default for AccessConfig {
|
||||
user_data_quota: HashMap::new(),
|
||||
user_rate_limits: HashMap::new(),
|
||||
cidr_rate_limits: HashMap::new(),
|
||||
user_source_deny: HashMap::new(),
|
||||
user_max_unique_ips: HashMap::new(),
|
||||
user_max_unique_ips_global_each: default_user_max_unique_ips_global_each(),
|
||||
user_max_unique_ips_mode: UserMaxUniqueIpsMode::default(),
|
||||
@@ -1939,6 +1946,15 @@ impl Default for AccessConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl AccessConfig {
|
||||
/// Returns true if `ip` is contained in any CIDR listed for `username` under `user_source_deny`.
|
||||
pub fn is_user_source_ip_denied(&self, username: &str, ip: IpAddr) -> bool {
|
||||
self.user_source_deny
|
||||
.get(username)
|
||||
.is_some_and(|nets| nets.iter().any(|n| n.contains(ip)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RateLimitBps {
|
||||
#[serde(default)]
|
||||
|
||||
@@ -1450,6 +1450,20 @@ where
|
||||
validated_secret.copy_from_slice(secret);
|
||||
}
|
||||
|
||||
if config
|
||||
.access
|
||||
.is_user_source_ip_denied(validated_user.as_str(), peer.ip())
|
||||
{
|
||||
auth_probe_record_failure_in(shared, peer.ip(), Instant::now());
|
||||
maybe_apply_server_hello_delay(config).await;
|
||||
warn!(
|
||||
peer = %peer,
|
||||
user = %validated_user,
|
||||
"TLS handshake rejected: client source IP on per-user deny list (access.user_source_deny)"
|
||||
);
|
||||
return HandshakeResult::BadClient { reader, writer };
|
||||
}
|
||||
|
||||
// Reject known replay digests before expensive cache/domain/ALPN policy work.
|
||||
let digest_half = &validation_digest[..tls::TLS_DIGEST_HALF_LEN];
|
||||
if replay_checker.check_tls_digest(digest_half) {
|
||||
@@ -1795,6 +1809,20 @@ where
|
||||
|
||||
let validation = matched_validation.expect("validation must exist when matched");
|
||||
|
||||
if config
|
||||
.access
|
||||
.is_user_source_ip_denied(matched_user.as_str(), peer.ip())
|
||||
{
|
||||
auth_probe_record_failure_in(shared, peer.ip(), Instant::now());
|
||||
maybe_apply_server_hello_delay(config).await;
|
||||
warn!(
|
||||
peer = %peer,
|
||||
user = %matched_user,
|
||||
"MTProto handshake rejected: client source IP on per-user deny list (access.user_source_deny)"
|
||||
);
|
||||
return HandshakeResult::BadClient { reader, writer };
|
||||
}
|
||||
|
||||
// Apply replay tracking only after successful authentication.
|
||||
//
|
||||
// This ordering prevents an attacker from producing invalid handshakes that
|
||||
@@ -1873,6 +1901,17 @@ where
|
||||
.auth_expensive_checks_total
|
||||
.fetch_add(validation_checks as u64, Ordering::Relaxed);
|
||||
|
||||
if config.access.is_user_source_ip_denied(user.as_str(), peer.ip()) {
|
||||
auth_probe_record_failure_in(shared, peer.ip(), Instant::now());
|
||||
maybe_apply_server_hello_delay(config).await;
|
||||
warn!(
|
||||
peer = %peer,
|
||||
user = %user,
|
||||
"MTProto handshake rejected: client source IP on per-user deny list (access.user_source_deny)"
|
||||
);
|
||||
return HandshakeResult::BadClient { reader, writer };
|
||||
}
|
||||
|
||||
// Apply replay tracking only after successful authentication.
|
||||
//
|
||||
// This ordering prevents an attacker from producing invalid handshakes that
|
||||
|
||||
Reference in New Issue
Block a user