OpenVPN und HTTPS auf Port 443: Wem gehört der Listener?
TCP und UDP 443 sind getrennte Sockets. Ein gemeinsamer TCP-Listener braucht einen Eigentümer, und die Portfreigabe von OpenVPN ist eine enge Vereinbarung, kein Proxy-Trick.
Zwei Dienste können beide auf Port 443 antworten, ohne je zu konkurrieren, denn ein Listener wird über Transport, Adresse und Port gemeinsam adressiert, nicht über die Nummer allein. Stellen Sie einen Webserver und OpenVPN auf eine Maschine, und die einzige Frage, die zuerst eine Antwort verdient, ist, welchen Socket jeder Prozess vom Kernel verlangt. Schreiben Sie diese Liste auf, bevor Sie eine Konfiguration bearbeiten, und die meisten Fehler „Adresse bereits in Gebrauch“ erklären sich selbst. Alles nach der Liste ist eine Wahl zwischen einem UDP-Listener, einem gemeinsamen TCP-Socket oder einem Frontend, das nach Protokoll weiterleitet.
Beginnen Sie mit dem Socket, den jeder Prozess verlangt
Ein Bind gelingt oder scheitert an diesem Tripel, also kollidieren zwei Daemons nur, wenn alle drei Teile übereinstimmen. Deshalb existiert eine Website auf TCP 443 unbegrenzt neben einem OpenVPN-Listener auf UDP 443, und deshalb beendet es auch die Diskussion, einen von beiden auf eine zweite lokale Adresse desselben Hosts zu verschieben. Lesen Sie die lebenden Listener statt der Dateien, die sie hätten erzeugen sollen, denn ein veraltetes Include oder eine vergessene Unit-Datei überlebt die Bearbeitung, an die Sie sich erinnern.
| Line in the listener list | What it establishes | What to do next |
|---|---|---|
| One udp row and one tcp row, each on 443 | Separate transport sockets, nothing contested | Point the VPN profile at udp and stop editing |
| A single tcp address and port listed by two processes | A real bind collision between two daemons | Move one service, or put a dispatcher in front of both |
| A proxy process owns the socket, no vpn process | The proxy accepts and has to hand off correctly | Check that its backend speaks the protocol it forwards |
Führen Sie ss -lntup als root aus und lesen Sie jede Zeile, die 443 nennt, IPv6-Einträge eingeschlossen. Ein Wildcard-Listener für v6 akzeptiert meist auch v4-Verkehr, und so hält ein Listener, den Sie vergessen haben, den Port belegt, nachdem Sie die Datei geändert haben, die Sie für verantwortlich hielten. Wenn ein Prozessname Sie überrascht, verengen Sie die Ausgabe mit ss -lntup 'sport = :443', bevor Sie irgendetwas anfassen.
Schalten Sie den Tunnel auf UDP um, wenn das Netz es zulässt
Ein UDP-Listener umgeht die Kollision vollständig und ist meist die kürzeste Reparatur, da kein Socket geteilt wird und kein zusätzliches Produkt in den Pfad tritt. Kostenlos ist das nicht. Manche Kundennetze verwerfen UDP 443, ohne ein Reset zu senden, sodass der Tunnel aufhört, sich aufzubauen, statt am Bind zu scheitern, und der Nutzer meldet das VPN als ausgefallen, ohne einen Fehler zum Lesen zu haben. Ein UDP-Listener überlebt außerdem einen Neustart der Webschicht, was auf einer Maschine zählt, deren Seite oft neu ausgerollt wird. Testen Sie aus dem Netz, in dem die Nutzer sitzen, denn eine Shell auf dem Server beweist nur, dass der Server sich selbst erreicht.
Ändern Sie den Transport in der Serverkonfiguration und im Clientprofil gemeinsam. Ein Profil, das noch TCP verlangt, läuft in Wiederholungsschleifen gegen einen reinen UDP-Listener, und das sieht wie ein Netzfehler aus, bis Sie die beiden Dateien vergleichen.
Lassen Sie den VPN-Prozess TCP 443 besitzen und leiten Sie den Rest weiter
Community OpenVPN im TCP-Servermodus liest die ersten Bytes einer eingehenden Verbindung und leitet alles, was nicht sein eigenes Protokoll ist, an ein HTTPS-Backend weiter, wofür die Direktive port-share da ist. Das Backend ist ein gewöhnlicher Webserver mit aktiviertem TLS, in dieser Direktive über Host und Port benannt statt über eine URL.
port-share 10.0.0.5 8080
Auf einer Maschine, auf der die Website eine zweite private Adresse hält, schickt diese Zeile Nicht-VPN-Verkehr an 10.0.0.5:8080, also muss der HTTPS-Virtualhost dort gebunden sein, und die Firewall muss den lokalen Hüpfer erlauben. Der Webserver muss TLS selbst terminieren, denn die ankommenden Bytes sind der ursprüngliche Handshake des Browsers, und nichts dazwischen hat sie entschlüsselt. Richten Sie die Direktive auf einen einfachen HTTP-Listener, und der Browser erhält einen Fehler wegen ungültiger Methode, der wie eine kaputte Seite und nicht wie ein falsch platziertes Backend aussieht. Die Direktive existiert nur im TCP-Servermodus, und ein UDP-Listener hat keinen Strom zum Prüfen.
Weil der VPN-Prozess jede Verbindung annimmt, sieht die Webanwendung die weitergeleitete Anfrage von einer der eigenen Adressen des Hosts ankommen statt vom Besucher. Alles, was die echte Clientadresse braucht, hängt von PROXY-Protokoll-Unterstützung im Backend ab oder von einem Frontend, das sie hinzufügt. Das Backend auf eine andere lokale Adresse zu verschieben bringt die Adresse des Besuchers nicht zurück; es ändert nur, welche der Hostadressen die Seite festhält. Schreiben Sie diese Einschränkung in die Betriebsnotizen, bevor ein Analysebericht die Frage aufwirft.
Ein Reverse-Proxy ist das falsche Werkzeug; ein Layer-Four-Router nicht
Ein HTTP-Reverse-Proxy terminiert TLS, um Anfragen lesen zu können, was bedeutet, dass er einen OpenVPN-Strom nicht unberührt durchlassen kann. Ein Layer-Four-Router, der nach SNI oder nach Prüfung des ersten Pakets weiterleitet, kann vor beiden stehen, sofern er nicht die Sitzung beendet, auf der das VPN beruht. Die beiden Geräte sehen im Diagramm gleich aus und verhalten sich am Socket völlig anders.
Der kommerzielle Access Server bringt eigene Einstellungen zur Portfreigabe mit, und die bilden nicht eins zu eins auf die Community-Direktive ab. Bestimmen Sie Produkt und Version, bevor Sie eine Anleitung anpassen, die für das andere geschrieben wurde. Eine kopierte Einstellung, die still ignoriert wird, ist schlimmer als keine Einstellung, weil die Listener-Liste danach noch plausibel aussieht.
Testen Sie Website und Tunnel als zwei getrennte Wege
Laden Sie die Seite und verbinden Sie den Tunnel, dann lesen Sie die Listener-Liste erneut, um zu sehen, welcher Prozess jetzt 443 besitzt. Eine Seite, die lädt, beweist nichts über das VPN, und ein Tunnel, der sich verbindet, beweist nichts über die Seite, obwohl beide dieselbe Nummer verwenden. Die drei Befehle unten prüfen den gemeinsamen Socket, den Webpfad und den VPN-Dienst in dieser Reihenfolge.
ss -lntup 'sport = :443' curl -sI https://vpn.example.com/ | head -n 1 journalctl -u openvpn-server@server -n 20
Vergleichen Sie die Clientadresse im Zugriffsprotokoll des Backends mit der im VPN-Protokoll zum selben Zeitpunkt. Wenn die Seite jeden Besucher als den Host selbst protokolliert, funktioniert die Weiterleitung und die Adressbehandlung nicht. Wenn beide Protokolle schweigen, hat das Frontend die Verbindung nie übergeben. So oder so entscheidet die Listener-Liste, wer den Socket annimmt, und das ist die Tatsache, die zu bestätigen ist, bevor Sie eine weitere Datei ändern.
Legen Sie diese Listener-Karte neben die Konfiguration, damit die nächste Person, die 443 anfasst, weiß, welcher Prozess annimmt und wohin das andere Protokoll gegangen ist. Bestätigen Sie den Besitz nach der Änderung, statt dem zu vertrauen, was die Bearbeitung bewirken sollte.