WebSocket não é uma requisição HTTP comum. Após o "handshake" inicial, a conexão permanece aberta, e os dados fluem em ambas as direções de forma contínua. É por isso que proxies HTTP padrão frequentemente interrompem conexões WS ou não conseguem processá-las. Neste artigo, vamos discutir como fazer proxy de tráfego WebSocket corretamente: quais proxies são adequados, como configurá-los e quais erros ocorrem com mais frequência.
Como funciona o WebSocket e por que é complicado para proxies
Para entender o problema, é necessário compreender a mecânica. A conexão WebSocket começa como uma requisição HTTP comum — o cliente envia o cabeçalho Upgrade: websocket e Connection: Upgrade. O servidor responde com o código 101 Switching Protocols — e a partir desse momento a conexão deixa de ser HTTP. Ela se transforma em um canal bidirecional permanente, onde os dados fluem em quadros.
Um proxy HTTP/1.1 padrão, que apenas reencaminha requisições e respostas, enfrenta um problema: ele não sabe o que fazer com a conexão após a resposta 101. Muitos servidores proxy simplesmente fecham a conexão nesse momento ou retornam um erro 502 Bad Gateway. Outros mantêm a conexão, mas não conseguem transmitir corretamente os quadros WebSocket, o que leva a interrupções ou distorções nos dados.
Aqui estão as principais diferenças entre WebSocket e HTTP do ponto de vista do proxy:
| Parâmetro | HTTP | WebSocket |
|---|---|---|
| Tipo de conexão | Requisição → Resposta → Fechamento | Permanente, bidirecional |
| Tempo de vida | Segundos (uma requisição) | Minutos, horas, dias |
| Iniciador de dados | Somente cliente | Cliente e servidor |
| Protocolo após handshake | HTTP | Proprietário (RFC 6455) |
| Portas | 80, 443 | 80 (WS), 443 (WSS) |
É precisamente por causa da mudança de protocolo após o handshake que a maioria das soluções de proxy simples não consegue lidar com WebSocket. É necessário usar um proxy que suporte explicitamente o tunelamento ou aplicar SOCKS5 — um protocolo que opera em um nível mais baixo e não analisa o conteúdo do tráfego.
Quais tipos de proxies suportam WebSocket
Nem todos os proxies são igualmente úteis para WebSocket. Vamos analisar cada tipo:
| Tipo de proxy | Suporte a WS | Mecanismo | Dificuldade |
|---|---|---|---|
| Proxy HTTP | ⚠️ Parcial | Através de túnel CONNECT | Média |
| Proxy HTTPS | ✅ Sim | CONNECT + TLS | Média |
| SOCKS4 | ⚠️ Limitado | Túnel TCP sem autenticação | Baixa |
| SOCKS5 | ✅ Completo | TCP/UDP transparente | Baixa |
| Proxy Transparente | ❌ Não | Apenas HTTP | — |
Conclusão: para tarefas de WebSocket, a escolha ideal é SOCKS5. Este protocolo opera no nível de transporte e simplesmente faz um túnel da conexão TCP, sem se preocupar com o conteúdo do tráfego. Não importa se dentro está HTTP, WebSocket, SSH ou qualquer outra coisa. Proxies HTTP também podem funcionar com WS, mas apenas através do método CONNECT — e aqui há nuances que discutiremos a seguir.
Método CONNECT: como proxies HTTP fazem túnel para WebSocket
O método HTTP CONNECT é um mecanismo especial que permite que um proxy HTTP crie um túnel "cego" até o servidor de destino. O proxy não analisa o tráfego dentro do túnel, apenas redireciona os bytes. É assim que HTTPS funciona através de um proxy HTTP — e é assim que se pode fazer proxy para WebSocket.
O processo é o seguinte:
- O cliente envia ao proxy a requisição:
CONNECT example.com:443 HTTP/1.1 - O proxy estabelece uma conexão TCP com
example.com:443 - O proxy responde ao cliente:
200 Connection Established - A partir desse momento, o proxy simplesmente transmite os bytes para frente e para trás — sem analisá-los
- O cliente realiza o handshake TLS diretamente com o servidor através do túnel
- Em seguida — o handshake WebSocket sobre TLS
Limitação chave: o método CONNECT geralmente é permitido apenas para a porta 443. Se o seu servidor WebSocket estiver operando em uma porta não padrão (por exemplo, 8080 ou 9000), o proxy pode rejeitar a conexão. Nesse caso, SOCKS5 é preferível — ele não tem restrições de porta.
Também é importante considerar que alguns proxies HTTP corporativos (como o Squid na configuração padrão) bloqueiam explicitamente o método CONNECT para determinadas portas ou exigem autenticação. Se você estiver trabalhando com provedores de proxy comerciais, a maioria deles suporta CONNECT sem restrições.
# Exemplo de requisição CONNECT através do curl (para teste)
curl -v -x http://proxy_host:proxy_port \
--proxytunnel \
https://echo.websocket.org
# Se o proxy suportar CONNECT — você verá:
# * CONNECT tunnel established, response 200
SOCKS5 e WebSocket: por que é a melhor opção
SOCKS5 é um protocolo de proxy no nível de conexões TCP/UDP. Ao contrário de proxies HTTP, o SOCKS5 não sabe nada sobre o protocolo de aplicação que está sendo transmitido. Ele simplesmente cria um túnel entre o cliente e o servidor de destino, e é isso. Isso o torna ideal para WebSocket por várias razões:
- Sem restrições de protocolo: SOCKS5 faz túnel para qualquer tráfego TCP, incluindo WS, WSS, SSH, FTP, etc.
- Sem restrições de portas: funciona com qualquer porta, não apenas 443 ou 80
- Sem interrupção ao mudar de protocolo: o proxy não "vê" a transição de HTTP para WebSocket
- Suporte à autenticação: SOCKS5 suporta login/senha, o que é conveniente para proxies comerciais
- Suporte a UDP: se seu aplicativo usa WebRTC ou UDP junto com WS — o SOCKS5 dará conta
Praticamente todas as bibliotecas modernas para trabalhar com WebSocket suportam SOCKS5, seja diretamente ou através de pacotes adicionais. Abaixo, veremos exemplos específicos para Python e Node.js.
💡 Quando escolher SOCKS5 e quando HTTP CONNECT?
Use SOCKS5 se: porta não padrão, precisa de suporte a UDP, quer o mínimo de configurações.
Use HTTP CONNECT se: o provedor de proxy não suporta SOCKS5, ou você está trabalhando através de um proxy corporativo.
Exemplos de código: WebSocket através de proxy em Python
Vamos considerar alguns cenários para Python. As bibliotecas mais populares para WebSocket em Python são websockets e websocket-client.
Opção 1: websocket-client através de proxy HTTP
import websocket
# Configurações do proxy HTTP
proxy_host = "proxy.example.com"
proxy_port = 8080
proxy_user = "username"
proxy_pass = "password"
ws = websocket.WebSocket()
ws.connect(
"wss://echo.websocket.org",
http_proxy_host=proxy_host,
http_proxy_port=proxy_port,
http_proxy_auth=(proxy_user, proxy_pass),
proxy_type="http" # ou "socks5"
)
ws.send("Olá, WebSocket!")
result = ws.recv()
print(f"Recebido: {result}")
ws.close()
Opção 2: websocket-client através de SOCKS5
import websocket
# Para SOCKS5, é necessário o pacote: pip install PySocks
ws = websocket.WebSocket()
ws.connect(
"wss://echo.websocket.org",
http_proxy_host="socks5_proxy.example.com",
http_proxy_port=1080,
http_proxy_auth=("username", "password"),
proxy_type="socks5"
)
ws.send("Mensagem de teste")
print(ws.recv())
ws.close()
Opção 3: biblioteca websockets (asyncio) através de SOCKS5
A biblioteca websockets (asyncio) não tem suporte embutido para proxy, então usamos python-socks para criar o túnel:
# pip install websockets python-socks[asyncio]
import asyncio
import websockets
from python_socks.async_.asyncio import Proxy
async def connect_via_socks5():
proxy = Proxy.from_url("socks5://username:[email protected]:1080")
# Criando uma conexão TCP através do proxy
sock = await proxy.connect(
dest_host="echo.websocket.org",
dest_port=443
)
# Passando o socket para websockets
async with websockets.connect(
"wss://echo.websocket.org",
sock=sock
) as ws:
await ws.send("Olá via SOCKS5!")
response = await ws.recv()
print(f"Resposta: {response}")
asyncio.run(connect_via_socks5())
Opção 4: patch global através do PySocks
Se você deseja direcionar todo o tráfego do aplicativo Python através do SOCKS5 sem alterar cada chamada — use socks.setdefaultproxy():
# pip install PySocks
import socks
import socket
import websocket
# Patch global do socket
socks.set_default_proxy(
socks.SOCKS5,
"proxy.example.com",
1080,
username="user",
password="pass"
)
socket.socket = socks.socksocket
# Agora todas as conexões vão através do SOCKS5
ws = websocket.WebSocket()
ws.connect("wss://echo.websocket.org")
ws.send("Proxy SOCKS5 global!")
print(ws.recv())
ws.close()
Exemplos de código: WebSocket através de proxy em Node.js
No ecossistema Node.js, a biblioteca mais popular para WebSocket é ws. Para fazer proxy através de HTTP/SOCKS5, usa-se o pacote https-proxy-agent ou socks-proxy-agent.
Opção 1: WSS através de proxy HTTP CONNECT
// npm install ws https-proxy-agent
const WebSocket = require('ws');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:[email protected]:8080';
const agent = new HttpsProxyAgent(proxyUrl);
const ws = new WebSocket('wss://echo.websocket.org', { agent });
ws.on('open', () => {
console.log('Conexão estabelecida através do proxy HTTP');
ws.send('Olá do Node.js!');
});
ws.on('message', (data) => {
console.log(`Recebido: ${data}`);
ws.close();
});
ws.on('error', (err) => {
console.error('Erro:', err.message);
});
Opção 2: WSS através de SOCKS5
// npm install ws socks-proxy-agent
const WebSocket = require('ws');
const { SocksProxyAgent } = require('socks-proxy-agent');
const proxyUrl = 'socks5://username:[email protected]:1080';
const agent = new SocksProxyAgent(proxyUrl);
const ws = new WebSocket('wss://echo.websocket.org', { agent });
ws.on('open', () => {
console.log('Conexão estabelecida através do SOCKS5');
ws.send(JSON.stringify({ type: 'ping', data: 'teste' }));
});
ws.on('message', (data) => {
console.log('Resposta:', data.toString());
});
ws.on('close', (code, reason) => {
console.log(`Fechado: ${code} - ${reason}`);
});
Opção 3: WS (sem TLS) através de proxy HTTP manualmente
Para WS não criptografado (porta 80) através de um proxy HTTP, é necessário enviar manualmente a requisição CONNECT, pois agentes padrão frequentemente funcionam apenas com HTTPS:
const net = require('net');
const WebSocket = require('ws');
function createTunnel(proxyHost, proxyPort, targetHost, targetPort) {
return new Promise((resolve, reject) => {
const socket = net.connect(proxyPort, proxyHost, () => {
const connectReq =
`CONNECT ${targetHost}:${targetPort} HTTP/1.1\r\n` +
`Host: ${targetHost}:${targetPort}\r\n` +
`Proxy-Authorization: Basic ${Buffer.from('user:pass').toString('base64')}\r\n` +
`\r\n`;
socket.write(connectReq);
});
socket.once('data', (data) => {
if (data.toString().includes('200')) {
resolve(socket);
} else {
reject(new Error(`Proxy rejeitou CONNECT: ${data.toString()}`));
}
});
socket.on('error', reject);
});
}
async function main() {
const socket = await createTunnel(
'proxy.example.com', 8080,
'echo.websocket.org', 80
);
const ws = new WebSocket('ws://echo.websocket.org', { socket });
ws.on('open', () => {
ws.send('Túnel CONNECT manual!');
});
ws.on('message', (data) => {
console.log('Recebido:', data.toString());
ws.close();
});
}
main().catch(console.error);
WSS (WebSocket Secure): características do proxy com TLS
WSS é WebSocket sobre TLS (semelhante ao HTTPS para HTTP). Ao fazer proxy de WSS através de SOCKS5 ou HTTP CONNECT, surge uma nuance importante: A criptografia TLS é estabelecida entre o cliente e o servidor final, e não entre o cliente e o proxy. Isso significa:
- O servidor proxy não vê o conteúdo do tráfego WSS — apenas o endereço IP e a porta de destino
- O certificado do servidor é verificado diretamente pelo cliente
- O proxy não pode "substituir" ou "interceptar" dados sem instalar seu próprio certificado CA
Isso é uma boa notícia do ponto de vista da segurança. Mas há também nuances práticas na configuração:
Verificação de certificado através do proxy
Às vezes, ao usar proxies corporativos (que realizam inspeção SSL), você pode receber um erro de verificação de certificado. Nesse caso, o proxy substitui o certificado do servidor pelo seu. Para funcionar em tal ambiente, é necessário adicionar o certificado CA do proxy aos confiáveis:
# Python: passando o certificado CA do proxy corporativo
import ssl
import websocket
ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations("/path/to/corporate-ca.crt")
ws = websocket.WebSocket(sslopt={"context": ssl_context})
ws.connect(
"wss://internal.example.com",
http_proxy_host="corp-proxy.company.com",
http_proxy_port=8080,
proxy_type="http"
)
# Em ambientes de teste (NÃO para produção!) é possível desativar a verificação:
ws_test = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
ws_test.connect("wss://test.example.com", http_proxy_host="proxy", http_proxy_port=8080)
⚠️ Importante
Desativar a verificação do certificado TLS (CERT_NONE) é aceitável apenas em ambiente de teste. Em produção, isso cria uma vulnerabilidade a ataques do tipo MITM (man-in-the-middle).
SNI (Server Name Indication) através do proxy
Ao usar SOCKS5, o cliente pode resolver DNS por conta própria ou delegar isso ao proxy. O modo socks5h (SOCKS5 com resolução de nome de host) significa que a consulta DNS é realizada do lado do servidor proxy. Isso é importante para WSS, pois o cabeçalho SNI no handshake TLS deve coincidir com o nome do host:
# socks5 — DNS é resolvido localmente (pelo cliente)
# socks5h — DNS é resolvido pelo servidor proxy (recomendado para anonimato)
from python_socks.async_.asyncio import Proxy
# DNS através do proxy (recomendado):
proxy = Proxy.from_url("socks5h://user:[email protected]:1080")
# DNS localmente:
proxy = Proxy.from_url("socks5://user:[email protected]:1080")
Erros comuns e como corrigi-los
Compilamos os problemas mais frequentes ao fazer proxy de WebSocket com soluções:
Erro 1: 407 Proxy Authentication Required
O proxy exige autenticação, mas você não forneceu as credenciais ou as forneceu incorretamente.
# ❌ Incorreto — sem autorização
ws.connect("wss://example.com", http_proxy_host="proxy.example.com", http_proxy_port=8080)
# ✅ Correto — fornecendo login e senha
ws.connect(
"wss://example.com",
http_proxy_host="proxy.example.com",
http_proxy_port=8080,
http_proxy_auth=("username", "password")
)
Erro 2: Connection reset by peer / 502 Bad Gateway
O proxy não suporta WebSocket ou o método CONNECT. Solução: mude para SOCKS5 ou verifique se seu provedor suporta tráfego WebSocket.
Erro 3: A conexão é interrompida após 30-60 segundos
Muitos servidores proxy fecham conexões TCP "inativas" após um timeout. A conexão WebSocket pode parecer inativa se não houver troca de dados. A solução é ativar ping/pong:
# Python — ativando ping keepalive a cada 20 segundos
import websocket
import threading
def run():
ws = websocket.WebSocketApp(
"wss://echo.websocket.org",
on_message=lambda ws, msg: print(msg),
on_error=lambda ws, err: print(f"Erro: {err}"),
on_close=lambda ws, c, m: print("Fechado")
)
ws.run_forever(
ping_interval=20, # enviar ping a cada 20 seg
ping_timeout=10, # esperar pong por no máximo 10 seg
http_proxy_host="proxy.example.com",
http_proxy_port=8080,
proxy_type="socks5"
)
thread = threading.Thread(target=run)
thread.start()
Erro 4: SSL: CERTIFICATE_VERIFY_FAILED
Ocorre com mais frequência ao usar um proxy corporativo com inspeção SSL. Solução: adicione o certificado CA do proxy aos confiáveis (veja a seção acima) ou use SOCKS5 em vez de um proxy HTTP — SOCKS5 não faz inspeção SSL.
Erro 5: Handshake status 403 Forbidden
O servidor de destino bloqueia a conexão. Razões: IP do proxy está na lista negra, faltam cabeçalhos necessários (Origin, User-Agent), ou o servidor bloqueia tráfego de data centers. Solução: use proxies residenciais com IPs reais de usuários domésticos — é muito mais difícil bloqueá-los.
Erro 6: [Errno 111] Connection refused
O servidor proxy está indisponível: host/porta incorretos, ou o proxy não está em execução. Verifique os dados de conexão e a disponibilidade do proxy através de uma simples requisição HTTP antes de testar o WebSocket.
Qual tipo de proxy escolher para tarefas de WebSocket
A escolha do tipo de proxy depende da tarefa específica. Aqui está um guia prático:
| Tarefa | Tipo recomendado | Por que |
|---|---|---|
| Parsing via WS (bolsas, dados financeiros) | Proxies de data center | Alta velocidade, baixa latência, conexão estável |
| Contornar bloqueios de serviços WebSocket | Proxies residenciais | IPs reais, risco mínimo de bloqueio |
| Aplicativos móveis com WS (trabalhando com APIs móveis) | Proxies móveis | IP de operadores móveis — alta confiança por parte dos serviços |
| Teste de carga do servidor WS | Proxies de data center | Barato, rápido, muitas conexões simultâneas |
| Teste de geolocalização do WS | Proxies residenciais | Grande variedade de países e cidades |
Parâmetros importantes do proxy para WebSocket
Ao escolher um provedor de proxy para tarefas de WebSocket, preste atenção aos seguintes parâmetros:
- Suporte a SOCKS5: certifique-se de que o provedor oferece SOCKS5, e não apenas HTTP
- Duração da sessão: para WebSocket, sessões "sticky" são importantes — um IP por um longo período. Proxies rotativos interromperão a conexão
- Timeout de conexão: o proxy deve suportar conexões TCP de longa duração (de alguns minutos a horas)
- Largura de banda: para WebSocket de streaming (vídeo, dados de bolsa), uma alta largura de banda sem restrições é importante
- Latência: para aplicativos financeiros e bots de negociação, uma latência mínima é crítica — escolha proxies com servidores mais próximos do serviço alvo
💡 Verificando o suporte a WebSocket pelo provedor de proxy
Antes de comprar proxies para tarefas de WebSocket, teste-os através de um servidor de eco gratuito:
wss://echo.websocket.org ou
wss://ws.postman-echo.com/raw.
Se a conexão for estabelecida e as mensagens retornarem — o proxy funciona corretamente com WebSocket.
Configurando a sessão sticky para WebSocket
A maioria dos provedores de proxies residenciais usa rotação de IP por padrão. Para WebSocket, isso é inaceitável — cada troca de IP significa uma interrupção na conexão. Certifique-se de usar o modo de sessão sticky (IP fixo). Normalmente, isso é feito através de um formato especial de URL do proxy:
# Exemplo de formato de sessão sticky (depende do provedor):
# Rotativo (NÃO adequado para WebSocket):
socks5://user:[email protected]:1080
# Sessão sticky (adequada para WebSocket):
socks5://user-session-abc123:[email protected]:1080
# Ou através do parâmetro de país e sessão:
socks5://user-country-us-session-12345:[email protected]:1080
Conclusão
WebSocket não é apenas "HTTP com uma conexão longa". É um protocolo separado que requer uma abordagem especial ao fazer proxy. As principais conclusões deste artigo:
- SOCKS5 é a escolha ideal para WebSocket: opera no nível de transporte, não analisa o protocolo, suporta quaisquer portas
- Proxy HTTP através de CONNECT também funciona, mas com restrições de portas e possíveis problemas com inspeção SSL
- Sessões sticky são obrigatórias: proxies rotativos interromperão a conexão WebSocket a cada troca de IP
- Ping/pong keepalive é necessário para evitar a interrupção da conexão por timeout do proxy
- WSS através de proxy é seguro: a criptografia TLS é estabelecida diretamente entre o cliente e o servidor, o proxy não vê o conteúdo
Se você está desenvolvendo um aplicativo que trabalha com WebSocket através de um proxy — comece com SOCKS5 e sessões sticky. Isso economizará horas de depuração. Para tarefas onde alta velocidade e estabilidade de conexão são importantes (bots de negociação, streaming de dados), proxies de data center com baixa latência são uma ótima opção. Se o serviço alvo bloqueia ativamente IPs de data center — considere proxies residenciais: eles têm IPs reais de usuários domésticos e são significativamente menos propensos a bloqueios, mesmo em sessões WebSocket prolongadas.
```