WebSockets и прокси-сервер Apache: как настроить mod_proxy_wstunnel?

У меня есть:

  • Apache (v2.4) на порту 80 моего сервера для www.domain1.com, mod_proxy и mod_proxy_wstunnel включен

  • node.js + socket.io на порт 3001 того же сервера.

Доступ к www.domain2.com (с портом 80) перенаправляет на 2. благодаря описанному здесь методу. Я установил это в конфигурации Apache:

<VirtualHost *:80>
    ServerName www.domain2.com
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/
    ProxyPass / ws://localhost:3001/
    ProxyPassReverse / ws://localhost:3001/
</VirtualHost>

Он работает для всего, кроме части websocket: ws://... не передаются, как это должно прокси.

Когда я обращаюсь к странице на www.domain2.com, у меня есть:

Impossible to connect ws://www.domain2.com/socket.io/?EIO=3&transport=websocket&sid=n30rqg9AEqZIk5c9AABN.

Вопрос: Как сделать прокси-сервер Apache и WebSockets?

Ответ 1

Мне удалось это сделать, благодаря этой теме.

TODO:

1) Установили ли Apache 2.4 (не работает с 2.2) и выполните следующие действия:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

2) Запустите nodejs на порт 3001

3) Сделайте это в конфигурации Apache

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
  RewriteCond %{QUERY_STRING} transport=websocket    [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]

  ProxyPass / http://localhost:3001/
  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

Примечание. Если у вас более одного сервиса на том же сервере, который использует веб-узлы, вы можете сделать это, чтобы отделить их.

Ответ 2

Вместо фильтрации по URL-адресу вы также можете фильтровать по HTTP-заголовку. Эта конфигурация будет работать для любых веб-приложений, которые используют веб-узлы, также если они не используют socket.io:

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:3001/$1 [P,L]

  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

Ответ 3

Может быть, будет полезно. Просто все запросы отправляются через ws на node

<VirtualHost *:80>
  ServerName www.domain2.com

  <Location "/">
    ProxyPass "ws://localhost:3001/"
  </Location>
</VirtualHost>

Ответ 4

Начиная с Socket.IO 1.0 (май 2014 г.), все подключения начинаются с запроса HTTP-опроса (подробнее здесь). Это означает, что в дополнение к пересылке трафика WebSocket вам необходимо перенаправить любые HTTP-запросы transport=polling.

В приведенном ниже решении необходимо перенаправить весь трафик сокета, не перенаправляя ни один другой трафик.

  • Включите следующие мотивы Apache2:

    sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
    
  • Используйте эти настройки в файле *.conf(например, /etc/apache2/sites-available/mysite.com.conf). Я включил комментарии для объяснения каждой части:

    <VirtualHost *:80>
        ServerName www.mydomain.com
    
        # Enable the rewrite engine
        # Requires: sudo a2enmod proxy rewrite proxy_http proxy_wstunnel
        # In the rules/conds, [NC] means case-insensitve, [P] means proxy
        RewriteEngine On
    
        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:3001/$1 [P]
    
        # When socket.io wants to initiate a WebSocket connection, it sends an
        # "upgrade: websocket" request that should be transferred to ws://
        RewriteCond %{HTTP:Upgrade} websocket               [NC]
        RewriteRule /(.*)           ws://localhost:3001/$1  [P]
    
        # OPTIONAL: Route all HTTP traffic at /node to port 3001
        ProxyRequests Off
        ProxyPass           /node   http://localhost:3001
        ProxyPassReverse    /node   http://localhost:3001
    </VirtualHost>
    
  • Я включил дополнительный раздел для маршрутизации /node трафика, который мне удобен, см. здесь для получения дополнительной информации.

Ответ 5

С помощью этих ответов я, наконец, получил обратный прокси-сервер для Node -RED, работающий на малине Pi с Ubuntu Mate и Apache2, используя эту конфигурацию сайта Apache2:

<VirtualHost *:80>
    ServerName nodered.domain.com
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:1880/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:1880/$1 [P,L]
</VirtualHost>

Мне также пришлось включить такие модули:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel

Ответ 6

Для меня это работает после добавления только одной строки в httpd.conf, как показано ниже (жирная линия).


<VirtualHost *:80>
    ServerName: xxxxx

    #ProxyPassReverse is not needed
    ProxyPass /log4j ws://localhost:4711/logs
<VirtualHost *:80>

Apache версия 2.4.6 для CentOS.

Ответ 7

