Ich habe mich gefragt, ob Nginx HTTP- und HTTPS-Anforderungen auf demselben Port verarbeiten kann . [*]
Das versuche ich zu tun. Ich verwende einen Webserver (lighttpd), der http-Anforderungen verarbeitet, und ein C-Programm, das über https einen bestimmten Abschnitt der Dokumentstruktur bedient. Diese beiden Prozesse werden auf demselben Server ausgeführt.
Auf der Firewall-Ebene kann ich nur einen Port für die Weiterleitung von Datenverkehr auf diesen Server haben . Also, was ich tun möchte, ist, Nginx auf diesem Server so einzurichten, dass es auf Anfragen an einem einzelnen Port wartet und dann:
A) leitet alle http://myhost.com/ * Anfragen um, so dass sie zu localhost gehen: 8080 (wo lighttpd lauscht)
B) Wenn ein Benutzer eine URL anfordert, die beispielsweise mit https: // myhost.com/app beginnt, sendet er diese Anforderung an localhost: 8008 (C-Programm). Beachten Sie, dass in diesem Fall der Datenverkehr zwischen dem Remote-Browser und Nginx verschlüsselt werden muss.
Glaubst du, das könnte möglich sein? Wenn ja, wie geht das?
Ich weiß, wie das mit zwei verschiedenen Ports geht. Die Herausforderung, der ich gegenüberstehe, besteht darin, dies mit nur einem einzigen Port zu tun (leider habe ich keine Kontrolle über die Firewall-Konfiguration in dieser bestimmten Umgebung, das ist also eine Einschränkung, die ich nicht vermeiden kann). Techniken wie Reverse-Port-Weiterleitung über ssh zur Umgehung der Firewall werden ebenfalls nicht funktionieren, da dies für Remotebenutzer funktionieren sollte, die nur einen Webbrowser und eine Internetverbindung haben.
Wenn dies über die Möglichkeiten von nginx hinausgeht, kennen Sie ein anderes Produkt, das diese Anforderungen erfüllen könnte? (Bisher habe ich es nicht geschafft, dies mit lighttpd und pound einzurichten). Ich würde es auch vorziehen, Apache zu meiden (obwohl ich bereit bin, es zu verwenden, wenn es die einzig mögliche Wahl ist).
Danke im Voraus, Alex
[*] Um es klar zu sagen, ich spreche über die Behandlung von verschlüsselten und unverschlüsselten HTTP-Verbindungen über denselben Port. Es spielt keine Rolle, ob die Verschlüsselung über SSL oder TLS erfolgt.
Antworten:
Für diejenigen, die vielleicht suchen:
Fügen Sie Ihrer Serverdefinition
ssl on;
und hinzuerror_page 497 $request_uri;
.quelle
ssl on;
underror_page 497 =200 $request_uri;
zu Ihrer Serverdefinition hinzu . Dies ändert den Statuscode auf 200.Laut Wikipedia-Artikel zu Statuscodes hat Nginx einen benutzerdefinierten Fehlercode, wenn HTTP-Datenverkehr an den https-Port gesendet wird (Fehlercode 497).
Und laut nginx docs auf error_page können Sie einen URI definieren, der für einen bestimmten Fehler angezeigt wird.
Auf diese Weise können wir eine URL erstellen, an die Clients gesendet werden, wenn der Fehlercode 497 ausgelöst wird.
nginx.conf
Wenn ein Client jedoch eine Anforderung über eine andere Methode als ein GET sendet, wird diese Anforderung in ein GET umgewandelt. So erhalten Sie die Anforderungsmethode, über die der Client hereinkam; Wir verwenden Weiterleitungen zur Fehlerverarbeitung, wie in den Nginx-Dokumenten auf error_page gezeigt
Und deshalb verwenden wir die
301 =307
Umleitung.Mit der hier gezeigten Datei nginx.conf können http und https auf demselben Port abhören
quelle
Wenn Sie wirklich clever sein möchten, können Sie mit einem Verbindungsproxy die ersten paar Bytes des eingehenden Datenstroms abrufen und die Verbindung basierend auf dem Inhalt von Byte 0 übergeben: Wenn es 0x16 ist (SSL / TLS). Handshake-Byte), leiten Sie die Verbindung an die SSL-Seite weiter. Wenn es sich um ein alphabetisches Zeichen handelt, führen Sie normales HTTP aus. Mein Kommentar zur Portnummerierung trifft zu .
quelle
Ja, es ist möglich, muss aber den Nginx-Quellcode patchen (HoverHell hat eine Lösung ohne Patchen). Nginx behandelt dies eher als Fehlkonfiguration als als gültige Konfiguration.
Die Variable $ ssl_session_id kann verwendet werden, um zwischen einer normalen und einer SSL-Verbindung zu unterscheiden.
Patch gegen Nginx-0.7.65:
Serverkonfiguration:
quelle
Ich glaube nicht, dass es irgendetwas gibt, das mit zwei verschiedenen Protokollen an einem einzigen Port umgehen kann ...
Ich bin gespannt, warum Sie nur einen Port weiterleiten können, aber abgesehen davon ... ist es nicht ideal, aber wenn ich in Ihren Schuhen stecke, würde ich alles über https bedienen.
quelle
Sie können HTTP und HTTPS nicht über denselben Port unterstützen, da beide Enden der Verbindung eine bestimmte Sprache erwarten und nicht klug genug sind, um herauszufinden, ob das andere Ende etwas anderes spricht.
Wie Ihr Kommentar zu Wils Antwort andeutete, könnten Sie ein TLS-Upgrade verwenden (ich glaube, neuere nginx-Releases unterstützen es, obwohl ich es nicht ausprobiert habe), aber auf diesem Server werden weder HTTP noch HTTPS ausgeführt, sondern nur HTTP mit TLS-Upgrade. Das Problem ist immer noch die Browserunterstützung - die meisten Browser unterstützen sie (immer noch) nicht. Wenn Sie einen begrenzten Pool an Kunden haben, ist dies jedoch möglich.
quelle
Ich bin mir nicht sicher, wie es funktioniert, aber CUPSD antwortet sowohl auf http als auch auf https auf Port 631. Wenn nginx das jetzt nicht kann, können sie vielleicht daraus lernen, wie das CUPS-Team es funktioniert, aber CUPS ist unter dem GPL, daher muss Nginx möglicherweise eine Änderung der Lizenz in Betracht ziehen, wenn sie eine solche Funktion implementieren möchten und den entsprechenden Code nicht an anderer Stelle finden können.
quelle
Theoretisch könnten Sie eine Webseite haben, auf die über HTTP zugegriffen werden kann und die in der Lage ist, ein WebSocket unter https: 443 an einer beliebigen Stelle zu öffnen . Der anfängliche WebSocket-Handshake ist HTTP. Ja, es ist möglich, eine unsicher aussehende Seite tatsächlich für eine sichere Kommunikation zu machen. Sie können dies mit der Netty Library tun .
quelle
Dies ist seit 1.15.2 endlich richtig möglich. Siehe die Informationen hier .
Fügen Sie in Ihrer nginx.conf einen Block wie diesen hinzu (außerhalb des http-Blocks):
Dann können Sie Ihren normalen Serverblock erstellen, aber diese verschiedenen Ports abhören:
Auf diese Weise kann der Stream-Block vorlesen und erkennen, ob es sich um TLS handelt oder nicht (in diesem Beispiel an Port 8080). Anschließend leitet der Proxy ihn lokal an den richtigen Server-Port weiter.
quelle