Ao trabalhar com proxies, os desenvolvedores frequentemente se deparam com o fato de que as configurações clássicas de proxy HTTP não funcionam para conexões WebSocket, e o gRPC simplesmente falha com erros de handshake TLS. O problema é que WebSocket, HTTP/2 e gRPC não são apenas "variações do HTTP", mas sim diferentes modelos de transporte com suas próprias exigências em relação ao tunelamento, multiplexação e manipulação de cabeçalhos. Neste artigo, vamos discutir como fazer proxy para cada um desses protocolos, quais armadilhas podem ser encontradas na prática e como escolher o protocolo e o tipo de proxy para uma tarefa específica — desde parsing via WebSocket até microserviços gRPC de alta carga.
Quais são as diferenças entre os protocolos e por que isso é importante para o proxy
HTTP/1.1 opera sob o modelo "pedido-resposta": o cliente abre uma conexão, envia um pedido, recebe uma resposta e ou fecha a conexão ou a mantém aberta para o próximo pedido (keep-alive). Os servidores proxy foram otimizados por décadas para esse modelo — parsing de cabeçalhos, bufferização do corpo do pedido, roteamento simples pelo cabeçalho Host.
WebSocket quebra esse modelo: após o handshake inicial do HTTP (Upgrade: websocket), a conexão se transforma em um canal bidirecional permanente, onde os dados podem fluir em ambas as direções a qualquer momento. O proxy deve "liberar" essa conexão e simplesmente transferir bytes em ambas as direções, sem tentar interpretá-los como pedidos HTTP.
HTTP/2 adiciona multiplexação — vários pedidos lógicos passam por uma única conexão TCP paralelamente, usando frames binários em vez de cabeçalhos textuais. Para o proxy, isso significa que não se pode simplesmente ler texto linha por linha — é necessária a suporte ao protocolo binário HTTP/2 no nível do proxy ou tunelamento TCP transparente sobre TLS.
gRPC vai ainda mais longe: ele é estritamente baseado em HTTP/2, utiliza Protocol Buffers para serialização e requer um transporte compatível com HTTP/2 em todo o caminho do cliente ao servidor. Se o proxy "downgrade" a conexão para HTTP/1.1 em algum ponto, o pedido gRPC simplesmente não passará.
Compreender essas diferenças é crítico, pois a escolha do tipo errado de proxy ou uma configuração incorreta de tunelamento leva a desconexões, timeouts e erros difíceis de explicar, que são difíceis de diagnosticar sem entender o nível de transporte.
WebSocket através de proxy: configuração e código
Para WebSocket através de proxy, existem dois cenários principais: proxy HTTP com o método CONNECT (para WSS, ou seja, WebSocket sobre TLS) e proxy SOCKS5, que tunela a conexão TCP sem interpretar o protocolo. O SOCKS5 geralmente causa menos problemas, pois foi projetado desde o início como um "tubo transparente" para qualquer tráfego TCP.
Exemplo de conexão a WebSocket através de um proxy SOCKS5 em Python com a biblioteca websockets e python-socks:
import asyncio
from python_socks.sync import Proxy
import websockets
import websockets.sync.client as ws_client
def connect_ws_via_proxy():
proxy = Proxy.from_url("socks5://user:pass@proxy_host:1080")
sock = proxy.connect(dest_host="echo.websocket.events", dest_port=443)
ws = ws_client.connect(
"wss://echo.websocket.events",
sock=sock,
server_hostname="echo.websocket.events"
)
ws.send("Hello via proxy")
print(ws.recv())
ws.close()
connect_ws_via_proxy()
No Node.js, uma tarefa semelhante é resolvida através do pacote ws em conjunto com socks-proxy-agent:
const WebSocket = require('ws');
const { SocksProxyAgent } = require('socks-proxy-agent');
const agent = new SocksProxyAgent('socks5://user:pass@proxy_host:1080');
const socket = new WebSocket('wss://echo.websocket.events', { agent });
socket.on('open', () => socket.send('Hello via proxy'));
socket.on('message', (data) => console.log(data.toString()));
Se o proxy estiver disponível apenas via HTTP (com o método CONNECT), o esquema é semelhante — a maioria dos clientes WebSocket modernos consegue trabalhar através de um túnel HTTP, é importante apenas garantir que o proxy não desconecte conexões de longa duração devido a timeouts. Este é um problema comum com proxies de data center baratos, que têm um limite rígido de 30-60 segundos para conexões inativas — para tarefas de streaming WebSocket, isso é crítico, e é melhor verificar os parâmetros de keep-alive com o provedor.
HTTP/2 através de proxy: multiplexação e armadilhas
A principal dificuldade com HTTP/2 através de proxy é que muitos servidores proxy (especialmente os antigos Squid ou proxies simples) funcionam apenas com HTTP/1.1 e automaticamente "downgrade" a conexão. Para o cliente, isso muitas vezes passa despercebido (o pedido ainda é executado), mas as vantagens da multiplexação são perdidas — as latências aumentam, especialmente com um grande número de pedidos paralelos a um único host.
Para verificar se a conexão através do proxy suporta HTTP/2, você pode usar o cURL com a flag --http2 e uma saída detalhada:
curl -v --http2 -x http://user:pass@proxy_host:8080 https://example.com
# Na saída, procure pela linha:
# * Using HTTP2, server supports multiplexing
# Se ela não estiver lá — a conexão foi reduzida para HTTP/1.1
Em Python, para HTTP/2 através de proxy, é necessária a biblioteca httpx com suporte a HTTP/2 habilitado:
import httpx
proxies = {
"http://": "http://user:pass@proxy_host:8080",
"https://": "http://user:pass@proxy_host:8080",
}
with httpx.Client(proxies=proxies, http2=True) as client:
response = client.get("https://example.com")
print(response.http_version) # esperamos "HTTP/2"
print(response.status_code)
Um ponto importante: HTTP/2 requer TLS com a extensão ALPN para negociação de protocolo, portanto, o proxy deve tunelar o tráfego TLS de forma transparente através do CONNECT, e não terminar o TLS por conta própria (a menos que seja um proxy especializado compatível com HTTP/2). É por isso que para tarefas com HTTP/2, proxies residenciais e proxies de data center se comportam de maneira diferente — é importante verificar com o provedor se o tunelamento TLS transparente é suportado sem interromper as negociações ALPN.
gRPC através de proxy: TLS, ALPN e requisitos especiais
gRPC é o protocolo mais exigente nesta combinação. Ele é rigidamente vinculado ao HTTP/2 e frequentemente utiliza TLS bidirecional (mTLS) para autenticação. Um proxy simples, que não suporta tunelamento HTTP/2 CONNECT "como está", simplesmente não permitirá o tráfego gRPC — a conexão falhará com erros do tipo UNAVAILABLE: upstream connect error.
Para fazer proxy de gRPC em Python (com a biblioteca grpc), o proxy é definido através de variáveis de ambiente, já que o suporte embutido a proxy nas opções de canal historicamente não existia:
import os
import grpc
os.environ["grpc_proxy"] = "http://user:pass@proxy_host:8080"
os.environ["https_proxy"] = "http://user:pass@proxy_host:8080"
channel = grpc.secure_channel(
"grpc.example.com:443",
grpc.ssl_channel_credentials()
)
# Exemplo de chamada através do stub gerado
# stub = YourServiceStub(channel)
# response = stub.YourMethod(request)
No Node.js, o proxy para gRPC é configurado através das opções do canal grpc-js em conjunto com um agente proxy compatível com HTTP/2:
const grpc = require('@grpc/grpc-js');
const { HttpsProxyAgent } = require('https-proxy-agent');
process.env.grpc_proxy = 'http://user:pass@proxy_host:8080';
process.env.https_proxy = 'http://user:pass@proxy_host:8080';
const client = new YourServiceClient(
'grpc.example.com:443',
grpc.credentials.createSsl()
);
Para o funcionamento estável do gRPC através de proxy, é crucial ter baixa latência e uma conexão TCP estável sem desconexões frequentes — os streams multiplexados de gRPC são mais sensíveis a falhas de rede do que pedidos HTTP/1.1 individuais. Em tais cenários, proxies residenciais muitas vezes mostram melhor estabilidade em comparação com pools de data center baratos, pois a rota até o servidor de destino passa por uma infraestrutura de rede mais previsível.
Tabela comparativa de protocolos
| Protocolo | Tipo de conexão | Requisitos para o proxy | Tipo de proxy recomendado |
|---|---|---|---|
| HTTP/1.1 | pedido-resposta, keep-alive | mínimos, qualquer proxy HTTP | Proxies de data center |
| WebSocket | canal bidirecional permanente | suporte a conexões longas, sem timeouts | Proxies residenciais |
| HTTP/2 | fluxos binários multiplexados | tunelamento TLS transparente, ALPN | Proxies residenciais ou de data center |
| gRPC | HTTP/2 + Protobuf, frequentemente mTLS | baixa latência, estabilidade, HTTP/2 CONNECT | Proxies móveis para contornar filtros rígidos |
Como escolher o protocolo e o proxy para sua pilha
A escolha do protocolo raramente é uma decisão livre — ela é ditada pela API de destino. Mas a escolha do tipo de proxy para esse protocolo é sua responsabilidade, e aqui é importante se basear no cenário específico:
Parsing de dados através de WebSocket (por exemplo, streaming de cotações ou dados em tempo real de sites de marketplaces) requer uma conexão estável e longa sem desconexões devido a timeouts. Aqui, proxies residenciais funcionam melhor — eles raramente são pegos pelos algoritmos de antifraude do serviço de destino e mantêm a conexão por mais tempo do que pools típicos de data center.
Integração com microserviços gRPC através de um proxy externo (por exemplo, ao testar APIs de diferentes geolocalizações) requer baixa latência e suporte a HTTP/2 em todo o caminho. Para isso, IPs residenciais com boa roteação são adequados, e para tarefas críticas em termos de tempo — proxies móveis, se o serviço de destino filtrar agressivamente os intervalos de data center.
Pedidos HTTP/2 em massa para APIs REST/GraphQL com multiplexação — o cenário mais comum, onde proxies de data center rápidos e baratos são suficientes, se o serviço de destino não bloquear intervalos de IP de data center por padrão.
Regra geral: quanto mais "caprichoso" o protocolo em relação à estabilidade da conexão (WebSocket, gRPC), mais sentido faz usar IPs residenciais ou móveis. Quanto mais simples e curto o pedido (HTTP/1.1 comum ou HTTP/2 sem longas sessões), mais confortável é trabalhar com proxies de data center — eles são mais rápidos e oferecem maior largura de banda.
Erros comuns e suas soluções
Erro 1: WebSocket desconecta a cada 30-60 segundos. A razão — o proxy ou balanceador intermediário fecha conexões "inativas". Solução: habilitar frames de ping/pong no nível da aplicação com um intervalo menor que o timeout do proxy (geralmente 20-25 segundos é suficiente).
Erro 2: gRPC falha com UNAVAILABLE através do proxy, embora funcione diretamente. O proxy não suporta tunelamento HTTP/2 CONNECT. Solução: verificar a documentação do provedor quanto ao suporte a HTTP/2, ou usar um proxy SOCKS5 que tunela TCP sem interpretar o protocolo.
Erro 3: HTTP/2 é "downgrade" para HTTP/1.1 sem aviso. Isso acontece frequentemente devido à falta de suporte ALPN no proxy. Verifique explicitamente a versão do protocolo no código (como no exemplo com httpx acima) — não confie que "tudo funciona" se você não checou http_version na resposta.
Erro 4: Alta latência ao multiplexar gRPC através do proxy. Frequentemente causada por um grande número de nós intermediários no provedor de proxy. Solução: testar a latência antecipadamente através de uma simples solicitação RTT e escolher um provedor com roteação direta, especialmente para chamadas gRPC sensíveis ao tempo.
Conclusão
WebSocket, HTTP/2 e gRPC exigem abordagens diferentes para a configuração do proxy exatamente porque operam em diferentes modelos de transporte: desde o simples "liberar a conexão TCP" para WebSocket até o suporte rigoroso ao HTTP/2 CONNECT e ALPN para gRPC. Verifique explicitamente a versão do protocolo no código, teste a estabilidade de conexões longas antecipadamente e escolha SOCKS5 onde a máxima transparência de tunelamento é necessária.
Se sua pilha inclui conexões WebSocket de longa duração ou chamadas gRPC sensíveis à latência, recomendamos experimentar proxies residenciais — eles oferecem conexões mais estáveis e previsíveis em comparação com pools típicos de data center. Para simples pedidos HTTP/2 com alta largura de banda, proxies de data center são adequados, e para tarefas com filtragem antifraude agressiva do serviço de destino — proxies móveis.