Configurando o Apache2 para proxy WebSocket?

40

O protocolo WebSocket é uma extensão do protocolo HTTP. No entanto, o módulo proxy do Apache2 parece desconhecer e joga fora cabeçalhos cruciais, convertendo a chamada em uma chamada HTTP padrão.

Existe uma maneira de fazer o Apache2 (1) entender o WebSocket ou (2) simplesmente transmitir cegamente o que obtém?

Blixt
fonte

Respostas:

23

Agora existe um módulo no tronco do Apache chamado mod_proxy_wstunnel que permite que o mod_proxy (ProxyPass / ProxyPassReverse) passe pelo tráfego do WebSocket. Alguém escreveu um post de blog sobre a portabilidade de mod_proxy_wstunnel para o Apache 2.4 / 2.2 e forneceu um patch para isso.

Eu descobri instruções concretas para configurar o mod_proxy_wstunnel no Ubuntu (testado com o Ubuntu Server 11.10 e Apache 2.2.20) e as publiquei no meu blog. Eu os copiei abaixo:

# 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
fonte
2
Quando segui o seu guia, houve um passo que você não deu. Depois de fazer os checkouts de abril, tive que executar ./buildconfigpara criar o arquivo de configuração. E havia algumas dependências que ele me disse para instalar.
notbad.jpeg
faz este gancho com Glassfish 4 sobre wss: (SSL)
Archimedes Trajano
11
@ notbad.jpeg: Você provavelmente quer dizer ./buildconf (não ./buildconfig) :-)
Erik Forsberg
11
Apenas o meu feedback ... este instalado e carregado no apache 2.2.22-1ubuntu1.10 do Ubuntu 12.04, mas não funcionou para mim no final. O proxy estava removendo o cabeçalho "Upgrade" (o código fonte diz "RFC2616 13.5.1 diz que devemos remover esses cabeçalhos"), que é um cabeçalho que o servidor espera, não apenas um salto, por isso não funcionou para mim, e substituí-o por uma regra DNAT do iptables.
Peter
11

Não há nada para indicar que o Apache httpd os apoiará em breve.

Se você deve executar websockets através do apache, tente mod_pywebsocket . Eu tentei e funciona.

Aqui estão algumas alternativas que eu prefiro:

h0tw1r3
fonte
3

Por favor, dê uma olhada em http://github.com/disconnect/apache-websocket

O módulo apache-websocket é um módulo do servidor Apache 2.x que pode ser usado para processar solicitações usando o protocolo WebSocket por um servidor Apache 2.x.

Marat Denenberg
fonte
Eu olhei para o projeto github acima. Não atua como proxy. citaçãoThe module consists of a plugin architecture ...
guettli
1

Isso adiciona à resposta de @Andrew Moss 'sobre como configurar corretamente o VirtualHostpara trabalhar com o socket.io 1.0! Sinta-se livre para pular a parte sobre o CentOS!


Se você está preso no CentOS 6, veja como fazê-lo:

  1. Faça o download da fonte de backport para o mod_proxy_wstunnelmódulo aqui (clone o Gist ou faça o download dos arquivos individualmente)
  2. Instale tudo o necessário para construir: yum install make gcc httpd-devel
  3. Configurar um ambiente RPM Build (basicamente um usuário sem privilégios e alguns diretórios)
  4. Copie o .carquivo-na SOURCESsubpasta do ambiente e o .specarquivo-na SPECSsubpasta.
  5. Corre rpmbuild -ba mod_proxy_wstunnel.spec
  6. O pacote está agora na SRPMSsubpasta
  7. Instale o pacote: rpm -i /path/to/package.rpm
  8. Lucro

Isso também carregará automaticamente o módulo no Apache, então você só precisa reiniciá-lo service httpd restart.


A configuração de um VirtualHostpara realmente servir o servidor Socket.io e o script do cliente (disponível por padrão em http://your.server/socket.io/socket.io.js) é um pouco mais complicado no Apache 2.2, devido a um erro no mod_proxymódulo :

Dada a seguinte regra de reescrita:

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

mod_rewrite trata esse caminho de arquivo para que o log de acesso mostre:

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

Portanto, você não pode usar o wsprotocolo-em uma regra de reescrita , porque isso se transformará internamente em uma solicitação HTTP GET.

Existe uma solução 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>

Isso garante que tudo enviado para /socket.iová para o ws://protocolo-, exceto a solicitação de pesquisa longa (que é um mecanismo de fallback quando o WebSockets não está disponível) e a solicitação da biblioteca-cliente.

Lukas Knuth
fonte