O PROXY Protocol permite que um proxy ou balanceador de carga comunique ao servidor de backend as informações de conexão do cliente original, incluindo seu endereço IP e porta reais, adicionando um pequeno cabeçalho padronizado no início da conexão TCP.
Por que o PROXY Protocol? O problema que ele resolve
Proxies TCP padrão funcionam estabelecendo uma nova conexão com o servidor de backend em nome do cliente. Da perspectiva do servidor de backend, a conexão se origina no endereço IP do proxy, e não no do cliente original. Esse comportamento oculta a identidade real do cliente e cria vários desafios:
- Logs: Os logs de acesso do servidor registram o IP do proxy, tornando impossível rastrear requisições até clientes individuais.
- Segurança: Web Application Firewalls (WAFs), limitadores de taxa e listas de controle de acesso (ACLs) nos servidores de backend não conseguem identificar e bloquear com precisão clientes maliciosos com base em seus endereços IP reais.
- Analytics: Geossegmentação, entrega de conteúdo personalizado e sistemas de detecção de abuso perdem dados críticos de localização e comportamento do cliente.
- Depuração: Diagnosticar problemas de rede ou comportamentos específicos de clientes fica significativamente mais complexo sem visibilidade da origem real do cliente.
O PROXY Protocol resolve isso oferecendo um mecanismo para que o proxy transmita os detalhes da conexão do cliente (IP de origem, porta de origem, IP de destino, porta de destino) através da camada de proxy, permitindo que o servidor de backend identifique corretamente o cliente original.
Como o PROXY Protocol funciona
O PROXY Protocol opera na camada de transporte (camada 4) do modelo OSI. Quando um proxy ou balanceador de carga compatível com o PROXY Protocol recebe uma conexão de um cliente, ele estabelece uma nova conexão com o servidor de backend. Antes de enviar qualquer dado da camada de aplicação (por exemplo, requisições HTTP ou consultas de banco de dados), o proxy envia primeiro um cabeçalho PROXY Protocol. Esse cabeçalho contém as informações de conexão do cliente.
Para que o PROXY Protocol funcione corretamente, duas condições precisam ser atendidas:
1. O proxy ou balanceador de carga deve estar configurado para enviar o cabeçalho PROXY Protocol.
2. O servidor de backend deve estar configurado para receber e interpretar o cabeçalho PROXY Protocol antes de processar qualquer dado da camada de aplicação. Se o servidor de backend não entender o cabeçalho, ele o interpretará como dados de aplicação malformados, gerando erros de conexão.
Versões do PROXY Protocol
Existem duas versões principais do PROXY Protocol: v1 e v2.
Versão 1 (v1)
O PROXY Protocol v1 usa um formato ASCII, legível por humanos. Ele suporta IPv4 e IPv6 sobre TCP.
Formato:
PROXY <INET_PROTOCOL> <CLIENT_IP> <PROXY_IP> <CLIENT_PORT> <PROXY_PORT>\r\n
<INET_PROTOCOL>:TCP4para IPv4 ouTCP6para IPv6.<CLIENT_IP>: O endereço IP do cliente original.<PROXY_IP>: O endereço IP do proxy (o IP que o backend enxerga como origem da conexão).<CLIENT_PORT>: A porta de origem do cliente original.<PROXY_PORT>: A porta de destino no proxy à qual o cliente se conectou.
Exemplo (IPv4):
PROXY TCP4 192.168.1.1 10.0.0.1 52345 80\r\n
Esse cabeçalho indica uma conexão TCPv4 do cliente 192.168.1.1:52345 para o proxy, que então se conectou ao backend em 10.0.0.1:80.
Limitações da v1:
* Limitada a conexões TCP.
* O overhead do ASCII pode ser um pouco menos eficiente.
* Não suporta metadados adicionais.
Versão 2 (v2)
O PROXY Protocol v2 é um formato binário projetado para eficiência e extensibilidade. Ele suporta IPv4, IPv6 e sockets UNIX sobre TCP e UDP, e inclui um mecanismo de campos Type-Length-Value (TLV) para transmitir metadados adicionais da conexão.
Vantagens da v2:
* Eficiência: O formato binário reduz o tamanho do cabeçalho.
* Suporte mais amplo a protocolos: Suporta TCP, UDP e sockets UNIX.
* Suporte a IPv6: Integra IPv6 por completo.
* Extensibilidade (TLV): Permite passar metadados arbitrários, como informações de conexão SSL, IDs únicos de conexão ou outros dados específicos da aplicação.
Visão geral da estrutura (simplificada):
O cabeçalho v2 começa com uma assinatura de 13 bytes, seguida por um campo de versão/comando de 1 byte, um campo de protocolo de 1 byte, um campo de comprimento de endereço de 2 bytes e, em seguida, as informações de endereço de tamanho variável e os campos TLV opcionais.
Embora o formato binário bruto seja complexo, o ponto essencial é sua capacidade de transmitir mais informações de forma eficiente e em uma gama mais ampla de protocolos.
PROXY Protocol vs. X-Forwarded-For (XFF)
Tanto o PROXY Protocol quanto o cabeçalho HTTP X-Forwarded-For (XFF) têm como objetivo repassar a informação de IP do cliente através de um proxy. No entanto, eles operam em camadas diferentes e têm características distintas.
| Característica | PROXY Protocol | Cabeçalho X-Forwarded-For (XFF) |
|---|---|---|
| Camada de operação | Camada de transporte (L4) | Camada de aplicação (L7 — especificamente HTTP) |
| Escopo de protocolo | Qualquer protocolo baseado em TCP/UDP (HTTP, FTP, SSH, SMTP etc.) | Apenas HTTP/HTTPS |
| Mecanismo | Cabeçalho adicionado ao fluxo bruto TCP/UDP | Cabeçalho de requisição HTTP |
| Controle do cliente | Não pode ser forjado por um cliente malicioso depois do primeiro proxy confiável | Pode ser forjado por um cliente malicioso se não for tratado corretamente pelo primeiro proxy confiável |
| Informação | IP do cliente, porta do cliente, IP do proxy, porta do proxy, (v2: TLVs) | IP do cliente (e possivelmente IPs de proxies anteriores) |
| Overhead | Mínimo, tamanho fixo (v1) ou binário pequeno (v2) | Pequena string adicionada aos cabeçalhos HTTP |
| Casos de uso | Qualquer serviço TCP/UDP que precise do IP real do cliente | Serviços HTTP/HTTPS que precisem do IP real do cliente |
O PROXY Protocol oferece uma solução mais robusta e universal para repassar a informação de IP do cliente, especialmente para serviços não HTTP ou em cenários que exigem garantias fortes contra falsificação de IP do cliente na camada de rede.
Implementando o PROXY Protocol
Implementar o PROXY Protocol exige configuração tanto no proxy/balanceador de carga que envia quanto no servidor de backend que recebe.
Configuração do proxy/balanceador de carga (enviando o PROXY Protocol)
HAProxy:
O HAProxy é uma escolha comum para balanceamento de carga e suporta totalmente o PROXY Protocol.
frontend http_in
bind *:80
mode tcp
default_backend web_servers
backend web_servers
mode tcp
server s1 192.168.1.10:80 send-proxy-v2 # Envia PROXY Protocol v2
server s2 192.168.1.11:80 send-proxy # Envia PROXY Protocol v1
AWS Network Load Balancer (NLB):
Ao configurar um Target Group para um NLB, você pode habilitar o suporte ao PROXY Protocol v2. Essa configuração é aplicada a todo o target group. Todos os targets desse grupo precisam estar configurados para aceitar o PROXY Protocol.
Cloudflare Spectrum:
Para serviços que passam pelo Cloudflare Spectrum, você pode habilitar o suporte ao PROXY Protocol. O Cloudflare enviará cabeçalhos PROXY Protocol v2 aos seus servidores de origem.
Nginx (módulo Stream — atuando como proxy):
O ngx_stream_proxy_module do Nginx pode ser configurado para enviar o PROXY Protocol, principalmente na versão comercial ou em builds específicos.
stream {
upstream backend_servers {
server 192.168.1.10:80;
server 192.168.1.11:80;
}
server {
listen 12345;
proxy_pass backend_servers;
proxy_protocol on; # O Nginx envia PROXY Protocol v1
}
}
Configuração do servidor de backend (recebendo e interpretando o PROXY Protocol)
Nginx (como servidor web de backend):
O Nginx pode ser configurado para escutar e interpretar cabeçalhos PROXY Protocol.
http {
server {
listen 80 proxy_protocol; # Escuta PROXY Protocol v1/v2 na porta 80
listen 443 ssl proxy_protocol;
set_real_ip_from 10.0.0.0/8; # Confia nos IPs da sua rede de proxy
real_ip_header proxy_protocol; # Usa o IP do cabeçalho PROXY Protocol
location / {
root /var/www/html;
index index.html;
# O IP real do cliente agora estará disponível em $remote_addr
# e $proxy_protocol_addr pode ser usado para logs ou lógica específica
log_format custom_log '$proxy_protocol_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log custom_log;
}
}
}
No Nginx, $remote_addr será definido com o IP do proxy, mas as variáveis $proxy_protocol_addr e $proxy_protocol_port conterão o IP e a porta reais do cliente. As diretivas set_real_ip_from e real_ip_header proxy_protocol permitem que o Nginx preencha corretamente $remote_addr com o IP real do cliente.
Apache HTTP Server:
O Apache pode usar o módulo mod_remoteip para interpretar cabeçalhos PROXY Protocol.
<IfModule mod_remoteip.c>
# Habilita a interpretação do PROXY Protocol
RemoteIPProxyProtocol On
# Define os proxies confiáveis
RemoteIPTrustedProxy 10.0.0.0/8
RemoteIPTrustedProxy 192.168.0.0/16
# Configura o formato de log para usar o IP real do cliente
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
</IfModule>
Com RemoteIPProxyProtocol On, o Apache espera o cabeçalho PROXY Protocol. A variável %a no LogFormat refletirá então corretamente o IP real do cliente.
Aplicações customizadas:
Para aplicações customizadas escritas em linguagens como Python, Node.js, Go ou Java, a própria aplicação precisa ler o fluxo TCP de entrada, verificar a presença do cabeçalho PROXY Protocol, interpretá-lo e só então prosseguir com o protocolo específico da aplicação.
- Detecção: A aplicação deve primeiro ler alguns bytes (por exemplo, 100–200 bytes) do socket para verificar se correspondem à assinatura do PROXY Protocol v1 (
PROXY) ou à assinatura da v2. - Parsing: Se um cabeçalho PROXY Protocol for detectado, a aplicação o interpreta para extrair o IP do cliente, a porta etc.
- Continuação: Depois do parsing, a aplicação processa os dados restantes do socket como seu protocolo nativo.
- Sem cabeçalho: Se nenhum cabeçalho PROXY Protocol for encontrado, a aplicação assume que a conexão vem diretamente de um cliente ou de um proxy sem PROXY Protocol e processa os dados diretamente.
Muitas bibliotecas e frameworks de rede oferecem middleware ou suporte nativo ao parsing do PROXY Protocol.
Benefícios de usar o PROXY Protocol
- Registro de IP preciso: Garante que os logs de acesso do servidor, firewalls e sistemas de monitoramento registrem o IP real do cliente.
- Segurança aprimorada: Permite que ferramentas de segurança (WAFs, mitigação de DDoS, limitadores de taxa) nos servidores de backend apliquem políticas com base na identidade real do cliente.
- Analytics melhores: Fornece dados geográficos e demográficos precisos para analytics, testes A/B e personalização.
- Arquitetura de rede simplificada: Consolida o tratamento do IP do cliente na camada de transporte, reduzindo a necessidade de cabeçalhos específicos de aplicação como o XFF.
- Ampla compatibilidade: Funciona com qualquer aplicação baseada em TCP/UDP, não apenas HTTP.
Considerações e boas práticas
- Fronteiras de confiança: Habilite o PROXY Protocol apenas a partir de proxies ou balanceadores de carga confiáveis que você controla. Se uma entidade não confiável enviar um cabeçalho PROXY Protocol forjado, seu servidor de backend pode ser enganado quanto à origem do cliente.
- Compatibilidade ponta a ponta: Garanta que o proxy e o servidor de backend estejam corretamente configurados para enviar e receber a mesma versão do PROXY Protocol (v1 ou v2). Incompatibilidades causam falhas de conexão.
- Desempenho: O overhead introduzido pelo cabeçalho do PROXY Protocol é mínimo, especialmente com o formato binário da v2. Ainda assim, o parsing em cada conexão adiciona um custo de processamento pequeno e desprezível.
- Monitoramento: Monitore os logs do servidor de backend e o tráfego de rede para verificar se os IPs dos clientes estão sendo identificados corretamente e se não ocorrem erros inesperados de PROXY Protocol.
