NGINX для обратного прокси-веб-сокетов и включения SSL (wss: //)?


136

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

Я не хочу включать SSL на самом сервере websocket, но вместо этого хочу использовать NGINX для добавления уровня SSL ко всему этому.

На каждой странице написано, что я не могу этого сделать, но я знаю, что могу! Спасибо тому, кто (я) может показать мне, как!

Ответы:


185

Стоит отметить, что nginx теперь поддерживает веб-сокеты в версии 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 .


У него те же проблемы с тайм-аутом, как указано выше;)
— 3rdEden

5
@ 3rdEden: По вопросам тайм-аута proxy_read_timeoutработает, я отредактировал ответ.
— Стив Кехлет,

2
Куда мне поместить эту конфигурацию и что такое backend_host?
— Айсеннусси

3
@Sekai: locationдиректива помещается в одну serverили другую locationдирективу (см. Документацию по местоположению ). backend_host- это upstream(см. документацию вверх по течению ) - один или группа серверов, к которым вы будете подключаться.
— Radko Dinev

1
Что насчет этой проблемы с тайм-аутом? Неужели мы действительно должны установить очень большое число, чтобы этого избежать? Нет ли более элегантного решения?
— Мохаммед Нурелдин

54

Не бойтесь, потому что отважная группа программистов Ops разрешила ситуацию, когда бренд порвал новый модуль nginx_tcp_proxy_module

Написано в августе 2012 года, поэтому, если вы из будущего, сделайте домашнее задание.

Предпосылки

Предполагается, что вы используете CentOS:

  • Удалить текущий экземпляр NGINX (предлагаем использовать для этого сервер разработки)
  • Если возможно, сохраните свои старые файлы конфигурации 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 {}директиву на самом высоком уровне в вашем conf. Убедитесь, что это не входит в вашу http {}директиву.

В приведенном ниже примере конфигурации показан один восходящий сервер websocket и два прокси для SSL и без 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 секунд. Мне удалось это исправить, установив следующее: 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 02

2
Спасибо, что поделились этим! Позже я понял, что у меня были похожие проблемы, и по совпадению сам Яовейбин также ответил на мою проблему GitHub ссылкой на ваш комментарий к проблеме №28. Маленький мир ...
— crockpotveggies

1
Я хотел обслуживать веб-сокеты с того же порта http и только после аутентификации браузера. Похоже, это не может обрабатывать веб-сокеты на том же порту. Как люди с этим справляются?
— uroc

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. К вашему сведению, будущие читатели :)
— Марио Таке

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

Мне больше всего нравится этот ответ, так как многие люди (как и вы) используют / как для веб-сокетов, так и для обычного HTTP2.
— mikemaccana

@Anyone, что будет за вызывающий 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;
}

Это сработало для меня


что такое код C #. В настоящее время у меня есть это для windows / iis _server = new WebSocketServer ("wss: //0.0.0.0: 8200 / MessageRelayer") {Certificate = new 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

У меня есть веб-сервер, работающий на порту 8097, и пользователи подключаются к wss на порту 8098, nginx просто расшифровывает контент и перенаправляет его на сервер веб-сокета

Итак, у меня есть этот файл конфигурации (в моем случае /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.