Al trabajar con proxies, los desarrolladores a menudo se enfrentan al hecho de que la configuración clásica de proxies HTTP no funciona para conexiones WebSocket, y gRPC se cae con errores de handshake TLS. El problema es que WebSocket, HTTP/2 y gRPC no son simplemente "variantes de HTTP", sino diferentes modelos de transporte con sus propios requisitos de tunelización, multiplexión y manejo de encabezados. En este artículo analizaremos cómo hacer proxy para cada uno de estos protocolos, qué trampas se encuentran en la práctica y cómo elegir el protocolo y el tipo de proxy para una tarea específica: desde el análisis a través de WebSocket hasta microservicios gRPC de alta carga.
Diferencias entre protocolos y por qué es importante para el proxy
HTTP/1.1 funciona bajo el modelo "solicitud - respuesta": el cliente abre una conexión, envía una solicitud, recibe una respuesta y cierra la conexión o la mantiene abierta para la siguiente solicitud (keep-alive). Los servidores proxy han sido optimizados durante décadas precisamente para este modelo: análisis de encabezados, almacenamiento en búfer del cuerpo de la solicitud, enrutamiento simple a través del encabezado Host.
WebSocket rompe este modelo: después del handshake inicial de HTTP (Upgrade: websocket), la conexión se convierte en un canal bidireccional permanente, donde los datos pueden fluir en ambas direcciones en cualquier momento. El proxy debe "liberar" esta conexión y simplemente transferir bytes en ambas direcciones, sin intentar interpretarlos como solicitudes HTTP.
HTTP/2 añade multiplexión: varias solicitudes lógicas pasan a través de una sola conexión TCP en paralelo, utilizando tramas binarias en lugar de encabezados de texto. Para el proxy, esto significa que no se puede simplemente leer texto línea por línea: se necesita soporte para el protocolo binario HTTP/2 a nivel de proxy o tunelización TCP transparente sobre TLS.
gRPC va aún más lejos: está construido estrictamente sobre HTTP/2, utiliza Protocol Buffers para la serialización y requiere transporte compatible con HTTP/2 en todo el camino desde el cliente hasta el servidor. Si el proxy en algún punto "degrada" la conexión a HTTP/1.1, la solicitud gRPC simplemente no pasará.
Comprender estas diferencias es crítico, porque elegir el tipo de proxy incorrecto o una configuración incorrecta de la tunelización lleva a caídas de conexiones, timeouts y errores difíciles de explicar, que son difíciles de diagnosticar sin entender el nivel de transporte.
WebSocket a través de proxy: configuración y código
Para WebSocket a través de proxy hay dos escenarios principales: proxy HTTP con el método CONNECT (para WSS, es decir, WebSocket sobre TLS) y proxy SOCKS5, que tuneliza la conexión TCP sin interpretar el protocolo. SOCKS5 generalmente presenta menos problemas, ya que fue diseñado originalmente como un "tubo transparente" para cualquier tráfico TCP.
Un ejemplo de conexión a WebSocket a través de un proxy SOCKS5 en Python con la biblioteca websockets
y 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("Hola a través del proxy")
print(ws.recv())
ws.close()
connect_ws_via_proxy()
En Node.js, una tarea similar se resuelve a través del paquete ws
en combinación con 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('Hola a través del proxy'));
socket.on('message', (data) => console.log(data.toString()));
Si el proxy está disponible solo a través de HTTP (con el método CONNECT), el esquema es similar: la mayoría de los clientes WebSocket modernos pueden trabajar a través de un túnel HTTP, solo es importante asegurarse de que el proxy no cierre conexiones de larga duración por timeout. Este es un problema común con proxies de centros de datos baratos, que tienen un límite rígido de 30-60 segundos para conexiones inactivas; para tareas de WebSocket en streaming, esto es crítico, y es mejor aclarar los parámetros de keep-alive con el proveedor.
HTTP/2 a través de proxy: multiplexión y trampas
La principal dificultad con HTTP/2 a través de proxy es que muchos servidores proxy (especialmente los antiguos Squid o simples proxies de reenvío) solo funcionan con HTTP/1.1 y degradan automáticamente la conexión. Para el cliente, esto a menudo es imperceptible (la solicitud se ejecuta de todos modos), pero se pierden las ventajas de la multiplexión: las latencias aumentan, especialmente con un gran número de solicitudes paralelas a un solo host.
Puedes verificar si la conexión a través del proxy soporta HTTP/2 usando cURL con la bandera
--http2
y salida detallada:
curl -v --http2 -x http://user:pass@proxy_host:8080 https://example.com
# En la salida busca la línea:
# * Using HTTP2, server supports multiplexing
# Si no está, la conexión ha caído a HTTP/1.1
En Python, para HTTP/2 a través de proxy se necesita la biblioteca httpx
con soporte habilitado para HTTP/2:
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)
Un matiz importante: HTTP/2 requiere TLS con la extensión ALPN para la negociación del protocolo, por lo que el proxy debe tunelizar el tráfico TLS a través de CONNECT de manera transparente, y no terminar TLS por sí mismo (a menos que sea un proxy especializado compatible con HTTP/2). Es por eso que para tareas con HTTP/2, los proxies residenciales y proxies de centros de datos se comportan de manera diferente: es importante aclarar con el proveedor si se admite la tunelización TLS de extremo a extremo sin interrumpir las negociaciones ALPN.
gRPC a través de proxy: TLS, ALPN y requisitos especiales
gRPC es el protocolo más exigente en este conjunto. Está estrictamente vinculado a HTTP/2 y a menudo utiliza
TLS bidireccional (mTLS) para la autenticación. Un proxy de reenvío normal, que no soporta HTTP/2 CONNECT
tunelización "tal cual", simplemente no permitirá el tráfico gRPC: la conexión fallará con errores como
UNAVAILABLE: upstream connect error.
Para hacer proxy de gRPC en Python (con la biblioteca grpc)
el proxy se establece a través de variables de entorno, ya que históricamente no ha habido soporte incorporado para proxies en las opciones de canal:
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()
)
# Ejemplo de llamada a través del stub generado
# stub = YourServiceStub(channel)
# response = stub.YourMethod(request)
En Node.js, el proxy para gRPC se configura a través de las opciones del canal grpc-js
en combinación con un agente proxy compatible con 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 un funcionamiento estable de gRPC a través de proxy, es críticamente importante una baja latencia y una conexión TCP estable sin caídas frecuentes: los flujos multiplexados de gRPC son más sensibles a fallos de red que las solicitudes individuales de HTTP/1.1. En tales escenarios, los proxies residenciales a menudo muestran mejor estabilidad en comparación con los grupos de centros de datos baratos, ya que la ruta hacia el servidor objetivo pasa a través de una infraestructura de red más predecible.
Tabla comparativa de protocolos
| Protocolo | Tipo de conexión | Requisitos para el proxy | Tipo de proxy recomendado |
|---|---|---|---|
| HTTP/1.1 | solicitud-respuesta, keep-alive | mínimos, cualquier proxy HTTP | Proxies de centros de datos |
| WebSocket | canal bidireccional permanente | soporte para conexiones largas, sin timeouts | Proxies residenciales |
| HTTP/2 | flujos binarios multiplexados | tunelización TLS de extremo a extremo, ALPN | Proxies residenciales o de centros de datos |
| gRPC | HTTP/2 + Protobuf, a menudo mTLS | baja latencia, estabilidad, HTTP/2 CONNECT | Proxies móviles para eludir filtros estrictos |
Cómo elegir el protocolo y el proxy para tu stack
La elección del protocolo rara vez es una decisión libre: está dictada por la API objetivo. Pero la elección del tipo de proxy para este protocolo es tu responsabilidad, y aquí debes basarte en el escenario específico:
Análisis de datos a través de WebSocket (por ejemplo, streaming de cotizaciones o datos en tiempo real de sitios de marketplaces) requiere una conexión estable y prolongada sin interrupciones por timeout. Aquí funcionan mejor los proxies residenciales: tienen menos probabilidades de ser atrapados por los algoritmos antifraude del servicio objetivo y mantienen la conexión más tiempo que los típicos grupos de centros de datos.
Integración con microservicios gRPC a través de un proxy externo (por ejemplo, al probar API desde diferentes geolocalizaciones) requiere baja latencia y soporte para HTTP/2 en todo el camino. Para esto son adecuados IP residenciales con buena enrutación, y para tareas críticas en tiempo, proxies móviles, si el servicio objetivo filtra agresivamente los rangos de centros de datos.
Solicitudes masivas HTTP/2 a REST/GraphQL API con multiplexión son el escenario más común donde bastan proxies de centros de datos rápidos y baratos, si el servicio objetivo no bloquea los rangos de IP de centros de datos por defecto.
Regla general: cuanto más "caprichoso" sea el protocolo respecto a la estabilidad de la conexión (WebSocket, gRPC), más sentido tiene usar IP residenciales o móviles. Cuanto más simple y corta sea la solicitud (HTTP/1.1 normal o HTTP/2 sin sesiones largas), más cómodo es trabajar con proxies de centros de datos: son más rápidos y ofrecen mayor ancho de banda.
Errores comunes y sus soluciones
Error 1: WebSocket se corta cada 30-60 segundos. La razón es que el proxy o el balanceador intermedio cierra las conexiones "inactivas". Solución: habilitar frames ping/pong a nivel de aplicación con un intervalo menor que el timeout del proxy (generalmente 20-25 segundos es suficiente).
Error 2: gRPC falla con UNAVAILABLE a través del proxy, aunque funciona directamente. El proxy no soporta la tunelización HTTP/2 CONNECT. Solución: verificar la documentación del proveedor sobre el soporte de HTTP/2, o usar un proxy SOCKS5 que tuneliza TCP sin interpretar el protocolo.
Error 3: HTTP/2 se degrada silenciosamente a HTTP/1.1. Esto ocurre a menudo debido a la falta de soporte ALPN en el proxy. Verifica la versión del protocolo explícitamente en el código (como en el ejemplo con httpx arriba): no confíes en que "todo funciona" si no has verificado http_version en la respuesta.
Error 4: Alta latencia al multiplexar gRPC a través del proxy. A menudo causada por un gran número de nodos intermedios en el proveedor de proxy. Solución: probar la latencia de antemano a través de una simple solicitud RTT y elegir un proveedor con enrutamiento directo, especialmente para llamadas gRPC sensibles al tiempo.
Conclusión
WebSocket, HTTP/2 y gRPC requieren un enfoque diferente para la configuración del proxy precisamente porque operan en diferentes modelos de transporte: desde el simple "liberar la conexión TCP" para WebSocket hasta el estricto soporte de HTTP/2 CONNECT y ALPN para gRPC. Verifica la versión del protocolo explícitamente en el código, prueba la estabilidad de las conexiones largas de antemano y elige SOCKS5 donde se necesite la máxima transparencia en la tunelización.
Si tu stack incluye conexiones WebSocket de larga duración o llamadas gRPC sensibles a la latencia, recomendamos probar proxies residenciales — proporcionan conexiones más estables y predecibles en comparación con los típicos grupos de centros de datos. Para solicitudes simples de HTTP/2 con alto ancho de banda, son adecuados proxies de centros de datos, y para tareas con filtración antifraude agresiva del servicio objetivo — proxies móviles.