NGINX, um Proxy-Websockets umzukehren UND SSL zu aktivieren (wss: //)?

136

Ich bin so verloren und neu darin, NGINX selbst zu erstellen, aber ich möchte in der Lage sein, sichere Websockets ohne zusätzliche Ebene zu aktivieren.

Ich möchte SSL nicht auf dem Websocket-Server selbst aktivieren, sondern stattdessen NGINX verwenden, um dem Ganzen eine SSL-Schicht hinzuzufügen.

Jede Webseite da draußen sagt, dass ich es nicht kann, aber ich weiß, dass ich es kann! Vielen Dank an alle, die mir zeigen können, wie!

Crockpotveggies
quelle

Antworten:

185

Nur um zu beachten, dass nginx jetzt Websockets in Version 1.3.13 unterstützt. Anwendungsbeispiel:

location /websocket/ {

    proxy_pass ​http://backend_host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;

}

Sie können auch das Nginx-Änderungsprotokoll und die WebSocket-Proxy- Dokumentation überprüfen .

Tarantel
quelle
Es hat die gleichen Timeout-Probleme wie oben angegeben;)
3rdEden
5
@ 3rdEden: Bei Timeout-Problemen habe proxy_read_timeoutich die Antwort bearbeitet.
Steve Kehlet
2
Wo soll ich diese Konfiguration ablegen und was ist backend_host?
Aysennoussi
3
@Sekai: Eine locationDirektive wird in eine serveroder eine andere locationDirektive eingefügt (siehe Standortdokumente ). backend_hostist ein upstream(siehe Upstream-Dokumente ) - ein oder eine Gruppe von Servern, für die Sie einen Proxy erstellen.
Radko Dinev
1
Was ist mit diesem Timeout-Problem? Müssen wir es wirklich auf eine sehr große Zahl einstellen, um es zu vermeiden? Gibt es jetzt keine elegantere Lösung?
Mohammed Noureldin
54

Hab keine Angst, denn eine mutige Gruppe von Ops-Programmierern hat die Situation mit einem brandneuen nginx_tcp_proxy_module gelöst

Geschrieben im August 2012, wenn Sie also aus der Zukunft kommen, sollten Sie Ihre Hausaufgaben machen.

Voraussetzungen

Angenommen, Sie verwenden CentOS:

  • Entfernen Sie die aktuelle Instanz von NGINX (schlagen Sie vor, dafür einen Dev-Server zu verwenden).
  • Speichern Sie nach Möglichkeit Ihre alten NGINX-Konfigurationsdateien, damit Sie sie wiederverwenden können (einschließlich Ihres init.d/nginxSkripts).
  • yum install pcre pcre-devel openssl openssl-devel und alle anderen notwendigen Bibliotheken zum Erstellen von NGINX
  • Holen Sie sich das nginx_tcp_proxy_module von GitHub hier https://github.com/yaoweibin/nginx_tcp_proxy_module und merken Sie sich den Ordner, in dem Sie es abgelegt haben (stellen Sie sicher, dass es nicht komprimiert ist).

Erstellen Sie Ihren neuen NGINX

Wiederum wird CentOS angenommen:

  • cd /usr/local/
  • wget 'http://nginx.org/download/nginx-1.2.1.tar.gz'
  • tar -xzvf nginx-1.2.1.tar.gz
  • cd nginx-1.2.1/
  • patch -p1 < /path/to/nginx_tcp_proxy_module/tcp.patch
  • ./configure --add-module=/path/to/nginx_tcp_proxy_module --with-http_ssl_module (Sie können weitere Module hinzufügen, wenn Sie sie benötigen)
  • make
  • make install

Optional:

  • sudo /sbin/chkconfig nginx on

Richten Sie Nginx ein

Denken Sie daran, zuerst Ihre alten Konfigurationsdateien zu kopieren, wenn Sie sie wiederverwenden möchten.

Wichtig: Sie müssen eine tcp {}Direktive auf höchster Ebene in Ihrer Conf erstellen. Stellen Sie sicher, dass es nicht in Ihrer http {}Richtlinie enthalten ist.

Die folgende Beispielkonfiguration zeigt einen einzelnen Upstream-Websocket-Server und zwei Proxys für SSL und Nicht-SSL.

