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.