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.