Konfigurujesz Apache2 do proxy WebSocket?

40

Protokół WebSocket jest rozszerzeniem protokołu HTTP. Jednak moduł proxy Apache2 nie wydaje się o tym wiedzieć i odrzuca kluczowe nagłówki, przekształcając wywołanie w standardowe wywołanie HTTP.

Czy istnieje sposób, aby Apache2 albo (1) rozumiał WebSocket, albo (2) po prostu ślepo przekazywał to, co dostaje?

Blixt
źródło

Odpowiedzi:

23

Obecnie w module Apache znajduje się moduł o nazwie mod_proxy_wstunnel, który umożliwia mod_proxy (ProxyPass / ProxyPassReverse) przechodzenie przez ruch WebSocket. Ktoś napisał post na blogu o back-portowaniu mod_proxy_wstunnel do Apache 2.4 / 2.2 i dostarczył łatkę, aby to zrobić.

Zrozumiałem konkretne instrukcje, jak skonfigurować mod_proxy_wstunnel na Ubuntu (testowany z Ubuntu Server 11.10 i Apache 2.2.20) i opublikowałem je na moim blogu. Skopiowałem je poniżej:

# 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
Andrew Moss
źródło
2
Kiedy poszedłem za twoim przewodnikiem, był krok, którego nie miałeś. Po dokonaniu transakcji APR musiałem uruchomić, ./buildconfigaby utworzyć plik konfiguracyjny. I było kilka zależności, które kazał mi zainstalować.
notbad.jpeg
robi to z Glassfish 4 przez wss: (SSL)
Archimedes Trajano
1
@ notbad.jpeg: Prawdopodobnie masz na myśli ./buildconf (nie ./buildconfig) :-)
Erik Forsberg
1
Tylko moja opinia ... to zostało zainstalowane i załadowane do apache 2.2.22-1ubuntu1.10 z Ubuntu 12.04, ale ostatecznie nie działało dla mnie. Serwer proxy usunął nagłówek „Upgrade” (kod źródłowy mówi „RFC2616 13.5.1 mówi, że powinniśmy usunąć te nagłówki”), który jest nagłówkiem, którego oczekuje serwer, a nie tylko jednym przeskokiem, więc nie zadziałało dla mnie, i zamiast tego zastąpiłem ją regułą DNAT iptables.
Peter
3

Proszę spojrzeć na http://github.com/disconnect/apache-websocket

Moduł apache-websocket to moduł serwera Apache 2.x, który może być wykorzystywany do przetwarzania żądań za pomocą protokołu WebSocket przez serwer Apache 2.x.

Marat Denenberg
źródło
Spojrzałem na powyższy projekt github. Nie działa jako proxy. cytatThe module consists of a plugin architecture ...
guettli
1

Ten dodatek do odpowiedzi @Andrew Moss na temat prawidłowej konfiguracji VirtualHostdo pracy z socket.io 1.0! Możesz pominąć część dotyczącą CentOS!


Jeśli utknąłeś na CentOS 6, oto jak to zrobić:

  1. Pobierz backportowaną źródło dla mod_proxy_wstunnelmodułu tutaj (albo sklonować GIST lub pobrać pliki indywidualnie)
  2. Zainstaluj wszystko, co niezbędne do zbudowania: yum install make gcc httpd-devel
  3. Skonfiguruj środowisko RPM Build (w zasadzie nieuprzywilejowany użytkownik i niektóre katalogi)
  4. Skopiuj .cplik do SOURCESpodfolderu środowiska, a .specplik do SPECSpodfolderu.
  5. Biegać rpmbuild -ba mod_proxy_wstunnel.spec
  6. Pakiet znajduje się teraz w SRPMSpodfolderze
  7. Zainstaluj pakiet: rpm -i /path/to/package.rpm
  8. Zysk

Spowoduje to również automatyczne załadowanie modułu do Apache, więc wystarczy go ponownie uruchomić service httpd restart.


Konfigurowanie VirtualHostserwera do obsługi serwera Socket.io i skryptu klienta (który domyślnie jest dostępny pod http://your.server/socket.io/socket.io.js) jest nieco bardziej skomplikowane w Apache 2.2, z powodu błędu w mod_proxymodule :

Biorąc pod uwagę następującą zasadę przepisywania:

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

mod_rewrite traktuje tę ścieżkę pliku, więc dziennik dostępu pokazuje:

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

Tak więc nie możesz użyć ws-protocol w regule przepisywania , ponieważ to wewnętrznie zamieni się w żądanie HTTP GET.

Istnieje jednak obejście:

<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>

Daje to pewność, że wszystko wysyłane do /socket.ioidzie do ws://-protocol, z wyjątkiem wniosku o długim odpytywania (co jest mechanizm awaryjnej gdy WebSockets nie są dostępne) oraz wniosek o Client-Library.

Lukas Knuth
źródło