Конфигурирование Apache2 для прокси WebSocket?

Протокол WebSocket является расширением протокола HTTP. Однако прокси-модуль Apache2, похоже, не знает об этом и отбрасывает важные заголовки, преобразовывая вызов в стандартный HTTP-вызов.

Есть ли способ заставить Apache2 либо (1) понимать WebSocket, либо (2) просто слепо передавать все, что получает?

6 ответов

Теперь в магистрали Apache есть модуль mod_proxy_wstunnel, который позволяет mod_proxy (ProxyPass/ProxyPassReverse) проходить через трафик WebSocket. Кто-то написал сообщение в блоге о обратном портировании mod_proxy_wstunnel в Apache 2.4/2.2 и предоставил для этого патч.

Я нашел конкретные инструкции по настройке mod_proxy_wstunnel в Ubuntu (протестирован с Ubuntu Server 11.10 и Apache 2.2.20) и разместил их в своем блоге. Я скопировал их ниже:

# Check apache version (should be 2.2.20 as of writing, if not adjust the next step)
dpkg -s apache2

# Checkout apache source
svn checkout http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.20/ httpd-2.2.20

# Get patch and apply it
wget http://cafarelli.fr/gentoo/apache-2.2.24-wstunnel.patch
cd httpd-2.2.20
patch -p1 < ../apache-2.2.24-wstunnel.patch

# Build Apache 
svn co http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x srclib/apr
svn co http://svn.apache.org/repos/asf/apr/apr-util/branches/1.3.x srclib/apr-util
./buildconf
./configure --enable-proxy=shared --enable-proxy_wstunnel=shared
make

# Copy the module and recompiled mod_proxy (for new symbols) to the ubuntu apache installation and update the permissions to match the other modules
sudo cp modules/proxy/.libs/mod_proxy{_wstunnel,}.so /usr/lib/apache2/modules/
sudo chmod 644 /usr/lib/apache2/modules/mod_proxy{_wstunnel,}.so
echo -e "# Depends: proxy\nLoadModule proxy_wstunnel_module /usr/lib/apache2/modules/mod_proxy_wstunnel.so" | sudo tee -a /etc/apache2/mods-available/proxy_wstunnel.load

# Enable the module (also make any configuration changes you need)
sudo a2enmod proxy_wstunnel
sudo service apache2 restart

Ничто не указывает на то, что Apache httpd поддержит их в ближайшее время.

Если вам нужно запустить websockets через apache, попробуйте mod_pywebsocket. Я попробовал это, и это работает.

Вот несколько альтернатив, которые я предпочитаю:

Похоже, с помощью комбинации подключаемого модуля и некоторого дополнительного кода это теперь возможно:

http://blog.alex.org.uk/2012/02/16/using-apache-websocket-to-proxy-tcp-connection/

Это дополнение к ответу Эндрю Мосса о том, как правильно настроить VirtualHost работать с socket.io 1.0! Не стесняйтесь пропустить часть о CentOS!


Если вы застряли на CentOS 6, вот как это сделать:

  1. Загрузите исходный код для mod_proxy_wstunnel Модуль здесь (либо клонировать Gist или загрузить файлы по отдельности)
  2. Установите все необходимое для сборки: yum install make gcc httpd-devel
  3. Настройка среды сборки RPM (в основном непривилегированный пользователь и некоторые каталоги)
  4. Скопируйте .c -файл в SOURCES подпапка окружающей среды и .spec -файл в SPECS вложенная папка.
  5. Бежать rpmbuild -ba mod_proxy_wstunnel.spec
  6. Пакет сейчас находится в SRPMS вложенная
  7. Установите пакет: rpm -i /path/to/package.rpm
  8. прибыль

Это также автоматически загрузит модуль в Apache, так что вам просто нужно перезапустить его с service httpd restart,


Настройка VirtualHost на самом деле обслуживать сервер Socket.io и клиентский скрипт (который по умолчанию доступен в http://your.server/socket.io/socket.io.js) немного сложнее в Apache 2.2 из-за ошибки в mod_proxy модуль:

Учитывая следующее правило переписывания:

RewriteRule    ^/ws(.*)$  ws://localhost:9000/ws  [P]

mod_rewrite рассматривает это как путь к файлу, поэтому журнал доступа показывает:

[26/Sep/2013:09:46:07 -0400] "GET /ws://localhost:9000/ws HTTP/1.1" 400 317

Итак, вы не можете использовать ws -protocol в rewrite-rule, потому что это внутренне превратится в HTTP-запрос GET.

Есть обходной путь, хотя:

<VirtualHost *:80>
        ServerName your.server

        # Proxy socket.io Websocket
        RewriteEngine On

        # socket.io 1.0+ starts all connections with an HTTP polling request
        RewriteCond %{QUERY_STRING} transport=polling       [NC]
        RewriteRule /(.*)           http://localhost:8081/$1 [P]

        ProxyRequests Off

        # Explicitly send the request for the client-script to HTTP:
        ProxyPass /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js
        ProxyPassReverse /socket.io/socket.io.js http://localhost:8081/socket.io/socket.io.js

        # Anything else goes to the WebSocket protocol:
        ProxyPass /socket.io/ ws://localhost:8081/socket.io/
        ProxyPassReverse /socket.io/ ws://localhost:8081/socket.io/

        # Any additional stuff (the actual site) comes here
        ProxyPass / http://localhost:8081/
        ProxyPassReverse / http://localhost:8081/
</VirtualHost>

Это гарантирует, что все отправлено /socket.io идет к ws:// -protocol, кроме запроса на длительный опрос (который является резервным механизмом, когда WebSockets недоступен) и запроса на клиентскую библиотеку.

Пожалуйста, посмотрите на http://github.com/disconnect/apache-websocket

Модуль apache-websocket - это серверный модуль Apache 2.x, который может использоваться для обработки запросов с использованием протокола WebSocket сервером Apache 2.x.

Я нашел другое решение проблемы с веб-сокетом. У меня apache 2.4.25. Все следующие конфигурации относятся к веб-приложению. Вы должны увидеть, какой запрос веб-сокета будет создан в ваших случаях, и соответствующим образом адаптироваться.

      #the following rule is specific for webtop application. 
RewriteCond %{REQUEST_URI}  ^/guaclite            [NC]
RewriteRule /(.*)           ws://yourdomain:your_port/$1 [P]
# the following blockcode is responsible for all request with /files/socket.io as prefix and transport=websocket. Such requests are created by webtop application (a virtual desktop applicaiton running on webbrowser)
RewriteCond %{REQUEST_URI}  ^/files/socket.io
RewriteCond %{QUERY_STRING} transport=websocket    [NC]
RewriteRule /(.*)           ws://yourdomain:your_port/$1 [P,L]
# the above rule is also last rule for all rewrite rule 
.....
ProxyPass / http://yourdomain:your_port/
ProxyPassReverse / http://yourdomain:your_port/

возможно, немного знаний в модуле перезаписи поможет https://httpd.apache.org/docs/current/mod/mod_rewrite.html

Другие вопросы по тегам