mirror of
https://github.com/telemt/telemt.git
synced 2026-10-31 21:02:01 +03:00
WEB: Common Profiles for multiple vhosts
This commit is contained in:
+177
-6
@@ -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. |
|
||||
|
||||
+170
-6
@@ -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 входит только настроенное поддерево с завершающим слешем. |
|
||||
|
||||
Reference in New Issue
Block a user