Reverse Proxy
Der eingebaute Reverse Proxy macht andere Dienste unter eigenen Domains auf den Ports 443 und 80 erreichbar: Eine Anfrage für media.home.arpa geht an den Dienst dahinter, mit einem Zertifikat für diesen Namen. Die Box selbst bleibt auf Port 7484; jeder Name, den du nicht eingerichtet hast, geht wie bisher dorthin (oder bekommt 404, wenn du das wählst). Streams leiten einen TCP- oder UDP-Port der Box an einen anderen Host weiter. Alles liegt unter Einstellungen > Reverse Proxy (nur Administratoren), gilt ab der nächsten Anfrage ohne Neustart und ist Teil des Konfigurations-Backups.
Bevor du anfängst
Abschnitt betitelt „Bevor du anfängst“Lass jede Domain in deinem DNS-Server oder Router auf die Box zeigen (ein A- oder AAAA-Eintrag mit der Adresse der Box, oder ein Platzhalter-Eintrag für *.apps.home.arpa). Der Proxy beantwortet nur Namen, die ihn erreichen. Ohne HTTPS auf der Box (Entwicklung oder Simulation) antwortet er nur mit einfachem HTTP, und ein Entwicklungs-Daemon lauscht auf den Proxy-Ports nur, wenn PITHYX_DEV_PROXY_PORTS sie nennt.
Proxy-Hosts
Abschnitt betitelt „Proxy-Hosts“Proxy-Host hinzufügen öffnet die Einstellungen eines Hosts:
- Domains: bis zu 50 Namen, getrennt durch Kommas oder Leerzeichen. Ein führendes
*.deckt eine beliebige Ebene davor ab (*.apps.home.arpabeantwortetphotos.apps.home.arpa, nichta.b.apps.home.arpa); ein genauer Name gewinnt gegen einen Platzhalter. Ein Name gehört nur zu einem Host (proxy.domain.taken). Ein ausgeschalteter Host beantwortet nichts; seine Namen gelten als unbekannt. - Ziel: Protokoll, Host und Port des Dienstes. Bei
httpswählst du, wie sein Zertifikat geprüft wird: gegen die vertrauenswürdigen Stellen des Systems, gegen die eigene Zertifizierungsstelle der Box (Geräte mit einem Zertifikat aus Einstellungen > Zertifikate) oder gar nicht, für ein selbstsigniertes Zertifikat. - Das Ziel ist ein Dienst auf dieser Box selbst: nötig für ein Ziel wie
localhost, den Namen der Box oder eine ihrer Adressen (proxy.target.on_box), zum Beispiel um die Weboberfläche auf 7484 unter einer Domain zu erreichen. Die Ports 80 und 443 der Box werden immer abgelehnt, weil die Anfrage wieder beim Proxy ankäme (proxy.target.loop). - WebSockets weiterleiten: standardmäßig an; ausgeschaltet bekommen Upgrades 403 (
proxy.websockets.disabled).
Antworten fließen ungepuffert durch, Server-Sent Events und große Downloads kommen also beim Browser an, sobald sie entstehen. Mit Zielen spricht der Proxy HTTP/1.1.
- Zertifikat: Von der Zertifizierungsstelle der Box stellt im Speicher ein Zertifikat für die Domains des Hosts aus (397 Tage, erneuert 30 Tage vor dem Ende und immer, wenn sich die Zertifizierungsstelle ändert). Jede Domain muss im Bereich der Zertifizierungsstelle liegen (
tls.name.not_permitted); deine eigene Domain nimmst du mit einer neuen Zertifizierungsstelle in Einstellungen > Zertifikate in den Bereich auf. Eigenes hochladen nimmt ein Zertifikat mit Kette und unverschlüsseltem Schlüssel im PEM-Format, das jede Domain abdeckt (proxy.certificate.name_mismatch), zum Beispiel eines für eine öffentliche Domain. Ein abgelaufener oder kaputter Upload wird durch das eigene Zertifikat der Box ersetzt, und der Host zeigt Kein Zertifikat, wenn er keines hat. - Die Box wählt das Zertifikat nach dem Namen, den der Browser beim TLS-Handshake nennt, auf 443 und auf 7484; ein Name ohne Host bekommt das Zertifikat der Box.
- HTTP auf HTTPS umleiten (standardmäßig an) beantwortet einfaches HTTP auf 80 mit einer Umleitung auf 443 (301 für GET und HEAD, sonst 308). Ausgeschaltet antwortet der Host auch auf 80.
- HTTP/2 anbieten (standardmäßig an) lässt Browser auf 443 HTTP/2 nutzen.
- HSTS senden setzt
Strict-Transport-Security: max-age=31536000auf HTTPS-Antworten.
Zugriff
Abschnitt betitelt „Zugriff“Der Proxy prüft in dieser Reihenfolge: die erlaubten und gesperrten Adressen, Basic Auth, dann die Pithyx-Anmeldung.
- Erlaubte Adressen und Gesperrte Adressen: IP-Adressen oder Bereiche wie
192.168.1.0/24. Eine gesperrte Adresse kommt nie herein; mit erlaubten Adressen nur diese (proxy.address.denied). Die Box sieht die Adresse, von der die Verbindung kommt. - Basic Auth: Benutzer mit einem Passwort, nach dem der Browser vor allem anderen fragt. Passwörter werden als Argon2id-Hashes gespeichert und nie angezeigt; lass das Feld leer, um ein gespeichertes Passwort zu behalten. Fehlversuche zählen zu denselben Grenzen wie fehlgeschlagene Anmeldungen. Das Ziel bekommt den Header
Authorizationnicht. - Pithyx-Anmeldung verlangen: Eine Seite des Hosts schickt Besucher ohne Zugang zur Anmeldung der Box, standardmäßig auf dem aufgerufenen Namen und Port 7484 (oder an die Anmeldeadresse der Seite). Nach der Anmeldung dort kommt der Browser mit einem Einmal-Ticket (30 Sekunden) zu
/.pithyx/authauf dem Host zurück, der ein Cookie des Hosts setzt und zur Seite weitergeht. Anfragen, die keine Seite laden, bekommen 401 (proxy.auth.required). Das Cookie gehört zur Sitzung auf der Box: Abmelden von der Box, eine widerrufene Sitzung, das verlorene Recht zur Desktop-Anmeldung oder das Entfernen aus den Benutzern und Gruppen des Hosts beendet den Zugang bei der nächsten Anfrage. Benutzer und Gruppen begrenzen, wer hereinkommt (proxy.access.denied); ohne beide kommt jeder herein, der sich anmelden darf, Administratoren immer. Das Ziel bekommt den Benutzer inX-Pithyx-User,X-Pithyx-User-Id,X-Pithyx-GroupsundX-Pithyx-Admin. Der Pfad/.pithyx/autheines solchen Hosts gehört dem Proxy. Benutzer und Gruppen werden mit Namen gespeichert: Nach dem Umbenennen einer Gruppe passe den Host an.
- Das Ziel bekommt nie eingehende
X-Pithyx-*-,X-Forwarded-*-,Forwarded- oder Trace-Header und auch nicht die eigenen Cookies der Box (pithyx_*); eine Antwort kann diese Cookies auch nicht setzen. - X-Forwarded-For, -Proto und -Host senden (standardmäßig an) nennt dem Ziel die Adresse des Clients, das Protokoll und den aufgerufenen Namen.
- Den aufgerufenen Namen als Host senden gibt den
Hostdes Browsers weiter; sonst bekommt das Ziel seinen eigenen Host und Port. Host-Header setzt stattdessen einen eigenenHost. - Anfrage-Header und Antwort-Header: einer pro Zeile als
Name: Wert;Name:allein entfernt den Header. Header, die der Proxy selbst steuert (Host,Connection,X-Forwarded-*,X-Pithyx-*,Strict-Transport-Securityund andere), werden abgelehnt (proxy.header.invalid).
Grenzen und Protokoll
Abschnitt betitelt „Grenzen und Protokoll“- Größter Upload in MB: leer für keine Grenze.
- Verbindungs-Timeout (1 bis 300 Sekunden, Standard 10) und Antwort-Timeout (1 bis 86400 Sekunden, Standard 100: wie lange das Ziel schweigen darf). Ein ruhender WebSocket bleibt bis zu einem Tag offen. Ein unerreichbares Ziel ergibt 502 (
proxy.target.unavailable), ein zu langsames 504 (proxy.target.timeout). - Zugriffslog schreiben (standardmäßig an): jede Anfrage im Log Center unter der Quelle
proxy/<erste Domain>, mit Methode, Name, Pfad (ohne die Abfrage, die Geheimnisse enthalten kann), Status, Dauer, Adresse des Clients und, hinter einer Anmeldung, dem Benutzer.
Die Liste zeigt für jeden Host, ob sein Ziel beim Öffnen der Seite geantwortet hat; Ziel prüfen schaut noch einmal nach.
Weiterleitungs-Hosts
Abschnitt betitelt „Weiterleitungs-Hosts“Ein Weiterleitungs-Host schickt Browser von seinen Domains mit 301, 302, 307 oder 308 zu einer anderen Adresse. Mit Pfad und Abfrage behalten geht eine Anfrage für /a?b=1 an die Zieladresse, gefolgt von /a?b=1. Auf 443 zeigt er ein Zertifikat vor wie ein Proxy-Host.
Namen ohne Host
Abschnitt betitelt „Namen ohne Host“Namen ohne Host legt fest, was 443 und 80 mit einem Namen tun, den kein aktiver Host hat: Auf die Weboberfläche auf Port 7484 umleiten (Standard, wie ohne Reverse Proxy) oder Mit „nicht gefunden“ (404) antworten (proxy.host.unknown). Die Prüfung /api/install-id des Installers auf Port 80 antwortet immer.
Streams
Abschnitt betitelt „Streams“Ein Stream leitet einen Port der Box, TCP, UDP oder beides, Byte für Byte an einen Host und Port weiter, für Dienste, die kein HTTP sprechen. Die Firewall öffnet den Port, solange der Stream aktiv ist. Die eigenen Ports der Box werden abgelehnt (21, 22, 80, 443, 445, 7484 und die passiven FTP-Ports 50000 bis 50099, proxy.stream.port_reserved), ebenso Ports, die ein anderes Programm belegt (proxy.stream.port_in_use), und Ports unter 1024, außer du bestätigst sie. Ein UDP-Client behält seine eigene Verbindung zum Ziel, bis er eine Minute lang schweigt; ein Stream nimmt bis zu 512 TCP-Verbindungen und 1024 UDP-Clients gleichzeitig an.
Sicherheit
Abschnitt betitelt „Sicherheit“Der Proxy läuft im Daemon, der als root läuft, und nur Administratoren dürfen Ziele festlegen. Anfragen, die der Proxy selbst geschickt hat, erkennt er und lehnt sie mit 508 ab (proxy.loop.detected). Die Einstellungen sind im Konfigurations-Backup als Teil Reverse Proxy; hochgeladene Zertifikate kommen mit dem Teil Zertifikate (Dateien proxy-host-<id>.pem und .key neben denen der Box).
Noch nicht gebaut
Abschnitt betitelt „Noch nicht gebaut“Lastverteilung mit Health-Checks, Regeln pro Pfad, Ratenbegrenzung und Let’s Encrypt kommen später.