tcp {
    upstream websockets {
        ## webbit websocket server in background
        server 127.0.0.1:5501;
        
        ## server 127.0.0.1:5502; ## add another server if you like!

        check interval=3000 rise=2 fall=5 timeout=1000;
    }   

    server {
        server_name _;
        listen 7070;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }

    server {
        server_name _;
        listen 7080;

        ssl on;
        ssl_certificate      /path/to/cert.pem;
        ssl_certificate_key  /path/to/key.key;

        timeout 43200000;
        websocket_connect_timeout 43200000;
        proxy_connect_timeout 43200000;

        so_keepalive on;
        tcp_nodelay on;

        websocket_pass websockets;
        websocket_buffer 1k;
    }
}
Crockpotveggies
quelle
5
Das war ziemlich hilfreich, aber ich bekam immer noch Timeouts bei 60 Sekunden. Ich konnte dies beheben, indem ich Folgendes einstellte: timeout 43200000; websocket_connect_timeout 43200000; websocket_read_timeout 43200000; websocket_send_timeout 43200000; proxy_connect_timeout 43200000; proxy_read_timeout 43200000; proxy_send_timeout 43200000;
jbg
2
Danke, dass du das geteilt hast! Später stellte ich fest, dass ich ähnliche Probleme hatte, und zufällig antwortete yaoweibin selbst auch auf mein GitHub-Problem mit einem Link zu Ihrem Kommentar zu Problem Nr. 28. Kleine Welt ...
Crockpotveggies
1
Ich wollte Websockets über denselben http-Port und erst nach der Authentifizierung des Browsers bereitstellen. Es sieht so aus, als ob dies keine Websockets am selben Port verarbeiten kann. Wie gehen die Leute damit um?
Uroc
1
Es sind einige Softwaremodifikationen erforderlich, um das eingehende Protokoll zu erkennen. Da Websockets tatsächlich als HTTP-Handshake (eine höhere Softwareversion als TCP) gestartet werden, müssen Sie Ihre App optimieren, um sowohl TCP- als auch HTTP-Verkehr zu verarbeiten. Ich kann noch keinen Weg empfehlen, dies zu tun.
Crockpotveggies
2
Falls andere Leute aus dem Jahr 2018 hierher kommen, funktionieren diese Richtlinien nicht mehr. Aktuelle Anweisungen finden Sie unter nginx.org/en/docs/http/websocket.html oder in der Antwort von Harlan T Wood weiter unten.
GaryO
37

Das hat bei mir funktioniert:

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

- ausgeliehen von: https://github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf

Harlan T Wood
quelle
3
Ich hatte Probleme, die Web-Sockets von TeamCity hinter meinem Reverse-Proxy zum Laufen zu bringen. Dein # WebSocket supportSnipped hat es für mich getan. Ich habe zuvor versucht, Port 400 weiterzuleiten, aber wss funktioniert über 443. Zu Ihrer Information zukünftige Leser :)
Mario Tacke
Haben Sie die Lösung herausgefunden? Da musste ich auch ein ähnliches Problem konfrontiert stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ
Ich mag diese Antwort am besten, da viele Leute (wie Sie) / sowohl für Websockets als auch für reguläres HTTP2 verwenden.
Mikemaccana
@Anyone was wäre das aufrufende Javascript?
Andrew Simpson
17

für .net Core 2.0 Nginx mit SSL

location / {
    # redirect all HTTP traffic to localhost:8080
    proxy_pass http://localhost:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
}

Das hat bei mir funktioniert

Altair CA.
quelle
Was ist der C # -Code? Ich habe dies derzeit in für Windows / iis _server = new WebSocketServer ("wss: //0.0.0.0: 8200 / MessageRelayer") {Certificate = new X509Certificate2 (PfxFileName, SslPassword), RestartAfterListenError = true};
Andrew Simpson
Ich benutze SignalR
Altair CA
Dies war die einzige Lösung, die für mich funktioniert hat. Vielen Dank!
m-ketan
8

Für mich kam es auf die proxy_passStandorteinstellung an. Ich musste auf die Verwendung des HTTPS-Protokolls umsteigen und ein gültiges SSL-Zertifikat auf der Seite des Knotenservers einrichten. Auf diese Weise muss ich beim Einführen eines externen Knotenservers nur die IP ändern und alles andere bleibt dieselbe Konfiguration.

Ich hoffe, das hilft jemandem auf dem Weg ... Ich habe die ganze Zeit auf das Problem gestarrt ... seufz ...

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
upstream nodeserver {
        server 127.0.0.1:8080;
}
server {
        listen 443 default_server ssl http2;
        listen [::]:443 default_server ssl http2 ipv6only=on;
        server_name mysite.com;
        ssl_certificate ssl/site.crt;
        ssl_certificate_key ssl/site.key;
        location /websocket { #replace /websocket with the path required by your application
                proxy_pass https://nodeserver;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_intercept_errors on;
                proxy_redirect off;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-NginX-Proxy true;
                proxy_ssl_session_reuse off;
            }
}
CyberDigital
quelle
Ich habe es versucht localtion /horizon, aber es funktioniert nicht. Nur localtion /oder location /websockifyfunktioniert. Ich weiß nicht warum ...
Njuguoyi
6

Ein guter, prägnanter Artikel von Pankaj Malhotra beschreibt, wie dies mit NGINX gemacht wird und ist hier verfügbar .

Die grundlegende NGINX-Konfiguration ist unten wiedergegeben:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

upstream appserver {
    server 192.168.100.10:9222; # appserver_ip:ws_port
}

server {
    listen 8888; // client_wss_port

    ssl on;
    ssl_certificate /path/to/crt;
    ssl_certificate_key /path/to/key;


    location / {
        proxy_pass http://appserver;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}
Übrigens
quelle
1
Beheben die modernen Versionen von NGINX auch die Timeout-Probleme?
Crockpotveggies
2

Verwenden von nginx / 1.14.0

Ich habe einen Websocket-Server, der auf Port 8097 ausgeführt wird, und Benutzer stellen eine Verbindung zu wss auf Port 8098 her. Nginx entschlüsselt nur den Inhalt und leitet ihn an den Websocket-Server weiter

Also habe ich diese Konfigurationsdatei (in meinem Fall /etc/nginx/conf.d/default.conf)

server {
    listen   8098;
        ssl on;
        ssl_certificate      /etc/ssl/certs/combined.pem;
        ssl_certificate_key  /root/domain.key;
    location / {

        proxy_pass http://hostname:8097;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;

    }
}
John Smith
quelle