NGINX повернути веб-розетки проксі і включити SSL (wss: //)?


136

Я настільки втрачена і новачка в створенні NGINX самостійно, але я хочу мати можливість ввімкнути захищені веб-розетки, не маючи додаткового шару.

Я не хочу вмикати SSL на самому сервері веб-сокетів, але замість цього я хочу використовувати NGINX для додання рівня SSL до всього.

Кожна веб-сторінка там говорить, що я не можу цього зробити, але я знаю, що можу! Завдяки тому, хто (я) може мені показати як!

Відповіді:


185

Зауважимо лише, що nginx тепер підтримує Websockets при випуску 1.3.13. Приклад використання:

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;

}

Ви також можете перевірити журнал змін nginx та супутню документацію WebSocket .


У нього є такі ж питання про час очікування, що й висловлені вище;)
го

5
@ 3rdEden: Про проблеми з таймаутом, proxy_read_timeoutроботами, я відредагував відповідь.
Стів Келет

2
Де я повинен розмістити цю конфігурацію і що таке backend_host?
Айсенноусси

3
@Sekai: locationДиректива міститься в межах тієї serverчи іншої locationдирективи (див. Документи про місцезнаходження ). backend_hostє upstream(див. Документи вище за течією ) - один або група серверів, на які ви будете проксі.
Радко Дінев

1
Що з проблемою очікування? Чи дійсно нам потрібно встановити його на дуже велику кількість, щоб уникнути цього? Невже зараз немає більш елегантного рішення?
Мухаммед Нурелдін

54

Не бійтеся, тому що хоробра група програмістів Ops вирішила ситуацію, коли бренд виплескав новий nginx_tcp_proxy_module

Написано в серпні 2012 року, тому якщо ви з майбутнього, ви повинні робити домашні завдання.

Передумови

Припускаємо, що ви використовуєте CentOS:

  • Видаліть поточний екземпляр NGINX (запропонуйте використовувати для цього сервер dev)
  • Якщо можливо, збережіть старі конфігураційні файли NGINX, щоб ви могли повторно їх використовувати (що включає ваш init.d/nginxсценарій)
  • yum install pcre pcre-devel openssl openssl-devel та будь-які інші необхідні для створення NGINX
  • Отримайте nginx_tcp_proxy_module від GitHub тут https://github.com/yaoweibin/nginx_tcp_proxy_module і запам’ятайте папку, де ви розмістили її (переконайтеся, що вона не зафіксована)

Створіть свій новий NGINX

Знову припускає 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 (ви можете додати більше модулів, якщо вони вам потрібні)
  • make
  • make install

Необов’язково:

  • sudo /sbin/chkconfig nginx on

Налаштування Nginx

Не забудьте скопіювати спочатку свої старі файли конфігурації, якщо ви хочете їх повторно використовувати.

Важливо: вам потрібно буде створити tcp {}директиву на найвищому рівні у вашому конфлікті. Переконайтесь, що він не знаходиться в межах вашої http {}директиви.

Наведений нижче приклад конфігурації показує один сервер веб-розширень верхнього потоку та два проксі для SSL та 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
Це було дуже корисно, але я все ще отримував тайм-аути в 60 сек. Мені вдалося виправити це, встановивши наступне: тайм-аут 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
Дякуємо, що поділилися цим! Пізніше я зрозумів, що у мене виникають подібні проблеми, і випадково сам Яовейбін також відповів на мою проблему GitHub із посиланням на ваш коментар до випуску №28. Маленький світ ...
crockpotveggies

1
Я хотів подавати веб-розетки з того самого http-порту і лише після того, як браузер був аутентифікований. Схоже, це не може обробляти веб-розетки на одному порті. Як люди справляються з цим?
уроч

1
Для виявлення вхідного протоколу знадобиться деяка модифікація програмного забезпечення. Оскільки веб-розетки насправді починаються як рукостискання HTTP (більш високий рівень програмного забезпечення, ніж TCP), ви повинні налаштувати додаток, щоб обробляти як TCP, так і HTTP-трафік. Я ще не можу рекомендувати спосіб зробити це.
crockpotveggies

2
Якщо сюди приходять інші люди з 2018 року, ці директиви вже не працюють. Перейдіть на nginx.org/en/docs/http/websocket.html, щоб отримати останні інструкції, або див. Відповідь Гарлана Т Вуда нижче.
GaryO

37

Це працювало для мене:

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

- запозичено з: https://github.com/nicokaiser/nginx-websocket-proxy/blob/df67cd92f71bfcb513b343beaa89cb33ab09fb05/simple-wss.conf


3
У мене виникли проблеми з тим, щоб веб-розетки TeamCity працювали за моїм зворотним проксі. Твій # WebSocket supportзнімок зробив це для мене. Раніше я намагався переслати порт 400, проте wss працює понад 443. Майбутні читачі FYI :)
Mario Tacke

Ви розібралися з рішенням? Так як я повинен був також стикався з подібною проблемою stackoverflow.com/q/53411060/7713811
Nɪsʜᴀɴᴛʜ

Мені подобається ця відповідь найкраще, оскільки багато людей (як і ви) використовують / як для веб-сокетів, так і для звичайних HTTP2.
mikemaccana

@Aoneone, що би викликало Javascript?
Ендрю Сімпсон

17

для .net core 2.0 Nginx з 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;
}

Це працювало для мене


що таке # код #. У мене зараз це для Windows / iis _server = new WebSocketServer ("wss: //0.0.0.0: 8200 / MessageRelayer") {Сертифікат = новий X509Certificate2 (PfxFileName, SslPassword), RestartAfterListenError = true};
Ендрю Сімпсон

Я використовую SignalR
Altair CA

Це було єдине рішення, яке працювало на мене. Дякую!
m-ketan

8

Для мене це дійшло до proxy_passналаштування місцеположення. Мені потрібно було перейти на використання протоколу HTTPS і мати дійсний сертифікат SSL, встановлений на стороні сервера вузлів речей. Таким чином, коли я впроваджую зовнішній сервер вузлів, мені залишається лише змінити IP, і все інше залишається тим самим конфігурацією.

Я сподіваюсь, що це допомагає комусь по дорозі ... Я весь час дивився на проблему ... зітхати ...

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

Я спробував localtion /horizon, але це не працює. Тільки localtion /або location /websockifyпрацює. Не знаю, чому ...
njuguoyi

6

Хороша, лаконічна стаття Панкая Малхотра розповідає про те, як це зробити з NGINX, і доступна тут .

Основна конфігурація NGINX відтворена нижче:

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
Чи також сучасні версії NGINX вирішують проблеми з очікуванням?
crockpotveggies

2

Використовуючи nginx / 1.14.0

У мене є сервер websocket, який працює на порт 8097, і користувачі підключаються до wss на порт 8098, nginx просто розшифровує вміст і пересилає його на сервер websocket

Отже, у мене є цей конфігураційний файл (у моєму випадку /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;

    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.