Моя настройка:

  • Apache 2.4.10 (работает на Debian)
  • Node.js (версия 4.1.1) Приложение, работающее на порте 3000, которое принимает WebSockets по пути /api/ws

Как уже упоминалось выше @Basj, убедитесь, что прокси a2enmod и ws_tunnel включены.

Это скриншот конфигурационного файла Apache, который решил мою проблему:

Apache config

Соответствующая часть в виде текста:

<VirtualHost *:80>
  ServerName *******
  ServerAlias *******
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/

  <Location "/api/ws">
      ProxyPass "ws://localhost:3000/api/ws"
  </Location>
</VirtualHost>

Надеюсь, это поможет.

Ответ 8

Сделал следующее для весеннего приложения, работающего со статическим содержимым, отдыхом и содержимым websocket.

Apache используется в качестве конечной точки прокси и SSL для следующих URI:

  • /app → статический контент
  • /api → REST API
  • /api/ws → websocket

Конфигурация Apache

<VirtualHost *:80>
    ServerName xxx.xxx.xxx    

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    <Proxy *>
         Require all granted
    </Proxy>

    RewriteEngine On

    # websocket 
    RewriteCond %{HTTP:Upgrade}         =websocket                      [NC]
    RewriteRule ^/api/ws/(.*)           ws://localhost:8080/api/ws/$1   [P,L]

    # rest
    ProxyPass /api http://localhost:8080/api
    ProxyPassReverse /api http://localhost:8080/api

    # static content    
    ProxyPass /app http://localhost:8080/app
    ProxyPassReverse /app http://localhost:8080/app 
</VirtualHost>

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

Конфигурация пружины

server.use-forward-headers: true

Ответ 9

Для "опроса" транспорта.

сторона Apache:

<VirtualHost *:80>
    ServerName mysite.com
    DocumentRoot /my/path


    ProxyRequests Off

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass /my-connect-3001 http://127.0.0.1:3001/socket.io
    ProxyPassReverse /my-connect-3001 http://127.0.0.1:3001/socket.io   
</VirtualHost>

Клиентская сторона:

var my_socket = new io.Manager(null, {
    host: 'mysite.com',
    path: '/my-connect-3001'
    transports: ['polling'],
}).socket('/');

Ответ 10

В дополнение к основному ответу: если у вас есть более одной службы на том же сервере, который использует веб-узлы, вы можете сделать это, чтобы отделить их, используя настраиваемый путь (*):

Node сервер:

var io = require('socket.io')({ path: '/ws_website1'}).listen(server);

Клиент HTML:

<script src="/ws_website1/socket.io.js"></script>
...
<script>
var socket = io('', { path: '/ws_website1' });
...

Конфигурация Apache:

RewriteEngine On

RewriteRule ^/website1(.*)$ http://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule ^(.*)$ ws://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteRule ^(.*)$ http://localhost:3001$1 [P,L]

(*) Примечание: использование по умолчанию RewriteCond %{REQUEST_URI} ^/socket.io не будет специфично для веб-сайта, а запросы веб-камер будут перемешаны между различными веб-сайтами!

Ответ 11

Используйте эту ссылку для идеального решения для ws https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html.

Вы должны просто сделать ниже шаг..

Перейдите в /etc/apache2/mods-available

Шаг 1

Включите mode proxy_wstunnel.load с помощью команды ниже

$a2enmod proxy_wstunnel.load

Шаг 2

Перейдите в /etc/apache2/sites-available

и добавьте строку ниже в вашем файле .conf внутри виртуального хоста

ProxyPass "/ws2/"  "ws://localhost:8080/"

ProxyPass "/wss2/" "wss://localhost:8080/"

Примечание: 8080 означают, что ваш, что ваш кот работает порт, потому что мы хотим, чтобы подключить ws, где наш файл война гнал в коте и коте служит апачу для ws. благодарю вас

Моя конфигурация

ws://localhost/ws2/ALLCAD-Unifiedcommunication-1.0/chatserver?userid=4 =Connected

Ответ 12

TODO:

  • Установлен ли Apache 2.4 (не работает с 2.2), a2enmod proxy и a2enmod proxy_wstunnel.load

  • Сделайте это в конфигурации Apache
    просто добавьте две строки в свой файл, где 8080 - ваш порт для работы с tomcat

    <VirtualHost *:80>
    ProxyPass "/ws2/" "ws://localhost:8080/" 
    ProxyPass "/wss2/" "wss://localhost:8080/"
    
    </VirtualHost *:80>