Puncte:0

Proxy dublu NGINX nu permite conexiuni websocket

drapel lb

Am două proxy-uri nginx configurate pe mașina mea, unul pentru a despacheta SSL și celălalt pentru a face proxy specific aplicației (doar al doilea este controlat de versiune). Când aveam un singur proxy, am reușit să realizez conexiuni websocket de succes, dar după ce am trecut la două, toate solicitările de actualizare websocket primesc o eroare 502 Bad Gateway. Pot confirma că solicitările normale http/https funcționează cu configurarea mea de proxy dublu. Iată configurația mea curentă.

Proxy 1

Server {

        # Configurare SSL
        #
        # asculta 443 ssl default_server;
        # asculta [::]:443 ssl default_server;
        #
        # Notă: ar trebui să dezactivați gzip pentru traficul SSL.
        # Vezi: https://bugs.debian.org/773332
        #
        # Citiți informații despre ssl_ciphers pentru a asigura o configurație sigură.
        # Vezi: https://bugs.debian.org/765782
        #
        # Certificate autosemnate generate de pachetul ssl-cert
        # Nu le folosiți pe un server de producție!
        #
        # include snippets/snakeoil.conf;

        nume_server staging.ambitx.io;

        Locație / {
                proxy_pass http://127.0.0.1:81;
                include proxy_params;
        }

    asculta [::]:443 ssl ipv6only=on; # gestionat de Certbot
    asculta 443 ssl; # gestionat de Certbot
    ssl_certificate /etc/letsencrypt/live/staging.ambitx.io/fullchain.pem; # gestionat de Certbot
    ssl_certificate_key /etc/letsencrypt/live/staging.ambitx.io/privkey.pem; # gestionat de Certbot
    includ /etc/letsencrypt/options-ssl-nginx.conf; # gestionat de Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # gestionat de Certbot

}
Server {
    dacă ($gazdă = staging.ambitx.io) {
        returnează 301 https://$host$request_uri;
    } # gestionat de Certbot

        asculta 80 default_server;
        asculta [::]:80 default_server;

        nume_server staging.ambitx.io;
    întoarce 404; # gestionat de Certbot

}

proxy_params

proxy_set_header Gazdă $http_host;
proxy_set_header X-Real-IP $adresă_la distanță;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $schema;

Proxy 2

(rulează pe docker cu portul 81 de pe mașina gazdă legat de portul 80 de pe container)

resolver 127.0.0.11 ipv6=off;

Server {
  asculta 80;
  asculta [::]:80;

  Locație / {
    rădăcină /var/www/staticfiles;
    index index.html index.htm;
    try_files $uri /index.html =404;
  }
  
  locație /ws {
    access_log off;

    proxy_pass http://wserver;

    proxy_http_versiunea 1.1;
    proxy_set_header Actualizare $http_upgrade;
    proxy_set_header Conexiune „upgrade”;
  }

  locație /api {
    proxy_pass http://apiserver;
  }
}

Am avut inițial declarațiile de mai jos în locație /ws bloc de configurare a lui Proxy 2...

proxy_set_header X-Real-IP $adresă_la distanță;
proxy_set_header Gazdă $gazdă;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

dar le-am eliminat pentru că ar suprascrie anteturile setate de Proxy 1.

Vreo idee? Vă rog să-mi spuneți dacă aveți nevoie de mai multe informații.

Puncte:0
drapel gr

Desigur, nu ar trebui să renunțați la suportul de proxy WebSocket de la oricare dintre serverele dumneavoastră proxy intermediare. WebSocket proxy este un lucru foarte sarcină specială, pentru a permite comutarea protocolului și pentru a menține conexiunea WebSocket stabilită și vie, ar trebui să returnați suportul acestuia și la primul proxy nginx:

...
Locație / {
    proxy_pass http://127.0.0.1:81;
    include proxy_params;
}
locație /ws {
    proxy_pass http://127.0.0.1:81;
    include proxy_params;
    proxy_http_versiunea 1.1;
    proxy_set_header Actualizare $http_upgrade;
    proxy_set_header Conexiune „upgrade”;
}
...

Îndepărtându-le pe toate trei proxy_set_header directivele de la al doilea proxy nginx a fost, de asemenea, o idee proastă. In timp ce X-Real-IP și X-Redirecţionat-Pentru anteturile vor fi transmise aplicației tale WebSocket exact așa cum au fost setate de primul tău proxy, the Gazdă antetul este unul special. Dacă nu este setat în mod explicit, acesta va fi transmis egal cu numele din amonte utilizat în proxy_pass directivă, adică Gazdă: wserver. După cum puteți citi din proxy_set_header directivă documentație:

În mod implicit, sunt redefinite doar două câmpuri:

proxy_set_header Gazdă $proxy_host;
proxy_set_header Închidere conexiune;

(a doua va întrerupe cu siguranță orice încercare de a stabili o conexiune WebSocket). Deci pentru a păstra originalul Gazdă antet de la solicitarea clientului (de obicei, o idee bună, puteți citi mai multe despre acest antet Aici), returnează

proxy_pass Gazdă $http_host;

linie către ambele Locație / { ... } și locație /ws { ... } a celei de-a doua configurații de proxy nginx.

Simon Richard avatar
drapel lb
Asta a funcționat pentru mine, mulțumesc. În scopul de a păstra proxy-ul 1 agnostic față de proxy-ul 2 (deoarece proxy-ul 1 nu este în prezent controlat de versiune), am decis să folosesc „exemplul mai sofisticat” (al doilea) listat pe acest site web: https://nginx.org /en/docs/http/websocket.html și adăugați-l în blocul `location / { ... }` din proxy 1. În acest fel, dacă schimb URL-ul websocket-ului, dar uit de proxy 1, nu se va rupe. Singurul dezavantaj la care mă pot gândi este că nu va putea gestiona http/2.0, dar serverul meu nu a fost configurat să se ocupe oricum.
Ivan Shatsky avatar
drapel gr
Sună rezonabil, prefer și eu acel mod de a folosi proxy WebSocket. Despre HTTP/2, este posibil să găsiți [this](https://serverfault.com/questions/765258/use-http-2-0-between-nginx-reverse-proxy-and-backend-webserver) firul destul de interesant.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.