O Que é Proxy Reverso - Wiki F5 Network
O Que é Proxy Reverso
4. O pipeline de uma requisição HTTP
5. Decompondo a URI
6. Fazendo uma requisição
7. Escutando uma porta
8. Proxy Reverso
9. Proxy Reverso é parte fundamental da internet
10. Docker, Swarm e Kubernetes
11. Um exemplo real
Para que fique claro, precisamos voltar no tempo e revisitar alguns assuntos. Vou dar uma pincelada em assuntos como DHCP, DNS, e alocação de portas. É fundamental para conseguirmos chegar no ponto exato em que os Proxies Reversos fazem sentido.
Quando teu computador se conecta à uma rede, ocorre um handshake (apertar de mãos) para registrar-se e obter as configurações da rede. Uma das coisas que seu computador recebe é o IP e endereços de 2 servidores DNS.
Desse assunto, o que tem de estar claro é que sua rede informa quais os endereços dos servidores DNS's, o servidor DHCP é quem entrega essa informação, mas você também pode sobrescrever isso, para cada interface de rede.
Se você usa hyper-v ou virtualbox, verá interfaces de rede virtuais adicionais. Se você possuir um a placa de rede WIFI, terá outra interface física também.
DNS, Domain Name Server é um protocolo de resolução de nomes.
O DNS traduz nome em IP
E note, ele só traduz nomes em ip's.
Não é do escopo do DNS tratar portas.
Anota isso que é tão óbvio, quanto importante.
O pipeline de uma requisição HTTP
Quando, por linha de comando, executamos curl portal.azure.com ou mesmo usamos o browser para acessar o mesmo link. Algumas tarefas são realizadas.
Decompondo a URI
O primeiro passo é decompor a URI usada. Essa uri sempre segue a sentença acima.
Outras regras estão ligadas ao schema vs porta. Alguns schemas possuem portas padrão. Como HTTP refere-se à porta 80, enquanto HTTPS refere-se à 443 ou rtmp referindo-se à porta 1935.
Embora possamos, explicitamente definir a porta, quando não fazemos, a porta default é usada, caso haja.
Assim, quando acessamos portal.azure.com, a biblioteca base de rede (possivelmente do SO ou da tecnologia) faz o trabalho sujo de usar a infra de DNS para descobrir o IP em questão, recorrendo às buscas pelas autoridades de .com e .azure.com, e por fim pergunta pra .azure.com quem é o portal.azure.com.
Uma vez de posse do IP, é hora de enviar os pacotes pela rede. Mas para enviar esse pacote, precisamos especificar a porta de destino. Lembra daquelas regras que citei acima? Elas se aplicam aqui! É assim que a porta é descoberta. Usa-se preferencialmente a porta declarada na URI, caso não haja, avalia-se a porta padrão do schema. Caso não haja, erro! Simples assim!
Por isso algumas implementações de acesso à rede possuem mais schemas/padrões que outras e isso faz com que eventualmente possamos ver comportamentos diferentes aqui ou acolá.
Uma vez que sabemos IP e porta é hora de montar a requisição. Parte dessa mensagem é o cabeçalho, que por sinal é conhecido por nós, são os cabeçalhos do HTTP. Aquela informação que usamos para determinar protocolo, host, ip do host e porta, são enviados no cabeçalho.
É agora que começa a mágica do lado do servidor é aqui que precisamos de um proxy reverso. Sim, eu levei toda essa explicação para conseguir chegar até aqui.
Escutando uma porta
Nos sistemas operacionais que conhecemos e estão no nosso cotidiano, podemos escutar portas.
Isso é, criar um programa que recebe o tráfego de rede de uma ou mais portas.
Mas uma coisa precisa estar muito, mas muito clara. 2 processos não podem escutar a mesma porta! Seja no windows1 ou no linux2 escutar uma porta é uma tarefa exclusiva* para somente 1 processo.
1) No Windows, temos o port sharing como uma features que cria um serviço de escuta tcp, distribuidor de requisições. É uma feature exclusiva para produtos da própria Microsoft, como WCF, pois ao estar ativo, internamente os serviços que tentariam consumir a porta, passam a usar protocolos alternativos de comunicação entre processos para realizar a comunicação com o proxy.
2) Desde o kernel 3.9 o linux o primeiro chamador a abrir o socket de escuta, pode informar um parâmetro adicional para que a porta possa ser compartilhada. Pesquise sobre SO_REUSEPORT em SOCKET Linux Programmer's Manual.
Os modelos de escuta compartilhada de portas nascem para viabilizar a utilização de todos os cores do sistema para atender às escutas de rede. Isso permite que você tenha uma instância principal de gestão e diversos processos-filho escutando a mesma porta, mas processando em um core diferente. Mas isso não permite que você tenha 2 serviços ou sequer 2 instancias DISTINTAS. Pois a distribuição de carga geraria um caos.
Dessa forma, não conseguimos lidar com um apache e um nginx, ambos escutando a mesma porta 80 na mesma interface de rede. Precisamos de um mediador para isso.
Um proxy reverso vem resolver essa questão. E ao longo do tempo essa categoria de aplicações foi se especializando, ganhando funcionalidades e se subdividindo em diversas categorias.
Um forward proxy fica entre sua máquina e a internet, fazendo seu trabalho mediando o tráfego que está saindo.
Um proxy reverso fica entre a internet e seu servidor, fazendo seu trabalho com o tráfego que está chegando. .
Hoje em dia, um proxy reverso pode ter algumas responsabilidades comuns:
Tolerância a indisponibilidade
Todos os elementos comuns
Métrica de Consumo
Estrangulamento de tráfego excedente (por métricas por API)
Análise de conteúdo trafegado
API Gateways podem ser considerados proxies reversos? De certa forma sim, mas eles são classificados de forma diferente, pois eles têm uma visão um pouco diferente dos Proxies Reversos comuns.
API Gateways são especialistas em API's. Um proxy reverso, é mais generalista.
Um proxy reverso consegue limitar sua quantidade de requests a X por minuto. Mas não é muito eficiente ao determinar que você só pode consultar um determinado serviço, X vezes por mês. Os dados do proxy reverso em geral são mantidos em memória, enquanto nos api gateways são necessários bancos de dados para armazenar essas métricas e impor essas políticas.
Eu não vou entrar em detalhes a respeito disso, mas alguns proxies reversos, ou plugins para proxy reverso são usados inclusive para otimizar o conteúdo entregue. Alguns são especializados em HTML e conseguem fazer mágicas como, otimizar seu output html de diversas formas, lidando com coisas complexas como substituir suas referências para PNG's, e ao mesmo tempo mapear esses PNG's e substituílos por formatos mais otimizados como WebP. Isso de fato é insano, e convido a ler sobre Google PageSpeed Module.
Proxy Reverso é parte fundamental da internet
Vamos supor que você tenha 2 servidores de backend. Como você faz com que um deployment não cause indisponibilidade?
O proxy reverso que consegue determinar que um dos backends está indisponível conseguiria servir todo o tráfego com o servidor que está disponível, enquanto o outro servidor ainda não está pronto. E assim vamos fazendo rollouts que geram baixo ou nenhum impacto dependendo do skill da aplicação.
Quando sua consciência desperta para a compreensão disso, você percebe que entre você e quase que 100% das aplicações que conhece, que são hospedadas na nuvem, há um proxy reverso entre vocês. Google, Globo.com, gago.io, Medium, não importa onde.
Um proxy reverso é útil por outros motivos também. Na medida que o hardware se torna mais barato, cada vez temos mais capacidade de processamento. . Em vez de termos 1 servidor para cada projeto, para cada nome. Usamos poucos servidores para hospedar diversos sites e aplicações. Um proxy reverso ajuda nessa tarefa. Permitindo distribuir a caga de trabalho de acordo com os cabeçalhos HTTP. Lembra do hostname que é passado no cabeçalho HTTP? Pois é. Ele é quem faz essa mágica.
Isso permite que seu servidor hospede diversas aplicações, que seja mais fácil lidar com SSL, distribuição de carga e todas as features que falei, a respeito de um proxy reverso.
Docker, Swarm e Kubernetes
Em workloads baseados em containers, é natural o aumentando da densidade computacional, aproveitando ociosidade dos nossos servidores.
Antes, o argumento para tantos servidores distintos e pequenos, era garantir a gestão e isolamento de forma a não permitir que aplicações causassem impacto uma nas outras.
Uma vez que essa solução (fragmentar em servidores) se torna datada com a chegada do Docker, queremos agora otimizar nossa capacidade computacional. Para isso, pré-alocamos aquilo que sabemos que é o mínimo, e alocamos dinamicamente aquilo que for necessário para atender workloads elásticos. Isso demanda clusterização.
No nosso caso, deixamos docker lidar com os IP's de cada container. E portanto passamos a ter de lidar com resolução de nomes também dentro do cluster, para entender qual é o IP dos containers para o qual precisamos mediar a comunicação. Mas docker oferece essa feature para que você não tenha de lidar com isso.
Um request que chega aqui no gago.io começa da seguinte forma:
A autoridade responsável por meu DNS é o GoDaddy, nele eu tenho 2 apontamentos que dizem que o servidor DNS que responde por meu domínio está em no CloudFlare. O CloudFlare responde dizendo o IP (o ip de final 141, que você vê na imagem abaixo).
Como apresentei na live sobre NGINX, uso esse serviço como Edge da minha infraestrutura, ele recebe todas as requisições das portas 80 e 443 do meu servidor e distribui entre diversos containers.