Das Relay hinter einem Reverse Proxy betreiben
Ein Reverse Proxy ist ein eigener Webserver, der die Verbindung vom Browser
annimmt und an das Relay weitergibt. Du brauchst einen, wenn du HTTPS für ein
Relay in deinem LAN oder auf einem Server willst, wenn das Relay unter einem
Unterpfad einer Website liegen soll, die du schon betreibst
(https://), oder wenn der Edge eines Tunnels (zum Beispiel
Cloudflare) zwischen Browser und Relay sitzt. Ein Proxy auf dem eigenen Rechner
des Relays funktioniert ohne jede Einstellung. Ein Proxy auf einem anderen
Rechner braucht zwei oder drei, gezeigt weiter unten. Fünf Keys
in config. informieren das Relay über den Proxy, und jeder regelt etwas
Bestimmtes; sie werden danach erklärt.
Was der Proxy tun muss #
Die Seite des Relays, seine API und seine Live-Verbindung nutzen alle einen
Port (3333, sofern du port nicht geändert hast). Der Proxy muss:
- WebSocket-Upgrades durchlassen. Die App hält eine Socket.IO-Verbindung
zum Relay offen, auf dem Pfad
/(mit Präfixsocket. io/ <prefix>/). Kommen Upgrades nicht durch, lädt die Seite, zeigt aber nie Live-Updates.socket. io/ - Langlebige Verbindungen nicht puffern und nicht per Timeout beenden. Dieser Socket bleibt offen, solange die Seite offen ist, und Turns werden in Echtzeit darüber gestreamt. Nimm lange Lese- und Leerlauf-Timeouts und puffere keine Antworten.
- Den Header
Hostdurchreichen oderX-senden. Das Relay baut daraus die Adresse eines geteilten Links und nimmt Neu in 0.9.11 die Live-Verbindung nur von einer Seite unter dieser Adresse an (sieheForwarded- Host allowed).Origins X-undForwarded- Host X-zählen nur von einem Proxy, dem das Relay vertraut.Forwarded- Proto X-senden, wenn der Proxy TLS terminiert, damit das Relay weiß, dass der Browser HTTPS benutzt hat (siehe Cookies und HTTPS), undForwarded- Proto X-, damit es die Adresse des Clients kennt.Forwarded- For - Den Pfad unverändert lassen. Schreib ihn nicht um. Lieferst du das Relay
unter einem Präfix aus, entfernt das Relay das Präfix selbst (siehe
remote).Path
Du brauchst keine Cache-Regel. Das Relay sendet Cache- für
seine Seite, seinen Service Worker, sein Manifest und seine API, außerdem
CDN- und Cloudflare-.
Leg keine Regel an, die / zwischenspeichert: Geteilte Ansichten
fragen regelmäßig nach neuem Inhalt, und eine zwischengespeicherte Antwort würde
Betrachtern einen alten Stand zeigen.
Ein minimales Caddy-Beispiel für ein Relay auf demselben Rechner. Caddy lässt
WebSocket-Upgrades von selbst durch und fügt X- hinzu:
relay.example.com {
reverse_proxy 127.0.0.1:3333
}
Bei nginx oder einem anderen Proxy schau in dessen eigener Dokumentation nach, wie man Upgrades durchlässt und Timeouts setzt, und gleiche das mit der Liste oben ab. Zu Tunneln siehe SSH-Tunnel und Cloudflare Tunnel; zum Zugriffstoken siehe Zugriff.
Ein Proxy auf einem anderen Rechner Neu in 0.9.11 #
Die eingebauten Tunnel und ein Proxy auf dem eigenen Rechner des Relays
erreichen das Relay über 127., und der Standard von trust glaubt
ihren weitergeleiteten Headern. Ein Proxy auf einem anderen Host oder in einem
anderen Container oder einer anderen VM ist ein anderer Peer. Solange du ihm
nicht vertraust, ignoriert das Relay seine Header X-,
X- und X-, also:
- hat jeder Besucher die Adresse des Proxys: eine Anmeldesperre für alle und eine Adresse in jedem Eintrag im Zugriffsprotokoll;
- beginnen neue geteilte Links mit
http://und dem Host, den der Proxy geschickt hat; - wird das Anmelde-Cookie nicht als
Securemarkiert.
Setz drei Keys in der Config-Datei und starte das Relay neu:
{
"localhostOnly": false,
"trustProxy": "192.0.2.10",
"allowedOrigins": ["https://relay.example.com"]
}
localhostlässt das Relay über Loopback hinaus lauschen. Halte den Port für alles außer dem Proxy geschlossen.Only: false trustist die Adresse des Proxys, sein Subnetz oder die Zahl der Proxys vor dem Relay (Proxy 1für einen). Siehe unten.allowedbrauchst du nur, wenn der Proxy den HeaderOrigins Hostumschreibt und keinX-sendet. Siehe unten.Forwarded- Host
Ein Proxy auf dem eigenen Rechner des Relays braucht weder trust noch
localhost, und allowed nur, wenn er Host umschreibt.
Unter einem URL-Präfix setz außerdem remote.
Die Keys, die das Relay über den Proxy informieren #
Alle fünf stehen in der Tabelle auf config.json. Starte das Relay neu, nachdem du sie geändert hast.
trustProxy #
Standard "loopback". Er entscheidet, wessen X--Header das Relay
glaubt. Mit dem Standard wird nur einem Proxy geglaubt, der sich vom selben
Rechner aus verbindet; das passt für Caddy, nginx oder cloudflared neben dem
Relay.
Was das Relay aus den Headern eines vertrauenswürdigen Proxys übernimmt:
- ob die Anfrage über HTTPS kam; davon hängt ab, ob das Anmelde-Cookie das
Flag
Secureträgt, und das Schema eines neuen geteilten Links; - den Host, den der Browser angesprochen hat (
X-), für neue geteilte Links und für die Origin-Prüfung der Live-Verbindung;Forwarded- Host - die Adresse des Clients, für die Anmeldesperre, das Anwesenheitslimit
geteilter Ansichten und das Zugriffsprotokoll geteilter Links. Das Land in
diesem Protokoll (
cf-) wird ebenfalls nur von einem vertrauenswürdigen Proxy gelesen.ipcountry
Läuft dein Proxy auf einem anderen Rechner, sieht das Relay einen nicht lokalen
Peer und ignoriert diese Header. Gib trust das, was Express’ trust proxy
annimmt: eine Hop-Anzahl (1), eine Adresse oder ein Subnetz
("10.), eine Liste davon oder "loopback".
Nur mit einem Proxy davor
Setz trust nur dann weiter als "loopback", wenn wirklich jede
Verbindung zum Relay über deinen Proxy kommt. Sonst kann jeder, der den Port
erreicht, ein gefälschtes X- senden.
Neu in 0.9.11 Jede Nutzung eines weitergeleiteten Headers folgt trust.
In 0.9.10 lasen das Anwesenheitslimit geteilter Ansichten und die Adresse eines
neuen geteilten Links sie von jedem Client.
allowedOrigins Neu in 0.9.11 #
Standard []. Die Live-Verbindung (Socket.IO) nimmt den Handshake eines
Browsers nur vom eigenen Origin des Relays an: Der Origin, den der Browser
sendet, muss den Host haben, den der Browser angesprochen hat; das ist
X-, wenn ein vertrauenswürdiger Proxy ihn sendet, sonst Host.
Eine Seite auf einer anderen Website kann dein Anmelde-Cookie nicht nutzen, um
eine Live-Verbindung zu öffnen. Clients, die keinen Origin senden, etwa
Skripte, sind nicht betroffen.
Ein Proxy, der den Header Host auf die interne Adresse des Relays umschreibt
und kein X- sendet, macht diesen Vergleich kaputt. Trag dann den
öffentlichen Origin ein, genau so, wie der Browser ihn zeigt, mit Schema, Host
und jedem Port außer dem Standardport:
"allowedOrigins": ["https://relay.example.com"]
Ohne das lädt die Seite und du kannst dich anmelden, aber nichts aktualisiert sich live, und das Relay schreibt einmal pro Origin ins Log:
[socket] Refused a handshake from origin https://relay.example.com (host 127.0.0.1:3333); list it in allowedOrigins if a proxy rewrites the Host header
remotePath #
Standard "". Setz ihn auf das Präfix, wenn der Proxy das Relay unter einem
Unterpfad ausliefert, zum Beispiel "/. Ein führender Schrägstrich wird
ergänzt, abschließende Schrägstriche werden entfernt.
Ist er gesetzt, dann:
- nimmt das Relay das Präfix von jeder eingehenden Anfrage ab; der Proxy reicht den Pfad also mit dem Präfix weiter und entfernt es nicht;
- setzt das Relay das Präfix in den Pfad des Anmelde-Cookies, den Socket-Pfad
(
/) und die Adressen von Dateien und geteilten Links.oar/ socket. io/
Ohne ihn findet ein Relay unter einem Präfix seine eigenen Dateien und seinen
Socket nicht, weil die Seite / und / an der Wurzel der
Website anfragt. Öffne das Relay mit abschließendem Schrägstrich
(https://).
Eine installierte App gehört zu der Adresse, von der aus sie installiert wurde; ein Relay unter einem Präfix ist also eine eigene App. Siehe Als App installieren.
publicHostnames #
Standard []. Trag die Hostnamen ein, über die das Relay selbst erreicht wird,
zum Beispiel ["relay.. Das Relay nutzt sie an einer Stelle: Die
Preview-Lane lehnt eine previews. auf einem dieser Namen (oder
auf localhost oder 127.) ab, damit eine App in der Preview nie ein
Anmelde-Cookie mit dem Relay teilt. Stellst du das Relay unter einem neuen
Namen hinter einen Proxy und nutzt Previews, füge
diesen Namen hier hinzu.
tunnelMarkerHeaders #
Standard []. Die Namen von Headern, die dein Proxy oder der Edge deines
Tunnels jeder weitergeleiteten Anfrage hinzufügt. Das Relay nutzt sie für den
Pfadschutz des Session-Workers unten. cf-, das Cloudflare
hinzufügt, steht immer auf der Liste. Der Wert kann ein Array oder ein durch
Kommas getrennter String sein. Die Umgebungsvariable
COPILOT_ (durch Kommas getrennt) fügt weitere Namen
hinzu; Neu in 0.9.11 die beiden Listen werden zusammengeführt, sodass
tunnel die Variable nicht mehr abschaltet. Siehe
Umgebungsvariablen.
Der Statuspunkt
tunnel färbt den Statuspunkt nicht bernsteinfarben. Der Punkt
ist bernsteinfarben, solange der eigene verwaltete Cloudflare Tunnel des Relays
verbunden ist (siehe das Konversationsmenü). Ein
Proxy, den du selbst betreibst, färbt ihn nie bernsteinfarben.
Der Pfadschutz des Session-Workers #
Jede Agent-Session läuft in einem Worker auf dem Rechner des Relays, und der
Worker spricht mit dem Relay über einen WebSocket auf /
(mit Präfix <prefix>/). Ein Proxy oder Tunnel leitet
jeden Pfad seines Hostnamens an das Relay weiter; ohne Schutz wäre dieser Pfad
also aus dem Internet erreichbar. Nur lokale Worker sollen ihn nutzen.
Neu in 0.9.11 Der Schutz lässt eine Anfrage an diesen Pfad nur durch, wenn sie vom eigenen Rechner des Relays kommt und nichts sie weitergeleitet hat:
- der verbindende Peer ist Loopback (
127.oder0. 0. 1 ::);1 - sie trägt keinen Marker-Header:
cf-oder einen ausray tunnel;Marker Headers - sie trägt kein
X-,Forwarded- For ForwardedoderX-.Real- IP
Alles andere wird abgelehnt, bevor die Anmeldung geprüft wird:
- eine einfache Anfrage bekommt
403mit{"error":"Session worker endpoints are reachable from this machine only"}; - ein WebSocket-Upgrade bekommt
403 Forbidden, und die Verbindung wird geschlossen.
Jede Ablehnung wird als [tunnel- protokolliert, mit dem Merkmal, das die Anfrage verraten hat. Lokale
Worker verbinden sich direkt mit 127., ohne einen dieser Header, und sind
nicht betroffen. Geteilte Links funktionieren weiter über den Tunnel: Der
Schutz richtet sich nur nach dem Worker-Pfad, nicht danach, ob eine Anfrage
anonym ist.
Cloudflare fügt cf- und Caddy X- von selbst hinzu, der
Schutz funktioniert mit ihnen also ohne Einstellung; bei nginx sende
X- mit proxy_. Ein Weiterleiter, der gar nichts
hinzufügt, etwa ein SSH-Reverse-Tunnel oder ein einfacher TCP-Proxy, sieht aus
wie ein lokaler Prozess; der Pfad ist dann nur durch das Zugriffstoken
geschützt. Lass einen solchen Weiterleiter einen Header mit festem, nicht leerem
Wert hinzufügen, zum Beispiel X-, und trag seinen Namen ein:
"tunnel. Oder sperr den Pfad vor dem Relay.
Endpunkte, die nur der Rechner des Relays nutzen darf #
Neu in 0.9.11 Zwei Dinge antworten nur auf Anfragen vom eigenen Rechner des Relays, die kein Proxy weitergeleitet hat, nach derselben Regel wie der Pfadschutz:
- der Socket des Session-Workers, oben;
- das Ausführen einer Bildoperation (
POST /), das die eigenen Worker des Relays aufrufen. Alles andere bekommtapi/ image- operations/ …/ execute 403Image operation execution is reachable from this machine only (Ausführen von Bildoperationen ist nur von diesem Rechner aus möglich).
Alles andere braucht nur das Zugriffstoken, egal woher die Anfrage kommt. Dazu gehören 🌄 Restart web relay (Web-Relay neu starten), das Zurückziehen eines eingereihten Neustarts mit dem Button Cancel (Abbrechen) auf seinem Banner sowie 🚮 Empty queue (Queue leeren): Jeder angemeldete Browser kann sie nutzen, auch über das LAN und durch jeden Proxy oder Tunnel.
Bis 0.9.10 waren diese drei nur für den Rechner des Relays gedacht, aber die
Prüfung ließ alles durch einen Tunnel oder einen Proxy auf demselben Rechner
durch und lehnte eine direkte LAN-Verbindung ab, während die Seite Erfolg
meldete. Wenn Nutzer aus der Ferne das Relay nicht neu starten oder seine Queue
nicht leeren dürfen, lass den Proxy POST /,
POST / und POST / ablehnen.
oar restart auf dem Rechner des Relays funktioniert immer.
Cookies und HTTPS #
Das Anmelde-Cookie ist Http und Same, gilt 30 Tage und hat den
Pfad / (oder das Präfix aus remote). Es trägt Secure, wenn das Relay
die Anfrage als sicher ansieht.
- Der Proxy terminiert TLS auf demselben Rechner. Der Proxy sendet
X-, der Standard vonForwarded- Proto: https trustglaubt das, und das Cookie istProxy Secure. - Der Proxy terminiert TLS auf einem anderen Rechner. Setz
trustwie oben. Bis dahin hat das Cookie kein FlagProxy Secure, funktioniert aber trotzdem. - Gemischte Setups. Öffnest du das Relay im LAN zusätzlich direkt über
einfaches
http, ist diese Anfrage nicht sicher, und ihr Cookie hat kein FlagSecure; die über den Proxy laufenden HTTPS-Anfragen bekommen das Flag. Browser speichern Cookies pro Adresse.
Das Setup prüfen #
- Öffne die Adresse über den Proxy in einem Browser. Die Anmeldung oder die Konversationsliste erscheint.
- Sieh auf den Statuspunkt: Er wird grün, und die Seite zeigt Live-Updates, wenn du einen Turn startest. Ein endloses Neuverbinden heißt, dass der WebSocket nicht durchkommt.
- Unter einem Präfix öffne die Adresse mit abschließendem Schrägstrich. Die Seite, ihre Styles und die Live-Verbindung laden, und der Pfad des Cookies ist das Präfix (sieh in den Entwicklertools des Browsers nach).
- Erstelle einen geteilten Link (Teilen). Seine
Adresse nutzt den öffentlichen Hostnamen und
httpsund das Präfix, falls du eins gesetzt hast. - Teste den Schutz von außen: Frag
https://an. Du solltestrelay. example. com/ api/ session- worker/ ws 403und eine Zeile[tunnel-im Log des Relays sehen. Bekommst du eine andere Antwort, fügt dein Proxy weder einen Marker-Header nochguard] X-hinzu.Forwarded- For - Hinter einem Proxy auf einem anderen Rechner: Melde dich von zwei Geräten an
und prüf unter Settings → Sharing (Einstellungen → Teilen), dass das Zugriffsprotokoll eines geteilten Links die
Adressen der Betrachter zeigt, nicht die des Proxys. Zeigt es die des
Proxys, passt
trustnicht zum Proxy.Proxy
Wenn es nicht funktioniert #
| Was du siehst | Wahrscheinliche Ursache |
|---|---|
| Die Seite lädt, verbindet sich aber endlos neu oder aktualisiert sich nie | Der Proxy lässt keine WebSocket-Upgrades auf / durch oder schließt untätige Verbindungen. |
Die Seite lädt, aber nichts aktualisiert sich live, und das Log sagt Refused a handshake from origin |
Der Proxy schreibt den Header Host um. Trag den öffentlichen Origin in allowed ein oder lass den Proxy Host durchreichen. |
| Die Anmeldung sagt Too many failed sign-in attempts (Zu viele fehlgeschlagene Anmeldeversuche) für alle gleichzeitig | Das Relay vertraut einem Proxy auf einem anderen Rechner nicht, also teilen sich alle Besucher seine Adresse und seine Sperre. Setz trust. |
| Unter einem Präfix ist die Seite leer, oder Dateien fehlen | remote ist nicht gesetzt, oder der Proxy entfernt das Präfix. Der Proxy muss es durchreichen. |
| Unter einem Präfix wirst du immer wieder zur Anmeldung aufgefordert | Der Pfad des Cookies ist das Präfix aus remote, also sendet der Browser es nur unter diesem Präfix. Öffne das Relay unter diesem Präfix und mit abschließendem Schrägstrich. |
| Geteilte Links oder Datei-Links haben die falsche Adresse oder kein Präfix | remote ist nicht gesetzt, oder der Proxy sendet kein Host bzw. kein X- / X-, oder das Relay vertraut dem Proxy nicht. |
Geteilte Links beginnen mit http://, oder das Cookie hat kein Flag Secure, hinter einem Proxy auf einem anderen Rechner |
trust ist noch "loopback". |
Der Worker-Pfad antwortet über deinen Proxy ohne 403 |
Der Proxy fügt weder einen Marker-Header noch X- hinzu. Siehe den Pfadschutz. |
| Der Punkt wird nie bernsteinfarben | Erwartet: Das macht nur der eigene verwaltete Cloudflare Tunnel des Relays. |
| Previews starten unter dem neuen Namen nicht | Füge den Hostnamen des Relays zu public hinzu. |
Zur ersten Anmeldung und zum Zugriffstoken siehe Erster Start.