Apache HTTP Server para devs – Proxy Reverso
Dando seguimento a nossa série sobre o Apache, um dos recursos mais poderosos do Apache (e aquele que me motivou a escrever este guia) é a possibilidade de termos um proxy reverso.
Este conceito – proxy reverso – não é muito conhecido por muitos desenvolvedores, mas uma vez estabelecido o contato inicial, poderá mudar bastante sua visão a respeito do modo como sua infraestrutura pode ser configurada.
Como quase todo capítulo deste guia vamos começar expondo os problemas para, na sequência, tratarmos do conceitual e irmos para a prática.
Os problemas
Você quer disponibilizar um serviço presente em um servidor que não deve ser totalmente exposto
Imagine que você tem um servidor no qual existam os seguintes serviços instalados:
- Seu ERP super poderoso com dados de altíssima confidencialidade – o que você não quer expor.
- A API de um sistema que será consumida pelo seu bem estruturado frontend – o que você quer sem dúvidas quer expor.
O diagrama da figura 1 exemplifica bem esse caso:
O computador no qual sua API está em execução não deve ser diretamente exposto na internet. Então o frontend irá interagir apenas com o Apache (disponibilizado na Internet) que, por sua vez, direcionará o tráfego apenas para o módulo API, deixando o ERP isolado.
O serviço a ser disponibilizado está usando uma porta diferente (ou você quer centralizar a configuração de TLS/HTTPS em um único ponto (neste caso o Apache))
Sabe o problema anterior? Talvez esteja tudo até mesmo no servidor, só que o serviço está usando uma porta diferente daquela que você deseja disponibilizar ao frontend.
Melhor ainda, dado que gerenciar certificados TLS/SSL pode ser um saco, você quer centralizar toda a gestão dos seus certificados digitais em um único ponto, o Apache.
O diagrama da figura 2 expõe esta situação: temos nossa API sendo servida internamente usando a porta 9090, mas a gestão dos certificados SSL/TLS está centralizada no Apache: as requisições chegarão ao Apache e este, por sua vez, realizará o meio de campo entre o frontend e a API. Você não precisará configurar certificados para o módulo API (imagine que está hospedado em algo como um Apache Tomcat, por exemplo), apenas no Apache HTTP.
Mas o que é um proxy?
Conceitualmente, proxy é algo que se faz passar por outra entidade. Voltando ao nosso exemplo, o frontend acredita estar lidando com nossa API. Entretanto ele interage diretamente com um substituto: alguém que se faz passar por algo que não é.
Mas não basta simplesmente se passar pelo que não é, pois caso contrário teríamos simplesmente um mock. O proxy, para ser um proxy, obrigatóriamente deve intermediar a interação entre o cliente (aquele que inicia a interação) e o servidor (aquele com o qual o cliente deseja interagir).
E durante esta intermediação o proxy pode, para não se tornar um objeto inútil, enriquecer este processamento executando ações tais como:
- Comprimir a resposta enviada ao cliente usando gzip.
- Ao invés de consultar o servidor, obter uma resposta cacheada, minimizando com isto o consumo computacional.
- Criptografia – o proxy pode, por exemplo, aplicar a criptografia SSL sem que o objeto alvo da interação sequer saiba (e veremos isto em um outro post).
- Controlar o acesso ao serviço com o qual desejamos interagir.
- E, para o mal, pode te fazer achar que está usando um serviço e na realidade, estar usando outro (e isto dá muito medo só de pensar).
O proxy é portanto um intermediário que tem como principal objetivo ocultar o objeto de interação ao mesmo tempo que enriquece o modo como interagimos com o serviço ocultado.
Então por que este proxy se chama proxy reverso? Por que aqui estamos fazendo o contrário: estamos expondo algo com nosso proxy (só que de forma indireta e modificando a interação com este).
Pondo em prática
Habilitando alguns módulos
Caso você esteja acompanhando nossa série sobre o Apache, até este momento ele não faz mais que servir conteúdo estático e definir alguns virtual hosts. Módulos são o que realmente dão graça ao Apache, sendo assim vamos começar a habilitar alguns.
Se você possui uma instalação virgem do Apache, é hora de conhecer um importante comando: a2enmod
. Como usuário root, digite-o na sua interface de linha de comando, você verá uma saída similar à exposta na figura 3:
A saída obtida são todos os módulos que vieram na instalação padrão do Apache (pode variar de acordo com a sua distribuição). O comando a2enmod
é usado para que possamos habilitar estes módulos. É importante que você saiba neste momento quais habilitar:
- proxy
- proxy_http
- proxy_ajp
- rewrite
- deflate
- headers
- proxy_balancer (usaremos este aqui num post futuro)
- proxy_connect
- proxy_html
Notou que no comando acima ele pede que você digite o nome dos módulos que deseja habilitar? Então, basta digitar esta lista que acabei de passar separando cada um por espaço, tal como no comando a seguir:
a2enmod proxy proxy_http proxy_ajp rewrite deflate headers proxy_balancer proxy_connect proxy_html
Após habilitar todos estes módulos você deverá reiniciar o Apache. Como fazer isto?
sudo
service apache2 restart
Configurando o proxy reverso
Configurar o proxy reverso requer apenas três linhas de configuração. Para tal, vamos editar um dos sites habilitados na sua instalação do Apache. Se a sua for uma instalação virgem, muito provavelmente este arquivo será o /etc/apache2/sites-enabled/000-default.conf
.
Nota: Releia o primeiro capítulo deste guia no qual falamos a respeito dos arquivos de configuração do Apache.
Edite-o para que fique similar ao exemplo a seguir:
<VirtualHost *:80>
# Da raíz ao servidor destino na porta 9444
ProxyPass / http://172.17.0.3:9444/
# E do servidor destino, na raíz, para a raíz deste Virtual Host
ProxyPassReverse / http://172.17.0.0.3:9444/
# E nós vamos preservar o host em todas as requisições
ProxyPreserveHost On
</VirtualHost>
Apache HTTP Server para devs – Proxy Reverso
Henrique Lobo WeissmannApache HTTPGuias 08/05/2024
Dando seguimento a nossa série sobre o Apache, um dos recursos mais poderosos do Apache (e aquele que me motivou a escrever este guia) é a possibilidade de termos um proxy reverso.
Este conceito – proxy reverso – não é muito conhecido por muitos desenvolvedores, mas uma vez estabelecido o contato inicial, poderá mudar bastante sua visão a respeito do modo como sua infraestrutura pode ser configurada.
Como quase todo capítulo deste guia vamos começar expondo os problemas para, na sequência, tratarmos do conceitual e irmos para a prática.
Os problemas
Você quer disponibilizar um serviço presente em um servidor que não deve ser totalmente exposto
Imagine que você tem um servidor no qual existam os seguintes serviços instalados:
- Seu ERP super poderoso com dados de altíssima confidencialidade – o que você não quer expor.
- A API de um sistema que será consumida pelo seu bem estruturado frontend – o que você quer sem dúvidas quer expor.
O diagrama da figura 1 exemplifica bem esse caso:
O computador no qual sua API está em execução não deve ser diretamente exposto na internet. Então o frontend irá interagir apenas com o Apache (disponibilizado na Internet) que, por sua vez, direcionará o tráfego apenas para o módulo API, deixando o ERP isolado.
O serviço a ser disponibilizado está usando uma porta diferente (ou você quer centralizar a configuração de TLS/HTTPS em um único ponto (neste caso o Apache))
Sabe o problema anterior? Talvez esteja tudo até mesmo no servidor, só que o serviço está usando uma porta diferente daquela que você deseja disponibilizar ao frontend.
Melhor ainda, dado que gerenciar certificados TLS/SSL pode ser um saco, você quer centralizar toda a gestão dos seus certificados digitais em um único ponto, o Apache.
O diagrama da figura 2 expõe esta situação: temos nossa API sendo servida internamente usando a porta 9090, mas a gestão dos certificados SSL/TLS está centralizada no Apache: as requisições chegarão ao Apache e este, por sua vez, realizará o meio de campo entre o frontend e a API. Você não precisará configurar certificados para o módulo API (imagine que está hospedado em algo como um Apache Tomcat, por exemplo), apenas no Apache HTTP.
Mas o que é um proxy?
Conceitualmente, proxy é algo que se faz passar por outra entidade. Voltando ao nosso exemplo, o frontend acredita estar lidando com nossa API. Entretanto ele interage diretamente com um substituto: alguém que se faz passar por algo que não é.
Mas não basta simplesmente se passar pelo que não é, pois caso contrário teríamos simplesmente um mock. O proxy, para ser um proxy, obrigatóriamente deve intermediar a interação entre o cliente (aquele que inicia a interação) e o servidor (aquele com o qual o cliente deseja interagir).
E durante esta intermediação o proxy pode, para não se tornar um objeto inútil, enriquecer este processamento executando ações tais como:
- Comprimir a resposta enviada ao cliente usando gzip.
- Ao invés de consultar o servidor, obter uma resposta cacheada, minimizando com isto o consumo computacional.
- Criptografia – o proxy pode, por exemplo, aplicar a criptografia SSL sem que o objeto alvo da interação sequer saiba (e veremos isto em um outro post).
- Controlar o acesso ao serviço com o qual desejamos interagir.
- E, para o mal, pode te fazer achar que está usando um serviço e na realidade, estar usando outro (e isto dá muito medo só de pensar).
O proxy é portanto um intermediário que tem como principal objetivo ocultar o objeto de interação ao mesmo tempo que enriquece o modo como interagimos com o serviço ocultado.
Então por que este proxy se chama proxy reverso? Por que aqui estamos fazendo o contrário: estamos expondo algo com nosso proxy (só que de forma indireta e modificando a interação com este).
Pondo em prática
Habilitando alguns módulos
Caso você esteja acompanhando nossa série sobre o Apache, até este momento ele não faz mais que servir conteúdo estático e definir alguns virtual hosts. Módulos são o que realmente dão graça ao Apache, sendo assim vamos começar a habilitar alguns.
Se você possui uma instalação virgem do Apache, é hora de conhecer um importante comando: a2enmod
. Como usuário root, digite-o na sua interface de linha de comando, você verá uma saída similar à exposta na figura 3:
A saída obtida são todos os módulos que vieram na instalação padrão do Apache (pode variar de acordo com a sua distribuição). O comando a2enmod
é usado para que possamos habilitar estes módulos. É importante que você saiba neste momento quais habilitar:
- proxy
- proxy_http
- proxy_ajp
- rewrite
- deflate
- headers
- proxy_balancer (usaremos este aqui num post futuro)
- proxy_connect
- proxy_html
Notou que no comando acima ele pede que você digite o nome dos módulos que deseja habilitar? Então, basta digitar esta lista que acabei de passar separando cada um por espaço, tal como no comando a seguir:
a2enmod proxy proxy_http proxy_ajp rewrite deflate headers proxy_balancer proxy_connect proxy_html
Após habilitar todos estes módulos você deverá reiniciar o Apache. Como fazer isto?
sudo
service apache2 restart
Configurando o proxy reverso
Configurar o proxy reverso requer apenas três linhas de configuração. Para tal, vamos editar um dos sites habilitados na sua instalação do Apache. Se a sua for uma instalação virgem, muito provavelmente este arquivo será o /etc/apache2/sites-enabled/000-default.conf
.
Nota: Releia o primeiro capítulo deste guia no qual falamos a respeito dos arquivos de configuração do Apache.
Edite-o para que fique similar ao exemplo a seguir:
<VirtualHost *:80>
# Da raíz ao servidor destino na porta 9444
ProxyPass / http://172.17.0.3:9444/
# E do servidor destino, na raíz, para a raíz deste Virtual Host
ProxyPassReverse / http://172.17.0.0.3:9444/
# E nós vamos preservar o host em todas as requisições
ProxyPreserveHost On
</VirtualHost>
Observe que na realidade estamos aqui editando um host virtual que recebe todas as requisições do servidor Apache na porta 80.
A primeira diretriz, ProxyPass, mapeia o contexto do host corrente (“/” neste caso) para um servidor de destino. Em nosso exemplo, este servidor consistirá no http://172.17.0.3:9444
(que 9444 é este? Estou usando o S3 Ninja como exemplo).
Agora precisamos realizar o caminho reverso. Entra em cena a diretiva ProxyPassReverse. Ela essencialmente obtém a resposta do serviço oculto (o segundo parâmetro) e mapeia para a resposta a ser enviada para o servidor proxy.
Finalmente, temos a terceira diretiva: ProxyPreserveHost, que apenas serve para repassar o mesmo host recebido na requisição de origem para o serviço que está sendo “proxiado”. Se o parâmetro for On, o host será passado para o serviço alvo, caso contrário, será usado o mesmo endereço definido em ProxyPassReverse no segundo parâmetro.
Lembre-se de reiniciar o Apache após ter alterado estas configurações.
Notou que não há um DocumentRoot nesta configuração? É por que não estamos transmitindo o conteúdo do Apache para o nosso cliente, apenas o conteúdo gerado pelo serviço que estamos “proxiando”.
E como testa isto? Simples: acesse o seu servidor Apache. Se tudo estiver bem configurado, uma página proveniente do sistema “proxiado” será o retorno apresentado pelo browser!
Proxy reverso com virtual hosts
Voltando ao /dev/All, vamos imaginar que a API, anteriormente mencionada, seja aquela usada para alimentar o nosso frontend e que esta estaria disponibilizada em outro servidor, usando outra porta. Como você configuraria o arquivo deste host virtual?
Segue um exemplo rápido:
Resumindo
Este foi o nosso primeiro contato com o conceito de proxy reverso no Apache, mas acredito que já tenha sido possível compreender a ideia e perceber o potencial que ele pode nos proporcionar.
Agora você sabe como expor parte dos seus servidores na web e, mais importante: viu que é um processo bastante simples.
De propósito apenas mencionei que podemos centralizar toda a gestão de certificados SSL no Apache, o que tornará sua vida muito mais fácil ao lidar com esta que, sabemos, é uma tarefa que pode ser tediosa.
Qual o motivo disso? Em nosso próximo post da série sobre o Apache, será possível aprender a lidar com esse tipo de gestão de maneira fácil e econômica, utilizando o Certbot e o projeto Let’s Encrypt.