¿Configurando Apache2 para proxy WebSocket?

40

El protocolo WebSocket es una extensión del protocolo HTTP. Sin embargo, el módulo proxy de Apache2 no parece saberlo y desecha encabezados cruciales, convirtiendo la llamada en una llamada HTTP estándar.

¿Hay alguna manera de hacer que Apache2 (1) entienda WebSocket o (2) simplemente pase a ciegas lo que sea que reciba?

Blixt
fuente

Respuestas:

23

Ahora hay un módulo en el tronco de Apache llamado mod_proxy_wstunnel que permite que mod_proxy (ProxyPass / ProxyPassReverse) pase a través del tráfico de WebSocket. Alguien escribió una publicación en el blog sobre la modificación de puertos mod_proxy_wstunnel a Apache 2.4 / 2.2 y proporcionó un parche para hacerlo.

Descubrí instrucciones concretas para configurar mod_proxy_wstunnel en Ubuntu (probado con Ubuntu Server 11.10 y Apache 2.2.20) y las publiqué en mi blog. Los he copiado a continuación:

# 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
fuente
2
Cuando seguí a tu guía, hubo un paso que no diste. Después de hacer los pagos apr tuve que ejecutar ./buildconfigpara crear el archivo de configuración. Y hubo un par de dependencias que me dijeron que instalara.
notbad.jpeg
Cómo se conecta esto con Glassfish 4 sobre wss: (SSL)
Archimedes Trajano
1
@ notbad.jpeg: Probablemente te refieres a ./buildconf (no ./buildconfig) :-)
Erik Forsberg
1
Solo mi comentario ... esta instalado y cargado en apache 2.2.22-1ubuntu1.10 de Ubuntu 12.04, pero al final no funcionó para mí. El proxy estaba eliminando el encabezado "Actualizar" (el código fuente dice "RFC2616 13.5.1 dice que deberíamos quitar estos encabezados"), que es un encabezado que el servidor espera, no solo un salto, por lo que no funcionó para mí, y lo he reemplazado con una regla DNAT de iptables en su lugar.
Peter
3

Por favor, eche un vistazo a http://github.com/disconnect/apache-websocket

El módulo apache-websocket es un módulo de servidor Apache 2.x que puede ser usado para procesar solicitudes usando el protocolo WebSocket por un servidor Apache 2.x.

Marat Denenberg
fuente
Miré el proyecto github anterior. No actúa como proxy. citaThe module consists of a plugin architecture ...
guettli
1

¡Esto se agrega a la respuesta de @Andrew Moss sobre cómo configurar correctamente VirtualHostpara que funcione con socket.io 1.0! ¡Siéntase libre de omitir la parte sobre CentOS!


Si está atascado en CentOS 6, aquí le mostramos cómo hacerlo:

  1. Descargue la fuente con respaldo para el mod_proxy_wstunnelmódulo aquí (clone Gist o descargue los archivos individualmente)
  2. Instala todo lo necesario para construir: yum install make gcc httpd-devel
  3. Configurar un entorno de compilación RPM (básicamente un usuario sin privilegios y algunos directorios)
  4. Copie el .carchivo en la SOURCESsubcarpeta del entorno y el .specarchivo en la SPECSsubcarpeta.
  5. correr rpmbuild -ba mod_proxy_wstunnel.spec
  6. El paquete ahora está en la SRPMSsubcarpeta
  7. Instala el paquete: rpm -i /path/to/package.rpm
  8. Lucro

Esto también cargará automáticamente el módulo en Apache, por lo que solo tendrá que reiniciarlo service httpd restart.


Configurar a VirtualHostpara que realmente sirva el servidor Socket.io y el script de cliente (que está disponible de forma predeterminada en http://your.server/socket.io/socket.io.js) es un poco más complicado en Apache 2.2, debido a un error en el mod_proxymódulo :

Dada la siguiente regla de reescritura:

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

mod_rewrite trata esto como una ruta de archivo para que el registro de acceso muestre:

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

Por lo tanto, no puede usar ws-protocol en una regla de reescritura , porque eso se convertirá internamente en una solicitud HTTP GET.

Sin embargo, hay una solución alternativa:

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

Esto asegura que todo lo que se envía /socket.iova al ws://protocolo, excepto la solicitud de sondeo largo (que es un mecanismo alternativo cuando WebSockets no está disponible) y la solicitud de la biblioteca cliente.

Lukas Knuth
fuente