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

136

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

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

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

crockpotveggies
источник

Ответы:

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;
    }
}
crockpotveggies
источник
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;
            }
}
CyberDigital
источник
Я пробовал 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;
    }
}
btiernay
источник
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;

    }
}
Джон Смит
источник