Docs for WEB

Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
Alexey
2026-08-23 03:32:40 +03:00
parent 1029703c2c
commit 79ad4cb541
7 changed files with 1246 additions and 2 deletions
+144
View File
@@ -24,6 +24,12 @@ Dieses Dokument listet alle Konfigurationsschlüssel auf, die `config.toml` akze
- [server.conntrack_control](#serverconntrack_control)
- [server.api](#serverapi)
- [server.listeners](#serverlisteners)
- [web](#web)
- [web.limits](#weblimits)
- [web.timeouts](#webtimeouts)
- [web.vhosts](#webvhosts)
- [web.vhosts.decoy](#webvhostsdecoy)
- [web.vhosts.profiles](#webvhostsprofiles)
- [timeouts](#timeouts)
- [censorship](#censorship)
- [censorship.tls_fetch](#censorshiptls_fetch)
@@ -2324,6 +2330,9 @@ Hinweis: Dieser Abschnitt akzeptiert auch den Legacy-Alias `[server.admin_api]`
| [`announce_ip`](#announce_ip) | `IpAddr` | — | `` |
| [`proxy_protocol`](#proxy_protocol) | `bool` | — | `` |
| [`reuse_allow`](#reuse_allow) | `bool` | `false` | `` |
| [`transport`](#transport-serverlisteners) | `"mtproxy"` oder `"web"` | `"mtproxy"` | `` |
| [`web_client_ip_source`](#web_client_ip_source-serverlisteners) | `"x_forwarded_for"` | `"x_forwarded_for"` | `` |
| [`web_trusted_proxy_cidrs`](#web_trusted_proxy_cidrs-serverlisteners) | `IpNetwork[]` | `[]` | `` |
## ip
- **Einschränkungen / Validierung**: Erforderliches Feld. Muss ein `IpAddr` sein.
@@ -2517,6 +2526,141 @@ Hinweis: Dieser Abschnitt akzeptiert auch den Legacy-Alias `[server.admin_api]`
reuse_allow = false
```
## transport (server.listeners)
- **Einschränkungen / Validierung**: `"mtproxy"` oder `"web"`.
- **Beschreibung**: Wählt das vom Listener akzeptierte Protokoll. Ein WEB-Listener empfängt unverschlüsseltes HTTP/1.1 von einem vertrauenswürdigen TLS-Terminator und erfordert einen Prozessneustart. Er muss `proxy_protocol = false` und `reuse_allow = false` verwenden; `client_mss`, `synlimit`, `announce` und `announce_ip` sind nicht zulässig.
- **Beispiel**:
```toml
[[server.listeners]]
ip = "127.0.0.1"
port = 18080
transport = "web"
proxy_protocol = false
web_trusted_proxy_cidrs = ["127.0.0.1/32"]
```
## web_client_ip_source (server.listeners)
- **Einschränkungen / Validierung**: Die erste WEB-Implementierung unterstützt ausschließlich `"x_forwarded_for"`.
- **Beschreibung**: Wählt die L7-Quelle der ursprünglichen Client-IP. Telemt akzeptiert genau eine kanonische `X-Forwarded-For`-Adresse und nur dann, wenn der direkte TCP-Peer zu `web_trusted_proxy_cidrs` gehört.
## web_trusted_proxy_cidrs (server.listeners)
- **Einschränkungen / Validierung**: Nicht leeres CIDR-Array nur für WEB; ein `/0`-Netz wird abgelehnt. Für einen MTProxy-Listener ist das Feld ungültig.
- **Beschreibung**: Vertrauensgrenze für den unmittelbar vorgeschalteten NGINX- oder HAProxy-Peer. Tragen Sie nur Adressen ein, die diesen Listener direkt erreichen können, und veröffentlichen Sie den unverschlüsselten Listener niemals in einem nicht vertrauenswürdigen Netz.
# [web]
Der WEB-Modus transportiert MTProxy-Datenverkehr von Telegram Desktop über HTTPS, dessen TLS-Verbindung von einem externen NGINX oder HAProxy terminiert wird. Telemt empfängt unverschlüsseltes HTTP/1.1 auf einem privaten Listener mit `transport = "web"`. Lesen Sie vor der Aktivierung die [vollständige WEB-Bereitstellungsanleitung](../WEB/WEB_PROXY.de.md).
| Schlüssel | Typ | Default | Hot-Reload |
| --- | --- | --- | --- |
| `enabled` | `bool` | `false` | `` |
| `limits` | Tabelle | begrenzte Defaults | `` |
| `timeouts` | Tabelle | begrenzte Defaults | `` |
| `vhosts` | Tabellen-Array | `[]` | `` |
`enabled = true` erfordert mindestens einen durch die Netzwerkrichtlinie zugelassenen WEB-Listener, einen vhost und mindestens ein Profil in jedem vhost. Das Deaktivieren von WEB beendet nach dem Reload die Ausgabe neuer Bridge- und Session-Zugangsdaten; zum Widerrufen aktiver Sitzungen eines einzelnen Benutzers verwenden Sie die Users-API.
# [web.limits]
Diese prozessweiten Obergrenzen begrenzen alle WEB-Register, Warteschlangen, Request-Bodys, statischen Snapshots und Admission-Pfade. Alle Werte werden gemeinsam validiert: Eigentümerbezogene Grenzen dürfen die globalen Grenzen nicht überschreiten, Queue-Reserven müssen den Fortschritt von Control Frames gewährleisten, Body-Reservierungen müssen in ihr globales Budget passen und alle deklarierten Byte-Grenzen müssen in `memory_envelope_bytes` passen. Jede Änderung in dieser Tabelle erfordert einen Prozessneustart.
| Schlüssel | Typ | Default | Beschreibung |
| --- | --- | --- | --- |
| `max_header_bytes` | `usize` | `16384` | Maximale Bytes in einem HTTP-Request-Head. |
| `max_body_bytes` | `usize` | `2097152` | Maximale Größe eines gesammelten Carrier-Request-Bodys. |
| `max_frame_payload_bytes` | `usize` | `1048576` | Maximale Nutzlast eines WEB-Frames. |
| `carrier_batch_bytes` | `usize` | `2097152` | Maximale Größe eines kodierten Downlink-Batches. |
| `max_frames_per_body` | `usize` | `4096` | Maximale Zahl geparster oder ausgegebener Frames pro Carrier-Body. |
| `max_http_connections` | `usize` | `1024` | Prozessweit akzeptierte WEB-HTTP-Verbindungen. |
| `max_http_handlers` | `usize` | `512` | Prozessweit gleichzeitig ausgeführte HTTP-Handler. |
| `max_body_readers` | `usize` | `32` | Prozessweit gleichzeitig gesammelte Request-Bodys. |
| `max_body_bytes_global` | `usize` | `67108864` | Globales Byte-Budget für gesammelte Bodys. |
| `max_sessions_global` | `usize` | `128` | Prozessweit aktive WEB-Sitzungen. |
| `max_sessions_per_ip` | `usize` | `16` | Aktive Sitzungen pro weitergeleiteter Client-IP. |
| `max_streams_per_session` | `usize` | `128` | Standardgrenze aktiver logischer Streams pro Sitzung. |
| `max_streams_global` | `usize` | `4096` | Prozessweit aktive logische Streams. |
| `max_stream_handshakes` | `usize` | `256` | Gleichzeitig ausgeführte innere MTProxy-Handshakes. |
| `max_tombstones_per_session` | `usize` | `4096` | Pro Sitzung gespeicherte IDs geschlossener Streams. |
| `pending_bytes_per_session` | `usize` | `33554432` | Eingereihte Daten- und Steuerbytes pro Sitzung. |
| `pending_bytes_global` | `usize` | `536870912` | Prozessweit eingereihte Daten- und Steuerbytes. |
| `pending_items_per_session` | `usize` | `16384` | Eingereihte Daten- und Steuerelemente pro Sitzung. |
| `pending_items_global` | `usize` | `262144` | Prozessweit eingereihte Daten- und Steuerelemente. |
| `control_bytes_per_session` | `usize` | `262144` | Nur für Control Frames verfügbares Byte-Budget pro Sitzung. |
| `control_bytes_global` | `usize` | `16777216` | Prozessweites, nur für Control Frames verfügbares Byte-Budget. |
| `max_bootstraps_global` | `usize` | `512` | Prozessweit aktive Bootstrap-Zugangsdaten. |
| `max_bootstraps_per_ip` | `usize` | `64` | Aktive Bootstrap-Zugangsdaten pro Client-IP. |
| `max_vhosts` | `usize` | `8` | Konfigurierte virtuelle WEB-Hosts. |
| `max_profiles` | `usize` | `32` | WEB-Profile über alle vhosts. |
| `max_static_files` | `usize` | `4096` | Einträge statischer Snapshots über alle vhosts. |
| `max_static_file_bytes` | `usize` | `8388608` | Maximale Größe einer statischen Datei. |
| `max_static_bytes` | `usize` | `67108864` | Bytes statischer Snapshots über alle vhosts. |
| `memory_envelope_bytes` | `usize` | `805306368` | Deklarierter Rahmen für HTTP-Heads, Bodys, Queues und statische Snapshots; maximal 4 GiB. |
| `new_bootstraps_per_minute` | `u32` | `1200` | Nachhaltige prozessweite Ausgaberate für Bootstraps. |
| `new_bootstraps_burst` | `u32` | `256` | Prozessweiter Burst für die Bootstrap-Ausgabe. |
| `new_sessions_per_minute` | `u32` | `600` | Nachhaltige prozessweite Erstellungsrate für Sitzungen. |
| `new_sessions_burst` | `u32` | `128` | Prozessweiter Burst für die Sitzungserstellung. |
| `new_streams_per_minute` | `u32` | `6000` | Nachhaltige Erstellungsrate für logische Streams. |
| `new_streams_burst` | `u32` | `512` | Prozessweiter Burst für die Stream-Erstellung. |
# [web.timeouts]
Alle Timeouts werden in Sekunden angegeben und müssen im Bereich `1..=3600` liegen. Die längste Request-Deadline muss kleiner als `http_idle_secs` sein.
| Schlüssel | Typ | Default | Hot-Reload | Beschreibung |
| --- | --- | --- | --- | --- |
| `header_secs` | `u64` | `10` | `` | Empfang eines vollständigen HTTP-Request-Heads. |
| `body_secs` | `u64` | `30` | `` | Sammeln eines authentifizierten Carrier-Bodys. |
| `stream_handshake_secs` | `u64` | `10` | `` | Abschluss eines inneren MTProxy-Handshakes. |
| `long_poll_secs` | `u64` | `25` | `` | Maximale Dauer eines leeren Downlink-Long-Polls. |
| `bootstrap_lifetime_secs` | `u64` | `120` | `` | Lebensdauer ungenutzter Bootstraps und geschlossener Token-Replay-Marker. |
| `reconnect_grace_secs` | `u64` | `120` | `` | Maximale Carrier-Inaktivität bis zum Schließen der Sitzung. |
| `http_idle_secs` | `u64` | `75` | `` | Idle-Lebensdauer einer WEB-HTTP-Keep-Alive-Verbindung. |
| `shutdown_secs` | `u64` | `15` | `` | Deadline für das kontrollierte Beenden von WEB. |
| `decoy_header_secs` | `u64` | `30` | `` | Deadline für Verbindung und Response-Head eines HTTP-Decoys. |
# [[web.vhosts]]
| Schlüssel | Typ | Erforderlich | Hot-Reload | Beschreibung |
| --- | --- | --- | --- | --- |
| `host` | `String` | ja | `` | Eindeutiger, kanonischer ACE-FQDN in Kleinbuchstaben ohne Port, Pfad, Zugangsdaten oder abschließenden Punkt. |
| `public_addr` | `SocketAddr` | ja | `` | Konkrete öffentliche IP auf Port `443`; wird im Ziel-Tupel des inneren Relays verwendet. |
| `decoy` | Tabelle | ja | `` | Gewöhnlicher Site-Fallback für nicht authentifizierten oder ungültigen Datenverkehr. |
| `profiles` | Tabellen-Array | bei aktiviertem WEB | `` | Explizite Benutzer und Client-Secret-Modi für diesen Hostnamen. |
Die weitergeleitete Client-Adresse und `public_addr` müssen dieselbe IP-Familie verwenden. Der Hostname wird bei der Validierung normalisiert und muss von Telegram Desktop akzeptiert werden.
# [web.vhosts.decoy]
Genau ein Decoy-Modus ist erforderlich:
| Modus | Erforderliche Schlüssel | Validierung |
| --- | --- | --- |
| `http_upstream` | `upstream` | Ein `http://`-Origin mit Loopback-, Link-Local- oder privater IP-Adresse als Literal; keine Zugangsdaten, kein Pfad, Query oder Fragment. |
| `static_directory` | `directory`; optional `index = "index.html"` | Absolutes reales Verzeichnis und ein sicherer Index-Dateiname. Symlinks und Pfade außerhalb des Verzeichnisses werden abgelehnt; der unveränderliche Snapshot wird innerhalb von `[web.limits]` geladen. |
# [[web.vhosts.profiles]]
| Schlüssel | Typ | Erforderlich | Default | Beschreibung |
| --- | --- | --- | --- | --- |
| `user` | `String` | ja | — | Vorhandener Schlüssel aus `[access.users]`. |
| `secret_mode` | `"plain"` oder `"dd"` | ja | — | Exakte Secret-Darstellung für Telegram Desktop. `ee` wird nicht unterstützt. |
| `max_sessions` | `usize` | nein | `web.limits.max_sessions_global` | Aktive Sitzungen für dieses Profil. |
| `max_streams` | `usize` | nein | `web.limits.max_streams_global` | Aktive logische Streams für dieses Profil. |
| `max_streams_per_session` | `usize` | nein | `web.limits.max_streams_per_session` | Aktive logische Streams in einer Profilsitzung. |
Profilgrenzen müssen ungleich null sein und dürfen die zugehörigen globalen Grenzen nicht überschreiten. Doppelte `(user, secret_mode)`-Profile in einem vhost werden abgelehnt.
## WEB-Lebenszyklus und API-Verwaltung
- Config-Watcher und Generations-Reload wenden `web.enabled`, `web.timeouts`, vhosts, Profile und Decoy-Snapshots ohne Prozessneustart an. Bestehende Sitzungen behalten die bei ihrer Erstellung übernommenen Grenzen und Deadlines; neue Arbeit verwendet die aktive Generation.
- Bestand und Vertrauensrichtlinie der WEB-Listener unter `server.listeners` sowie alle Werte in `web.limits` sind prozesseigen und erfordern einen Neustart.
- Es gibt keinen eigenen Endpunkt `/v1/web`. `GET /v1/config` lässt `[web]` aus und `PATCH /v1/config` lehnt einen Schlüssel `web` mit `400 section_not_editable` ab.
- Zum entfernten Anwenden einer WEB-Richtlinie ändern Sie die zuständige TOML-Datei und rufen `POST /v1/system/reload` auf. Prüfen Sie anschließend `GET /v1/system/reload/{id}` und dessen `deferred_process_fields`. Starten Sie Telemt neu, wenn das Feld `server.listeners` oder `web.limits` enthält.
- Vorhandene Access-Benutzer können über `/v1/users` erstellt, geändert, rotiert, aktiviert, deaktiviert und gelöscht werden. Das Erstellen eines Benutzers fügt kein WEB-Profil hinzu. Das Deaktivieren aktualisiert die Admission sofort und beendet die aktiven Sitzungen dieses Benutzers.
- `PATCH /v1/config` kann `server.listeners` einschließlich der WEB-Listener-Felder speichern; ein geänderter WEB-Listener wird jedoch erst nach einem Prozessneustart aktiv.
# [timeouts]
+144
View File
@@ -24,6 +24,12 @@ This document lists all configuration keys accepted by `config.toml`.
- [server.conntrack_control](#serverconntrack_control)
- [server.api](#serverapi)
- [server.listeners](#serverlisteners)
- [web](#web)
- [web.limits](#weblimits)
- [web.timeouts](#webtimeouts)
- [web.vhosts](#webvhosts)
- [web.vhosts.decoy](#webvhostsdecoy)
- [web.vhosts.profiles](#webvhostsprofiles)
- [timeouts](#timeouts)
- [censorship](#censorship)
- [censorship.tls_fetch](#censorshiptls_fetch)
@@ -2324,6 +2330,9 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
| [`announce_ip`](#announce_ip) | `IpAddr` | — | `` |
| [`proxy_protocol`](#proxy_protocol) | `bool` | — | `` |
| [`reuse_allow`](#reuse_allow) | `bool` | `false` | `` |
| [`transport`](#transport-serverlisteners) | `"mtproxy"` or `"web"` | `"mtproxy"` | `` |
| [`web_client_ip_source`](#web_client_ip_source-serverlisteners) | `"x_forwarded_for"` | `"x_forwarded_for"` | `` |
| [`web_trusted_proxy_cidrs`](#web_trusted_proxy_cidrs-serverlisteners) | `IpNetwork[]` | `[]` | `` |
## ip
- **Constraints / validation**: Required field. Must be an `IpAddr`.
@@ -2517,6 +2526,141 @@ Note: This section also accepts the legacy alias `[server.admin_api]` (same sche
reuse_allow = false
```
## transport (server.listeners)
- **Constraints / validation**: `"mtproxy"` or `"web"`.
- **Description**: Selects the protocol accepted by this listener. A WEB listener receives plain HTTP/1.1 from a trusted TLS terminator and is restart-required. It must set `proxy_protocol = false`, `reuse_allow = false`, and cannot use `client_mss`, `synlimit`, `announce`, or `announce_ip`.
- **Example**:
```toml
[[server.listeners]]
ip = "127.0.0.1"
port = 18080
transport = "web"
proxy_protocol = false
web_trusted_proxy_cidrs = ["127.0.0.1/32"]
```
## web_client_ip_source (server.listeners)
- **Constraints / validation**: Only `"x_forwarded_for"` is supported by the initial WEB implementation.
- **Description**: Chooses the L7 source of the original client IP. Telemt accepts exactly one canonical `X-Forwarded-For` address and only when the direct TCP peer belongs to `web_trusted_proxy_cidrs`.
## web_trusted_proxy_cidrs (server.listeners)
- **Constraints / validation**: WEB-only non-empty CIDR array. A `/0` network is rejected. It is invalid on an MTProxy listener.
- **Description**: Trust boundary for the immediate NGINX or HAProxy peer. List only addresses that can connect directly to this listener; never expose the plain listener to an untrusted network.
# [web]
WEB mode carries Telegram Desktop MTProxy traffic through HTTPS terminated by an external NGINX or HAProxy. Telemt receives plain HTTP/1.1 on a private `transport = "web"` listener. See the [complete WEB deployment guide](../WEB/WEB_PROXY.en.md) before enabling this mode.
| Key | Type | Default | Hot-Reload |
| --- | --- | --- | --- |
| `enabled` | `bool` | `false` | `` |
| `limits` | table | bounded defaults | `` |
| `timeouts` | table | bounded defaults | `` |
| `vhosts` | array of tables | `[]` | `` |
`enabled = true` requires at least one network-eligible WEB listener, at least one vhost, and at least one profile in every vhost. Disabling WEB stops issuance of new bridge and session credentials after reload; use the users API to revoke one user's active sessions.
# [web.limits]
These process-wide ceilings make every WEB registry, queue, request body, static snapshot, and admission path bounded. All values are validated together. Per-owner limits cannot exceed global limits, queue reserves must preserve control-frame progress, body reservations must fit their global budget, and all declared byte ceilings must fit `memory_envelope_bytes`. Changing any value in this table requires a process restart.
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `max_header_bytes` | `usize` | `16384` | Maximum bytes in one HTTP request head. |
| `max_body_bytes` | `usize` | `2097152` | Maximum collected carrier request body. |
| `max_frame_payload_bytes` | `usize` | `1048576` | Maximum payload in one WEB frame. |
| `carrier_batch_bytes` | `usize` | `2097152` | Maximum encoded downlink batch. |
| `max_frames_per_body` | `usize` | `4096` | Maximum frames parsed or emitted per carrier body. |
| `max_http_connections` | `usize` | `1024` | Accepted WEB HTTP connections process-wide. |
| `max_http_handlers` | `usize` | `512` | Concurrent HTTP handlers process-wide. |
| `max_body_readers` | `usize` | `32` | Concurrent collected request bodies process-wide. |
| `max_body_bytes_global` | `usize` | `67108864` | Global byte reservation for collected bodies. |
| `max_sessions_global` | `usize` | `128` | Live WEB sessions process-wide. |
| `max_sessions_per_ip` | `usize` | `16` | Live sessions for one forwarded client IP. |
| `max_streams_per_session` | `usize` | `128` | Default live logical streams per session. |
| `max_streams_global` | `usize` | `4096` | Live logical streams process-wide. |
| `max_stream_handshakes` | `usize` | `256` | Concurrent inner MTProxy handshakes. |
| `max_tombstones_per_session` | `usize` | `4096` | Closed stream IDs retained per session. |
| `pending_bytes_per_session` | `usize` | `33554432` | Queued data and control bytes per session. |
| `pending_bytes_global` | `usize` | `536870912` | Queued data and control bytes process-wide. |
| `pending_items_per_session` | `usize` | `16384` | Queued data and control items per session. |
| `pending_items_global` | `usize` | `262144` | Queued data and control items process-wide. |
| `control_bytes_per_session` | `usize` | `262144` | Per-session byte reserve available only to control frames. |
| `control_bytes_global` | `usize` | `16777216` | Process-wide byte reserve available only to control frames. |
| `max_bootstraps_global` | `usize` | `512` | Live bootstrap credentials process-wide. |
| `max_bootstraps_per_ip` | `usize` | `64` | Live bootstrap credentials per client IP. |
| `max_vhosts` | `usize` | `8` | Configured WEB virtual hosts. |
| `max_profiles` | `usize` | `32` | WEB profiles across all vhosts. |
| `max_static_files` | `usize` | `4096` | Static snapshot entries across all vhosts. |
| `max_static_file_bytes` | `usize` | `8388608` | Maximum bytes in one static file. |
| `max_static_bytes` | `usize` | `67108864` | Static snapshot bytes across all vhosts. |
| `memory_envelope_bytes` | `usize` | `805306368` | Declared envelope for HTTP heads, bodies, queues, and static snapshots; maximum 4 GiB. |
| `new_bootstraps_per_minute` | `u32` | `1200` | Sustained process-wide bootstrap issuance rate. |
| `new_bootstraps_burst` | `u32` | `256` | Process-wide bootstrap issuance burst. |
| `new_sessions_per_minute` | `u32` | `600` | Sustained process-wide session creation rate. |
| `new_sessions_burst` | `u32` | `128` | Process-wide session creation burst. |
| `new_streams_per_minute` | `u32` | `6000` | Sustained logical-stream creation rate. |
| `new_streams_burst` | `u32` | `512` | Process-wide logical-stream creation burst. |
# [web.timeouts]
Every timeout is measured in seconds and must be within `1..=3600`. The longest request deadline must be lower than `http_idle_secs`.
| Key | Type | Default | Hot-Reload | Description |
| --- | --- | --- | --- | --- |
| `header_secs` | `u64` | `10` | `` | Receive one complete HTTP request head. |
| `body_secs` | `u64` | `30` | `` | Collect one authenticated carrier body. |
| `stream_handshake_secs` | `u64` | `10` | `` | Complete one inner MTProxy handshake. |
| `long_poll_secs` | `u64` | `25` | `` | Maximum empty downlink long poll. |
| `bootstrap_lifetime_secs` | `u64` | `120` | `` | Unused bootstrap and closed-token replay lifetime. |
| `reconnect_grace_secs` | `u64` | `120` | `` | Maximum carrier inactivity before session closure. |
| `http_idle_secs` | `u64` | `75` | `` | WEB HTTP keep-alive idle lifetime. |
| `shutdown_secs` | `u64` | `15` | `` | Graceful WEB shutdown deadline. |
| `decoy_header_secs` | `u64` | `30` | `` | Connect and response-head deadline for an HTTP decoy. |
# [[web.vhosts]]
| Key | Type | Required | Hot-Reload | Description |
| --- | --- | --- | --- | --- |
| `host` | `String` | yes | `` | Unique, canonical lowercase ACE FQDN without port, path, credentials, or trailing dot. |
| `public_addr` | `SocketAddr` | yes | `` | Concrete public IP on port `443`; used in the inner relay destination tuple. |
| `decoy` | table | yes | `` | Ordinary-site fallback for unauthenticated or invalid traffic. |
| `profiles` | array of tables | when enabled | `` | Explicit users and client secret modes exposed by this hostname. |
The forwarded client address and `public_addr` must use the same IP family. The hostname must be accepted by Telegram Desktop and is normalized during validation.
# [web.vhosts.decoy]
Exactly one decoy mode is required:
| Mode | Required keys | Validation |
| --- | --- | --- |
| `http_upstream` | `upstream` | An `http://` origin using a loopback, link-local, or private IP literal; no credentials, path, query, or fragment. |
| `static_directory` | `directory`; optional `index = "index.html"` | Absolute real directory and one safe index file name. Symlinks and escaping paths are rejected; the immutable snapshot is loaded under `[web.limits]`. |
# [[web.vhosts.profiles]]
| Key | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `user` | `String` | yes | — | Existing key from `[access.users]`. |
| `secret_mode` | `"plain"` or `"dd"` | yes | — | Exact Telegram Desktop secret representation. `ee` is not supported. |
| `max_sessions` | `usize` | no | `web.limits.max_sessions_global` | Live sessions for this profile. |
| `max_streams` | `usize` | no | `web.limits.max_streams_global` | Live logical streams for this profile. |
| `max_streams_per_session` | `usize` | no | `web.limits.max_streams_per_session` | Live logical streams in one profile session. |
Profile limits must be non-zero and no greater than their corresponding global limits. Duplicate `(user, secret_mode)` profiles in one vhost are rejected.
## WEB lifecycle and API management
- The config watcher and generation reload apply `web.enabled`, `web.timeouts`, vhosts, profiles, and decoy snapshots without a process restart. Existing sessions keep their acquisition-time limits and deadlines; new work uses the active generation.
- WEB listener inventory and trust policy under `server.listeners`, and every `web.limits` value, are process-owned and restart-required.
- There is no dedicated `/v1/web` endpoint. `GET /v1/config` omits `[web]`, and `PATCH /v1/config` rejects a `web` key with `400 section_not_editable`.
- To manage WEB policy remotely, update the owned TOML file and call `POST /v1/system/reload`; inspect `GET /v1/system/reload/{id}` and its `deferred_process_fields`. Restart Telemt when it contains `server.listeners` or `web.limits`.
- Existing access users can be created, changed, rotated, enabled, disabled, and deleted through `/v1/users`. Creating a user does not add a WEB profile. Disabling a user immediately updates admission and cancels that user's active sessions.
- `PATCH /v1/config` can persist `server.listeners`, including WEB listener fields, but a changed WEB listener does not become active until process restart.
# [timeouts]
+144
View File
@@ -23,6 +23,12 @@
- [server.conntrack_control](#serverconntrack_control)
- [server.api](#serverapi)
- [server.listeners](#serverlisteners)
- [web](#web)
- [web.limits](#weblimits)
- [web.timeouts](#webtimeouts)
- [web.vhosts](#webvhosts)
- [web.vhosts.decoy](#webvhostsdecoy)
- [web.vhosts.profiles](#webvhostsprofiles)
- [timeouts](#timeouts)
- [censorship](#censorship)
- [censorship.tls_fetch](#censorshiptls_fetch)
@@ -2250,6 +2256,9 @@
| [`announce_ip`](#announce_ip) | `IpAddr` | — | `` |
| [`proxy_protocol`](#proxy_protocol) | `bool` | — | `` |
| [`reuse_allow`](#reuse_allow) | `bool` | `false` | `` |
| [`transport`](#transport-serverlisteners) | `"mtproxy"` или `"web"` | `"mtproxy"` | `` |
| [`web_client_ip_source`](#web_client_ip_source-serverlisteners) | `"x_forwarded_for"` | `"x_forwarded_for"` | `` |
| [`web_trusted_proxy_cidrs`](#web_trusted_proxy_cidrs-serverlisteners) | `IpNetwork[]` | `[]` | `` |
## ip
- **Ограничения / валидация**: Обязательный параметр. Значение должно содержать IP-адрес в формате строки.
@@ -2443,6 +2452,141 @@
reuse_allow = false
```
## transport (server.listeners)
- **Ограничения / валидация**: `"mtproxy"` или `"web"`.
- **Описание**: Выбирает протокол listener’а. WEB-listener принимает обычный HTTP/1.1 от доверенного TLS-терминатора и требует перезапуска процесса. Для него обязательны `proxy_protocol = false` и `reuse_allow = false`; параметры `client_mss`, `synlimit`, `announce` и `announce_ip` запрещены.
- **Пример**:
```toml
[[server.listeners]]
ip = "127.0.0.1"
port = 18080
transport = "web"
proxy_protocol = false
web_trusted_proxy_cidrs = ["127.0.0.1/32"]
```
## web_client_ip_source (server.listeners)
- **Ограничения / валидация**: Первая реализация WEB поддерживает только `"x_forwarded_for"`.
- **Описание**: Выбирает L7-источник исходного IP клиента. Telemt принимает ровно один канонический адрес `X-Forwarded-For`, только если прямой TCP peer входит в `web_trusted_proxy_cidrs`.
## web_trusted_proxy_cidrs (server.listeners)
- **Ограничения / валидация**: Непустой массив CIDR только для WEB. Сеть `/0` запрещена. Параметр недопустим для MTProxy-listener’а.
- **Описание**: Граница доверия для непосредственного NGINX или HAProxy. Указывайте только адреса, которые могут напрямую подключаться к этому listener’у; не публикуйте plain HTTP listener в недоверенной сети.
# [web]
WEB-режим переносит MTProxy-трафик Telegram Desktop внутри HTTPS, который терминирует внешний NGINX или HAProxy. Telemt принимает обычный HTTP/1.1 на приватном listener’е с `transport = "web"`. Перед включением режима прочитайте [полное руководство по развёртыванию WEB](../WEB/WEB_PROXY.ru.md).
| Ключ | Тип | По умолчанию | Hot-Reload |
| --- | --- | --- | --- |
| `enabled` | `bool` | `false` | `` |
| `limits` | таблица | ограниченные defaults | `` |
| `timeouts` | таблица | ограниченные defaults | `` |
| `vhosts` | массив таблиц | `[]` | `` |
Для `enabled = true` нужен как минимум один доступный по сетевой политике WEB-listener, один vhost и один профиль в каждом vhost. Отключение WEB после reload прекращает выдачу новых bridge- и session-credentials; для отзыва активных сессий отдельного пользователя используйте users API.
# [web.limits]
Эти process-wide границы ограничивают все WEB-реестры, очереди, тела запросов, статические snapshots и admission-пути. Значения проверяются совместно: per-owner лимиты не могут превышать глобальные, резервы очередей должны сохранять прогресс control frames, body-резервы должны помещаться в общий бюджет, а все заявленные байтовые границы — в `memory_envelope_bytes`. Изменение любого значения этой таблицы требует перезапуска процесса.
| Ключ | Тип | По умолчанию | Описание |
| --- | --- | --- | --- |
| `max_header_bytes` | `usize` | `16384` | Максимальный размер заголовка одного HTTP-запроса. |
| `max_body_bytes` | `usize` | `2097152` | Максимальный размер собранного carrier body. |
| `max_frame_payload_bytes` | `usize` | `1048576` | Максимальный payload одного WEB frame. |
| `carrier_batch_bytes` | `usize` | `2097152` | Максимальный закодированный downlink batch. |
| `max_frames_per_body` | `usize` | `4096` | Максимальное число frames в одном carrier body. |
| `max_http_connections` | `usize` | `1024` | Принятые WEB HTTP connections на весь процесс. |
| `max_http_handlers` | `usize` | `512` | Одновременно выполняемые HTTP handlers на весь процесс. |
| `max_body_readers` | `usize` | `32` | Одновременно собираемые request bodies на весь процесс. |
| `max_body_bytes_global` | `usize` | `67108864` | Глобальный байтовый резерв для собранных bodies. |
| `max_sessions_global` | `usize` | `128` | Активные WEB-сессии на весь процесс. |
| `max_sessions_per_ip` | `usize` | `16` | Активные сессии одного forwarded client IP. |
| `max_streams_per_session` | `usize` | `128` | Default активных logical streams на сессию. |
| `max_streams_global` | `usize` | `4096` | Активные logical streams на весь процесс. |
| `max_stream_handshakes` | `usize` | `256` | Одновременные внутренние MTProxy handshakes. |
| `max_tombstones_per_session` | `usize` | `4096` | Закрытые stream IDs, сохраняемые одной сессией. |
| `pending_bytes_per_session` | `usize` | `33554432` | Байты данных и управления в очередях одной сессии. |
| `pending_bytes_global` | `usize` | `536870912` | Байты данных и управления в очередях всего процесса. |
| `pending_items_per_session` | `usize` | `16384` | Элементы данных и управления в очередях одной сессии. |
| `pending_items_global` | `usize` | `262144` | Элементы данных и управления в очередях всего процесса. |
| `control_bytes_per_session` | `usize` | `262144` | Резерв одной сессии только для control frames. |
| `control_bytes_global` | `usize` | `16777216` | Process-wide резерв только для control frames. |
| `max_bootstraps_global` | `usize` | `512` | Активные bootstrap credentials на весь процесс. |
| `max_bootstraps_per_ip` | `usize` | `64` | Активные bootstrap credentials на один client IP. |
| `max_vhosts` | `usize` | `8` | Настроенные WEB virtual hosts. |
| `max_profiles` | `usize` | `32` | WEB-профили всех vhosts. |
| `max_static_files` | `usize` | `4096` | Элементы static snapshot всех vhosts. |
| `max_static_file_bytes` | `usize` | `8388608` | Максимальный размер одного статического файла. |
| `max_static_bytes` | `usize` | `67108864` | Размер static snapshots всех vhosts. |
| `memory_envelope_bytes` | `usize` | `805306368` | Заявленный envelope для HTTP heads, bodies, очередей и static snapshots; максимум 4 GiB. |
| `new_bootstraps_per_minute` | `u32` | `1200` | Устойчивая process-wide скорость выдачи bootstrap. |
| `new_bootstraps_burst` | `u32` | `256` | Process-wide burst выдачи bootstrap. |
| `new_sessions_per_minute` | `u32` | `600` | Устойчивая process-wide скорость создания сессий. |
| `new_sessions_burst` | `u32` | `128` | Process-wide burst создания сессий. |
| `new_streams_per_minute` | `u32` | `6000` | Устойчивая скорость создания logical streams. |
| `new_streams_burst` | `u32` | `512` | Process-wide burst создания logical streams. |
# [web.timeouts]
Все таймауты задаются в секундах и должны входить в диапазон `1..=3600`. Самый длинный request deadline должен быть меньше `http_idle_secs`.
| Ключ | Тип | По умолчанию | Hot-Reload | Описание |
| --- | --- | --- | --- | --- |
| `header_secs` | `u64` | `10` | `` | Получение полного заголовка HTTP-запроса. |
| `body_secs` | `u64` | `30` | `` | Сбор одного аутентифицированного carrier body. |
| `stream_handshake_secs` | `u64` | `10` | `` | Выполнение внутреннего MTProxy handshake. |
| `long_poll_secs` | `u64` | `25` | `` | Максимальная длительность пустого downlink long poll. |
| `bootstrap_lifetime_secs` | `u64` | `120` | `` | Срок неиспользованного bootstrap и replay-marker закрытого token. |
| `reconnect_grace_secs` | `u64` | `120` | `` | Максимальная неактивность carrier до закрытия сессии. |
| `http_idle_secs` | `u64` | `75` | `` | Idle lifetime WEB HTTP keep-alive connection. |
| `shutdown_secs` | `u64` | `15` | `` | Deadline корректного завершения WEB. |
| `decoy_header_secs` | `u64` | `30` | `` | Deadline подключения и получения response head от HTTP decoy. |
# [[web.vhosts]]
| Ключ | Тип | Обязательный | Hot-Reload | Описание |
| --- | --- | --- | --- | --- |
| `host` | `String` | да | `` | Уникальный канонический lowercase ACE FQDN без порта, пути, credentials и завершающей точки. |
| `public_addr` | `SocketAddr` | да | `` | Конкретный публичный IP на порту `443`, используемый во внутреннем destination tuple relay. |
| `decoy` | таблица | да | `` | Обычный сайт для неаутентифицированного или некорректного трафика. |
| `profiles` | массив таблиц | при включённом WEB | `` | Явные пользователи и client secret modes для этого hostname. |
Forwarded client address и `public_addr` должны относиться к одному семейству IP. Hostname нормализуется при валидации и должен приниматься Telegram Desktop.
# [web.vhosts.decoy]
Обязателен ровно один decoy mode:
| Mode | Обязательные ключи | Валидация |
| --- | --- | --- |
| `http_upstream` | `upstream` | `http://` origin с loopback, link-local или private IP literal; без credentials, path, query и fragment. |
| `static_directory` | `directory`; необязательный `index = "index.html"` | Абсолютный реальный каталог и одно безопасное имя index-файла. Symlinks и выход за пределы каталога запрещены; immutable snapshot загружается в пределах `[web.limits]`. |
# [[web.vhosts.profiles]]
| Ключ | Тип | Обязательный | По умолчанию | Описание |
| --- | --- | --- | --- | --- |
| `user` | `String` | да | — | Существующий ключ из `[access.users]`. |
| `secret_mode` | `"plain"` или `"dd"` | да | — | Точное представление секрета для Telegram Desktop. `ee` не поддерживается. |
| `max_sessions` | `usize` | нет | `web.limits.max_sessions_global` | Активные сессии этого профиля. |
| `max_streams` | `usize` | нет | `web.limits.max_streams_global` | Активные logical streams этого профиля. |
| `max_streams_per_session` | `usize` | нет | `web.limits.max_streams_per_session` | Активные logical streams в одной сессии профиля. |
Лимиты профиля должны быть ненулевыми и не превышать соответствующие глобальные границы. Повторяющиеся профили `(user, secret_mode)` в одном vhost запрещены.
## Lifecycle WEB и управление через API
- Config watcher и generation reload применяют `web.enabled`, `web.timeouts`, vhosts, profiles и decoy snapshots без перезапуска процесса. Существующие сессии сохраняют лимиты и deadlines своего момента создания; новая работа использует активное поколение.
- Состав WEB-listeners и их trust policy в `server.listeners`, а также все значения `web.limits` принадлежат процессу и требуют перезапуска.
- Отдельного endpoint `/v1/web` нет. `GET /v1/config` не возвращает `[web]`, а `PATCH /v1/config` отклоняет ключ `web` с `400 section_not_editable`.
- Для удалённого применения WEB policy измените соответствующий TOML-файл и вызовите `POST /v1/system/reload`; проверьте `GET /v1/system/reload/{id}` и поле `deferred_process_fields`. Если оно содержит `server.listeners` или `web.limits`, перезапустите Telemt.
- Существующих access users можно создавать, изменять, ротировать, включать, выключать и удалять через `/v1/users`. Создание пользователя не добавляет WEB-профиль. Отключение пользователя немедленно обновляет admission и завершает его активные сессии.
- `PATCH /v1/config` может сохранить `server.listeners`, включая поля WEB-listener’а, но изменённый WEB-listener активируется только после перезапуска процесса.
# [timeouts]