web-dev-qa-db-fra.com

Configurer Apache2 pour proxy WebSocket?

Le protocole WebSocket est une extension du protocole HTTP. Cependant, le module proxy d'Apache2 ne semble pas le savoir et jette les en-têtes cruciaux, convertissant l'appel en un appel HTTP standard.

Existe-t-il un moyen de faire Apache2 soit (1) comprendre WebSocket ou (2) simplement transmettre aveuglément tout ce qu'il obtient?

41
Blixt

Il y a maintenant un module dans le tronc Apache appelé mod_proxy_wstunnel qui permet à mod_proxy (ProxyPass/ProxyPassReverse) de traverser le trafic WebSocket. Quelqu'un a écrit un article de blog sur back-porting mod_proxy_wstunnel vers Apache 2.4/2.2 et a fourni un correctif pour le faire.

J'ai trouvé concret instructions pour configurer mod_proxy_wstunnel sur Ubunt (testé avec Ubuntu Server 11.10 et Apache 2.2.20) et les ai postés sur mon blog. Je les ai copiés ci-dessous:

# 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
23
Andrew Moss

Il y a rien à indiquer Apache httpd les supportera de sitôt.

Si vous devez exécuter des websockets via Apache, essayez mod_pywebsocket . Je l'ai essayé et ça marche.

Voici quelques alternatives que je préfère:

11
h0tw1r3

On dirait qu'avec une combinaison du plugin de déconnexion et du code supplémentaire, cela est maintenant possible:

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

6
pablojim

Veuillez jeter un œil à http://github.com/disconnect/Apache-websocket

Le module Apache-websocket est un module serveur Apache 2.x qui peut être utilisé pour traiter les demandes utilisant le protocole WebSocket par un serveur Apache 2.x.

4
Marat Denenberg

Cet ajout à @ Andrew Moss 'répond à la façon de configurer correctement le VirtualHost pour qu'il fonctionne avec socket.io 1.0! N'hésitez pas à sauter la partie sur CentOS!


Si vous êtes bloqué sur CentOS 6, voici comment procéder:

  1. Téléchargez la source rétroportée pour le mod_proxy_wstunnel module ici (soit clonez le Gist, soit téléchargez les fichiers individuellement)
  2. Installez tout le nécessaire pour construire: yum install make gcc httpd-devel
  3. Configurer un environnement de génération RPM (essentiellement un utilisateur non privilégié et certains répertoires)
  4. Copiez le .c- fichier dans le sous-dossier SOURCES de l'environnement et le .spec- fichier dans le sous-dossier SPECS.
  5. Courir rpmbuild -ba mod_proxy_wstunnel.spec
  6. Le package est maintenant dans le sous-dossier SRPMS
  7. Installez le package: rpm -i /path/to/package.rpm
  8. Profit

Cela chargera également automatiquement le module dans Apache, il vous suffit donc de le redémarrer avec service httpd restart.


Configuration d'un VirtualHost pour réellement servir le serveur Socket.io et le script client (qui est par défaut disponible sous http://your.server/socket.io/socket.io.js) est un peu plus compliqué sur Apache 2.2, à cause d'un Bug dans le mod_proxy module :

Étant donné la règle de réécriture suivante:

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

mod_rewrite traite cela comme un chemin de fichier afin que le journal d'accès affiche:

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

Donc, vous ne pouvez pas utiliser le protocole ws- dans une règle de réécriture , car cela se transformera en interne en une requête HTTP GET .

Il existe cependant une solution:

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

Cela garantit que tout ce qui est envoyé à /socket.io va au ws://- protocole, à l'exception de la demande d'interrogation longue (qui est un mécanisme de secours lorsque les WebSockets ne sont pas disponibles) et de la demande de la bibliothèque cliente.

1
Lukas Knuth