diff --git a/docs/WEB/WEB_PROXY.de.md b/docs/WEB/WEB_PROXY.de.md index c61b858..b65d28a 100644 --- a/docs/WEB/WEB_PROXY.de.md +++ b/docs/WEB/WEB_PROXY.de.md @@ -115,8 +115,177 @@ Die Behandlung überlasteter angenommener Sockets ist separat konfigurierbar. `d `decoy_fasttrack_mode` steuert ausschließlich die Capability-Verarbeitung für `GET/HEAD` am konfigurierten Basis-Root. `off` ist der Default und behält den vollständigen bisherigen Scan ohne Fast-Track-Zähler bei. `shadow` erfasst, welche strukturell unmöglichen Requests den Scan umgehen könnten, führt ihn aber weiterhin vollständig aus. `enforce` umgeht Capability-Arbeit nur bei `HEAD` oder fehlender beziehungsweise nicht kanonischer `bridge`-Query. Jeder exakte kanonische Bridge-GET am Basis-Root scannt bei Treffer und Fehlschlag vollständig alle Profile des ausgewählten vhost. Die Einstellung erfordert einen Prozessneustart; Reload speichert den gewünschten Wert, meldet `web.decoy_fasttrack_mode` aber als zurückgestellt. Fast-Track schützt nicht vor gegnerischer CPU-Last, da ein Scanner stets kanonische Kandidaten senden kann; `enforce` kann außerdem eine öffentliche Timing-Klasse der Request-Form sichtbar machen, insbesondere bei einem statischen Decoy. Aktivieren Sie diesen Modus nicht ohne externe Timing-Messungen über den produktiven TLS-Terminator. +## Gemeinsame Profile für mehrere Hostnamen + +Ersetzen Sie den Selektor `host` durch eine nicht leere Liste `hosts`, damit +mehrere Domains dieselben Profildefinitionen und denselben Decoy-Snapshot nutzen: + +```toml +[[web.vhosts]] +hosts = ["proxy.example.com", "backup.example.com"] +base_path = "telegram/web" +public_addr = "203.0.113.10:443" + +[web.vhosts.decoy] +mode = "http_upstream" +upstream = "http://127.0.0.1:18081" + +[[web.vhosts.profiles]] +user = "web-user" +secret_mode = "dd" +max_sessions = 8 +max_streams = 512 +max_streams_per_session = 64 +``` + +Dieses Fragment ergänzt den Zugangsbenutzer und WEB-Listener aus dem vorherigen +Beispiel. Geben Sie genau einen Selektor an: `host` oder `hosts`. Hostnamen werden +beim Laden normalisiert; danach identische Namen werden abgewiesen. Wildcard-Muster +und `*` erfordern die unten beschriebene ausdrückliche Aktivierung. Alle Mitglieder +teilen `base_path`, `public_addr`, Profile und Decoy. Bei abweichenden Einstellungen +sind getrennte Gruppen nötig. Der TLS-Terminator muss jeden aufgeführten Hostnamen +bedienen und den ursprünglichen kanonischen `Host` weiterreichen. + +Jeder Hostname hat eigene Capabilities, Bootstrap-/Sitzungszuordnungen und +Profilquoten. Das Beispiel erlaubt bis zu acht Sitzungen dieses Profils je Domain, +weiterhin begrenzt durch Prozess-, IP- und Zugangsbenutzerlimits. Beim Start werden +Links für jeden ausgewählten Benutzer/jedes Profil und jeden konkreten Hostnamen +ausgegeben. Die Gruppierung leitet Clients nicht um und macht Zugangsdaten nicht +zwischen Aliasnamen übertragbar. + +Bei exakten Namen zählt `max_vhosts` jeden Hostnamen und `max_profiles` jedes +Host-/Profilpaar. Acht Domains mit 100 Profilen benötigen beispielsweise mindestens +acht vhosts und 800 profiles. Statische Dateien und Bytes eines Gruppensnapshots +werden einmal gezählt; getrennte Gruppen behalten getrennte Snapshots. Konfigurierte +Sitzungsobergrenzen reservieren keine Sitzungen vorab. Gemeinsame unveränderliche +Richtlinien reduzieren Duplikate, Capability-Indizes wachsen aber weiterhin mit +der Anzahl der Host-/Profilpaare. + +Installieren Sie zuerst die neue Binärdatei mit der bisherigen Konfiguration +einzelner `host`-Einträge. Fassen Sie danach gleich konfigurierte Einträge per Reload +zusammen. Gruppierung und Umordnung erhalten kompatible Bootstrap-Zugangsdaten, +Quotenidentitäten und Lerndaten der Profile. Das Entfernen eines Aliasnamens weist +neue Requests für diesen Namen ab, ohne neue Abbruchregeln für bestehende +Verbindungen einzuführen. Höhere Limits erfordern einen Neustart und müssen vor +dem Hinzufügen von Bindungen oberhalb der aktiven Grenzen wirksam sein. Vor einem +Downgrade auf eine Version ohne `hosts` müssen Gruppen wieder in einzelne +`host`-Einträge aufgeteilt und die Budgets statischer Snapshots geprüft werden. + +## Automatische Wildcard-Hosts + +Exakte `host`-/`hosts`-Einträge bleiben der Standard. Für beliebige Subdomains +setzen Sie `web.allow_wildcard_hosts = true` und starten Telemt neu. Die vorhandenen +Selektoren akzeptieren dann auch `*.example.com` und `*`, einschließlich gemischter +Listen aus exakten Namen und Mustern: + +```toml +[web] +enabled = true +allow_wildcard_hosts = true + +[web.limits] +# Additional wildcard reservations must fit the declared envelope. +memory_envelope_bytes = 1610612736 + +[web.limits.wildcard] +max_rules = 32 +max_profiles_per_request = 256 +cache_hosts = 256 +cache_bytes = 8388608 +cold_hmac_per_minute = 1000000 +cold_hmac_burst = 65536 + +[[web.vhosts]] +hosts = ["proxy.example.com", "*.example.com"] +base_path = "relay" +public_addr = "203.0.113.10:443" + +[web.vhosts.decoy] +mode = "http_upstream" +upstream = "http://127.0.0.1:8080" + +[[web.vhosts.profiles]] +user = "web-user" +secret_mode = "dd" +``` + +Das Beispiel ergänzt den zuvor gezeigten Listener und Zugangsbenutzer. Ein Request +wählt genau eine Gruppe: zuerst den exakten Host, dann das längste passende Suffix, +dann `*`. Ein Suffix erfasst Nachfahren beliebiger Tiefe, auch `a.b.example.com`, +aber nicht den Stammnamen `example.com`. Fehlgeschlagene Authentifizierung fällt +nicht auf eine andere Regel zurück. Eingebettete Wildcards, reguläre Ausdrücke und +nach der Normalisierung doppelte Selektoren zwischen Gruppen sind unzulässig. +Die ausgewählte Gruppe behält ihre festen Werte für `public_addr`, Basispfad, +Profile und Decoy. Der Request-Host bestimmt keine Upstream-Adresse. + +In diesem Modus wird HTTP Host ohne Beachtung der ASCII-Groß-/Kleinschreibung +normalisiert; entfernt wird nur ein optionales wörtliches `:443`. Doppelte +Host-Header, IP-Literale, ungültige DNS-/ACE-Labels, abschließende Punkte und andere +Ports werden abgewiesen. `X-Forwarded-Host` wird nicht ausgewertet. Capabilities +verwenden den tatsächlichen kanonischen Hostnamen und die bestehende +Client-Ableitung; Clientänderungen sind nicht nötig. Sitzungs-/Stream-/Profilquoten +bleiben an das konkrete Tupel `(host, user, secret_mode)` gebunden; Prozess-, IP- +und Zugangsbenutzerlimits gelten weiterhin. Startlinks enthalten nur konfigurierte +exakte Hostnamen. + +Das Frontend **muss zulässige Host-Werte einschränken**; das unverschlüsselte WEB- +Backend muss privat erreichbar bleiben. TLS-Zertifikate müssen jeden tatsächlichen +Client-Hostnamen abdecken. Dies ist eine ausdrückliche Sicherheitsgrenze: Eine +Capability für einen unbekannten oder aus dem Cache verdrängten fremden Wildcard- +Host kann bei Übermittlung an einen anderen Host dessen Decoy erreichen, auch bei +einem exakten Host in einer gemischten Konfiguration. Capabilities des aktuellen +Hosts, der endlichen exakten Hostliste und des bekannten Positiv-Caches sowie +authentische Bootstrap-/Sitzungstokens des Prozesses bleiben in Request-URI und +Header-Metadaten lokal, einschließlich percent-encoded Formen. Öffentliche URLs, +Cookies und Header werden nicht allein wegen ihrer Ähnlichkeit mit Zugangsdaten +abgewiesen. Diagnosekopien maskieren dagegen vorsorglich ähnlich aussehende Texte, +auch abgeschnittene Präfixe; öffentliche Request-/Response-Bytes und ursprüngliche +User-Agent-Hashes bleiben unverändert. Daher kann die Diagnose auch gewöhnliche +lange Zeichenfolgen maskieren. + +Ein kalter Request reserviert vor jeder Ableitung atomar das HMAC-Budget für die +vollständige Profilzahl der ausgewählten Gruppe. Bei Erschöpfung folgt sofort +HTTP 503 mit no-store, ohne Warteschlange oder Teilscan. Ein Request verwendet +seine Tabelle sowohl zur Vermeidung von Credential-Lecks als auch zur Bridge- +Authentifizierung. Cachetreffer vermeiden die Ableitung. Authentifizierte Carrier +umgehen Capability-Tabellencache und Ableitung vollständig. Die Fast-Track-Modi +Off/Shadow/Enforce steuern weiterhin die Authentifizierung am Basis-Root; +fehlplatzierte Zugangsdaten des aktuellen Hosts bleiben in jedem Modus lokal. + +Nur eine erfolgreiche Bootstrap-Ausgabe für Bridge/Recovery füllt den FIFO-Cache. +`cache_hosts = 0` deaktiviert die Speicherung. Eintrags- und Byteobergrenzen sind +unabhängig; verdrängte Einträge belasten das Bytebudget weiter, solange ein Request +sie referenziert. Ein fehlgeschlagener Cacheeintrag verwirft keinen gültigen +Bootstrap, und Verdrängung setzt keine Quoten zurück. Cacheschlüssel enthalten die +eindeutige ID des unveränderlichen WEB-Snapshots, auch bei Reloads innerhalb +derselben Runtime-Generation. Einträge halten weder Decoy noch Generation fest. + +`max_vhosts` zählt exakte Einträge; `max_profiles` zählt exakte Bindungen sowie einen +gemeinsamen Profilsatz je Wildcard-Quellgruppe. `max_rules` begrenzt Muster und +`max_profiles_per_request` den vollständigen Scan einer Wildcard-Gruppe. Außer +`cache_hosts` müssen die Limits positiv sein; der HMAC-Burst muss eine vollständige +Request-Tabelle abdecken. Geprüfte Speicherreservierungen umfassen Vorlagen/Regeln, +Cache, Arbeitsspeicher der Handler und lebende Hostbindungen nur bei aktivem +Wildcard-Modus. Bei ansonsten standardmäßigen Limits reicht der bisherige Rahmen +von 1280 MiB nicht aus; 1290 MiB genügen nach aktueller Berechnung, das Beispiel +sieht 1536 MiB vor. Der Speicherrahmen und die Verarbeitung bei ausschließlich +exakten Hosts bleiben unverändert. + +Der Aktivierungsparameter und alle `web.limits` erfordern einen Prozessneustart. +Nach der Aktivierung lassen sich Selektoren und Profile per Reload ändern. Ein +API-Update kann den Parameter und ausreichende Limits als zurückgestellte +Änderungen speichern. Muster vor dem tatsächlichen Neustart hinzuzufügen wird +atomar abgewiesen, auch wenn der Parameter bereits in der gewünschten Konfiguration +steht. Zum Deaktivieren ersetzen Sie zuerst Muster durch exakte Selektoren und +starten dann mit deaktiviertem Parameter neu. Vor einem Downgrade entfernen Sie +Wildcard-Selektoren, den neuen Parameter und die Limittabelle. + ## Serverseitige Carrier-Negotiation +Bei `websocket-lanes` löst eine Ablehnung oder ein Timeout vor dem Upgrade einer Lane die gemeinsame Sitzungswiederherstellung aus. Fehler nach dem Upgrade bleiben auf die Lane begrenzt. Dieses Protokollverhalten belegt keine native macOS-/iOS-Kompatibilität bei Rückkehr aus dem Hintergrund. + +Die unveränderliche Bridge-Grundstruktur wird gecacht; Nonce, Bootstrap, Host und Basispfad werden für jede Antwort frisch eingesetzt. Ablaufprüfungen nutzen konservative Hinweise auf Deadlines, ohne Ablaufgrenzen zu verlängern. Diese internen Optimierungen ändern weder Wire-Formate, Zulassungslimits noch konfigurierte Timeouts und belegen allein keine kürzere Ende-zu-Ende-Verbindungszeit. + Auto-Negotiation ist optional und bleibt deaktiviert, solange `carriers` nicht als explizites, nicht leeres Array gesetzt ist. Der konfigurierte `carrier` bleibt der letzte Fallback und wird genau einmal angehängt, auch wenn er bereits im Array steht: ```toml @@ -175,7 +344,9 @@ Jeder Authentifizierungs-, Shape-, Lane-Reservierungs- oder Kapazitätsfehler vo Der WEB-Listener muss `proxy_protocol = false` und `reuse_allow = false` verwenden. `client_mss`, `synlimit`, `announce` und `announce_ip` sind nicht zulässig. `web_trusted_proxy_cidrs` muss nicht leer sein und darf nur die unmittelbar vorgeschalteten NGINX- oder HAProxy-Peers enthalten; `/0`-Netze werden abgelehnt. -Der HTTP-Decoy-Origin muss eine Loopback-, Link-Local- oder private IP-Adresse als Literal verwenden. Telemt bewahrt bei gewöhnlichen Requests Methode, Pfad, Query, Header, gestreamten Body, Response-Status, Header und Body und entfernt Hop-by-Hop-Header. Vor dem Fallback auf den Decoy entfernt Telemt Carrier-Zugangsdaten und Bodys aus fehlerhaften Carrier-Requests. Ein literaler Decoy-Endpunkt, der exakt einem effektiven WEB-Listener entspricht oder auf demselben Port von dessen gleichfamiliärer Wildcard-Adresse erfasst wird, wird abgelehnt. Indirekte Schleifen über DNS, NGINX, HAProxy oder eine andere Weiterleitungsschicht sind aus der Telemt-Konfiguration nicht beweisbar und müssen betrieblich ausgeschlossen werden. +Für `http_upstream` akzeptiert `resolve` die Werte `"never"` (Standard) und `"startup"`. Standardmäßig ist ein Loopback-, Link-Local- oder privates IP-Literal erforderlich. `startup` erlaubt zusätzlich DNS-Namen: Die asynchrone Konfigurationsvorbereitung löst jedes eindeutige Host-/Portpaar auf, prüft alle Antworten gegen erlaubte Adressklassen und effektive WEB-Listener und fixiert die erste Adresse in Resolver-Reihenfolge. Fehler, leere Antworten, öffentliche Adressen oder direkte Listener-Schleifen verwerfen die Vorbereitung. Der konfigurierte Hostname bleibt in der Upstream-Authority erhalten. Es gibt weder DNS während der Request-Verarbeitung noch automatischen Wechsel zu weiteren Antworten; Reload erstellt einen frischen Snapshot. `web.timeouts.decoy_resolve_secs` begrenzt jede DNS-Abfrage für ein eindeutiges Host-/Portpaar. Die Abfragen laufen nacheinander, ohne gemeinsame Deadline für die gesamte Vorbereitung. Indirekte Schleifen über weitere Weiterleitungsschichten müssen Betreiber ausschließen. + +Gewöhnliche Requests behalten Methode, Pfad, Query, Header, gestreamten Body sowie Response-Status und Body, außer Hop-by-Hop-Headern. Fehlerhafte Carrier-Requests verlieren vor der Decoy-Weiterleitung Zugangsdaten und Bodys. Alternativ kann ein unveränderlicher Snapshot einer statischen Site verwendet werden: @@ -307,7 +478,7 @@ proxy.example.com { } handle { - # gewöhnliche Site + # ordinary site } } ``` @@ -335,7 +506,7 @@ Tragen Sie in `web_trusted_proxy_cidrs` die Adresse ein, von der aus Caddy Telem | Konfiguration | Runtime-Verhalten | | --- | --- | | Bestand der WEB-Listener, Bind-Adresse und Vertrauensrichtlinie | Prozesseigen; Telemt neu starten. | -| Jeder Wert in `[web.limits]` | Prozesseigener Speicher- und Ressourcenvertrag; Telemt neu starten. | +| `web.allow_wildcard_hosts` und jeder Wert in `[web.limits]` | Prozesseigener Speicher- und Ressourcenvertrag; Telemt neu starten. | | `web.enabled`, Carrier-/Negotiation-Richtlinie, `web.debug`, Timeouts, vhosts, Profile und Decoys | Werden vom Config-Watcher oder durch einen Runtime-Generations-Reload angewendet. | | Änderung des `base_path` eines vhost | Schaltet Routing neuer HTTP-Requests und Capability-Ableitung atomar um. Geben Sie den generierten Link neu aus. Bereits hochgestufte WebSockets und laufende geroutete Austauschvorgänge laufen weiter. Spätere Requests an die alte Basis mit einem prozessauthentischen Bootstrap- oder Session-Token erhalten ein lokales, nicht cachebares `404`; die nun inaktive alte Capability folgt der gewöhnlichen Decoy-Behandlung. Ein bestehender Session-Bearer bleibt nur an der neuen exakten Basis verwendbar, während ein für die alte Capability ausgegebener ungenutzter Bootstrap an der neuen Basis keine Sitzung erstellen kann. | | Operator-Pause/-Drain-Zustand | Prozesseigen und flüchtig; übersteht einen Generations-Reload, schreibt niemals Konfiguration und wird nach einem Prozessneustart auf `running` zurückgesetzt. | @@ -356,7 +527,7 @@ WEB-Konfiguration, Runtime-Status und begrenzte Runtime-Steuerung verwenden dens | Operation | API-Unterstützung | | --- | --- | -| `[web]`, vhosts, Profile, Decoys, Timeouts oder Limits lesen oder ändern | Ja, über `GET` oder `PATCH /v1/config`. Der abgeleitete Snapshot `web.runtime` wird weder ausgegeben noch kann er geschrieben werden. Verschachtelte Tabellen werden feldweise zusammengeführt; Arrays ersetzen das bisherige Array vollständig. Jede Änderung an `[web.limits]` wird als gewünschte Konfiguration angenommen, aber bis zum Prozessneustart als zurückgestellt gemeldet. | +| `[web]`, vhosts, Profile, Decoys, Timeouts oder Limits lesen oder ändern | Ja, über `GET` oder `PATCH /v1/config`. Der abgeleitete Snapshot `web.runtime` wird weder ausgegeben noch kann er geschrieben werden. Verschachtelte Tabellen werden feldweise zusammengeführt; Arrays ersetzen das bisherige Array vollständig. Änderungen an `web.allow_wildcard_hosts` und `[web.limits]` bleiben bis zum Prozessneustart zurückgestellt. Muster setzen einen bereits aktivierten Wildcard-Modus im laufenden Prozess voraus. | | `server.listeners` speichern | Ja, über `PATCH /v1/config`; ein geänderter WEB-Listener bleibt jedoch bis zum Prozessneustart zurückgestellt. | | Außerhalb der API geänderte WEB-Konfiguration anwenden | Ja, über `POST /v1/system/reload` und anschließende Abfrage des Vorgangsstatus. | | Begrenzte serverseitige WEB-Request- und Lifecycle-Details untersuchen | Ja, über ein authentifiziertes `GET /web-status`. | @@ -441,7 +612,7 @@ curl -sS http://127.0.0.1:9091/v1/system/reload/RELOAD_ID \ -H "Authorization: ${TELEMT_API_AUTH}" ``` -Der terminale Status `succeeded` bestätigt die Runtime-Aktivierung. Geänderte Carrier-, Kandidaten-, Deadline- oder Learning-Richtlinien werden von neu ausgegebenen Bridge-Sitzungen verwendet; bestehende Sitzungen und laufende Versuchsketten werden nicht migriert. Enthält `deferred_process_fields` den Wert `server.listeners` oder `web.limits`, ist die Datei gültig und gespeichert, diese Einstellungen erfordern aber weiterhin einen Telemt-Neustart. +Der terminale Status `succeeded` bestätigt die Runtime-Aktivierung. Geänderte Carrier-, Kandidaten-, Deadline- oder Learning-Richtlinien werden von neu ausgegebenen Bridge-Sitzungen verwendet; bestehende Sitzungen und laufende Versuchsketten werden nicht migriert. Enthält `deferred_process_fields` den Wert `server.listeners`, `web.allow_wildcard_hosts` oder `web.limits`, ist die Datei gültig und gespeichert, diese Einstellungen erfordern aber weiterhin einen Telemt-Neustart. Operationen für Access-Benutzer verwenden die vorhandenen Endpunkte, zum Beispiel: @@ -485,7 +656,7 @@ Der vollständige Vertrag für Requests, Revisionen, Fehler und alle Benutzer-En | Symptom | Prüfung | | --- | --- | -| WEB-Konfiguration ist auf dem Datenträger gültig, aber das Listener-Verhalten hat sich nicht geändert | Prüfen Sie `deferred_process_fields`; Listener- und `[web.limits]`-Änderungen erfordern einen Neustart. | +| WEB-Konfiguration ist auf dem Datenträger gültig, aber das Listener-Verhalten hat sich nicht geändert | Prüfen Sie `deferred_process_fields`; Listener- und `web.allow_wildcard_hosts` / `[web.limits]`-Änderungen erfordern einen Neustart. | | Carrier-Requests erreichen den Decoy | Prüfen Sie den exakten vhost, den Secret-Modus des Links, das CIDR des direkten Proxys und genau einen syntaktisch gültigen `X-Forwarded-For`-Wert. | | Ein Link funktioniert nach einer Änderung von `base_path` nicht mehr | Importieren Sie den neu ausgegebenen Pfad-Link und prüfen Sie, dass das vollständige neue Präfix Telemt unverändert erreicht. Bestehende Sitzungen können sich nur über die neue exakte Basis wiederherstellen; alte Capabilities sind nicht wiederverwendbar. | | `/telegram/web` leitet auf `/telegram/web/` um | Fügen Sie für den Pfad ohne Schrägstrich einen exakten Non-WEB-Handler hinzu. Nur der mit Schrägstrich abgeschlossene konfigurierte Teilbaum gehört zum WEB-Vertrag von Telemt. | diff --git a/docs/WEB/WEB_PROXY.ru.md b/docs/WEB/WEB_PROXY.ru.md index bc017c7..516df30 100644 --- a/docs/WEB/WEB_PROXY.ru.md +++ b/docs/WEB/WEB_PROXY.ru.md @@ -115,8 +115,170 @@ max_streams_per_session = 64 `decoy_fasttrack_mode` управляет только capability processing для `GET/HEAD` на настроенном base root. Значение `off` по умолчанию сохраняет полный прежний scan без fast-track counters. `shadow` учитывает, какие структурно невозможные запросы могли бы обойти scan, но всё равно выполняет его полностью. `enforce` обходит capability work только для `HEAD` либо отсутствующего или неканонического query `bridge`. Каждый точный канонический bridge GET на base root выполняет полный scan всех профилей выбранного vhost и при совпадении, и при промахе. Настройка требует перезапуска процесса: reload сохраняет желаемое значение, но сообщает `web.decoy_fasttrack_mode` как deferred. Fast-track не защищает от злонамеренной CPU-нагрузки, потому что scanner всегда может отправлять канонические candidates; кроме того, `enforce` может создать публично наблюдаемый timing class формы запроса, особенно при статическом decoy. Не включайте этот режим без внешних timing measurements через production TLS-терминатор. +## Общие профили для нескольких доменов + +Замените селектор `host` непустым списком `hosts`, чтобы несколько доменов +использовали общие определения профилей и один снимок decoy: + +```toml +[[web.vhosts]] +hosts = ["proxy.example.com", "backup.example.com"] +base_path = "telegram/web" +public_addr = "203.0.113.10:443" + +[web.vhosts.decoy] +mode = "http_upstream" +upstream = "http://127.0.0.1:18081" + +[[web.vhosts.profiles]] +user = "web-user" +secret_mode = "dd" +max_sessions = 8 +max_streams = 512 +max_streams_per_session = 64 +``` + +Этот фрагмент дополняет пользователя доступа и WEB listener из предыдущего +примера. Укажите ровно один селектор: `host` или `hosts`. При загрузке имена +нормализуются; совпадающие после нормализации имена запрещены. Шаблоны wildcard +и `*` требуют явного включения режима, описанного ниже. У всех доменов группы +общие `base_path`, `public_addr`, профили и decoy. Если эти настройки различаются, +создайте отдельные группы. TLS-терминатор должен обслуживать каждый домен из +списка и передавать исходный канонический `Host`. + +У каждого домена свои capability, bootstrap/session credentials и квота профиля. +В примере профиль допускает до восьми сессий на каждом домене с учётом общих +ограничений процесса, IP и пользователя доступа. При запуске ссылки формируются +отдельно для каждого выбранного пользователя/профиля и конкретного домена. +Группировка не перенаправляет клиентов и не позволяет переносить credentials +между доменами. + +В режиме точных имён `max_vhosts` учитывает каждый домен, а `max_profiles` — +каждую пару домен/профиль. Для восьми доменов со 100 профилями нужны пределы +не менее восьми vhosts и 800 profiles. Статические файлы и байты снимка одной +группы учитываются один раз; у отдельных групп снимки отдельные. Настроенные +максимумы сессий не резервируют сессии заранее. Общая неизменяемая политика +уменьшает дублирование, но индексы capability растут с числом пар домен/профиль. + +Сначала установите новую сборку с прежней конфигурацией одиночных `host`, затем +объедините одинаково настроенные записи через reload. Группировка и перестановка +доменов сохраняют совместимые bootstrap credentials, идентичность квот и данные +обучения профиля. Удаление домена запрещает новые запросы к нему, не вводя новых +правил завершения существующих соединений. Увеличение лимитов требует перезапуска +и должно вступить в силу до добавления записей сверх действующих пределов. +Перед откатом на сборку без поддержки `hosts` разверните группы в одиночные +записи `host` и повторно проверьте бюджет статических снимков. + +## Wildcard-хосты + +По умолчанию используются точные `host` / `hosts`. Для произвольных поддоменов +установите `web.allow_wildcard_hosts = true` и перезапустите Telemt. После этого +селекторы также принимают `*.example.com` и `*`; точные имена и шаблоны можно +смешивать в одном списке: + +```toml +[web] +enabled = true +allow_wildcard_hosts = true + +[web.limits] +# Additional wildcard reservations must fit the declared envelope. +memory_envelope_bytes = 1610612736 + +[web.limits.wildcard] +max_rules = 32 +max_profiles_per_request = 256 +cache_hosts = 256 +cache_bytes = 8388608 +cold_hmac_per_minute = 1000000 +cold_hmac_burst = 65536 + +[[web.vhosts]] +hosts = ["proxy.example.com", "*.example.com"] +base_path = "relay" +public_addr = "203.0.113.10:443" + +[web.vhosts.decoy] +mode = "http_upstream" +upstream = "http://127.0.0.1:8080" + +[[web.vhosts.profiles]] +user = "web-user" +secret_mode = "dd" +``` + +Этот пример дополняет ранее показанные listener и пользователя доступа. Запрос +выбирает одну группу: сначала точное имя, затем самый длинный подходящий суффикс, +затем `*`. Суффикс охватывает потомков любой глубины, включая `a.b.example.com`, +но не сам `example.com`. Неуспешная аутентификация не переключает запрос на +другое правило. Встроенные wildcard и регулярные выражения запрещены, как и +дубли селекторов после нормализации между группами. Выбранная группа сохраняет +свои фиксированные `public_addr`, базовый путь, профили и decoy. Заголовок Host +не выбирает адрес upstream. + +В этом режиме HTTP Host нормализуется без учёта регистра ASCII; удаляется только +необязательный буквальный порт `:443`. Повторные Host, IP-адреса вместо домена, +некорректные DNS/ACE-метки, завершающая точка и другие порты запрещены. +`X-Forwarded-Host` не используется. Capability вычисляется по фактическому +каноническому имени с существующим клиентским алгоритмом; менять клиентов не +нужно. Квоты сессий/потоков/профиля остаются привязаны к конкретной тройке +`(host, user, secret_mode)`. Ограничения процесса, IP и пользователя доступа +продолжают действовать. Ссылки при запуске выводятся только для точных имён. + +Frontend **обязан ограничивать допустимые Host**, а незашифрованный WEB backend +должен оставаться в закрытой сети. Сертификаты TLS должны покрывать каждое +фактическое имя клиента. Это явная граница безопасности: capability неизвестного +или вытесненного из кэша wildcard-домена, отправленная на другой домен, может +попасть в его decoy, в том числе на точный домен смешанной конфигурации. +Capability текущего домена, конечного списка точных доменов, известного +положительного кэша и подлинные bootstrap/session tokens процесса не передаются +в decoy в URI и заголовках, включая percent-encoded формы. Публичные URL, cookies +и заголовки не отклоняются лишь за сходство с credentials. Диагностические копии, +напротив, консервативно маскируют похожие строки, включая обрезанные префиксы; +байты публичных запросов/ответов и исходные хеши User-Agent не меняются. Поэтому +диагностика может маскировать и обычные длинные строки. + +Перед вычислениями холодный запрос атомарно резервирует HMAC-бюджет для всех +профилей выбранной группы. При нехватке сразу возвращается HTTP 503 с no-store, +без очереди и частичного перебора. В пределах запроса одна таблица используется +для защиты от утечки credentials и аутентификации bridge. Попадание в кэш не +требует вычислений. Аутентифицированные carriers полностью обходят кэш таблиц +capability и их вычисление. Режимы fast-track Off/Shadow/Enforce по-прежнему +управляют проверкой корня; ошибочно размещённые credentials текущего домена +удерживаются локально в любом режиме. + +FIFO-кэш заполняется только после успешной выдачи bootstrap для bridge/recovery. +`cache_hosts = 0` отключает хранение. Пределы количества записей и байтов независимы; +вытесненная запись продолжает занимать байтовый бюджет, пока запрос удерживает +ссылку на неё. Неудача вставки не отменяет корректный bootstrap; вытеснение не +сбрасывает квоты. Ключ кэша содержит уникальный идентификатор неизменяемого WEB +снимка, в том числе при reload внутри одного поколения runtime. Записи не +удерживают decoy или поколение runtime. + +`max_vhosts` учитывает точные имена; `max_profiles` — точные привязки и один +общий набор профилей на каждую группу с wildcard. `max_rules` ограничивает число +шаблонов, а `max_profiles_per_request` — полный перебор группы wildcard. Все +пределы, кроме `cache_hosts`, должны быть положительными; HMAC burst должен +вмещать полную таблицу запроса. Проверяемый бюджет памяти включает шаблоны/правила, +кэш, рабочую память обработчиков и живые привязки доменов только при включённом +wildcard. С остальными стандартными лимитами прежних 1280 MiB недостаточно; +1290 MiB достаточно по текущему расчёту, а пример задаёт 1536 MiB. Бюджет и +обработка режима только с точными именами не меняются. + +Флаг включения и все `web.limits` требуют перезапуска. После включения селекторы +и профили можно менять через reload. API может сохранить флаг и достаточные +лимиты как отложенные изменения. Добавление шаблонов до фактического перезапуска +отклоняется атомарно, даже если флаг уже записан в желаемой конфигурации. Для +отключения сначала замените шаблоны точными именами, затем перезапустите процесс +с выключенным флагом. Перед откатом на старую сборку удалите wildcard-селекторы, +новый флаг и таблицу лимитов. + ## Server-side negotiation carrier +Для `websocket-lanes` отказ или таймаут до Upgrade отдельной lane запускает общее восстановление сессии. Сбой после Upgrade остаётся локальным для lane. Это свойство протокола не подтверждает совместимость восстановления нативных macOS/iOS клиентов после фонового режима. + +Неизменяемая основа bridge кэшируется, а nonce, bootstrap, host и base path подставляются заново для каждого ответа. Обработка истечения сроков использует консервативные оценки ближайших сроков, не продлевая сроки. Эти внутренние оптимизации не меняют форматы протокола, лимиты приёма или таймауты и сами по себе не доказывают сокращения полного времени подключения. + Auto-negotiation необязателен и выключен, пока `carriers` не задан явным непустым массивом. Настроенный `carrier` остаётся последним fallback и добавляется ровно один раз, даже если уже присутствует в массиве: ```toml @@ -175,7 +337,9 @@ WebSocket codec buffers и находящиеся в обработке read/wri Для WEB-listener обязательны `proxy_protocol = false` и `reuse_allow = false`. В нём нельзя использовать `client_mss`, `synlimit`, `announce` и `announce_ip`. Массив `web_trusted_proxy_cidrs` должен быть непустым и содержать только непосредственные адреса NGINX или HAProxy; сети `/0` запрещены. -HTTP decoy origin должен быть loopback, link-local или private IP literal. Для обычных запросов Telemt сохраняет method, path, query, headers, streamed body, response status, headers и body, удаляя hop-by-hop headers. Перед отправкой некорректного carrier-запроса в decoy Telemt удаляет из него carrier credentials и body. Literal decoy endpoint отклоняется, если он точно совпадает с effective WEB-listener либо покрывается wildcard address того же IP-семейства на том же порту. Косвенные loops через DNS, NGINX, HAProxy или другой forwarding layer нельзя доказать из конфигурации Telemt; оператор обязан исключить их самостоятельно. +Для `http_upstream` параметр `resolve` принимает `"never"` (по умолчанию) или `"startup"`. По умолчанию нужен IP-адрес из loopback, link-local или private диапазона. `startup` также разрешает DNS-имена: асинхронная подготовка конфигурации разрешает каждую уникальную пару имя/порт, проверяет все ответы по допустимым классам адресов и действующим WEB listeners и закрепляет первый адрес в порядке ответа resolver. Ошибка, пустой ответ, публичный адрес или прямая петля к listener отклоняют подготовку. В upstream authority сохраняется настроенное имя. DNS при обработке запросов и автоматического перехода к другим ответам нет; reload готовит новый снимок. `web.timeouts.decoy_resolve_secs` ограничивает отдельный DNS-запрос для каждой уникальной пары имя/порт. Запросы выполняются последовательно, общего таймаута подготовки нет. Косвенные петли через другие прокси оператор должен исключить самостоятельно. + +В обычных запросах сохраняются метод, путь, query, заголовки, потоковое тело, статус и тело ответа, кроме hop-by-hop заголовков. Из некорректных carrier-запросов перед передачей в decoy удаляются credentials и тело. Вместо origin можно использовать immutable snapshot статического сайта: @@ -307,7 +471,7 @@ proxy.example.com { } handle { - # обычный сайт + # ordinary site } } ``` @@ -335,7 +499,7 @@ log { | Конфигурация | Поведение runtime | | --- | --- | | Состав WEB-listeners, bind address и trust policy | Принадлежат процессу; перезапустите Telemt. | -| Любое значение `[web.limits]` | Process-owned контракт памяти и ресурсов; перезапустите Telemt. | +| `web.allow_wildcard_hosts` и любое значение `[web.limits]` | Process-owned контракт памяти и ресурсов; перезапустите Telemt. | | `web.enabled`, policy carrier/negotiation, `web.debug`, timeouts, vhosts, profiles и decoys | Применяются config watcher или runtime generation reload. | | Изменение `base_path` vhost | Атомарно переключает маршрутизацию новых HTTP-запросов и derivation capability. Выпустите новую сгенерированную ссылку. Уже upgraded WebSockets и начатые маршрутизированные обмены продолжаются. Последующие запросы к старому base с подлинным для процесса bootstrap- или session-token получают локальный no-store `404`, а ставшая неактивной прежняя capability обрабатывается как обычный decoy traffic. Существующий session bearer остаётся пригодным только на новом точном base, а неиспользованный bootstrap, выданный для старой capability, не может создать session на новом base. | | Operator pause/drain state | Process-owned и ephemeral; переживает generation reload, никогда не записывает конфигурацию и после перезапуска процесса возвращается в `running`. | @@ -356,7 +520,7 @@ HTTP idle accounting защищает только явно ограниченн | Операция | Поддержка API | | --- | --- | -| Чтение или изменение `[web]`, vhosts, profiles, decoys, timeouts или limits | Да, через `GET` или `PATCH /v1/config`. Производный snapshot `web.runtime` не возвращается и недоступен для записи. Вложенные tables сливаются по полям; arrays целиком заменяют прежний array. Любое изменение `[web.limits]` принимается как desired configuration, но помечается deferred до перезапуска процесса. | +| Чтение или изменение `[web]`, vhosts, profiles, decoys, timeouts или limits | Да, через `GET` или `PATCH /v1/config`. Производный snapshot `web.runtime` не возвращается и недоступен для записи. Вложенные tables сливаются по полям; arrays целиком заменяют прежний array. Изменения `web.allow_wildcard_hosts` и `[web.limits]` откладываются до перезапуска процесса. Добавлять шаблоны можно только после включения wildcard в действующем процессе. | | Сохранение `server.listeners` | Да, через `PATCH /v1/config`, но изменённый WEB-listener остаётся deferred до перезапуска процесса. | | Применение WEB-конфигурации, изменённой вне API | Да, через `POST /v1/system/reload` с последующей проверкой статуса операции. | | Просмотр bounded серверных WEB request- и lifecycle-деталей | Да, через аутентифицированный `GET /web-status`. | @@ -441,7 +605,7 @@ curl -sS http://127.0.0.1:9091/v1/system/reload/RELOAD_ID \ -H "Authorization: ${TELEMT_API_AUTH}" ``` -Терминальный статус `succeeded` подтверждает активацию runtime. Изменённые carrier, candidates, deadlines или learning policy используют новые bridge sessions; существующие сессии и начатые attempt chains не мигрируют. Если `deferred_process_fields` содержит `server.listeners` или `web.limits`, файл валиден и сохранён, но эти настройки всё ещё требуют перезапуска Telemt. +Терминальный статус `succeeded` подтверждает активацию runtime. Изменённые carrier, candidates, deadlines или learning policy используют новые bridge sessions; существующие сессии и начатые attempt chains не мигрируют. Если `deferred_process_fields` содержит `server.listeners`, `web.allow_wildcard_hosts` или `web.limits`, файл валиден и сохранён, но эти настройки всё ещё требуют перезапуска Telemt. Операции с access users используют существующие endpoints, например: @@ -485,7 +649,7 @@ curl -sS -X POST http://127.0.0.1:9091/v1/users/web-user/rotate-secret \ | Симптом | Что проверить | | --- | --- | -| WEB-конфигурация валидна на диске, но поведение listener’а не изменилось | Проверьте `deferred_process_fields`; listener и `[web.limits]` требуют перезапуска. | +| WEB-конфигурация валидна на диске, но поведение listener’а не изменилось | Проверьте `deferred_process_fields`; listener и `web.allow_wildcard_hosts` / `[web.limits]` требуют перезапуска. | | Carrier-запросы попадают в decoy | Проверьте точный vhost, secret mode ссылки, CIDR непосредственного proxy и единственное корректно разбираемое значение `X-Forwarded-For`. | | Ссылка перестала работать после изменения `base_path` | Импортируйте заново напечатанную path-ссылку и убедитесь, что полный новый prefix без изменений попадает в Telemt. Существующие sessions могут восстановиться только через новый точный base; старые capabilities нельзя использовать повторно. | | `/telegram/web` перенаправляет на `/telegram/web/` | Добавьте точный non-WEB handler для path без слеша. В WEB-контракт Telemt входит только настроенное поддерево с завершающим слешем. |