From 5c573a926bd76ffb2cbff92fe37242e04f038338 Mon Sep 17 00:00:00 2001 From: Alexey <247128645+axkurcom@users.noreply.github.com> Date: Mon, 1 Jun 2026 20:03:56 +0300 Subject: [PATCH] Update Docs after Dualstack + Disable User adding Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com> --- docs/Advanced_settings/TUNING.de.md | 3 +++ docs/Advanced_settings/TUNING.en.md | 3 +++ docs/Advanced_settings/TUNING.ru.md | 3 +++ docs/Architecture/API/API.md | 11 +++++++++++ docs/Config_params/CONFIG_PARAMS.en.md | 26 +++++++++++++++++++++++++- docs/Config_params/CONFIG_PARAMS.ru.md | 15 ++++++++++++++- 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/docs/Advanced_settings/TUNING.de.md b/docs/Advanced_settings/TUNING.de.md index 3b0f31d..4ae113e 100644 --- a/docs/Advanced_settings/TUNING.de.md +++ b/docs/Advanced_settings/TUNING.de.md @@ -86,6 +86,9 @@ Die unten angegebenen `Default`-Werte sind Code-Defaults (bei fehlendem Schlüss | `[[upstreams]].weight` | alle Upstreams | `u16` | nein | `1` | Basisgewicht für weighted-random Auswahl. | | `[[upstreams]].enabled` | alle Upstreams | `bool` | nein | `true` | Deaktivierte Einträge werden beim Start ignoriert. | | `[[upstreams]].scopes` | alle Upstreams | `String` | nein | `""` | Komma-separierte Scope-Tags für Request-Routing. | +| `[[upstreams]].ipv4` | alle Upstreams | `Option` | nein | `auto` | Erlaubt IPv4-DC-Ziele für diesen Upstream. | +| `[[upstreams]].ipv6` | alle Upstreams | `Option` | nein | `auto` | Erlaubt IPv6-DC-Ziele für diesen Upstream, inklusive Proxy-Egress unabhängig vom Host-IPv6. | +| `[[upstreams]].prefer` | alle Upstreams | `Option<4 \| 6>` | nein | effective `[network].prefer` | Pro-Upstream-Präferenz für die DC-Ziel-Adressfamilie. | | `interface` | `direct` | `Option` | nein | `null` | Interface-Name (z. B. `eth0`) oder lokale Literal-IP. | | `bind_addresses` | `direct` | `Option>` | nein | `null` | Explizite Source-IP-Kandidaten (strikter Vorrang vor `interface`). | | `address` | `socks4` | `String` | ja | n/a | SOCKS4-Server (`ip:port` oder `host:port`). | diff --git a/docs/Advanced_settings/TUNING.en.md b/docs/Advanced_settings/TUNING.en.md index 6a6a320..e9d705a 100644 --- a/docs/Advanced_settings/TUNING.en.md +++ b/docs/Advanced_settings/TUNING.en.md @@ -86,6 +86,9 @@ Defaults below are code defaults (used when a key is omitted), not necessarily v | `[[upstreams]].weight` | all upstreams | `u16` | no | `1` | Base weight for weighted-random selection. | | `[[upstreams]].enabled` | all upstreams | `bool` | no | `true` | Disabled entries are ignored at startup. | | `[[upstreams]].scopes` | all upstreams | `String` | no | `""` | Comma-separated scope tags for request-level routing. | +| `[[upstreams]].ipv4` | all upstreams | `Option` | no | `auto` | Allow IPv4 DC targets for this upstream. | +| `[[upstreams]].ipv6` | all upstreams | `Option` | no | `auto` | Allow IPv6 DC targets for this upstream, including proxy egress independent of host IPv6. | +| `[[upstreams]].prefer` | all upstreams | `Option<4 \| 6>` | no | effective `[network].prefer` | Per-upstream DC target family preference. | | `interface` | `direct` | `Option` | no | `null` | Interface name (e.g. `eth0`) or literal local IP for bind selection. | | `bind_addresses` | `direct` | `Option>` | no | `null` | Explicit local source IP candidates (strict priority over `interface`). | | `address` | `socks4` | `String` | yes | n/a | SOCKS4 server endpoint (`ip:port` or `host:port`). | diff --git a/docs/Advanced_settings/TUNING.ru.md b/docs/Advanced_settings/TUNING.ru.md index bae8fdd..0649bca 100644 --- a/docs/Advanced_settings/TUNING.ru.md +++ b/docs/Advanced_settings/TUNING.ru.md @@ -86,6 +86,9 @@ | `[[upstreams]].weight` | все upstream | `u16` | нет | `1` | Базовый вес в weighted-random выборе. | | `[[upstreams]].enabled` | все upstream | `bool` | нет | `true` | Выключенные записи игнорируются на старте. | | `[[upstreams]].scopes` | все upstream | `String` | нет | `""` | Список scope-токенов через запятую для маршрутизации. | +| `[[upstreams]].ipv4` | все upstream | `Option` | нет | `auto` | Разрешает IPv4 DC-targets для этого upstream. | +| `[[upstreams]].ipv6` | все upstream | `Option` | нет | `auto` | Разрешает IPv6 DC-targets для этого upstream, включая proxy egress независимо от IPv6 на хосте. | +| `[[upstreams]].prefer` | все upstream | `Option<4 \| 6>` | нет | эффективный `[network].prefer` | Предпочтительное семейство DC-target для конкретного upstream. | | `interface` | `direct` | `Option` | нет | `null` | Имя интерфейса (например `eth0`) или literal локальный IP. | | `bind_addresses` | `direct` | `Option>` | нет | `null` | Явные кандидаты source IP (имеют приоритет над `interface`). | | `address` | `socks4` | `String` | да | n/a | Адрес SOCKS4 сервера (`ip:port` или `host:port`). | diff --git a/docs/Architecture/API/API.md b/docs/Architecture/API/API.md index f037fc7..d8398bd 100644 --- a/docs/Architecture/API/API.md +++ b/docs/Architecture/API/API.md @@ -111,6 +111,8 @@ Notes: | `PATCH` | `/v1/users/{username}` | `PatchUserRequest` | `200` or `202` | `UserInfo` | | `DELETE` | `/v1/users/{username}` | none | `200` or `202` | `DeleteUserResponse` | | `POST` | `/v1/users/{username}/rotate-secret` | `RotateSecretRequest` or empty body | `200` or `202` | `CreateUserResponse` | +| `POST` | `/v1/users/{username}/enable` | empty body | `200` or `202` | `UserInfo` | +| `POST` | `/v1/users/{username}/disable` | empty body | `200` or `202` | `UserInfo` | | `POST` | `/v1/users/{username}/reset-quota` | empty body | `200` | `ResetUserQuotaResponse` | ## Endpoint Behavior @@ -146,6 +148,8 @@ Notes: | `PATCH /v1/users/{username}` | Updates selected per-user fields with JSON Merge Patch semantics. | | `DELETE /v1/users/{username}` | Deletes one user and related per-user access-map entries. | | `POST /v1/users/{username}/rotate-secret` | Rotates one user's secret and returns the effective secret. | +| `POST /v1/users/{username}/enable` | Enables one user, removing any disabled override from config. | +| `POST /v1/users/{username}/disable` | Disables one user and closes active runtime sessions for that user. | | `POST /v1/users/{username}/reset-quota` | Resets one user's runtime quota counter and persists quota state. | ## Common Error Codes @@ -175,6 +179,8 @@ Notes: | `PUT /v1/users/{username}` | `405 method_not_allowed`. | | `POST /v1/users/{username}` | `404 not_found`. | | `POST /v1/users/{username}/rotate-secret/` | Trailing slash is trimmed and the route matches `rotate-secret`. | +| `POST /v1/users/{username}/enable/` | Trailing slash is trimmed and the route matches `enable`. | +| `POST /v1/users/{username}/disable/` | Trailing slash is trimmed and the route matches `disable`. | | `POST /v1/users/{username}/reset-quota/` | Trailing slash is trimmed and the route matches `reset-quota`. | ## Body and JSON Semantics @@ -208,6 +214,7 @@ Notes: | `rate_limit_up_bps` | `u64` | no | Per-user upload rate limit in bytes per second. | | `rate_limit_down_bps` | `u64` | no | Per-user download rate limit in bytes per second. | | `max_unique_ips` | `usize` | no | Per-user unique source IP limit. | +| `enabled` | `bool` | no | User enable flag. Missing means enabled. `false` persists a disabled override. | ### `PatchUserRequest` | Field | Type | Required | Description | @@ -220,6 +227,7 @@ Notes: | `rate_limit_up_bps` | `u64|null` | no | Per-user upload rate limit in bytes per second; `null` removes the upload direction limit. | | `rate_limit_down_bps` | `u64|null` | no | Per-user download rate limit in bytes per second; `null` removes the download direction limit. | | `max_unique_ips` | `usize|null` | no | Per-user unique source IP limit; `null` removes the per-user override. | +| `enabled` | `bool|null` | no | `false` disables the user. `true` or `null` removes the disabled override, so the user is enabled. | ### `access.user_source_deny` via API - In current API surface, per-user deny-list is **not** exposed as a dedicated field in `CreateUserRequest` / `PatchUserRequest`. @@ -1165,6 +1173,7 @@ An empty request body is accepted and generates a new secret automatically. | Field | Type | Description | | --- | --- | --- | | `username` | `string` | Username. | +| `enabled` | `bool` | Effective user enable flag. Missing config entry is reported as `true`. | | `in_runtime` | `bool` | Whether current runtime config already contains this user. | | `user_ad_tag` | `string?` | Optional ad tag (32 hex chars). | | `max_tcp_conns` | `usize?` | Optional max concurrent TCP limit. | @@ -1239,6 +1248,8 @@ Link generation uses active config and enabled modes: | `POST /v1/users` | Creates user, validates config, then atomically updates only affected `access.*` TOML tables (`access.users` always, plus optional per-user tables present in request). | | `PATCH /v1/users/{username}` | Partial update of provided fields only. Missing fields remain unchanged; explicit `null` removes optional per-user entries. The write path updates only affected `access.*` TOML tables. | | `POST /v1/users/{username}/rotate-secret` | Replaces the user's secret with a provided valid 32-hex value or a generated value, then returns the effective secret in `CreateUserResponse`. | +| `POST /v1/users/{username}/enable` | Enables the user idempotently by removing the `access.user_enabled[username]` override and updating the runtime admission state immediately. | +| `POST /v1/users/{username}/disable` | Disables the user idempotently by writing `access.user_enabled[username] = false`, updating runtime admission immediately, and cancelling active sessions for that username. | | `POST /v1/users/{username}/reset-quota` | Resets the runtime quota counter for the route username, persists quota state to `general.quota_state_path`, and does not modify user config. | | `DELETE /v1/users/{username}` | Deletes only specified user, removes this user from related optional `access.user_*` maps, blocks last-user deletion, and atomically updates only related `access.*` TOML tables. | diff --git a/docs/Config_params/CONFIG_PARAMS.en.md b/docs/Config_params/CONFIG_PARAMS.en.md index f28e338..7425018 100644 --- a/docs/Config_params/CONFIG_PARAMS.en.md +++ b/docs/Config_params/CONFIG_PARAMS.en.md @@ -2934,6 +2934,7 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p | Key | Type | Default | Hot-Reload | | --- | ---- | ------- | ---------- | | [`users`](#users) | `Map` | `{"default": "000…000"}` | `✔` | +| [`user_enabled`](#user_enabled-1) | `Map` | `{}` | `✔` | | [`user_ad_tags`](#user_ad_tags) | `Map` | `{}` | `✔` | | [`user_max_tcp_conns`](#user_max_tcp_conns) | `Map` | `{}` | `✔` | | [`user_max_tcp_conns_global_each`](#user_max_tcp_conns_global_each) | `usize` | `0` | `✔` | @@ -2960,6 +2961,16 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p alice = "00112233445566778899aabbccddeeff" bob = "0123456789abcdef0123456789abcdef" ``` +## user_enabled + - **Constraints / validation**: `Map`. + - **Description**: Optional per-user enable overrides. Missing users are enabled by default. A value of `false` disables new sessions for that user; setting the value to `true` is accepted but equivalent to removing the override. API enable operations remove the override, while disable operations write `false`. + - **Runtime behavior**: Hot reload applies this map immediately. Users disabled through API or config reload are rejected after successful authentication and active runtime sessions for that username are cancelled. + - **Example**: + + ```toml + [access.user_enabled] + alice = false + ``` ## user_ad_tags - **Constraints / validation**: Each value must be **exactly 32 hex characters** (same format as `general.ad_tag`). An all-zero tag is allowed but logs a warning. - **Description**: Per-user sponsored-channel ad tag override. When a user has an entry here, it takes precedence over `general.ad_tag`. @@ -3120,6 +3131,7 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p | [`scopes`](#scopes) | `String` | `""` | `✘` | | [`ipv4`](#ipv4-upstreams) | `bool` | — (auto) | `✘` | | [`ipv6`](#ipv6-upstreams) | `bool` | — (auto) | `✘` | +| [`prefer`](#prefer-upstreams) | `4` or `6` | effective `[network].prefer` | `✘` | | [`interface`](#interface) | `String` | — | `✘` | | [`bind_addresses`](#bind_addresses) | `String[]` | — | `✘` | | [`bindtodevice`](#bindtodevice) | `String` | — | `✘` | @@ -3191,7 +3203,7 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p ``` ## ipv6 (upstreams) - **Constraints / validation**: `bool` (optional). - - **Description**: Allows IPv6 DC targets for this upstream. When omitted, Telemt auto-detects support from runtime connectivity state. + - **Description**: Allows IPv6 DC targets for this upstream. When omitted, Telemt auto-detects support from runtime connectivity state. Set this to `true` when the upstream proxy is reachable from the local host over IPv4 but the proxy itself can connect to Telegram DCs over IPv6. - **Example**: ```toml @@ -3199,6 +3211,18 @@ If your backend or network is very bandwidth-constrained, reduce cap first. If p type = "direct" ipv6 = false ``` +## prefer (upstreams) + - **Constraints / validation**: Optional integer. Must be `4` or `6`. + - **Description**: Overrides the IP family preference for Telegram DC targets selected through this upstream. When omitted, the upstream inherits the effective global `[network].prefer` decision. Use `prefer = 6` together with `ipv6 = true` for a SOCKS or Shadowsocks upstream that can egress over IPv6 even when the local Telemt host is IPv4-only. + - **Example**: + + ```toml + [[upstreams]] + type = "socks5" + address = "192.0.2.10:1080" + ipv6 = true + prefer = 6 + ``` ## interface - **Constraints / validation**: `String` (optional). - For `"direct"`: may be an IP address (used as explicit local bind) or an OS interface name (resolved to an IP at runtime; Unix only). diff --git a/docs/Config_params/CONFIG_PARAMS.ru.md b/docs/Config_params/CONFIG_PARAMS.ru.md index 75c4cb0..97e84a6 100644 --- a/docs/Config_params/CONFIG_PARAMS.ru.md +++ b/docs/Config_params/CONFIG_PARAMS.ru.md @@ -3127,6 +3127,7 @@ | [`scopes`](#scopes) | `String` | `""` | `✘` | | [`ipv4`](#ipv4-upstreams) | `bool` | — (auto) | `✘` | | [`ipv6`](#ipv6-upstreams) | `bool` | — (auto) | `✘` | +| [`prefer`](#prefer-upstreams) | `4` или `6` | эффективный `[network].prefer` | `✘` | | [`interface`](#interface) | `String` | — | `✘` | | [`bind_addresses`](#bind_addresses) | `String[]` | — | `✘` | | [`bindtodevice`](#bindtodevice) | `String` | — | `✘` | @@ -3198,7 +3199,7 @@ ``` ## ipv6 (upstreams) - **Ограничения / валидация**: `bool` (необязательный параметр). - - **Описание**: Разрешает IPv6 DC-targets для этого upstream. Если не задан, Telemt определяет поддержку автоматически по runtime-состоянию connectivity. + - **Описание**: Разрешает IPv6 DC-targets для этого upstream. Если не задан, Telemt определяет поддержку автоматически по runtime-состоянию connectivity. Установите `true`, если upstream proxy доступен с локального хоста по IPv4, но сам proxy умеет подключаться к Telegram DC по IPv6. - **Пример**: ```toml @@ -3206,6 +3207,18 @@ type = "direct" ipv6 = false ``` +## prefer (upstreams) + - **Ограничения / валидация**: Необязательное число. Должно быть `4` или `6`. + - **Описание**: Переопределяет предпочтительное IP-семейство для Telegram DC-targets, выбранных через этот upstream. Если параметр не задан, upstream наследует эффективное глобальное решение `[network].prefer`. Используйте `prefer = 6` вместе с `ipv6 = true` для SOCKS или Shadowsocks upstream, который умеет выходить в IPv6, даже если локальный хост с Telemt работает только по IPv4. + - **Пример**: + + ```toml + [[upstreams]] + type = "socks5" + address = "192.0.2.10:1080" + ipv6 = true + prefer = 6 + ``` ## interface - **Ограничения / валидация**: `String` (необязательный параметр). - для `"direct"`: может быть IP-адресом (используется как явный local bind) или именем сетевого интерфейса ОС (резолвится в IP во время выполнения; только Unix).