Configurando Proxy Reverso para Websocket no Apache

Em um post anterior mostramos como configurar o Apache como um Proxy Reverso, permitindo publicar sites hospedados em um servidor interno ou em sua DMZ externamente, sem expor diretamente esse servidor para acessos externos.

No entanto, caso a aplicação web hospedada no servidor de backend utilize o protocolo Websocket para manter uma conexão permanente entre cliente e servidor, são necessárias algumas configurações adicionais.

Basicamente, para que o Apache possa fazer corretamente o Proxy desse protocolo, é necessário utilizar o RewriteEngine para que quando seja identificado no cabeçalho HTTP enviado pelo cliente uma solicitação de “Upgrade” para Websocket, seja realizada a reescrita da requisição usando o endereço do servidor backend da aplicação.

RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "wss://localhost:8443%{REQUEST_URI}" [P,L]

As condições acima fazem simplesmente identificar no cabeçalho se os campos Upgrade e Connection foram definidos conforme a RFC que define o protocolo Websocket e faz a reescrita da URL da Request, trocando a parte do Host pelo endereço do servidor interno. No caso desse exemplo acima, o servidor de backend está no mesmo Host (localhost) mas em outra porta (8443).

Configurando Proxy Reverso no Apache

Existem diversas situações que podem requerer a configuração de um proxy reverso. As mais comuns que encontramos no nosso dia-a-dia são para criar uma camada adicional de proteção para um servidor que pode estar rodando um software mais antigo e não apresentar nível de segurança suficiente para ficar exposto na internet.

Outra situação é configurar um balanceamento de carga entre servidores de aplicação, ficando o proxy reverso na função de centralizar as conexões e distribuí-las para os servidores de aplicação disponíveis.

A configuração mais simples é a que possui apenas um servidor de aplicação como backend sendo acessado pelo proxy reverso. Sua configuração requer apenas as instruções abaixo.

ProxyPass "/" "http://localhost:8080/"
ProxyPassReverse "/" "http://localhost:8080/"

Essas instruções devem, preferencialmente, estar dentro de um VirtualHost, para evitar confusões com outros sites que o Apache possa estar servindo. Mas caso seja um servidor usado apenas para o proxy reverso de um site apenas, é possível colocar na sessão principal do httpd.conf.

O que essa instrução faz é passar todas as requisições para o backend. No entanto, é possível fazer proxy apenas de determinadas pastas.

ProxyPass "/imagens/" "http://localhost:8080/imagens/"
ProxyPassReverse "/imagens/" "http://localhost:8080/imagens/"

Nesse exemplo acima, no caso de uma requisição para http://www.exemplo.com.br/imagens/logo.png seria feito o proxy para o serviço rodando na porta 8080, mas uma requisição para http://www.exemplo.com.br/index.php seria servido pelo próprio Apache local.

Uma questão importante é que os diretórios do proxy e do backend não precisam ser sempre iguais.

ProxyPass "/" "http://localhost:8080/site/"
ProxyPassReverse "/" "http://localhost:8080/site/"

Nas instruções acima, um acesso ao endereço http://www.exemplo.com.br/index.php seria direcionado para o backend no caminho http://localhost:8080/site/index.php

Isso é bastante útil e permite inclusive que caminhos diferentes da URL sejam servidos por servidores backend diferentes.