NGINX per invertire i socket Web proxy E abilitare SSL (wss: //)?


136

Sono così perso e nuovo nel creare NGINX da solo, ma voglio essere in grado di abilitare i websocket sicuri senza avere un livello aggiuntivo.

Non voglio abilitare SSL sul server websocket stesso ma invece voglio usare NGINX per aggiungere un livello SSL a tutto.

Ogni pagina web là fuori dice che non posso farlo, ma so che posso! Grazie a chiunque (me stesso) può mostrarmi come!

Risposte:


185

Solo per notare che nginx ha ora il supporto per Websocket nella versione 1.3.13. Esempio di utilizzo:

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;

}

È inoltre possibile controllare il log delle modifiche nginx e la documentazione di proxy WebSocket .


Ha gli stessi problemi di timeout espressi sopra;)
°

5
@ 3rdEden: per problemi di timeout, proxy_read_timeoutfunziona, ho modificato la risposta.
Steve Kehlet,

2
Dove devo inserire questa configurazione e cos'è backend_host?
Aysennoussi,

3
@Sekai: una locationdirettiva è inserita in una servero un'altra locationdirettiva (vedi documenti di localizzazione ). backend_hostè un upstream(vedi documenti upstream ) - uno o un gruppo di server a cui eseguirai il proxy.
Radko Dinev,

1
Che dire di questo problema di timeout? Dobbiamo davvero impostarlo su un numero molto grande per evitarlo? Non esiste ora una soluzione più elegante?
Mohammed Noureldin,

54

Non abbiate paura, perché un coraggioso gruppo di programmatori di Ops ha risolto la situazione con un marchio che ha sculacciato il nuovo nginx_tcp_proxy_module

Scritto nell'agosto 2012, quindi se vieni dal futuro dovresti fare i compiti.

Prerequisiti

Supponiamo che tu stia utilizzando CentOS:

  • Rimuovi l'attuale istanza di NGINX (suggerisci di usare dev server per questo)
  • Se possibile, salva i tuoi vecchi file di configurazione NGINX in modo da poterli riutilizzare (incluso il tuo init.d/nginxscript)
  • yum install pcre pcre-devel openssl openssl-devel e qualsiasi altra libreria necessaria per la creazione di NGINX
  • Prendi il nginx_tcp_proxy_module da GitHub qui https://github.com/yaoweibin/nginx_tcp_proxy_module e ricorda la cartella in cui l'hai posizionato (assicurati che non sia zippato)

Costruisci il tuo nuovo NGINX

Ancora una volta, assume CentOS:

  • 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 (puoi aggiungere più moduli se ne hai bisogno)
  • make
  • make install

Opzionale:

  • sudo /sbin/chkconfig nginx on

Installa Nginx

Ricordarsi di copiare prima i vecchi file di configurazione se si desidera riutilizzarli.

Importante: dovrai creare una tcp {}direttiva ai massimi livelli nella tua conf. Assicurati che non sia all'interno della tua http {}direttiva.

L'esempio di configurazione riportato di seguito mostra un singolo server websocket upstream e due proxy sia per SSL che non 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;
    }
}

5
Questo è stato abbastanza utile, ma stavo ancora ottenendo timeout a 60 secondi. Sono riuscito a risolvere il problema impostando quanto segue: 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
Grazie per averlo condiviso! In seguito mi sono reso conto di avere problemi simili e per coincidenza anche yaoweibin stesso ha risposto al mio problema con GitHub con un link al tuo commento sul numero 28. Piccolo mondo ...
crockpotveggies

1
Volevo servire i websocket dalla stessa porta http e solo dopo che il browser era stato autenticato. Sembra che questo non possa gestire i websocket sulla stessa porta. Come lo gestiscono le persone?
uroc,

1
Ci vorranno alcune modifiche al software per rilevare il protocollo in arrivo. Poiché i websocket iniziano effettivamente come un handshake HTTP (un livello software superiore a TCP), è necessario modificare l'app per gestire sia il traffico TCP che HTTP. Non posso raccomandare un modo per farlo ancora.
crockpotveggies,

2
Nel caso in cui altre persone del 2018 vengano qui, queste direttive non funzionano più. Vai su nginx.org/it/docs/http/websocket.html per istruzioni recenti o vedi la risposta di Harlan T Wood di seguito.
GaryO,

37

Questo ha funzionato per me:

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";
}

- preso in prestito da: https://github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
Ho avuto problemi a far funzionare i socket Web di TeamCity dietro il mio proxy inverso. Il tuo # WebSocket supportframmento l'ha fatto per me. In precedenza stavo cercando di inoltrare la porta 400, tuttavia wss funziona su 443. FYI futuri lettori :)
Mario Tacke,

Hai capito la soluzione? Dal momento che ho dovuto affrontare anche un problema simile stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

Mi piace questa risposta al meglio, poiché molte persone (come te) usano / sia per i websocket sia per i normali HTTP2.
Mikemaccana,

@ Qualcuno quale sarebbe il Javascript chiamante?
Andrew Simpson,

17

per .net core 2.0 Nginx con 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;
}

Questo ha funzionato per me


qual è il codice c #. Attualmente ho questo in per windows / iis _server = new WebSocketServer ("wss: //0.0.0.0: 8200 / MessageRelayer") {Certificate = new X509Certificate2 (PfxFileName, SslPassword), RestartAfterListenError = true};
Andrew Simpson, il

Sto usando SignalR
Altair CA il

Questa è stata l'unica soluzione che ha funzionato per me. Grazie!
m-ketan,

8

Per me, è arrivato al proxy_pass dipeso dall'impostazione posizione. Avevo bisogno di passare all'utilizzo del protocollo HTTPS e di avere un certificato SSL valido impostato sul lato server del nodo delle cose. In questo modo quando introduco un server nodo esterno, devo solo cambiare l'IP e tutto il resto rimane la stessa configurazione.

Spero che questo aiuti qualcuno lungo la strada ... Stavo fissando il problema tutto il tempo ... sospiro ...

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;
            }
}

Ho provato localtion /horizon, ma non funziona. Solo localtion /o location /websockifyfunziona. Non so perché ...
njuguoyi,

6

Un buon articolo conciso di Pankaj Malhotra parla di come farlo con NGINX ed è disponibile qui .

La configurazione di base di NGINX è riprodotta di seguito:

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;
    }
}

1
Le versioni moderne di NGINX risolvono anche i problemi di timeout?
crockpotveggies dal

2

Utilizzando nginx / 1.14.0

ho un websocket-server in esecuzione sulla porta 8097 e gli utenti si connettono da a wss sulla porta 8098, nginx decodifica il contenuto e lo inoltra al server websocket

Quindi ho questo file di configurazione (nel mio caso /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;

    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.