HAProxy 302 zu einer privaten App: Wer öffnet den zweiten Sprung?
Eine Weiterleitung gibt die zweite Verbindung an den Browser zurück. Schicken Sie die Anfrage stattdessen an ein Backend und korrigieren Sie dann die absoluten Weiterleitungen und Cookies der App selbst.
Jemand richtet einen öffentlichen HAProxy-Host auf eine lokale Anwendung und fragt, warum der Browser nicht folgen kann. Der Proxy erreicht die App über sein VPN, die Weiterleitung liefert einen Location-Header zurück, und der Browser versucht dann eine Adresse, die nur innerhalb des Tunnels existiert. Von außen hängt die Seite einfach. Die Entscheidung betrifft die Frage, welche Seite die zweite Verbindung öffnet, und genau das unterscheidet eine Weiterleitung von einem Backend.
Zwei Wege, die in der Konfiguration ähnlich aussehen
Eine Weiterleitung beendet den Austausch mit einer Antwort. Der Client liest Location und startet eine neue Anfrage von dem Ort aus, an dem er gerade sitzt, also aus dem Netz, das Sie nie kontrolliert haben. Der Proxy ist nicht mehr beteiligt. Alles Weitere hängt von DNS, Route und Vertrauen des Clients ab, deshalb variiert das Ergebnis je nachdem, wo der Benutzer den Browser geöffnet hat:
GET /app client -> proxy
302 Location proxy -> client (http://10.40.0.20:8080/)
GET /app client -> 10.40.0.20:8080 client network, no route
Ein Proxy-Backend behält die zweite Etappe auf der Serverseite. Der Proxy öffnet sie über den Weg, den er bereits hat, und der Client spricht weiter mit einem öffentlichen Namen. Fällt der Tunnel aus, erhält der Client einen Fehler statt einer URL, der er nicht folgen kann. Dieser Unterschied macht den Fehler auch diagnostizierbar, weil er dort auftaucht, wo die Protokolle liegen:
GET /app client -> proxy
GET /app proxy -> 10.40.0.20:8080 over the VPN
response proxy -> client
Die Dokumentation zu Weiterleitungen von HAProxy zieht genau diese Grenze: dem Client mit einer Weiterleitung zu antworten ist eine andere Aktion, als die Anfrage an ein Backend weiterzuleiten. Die beiden Direktiven stehen in einer Konfigurationsdatei nur wenige Zeilen auseinander und verhalten sich völlig unterschiedlich. Die eine beendet die Anfrage, die andere beginnt eine zweite, die dem Proxy gehört.
Was der Browser braucht und das VPN des Servers ihm nicht gibt
Die Anfrage des Browsers selbst braucht vier Dinge, die er womöglich nicht hat: eine DNS-Antwort für den privaten Namen, eine Route zu dieser Adresse, die Erlaubnis, den lauschenden Dienst zu erreichen, und Vertrauen in das Zertifikat, das dieser Dienst vorlegt. Der Proxy-Host besitzt alle vier über seinen Tunnel. Nichts davon überträgt sich auf einen Client, der nie in diesem Tunnel war, denn der Tunnel ist eine Eigenschaft des Hosts, nicht der URL.
Diese Lücke erklärt das Symptom des Fast-Funktionierens. Die erste Anfrage gelingt, die Adressleiste ändert sich, und danach hängt die Verbindung oder scheitert, während der Proxy die ganze Zeit gesund ist. An der Proxy-Konfiguration ist nichts kaputt, und sie anzupassen hilft keinem Client, der keinen Weg zu 10.40.0.20 hat. Entweder bekommt der Client eine Route, oder der Proxy muss die Verbindung für ihn aufbauen.
Wenn nur der Proxy die App erreichen kann
Entfernen Sie die Weiterleitungsaktion und schicken Sie diese Anfragen an ein Backend, das auf die private Adresse zeigt. Das Frontend behält seinen öffentlichen Namen, während das Backend entscheidet, wohin die Anfrage tatsächlich geht. Am Pfad des Clients ändert sich nichts, weil der Proxy aufhört, ein Ziel zu beschreiben, und anfängt, eines zu sein. Für eine Anwendung, die absichtlich auf dem internen Port 8080 lauscht, ist der Server-Block kurz:
backend private_app
mode http
option httpchk GET /health
server app1 10.40.0.20:8080 check
Lesen Sie diesen Block als Aussage über die Routing-Tabelle des Proxys: 10.40.0.20 muss vom Proxy-Host selbst erreichbar sein, was hier über die VPN-Schnittstelle statt über die Standardroute bedeutet. Das Schlüsselwort check meldet nur, was diese Route tut, und der Health-Pfad muss auf der Anwendung existieren, sonst stuft jede Prüfung den Server als down ein. Eine bestandene Prüfung beweist nichts über den Client und ersetzt nicht die Richtlinie, die entscheidet, wer das Backend nutzen darf.
Das Fragment ist kein vollständiges Frontend. Behalten Sie den Listener, die Authentifizierung, die Auswahl erlaubter Hosts und Pfade sowie die Regel, die überhaupt entscheidet, wer die Anwendung erreichen darf. Passen Sie auch das Backend-Protokoll an, denn ein HTTPS-Backend braucht Zertifikatsprüfung und eine Server-Identitätskonfiguration, und wer diese Prüfung auslässt, macht aus einer privaten Verbindung eine ungeprüfte.
Bestätigen Sie den Rückweg in beide Richtungen, bevor Sie den Sieg ausrufen. Die Anwendung sieht jetzt eine Verbindung vom Proxy, also beschreiben ihre Protokolle und alle Client-Adress-Metadaten den Proxy, sofern Sie nichts anderes einrichten. Entscheiden Sie, wie Identität und weitergeleitete Adressen behandelt werden, und testen Sie die Entscheidung, statt sie anzunehmen.
Die eigenen Weiterleitungen der App zeigen weiterhin nach innen
Die erste Anfrage weiterzuleiten ist nur die halbe Integration. Die Anwendung kann absolute Weiterleitungen, hart kodierte Asset-URLs oder Cookies ausgeben, die auf den Namen beschränkt sind, den sie intern kennt, und jedes davon schickt den Browser zurück an eine Adresse, die er nicht erreichen kann. Ein Location-Header, der auf den internen Namen zeigt, sieht genauso aus wie das ursprüngliche Problem, weshalb er als Proxy-Fehler fehldiagnostiziert wird.
Setzen Sie die dokumentierte externe URL der Anwendung und ihre Proxy-Optionen und bringen Sie dann den Host-Header mit dem virtuellen Host und den Zertifikatserwartungen in Einklang. Ein Cookie, das auf den internen Namen beschränkt ist, kommt über den öffentlichen Namen nicht zurück, und die Anmeldeschleife, die daraus folgt, liest sich wie ein Authentifizierungsfehler. Ändern Sie zuerst die externe URL, testen Sie erneut mit einem sauberen Browserprofil, und rechnen Sie damit, dass halb migrierte Einstellungen eine Anmeldung erzeugen, die gelingt, und eine Sitzung, die sofort stirbt.
Vertrauen Sie weitergeleiteten Metadaten nur vom dafür bestimmten Proxy. Ein Header, den jeder Client setzen kann, darf niemals ein Autorisierungswert werden, sonst wird der Proxy zu einem Weg für einen Aufrufer, die Identität eines anderen zu beanspruchen. Diese Regel ist unabhängig von der Weiterleitungsfrage und überlebt jedes spätere Redesign.
Entscheiden Sie, welches Design Sie tatsächlich haben
Wenn jeder Benutzer bereits autorisierten VPN-Zugang hat, kann eine Weiterleitung auf eine private URL ein bewusstes Design sein. Bestätigen Sie diese Anforderung ausdrücklich, statt sie anzunehmen, denn die beiden Designs bedienen völlig verschiedene Gruppen. Eines davon funktioniert aus einem Hotelnetz überhaupt nicht, und das andere stellt die Anwendung jedem zur Verfügung, der die öffentliche URL laden kann. Diese Unterscheidung gehört in die Design-Notiz.
Führen Sie die Prüfung von einem Rechner im Netz der Benutzer aus und verfolgen Sie jeden Sprung des Browsers, nicht nur die erste Antwort. Behalten Sie die Adressleiste und jede weitere Anfrage im Blick, denn eine einzige absolute URL in einem Asset-Tag genügt, um einen Ablauf zu brechen, den der erste Sprung bestanden hat. Die Anmeldung muss über den öffentlichen Namen funktionieren, und Ressourcen, die verweigert werden sollen, müssen verweigert bleiben.
Einen Reverse-Proxy zu veröffentlichen ist eine eigene Zugriffsentscheidung und keine transparente Erweiterung des VPN des Proxys auf jeden, der seine öffentliche URL laden kann. Im Diagramm sehen beide gleich aus, und sie unterscheiden sich darin, wer hineingelassen wird. Diese Frage erst nach dem Deployment zu entscheiden, ist der Weg, auf dem aus einer internen Anwendung versehentlich eine öffentliche wird.
Schreiben Sie auf, welche der beiden Varianten Sie gebaut haben und warum. Die nächste Person, die die Konfiguration anfasst, wird die andere annehmen. Eine einzelne aus Bequemlichkeit hinzugefügte Weiterleitung genügt, um den ursprünglichen Fehler wieder herzustellen, und das Symptom wird genau wie das eben behobene aussehen.