Development
15 min read
35 views

Túneles multiplexados multi-inquilino: Ejecuta 50+ servicios locales sobre una sola conexión QUIC con HTTP/3 Extended CONNECT

Aprende a ejecutar más de 50 servicios locales concurrentes en un solo puerto TCP usando HTTP/3 Extended CONNECT con túneles multiplexados multi-inquilino.

IT
InstaTunnel Team
Published by the InstaTunnel team | Editorial policy
Túneles multiplexados multi-inquilino: Ejecuta 50+ servicios locales sobre una sola conexión QUIC con HTTP/3 Extended CONNECT

Quick answer

Túneles multiplexados multi-inquilino: Ejecuta 50+ servicios en uno: webhook testing answer

For local webhook testing, run your app locally, expose it with a public HTTPS tunnel, and paste the stable callback URL into the provider dashboard.

How do I test webhooks on localhost?

Start your local server, open a public HTTPS tunnel to that port, configure the provider webhook URL, and inspect events in your local logs.

Why does a stable webhook URL matter?

Stable URLs prevent provider dashboards from needing manual callback updates every time you restart a tunnel.

Exponer unos pocos servicios locales a internet es sencillo. Exponer docenas de forma fiable es más difícil. Una máquina de desarrollo o gateway en el borde puede ejecutar APIs REST, endpoints gRPC, servidores WebSocket y UIs administrativas al mismo tiempo. Asignarles puertos, conexiones TCP o túneles separados rápidamente se vuelve costoso.

Este artículo analiza cómo los túneles modernos resuelven este problema. multiplexan muchos servicios sobre una sola conexión saliente, y cada vez más esa conexión es QUIC en un puerto UDP único (normalmente 443). También explica qué hace y qué no hace HTTP/3 Extended CONNECT, porque los detalles importan en el diseño del túnel.


El cuello de botella: un puerto o una conexión por servicio

Tres problemas aparecen cuando un túnel escala con el número de servicios que expone.

1. Sobrecarga por conexión

Si cada servicio expuesto tiene su propia conexión TCP + TLS, el agente paga en varias formas:

  • Costo del handshake. Cada conexión repite un handshake TCP y uno TLS.
  • Estado del kernel y descriptores de archivos. Cada conexión mantiene un socket, buffers y una máquina de estado TCP. Esto afecta más en gateways pequeños y portátiles.
  • Estado NAT y firewall. Cada flujo adicional es otra entrada en la tabla de un dispositivo con estado, y las asignaciones NAT eventualmente caducan.

2. Expansión de puertos

El reenvío clásico SSH (-L/-R) necesita un puerto de escucha distinto para cada servicio reenviado. Esto genera más reglas en el firewall, gestión de puertos y tráfico en puertos poco comunes que redes restrictivas suelen bloquear.

3. Bloqueo head-of-line (HoL) en TCP

Multiplexar muchos flujos lógicos sobre una sola conexión TCP, como hace HTTP/2, soluciona el conteo de conexiones. Pero crea un nuevo problema: TCP entrega un flujo de bytes ordenados, por lo que un paquete perdido bloquea todos los flujos detrás hasta que llega la retransmisión. Una carga bulk a un servicio puede retrasar llamadas API sensibles a la latencia que comparten el mismo túnel.

Lo que ya hacen los túneles existentes

La mayoría de productos de túneles maduros multiplexan muchos servicios sobre una sola conexión en lugar de abrir una por servicio:

  • ngrok usa un protocolo de multiplexación de streams llamado muxado, que sus SDKs en Rust y Go describen como el protocolo que impulsa los túneles de ngrok.
  • Cloudflare Tunnel (cloudflared) abre cuatro conexiones salientes a al menos dos centros de datos de Cloudflare, en el puerto 7844. Su modo --protocol auto prefiere QUIC sobre UDP y vuelve a HTTP/2 si no se pueden establecer conexiones UDP. El protocolo legado h2mux ya no se soporta. El transporte QUIC de cloudflared está basado en la librería quic-go.

La idea de este artículo, una conexión que lleva muchos servicios, ya es práctica establecida. La pregunta abierta es en qué capa de multiplexación construirla y cómo.


Por qué QUIC cambia el panorama

QUIC (RFC 9000) funciona sobre UDP e integra TLS 1.3 (RFC 9001). Tiene flujos nativos, y la recuperación de pérdida se rastrea por flujo. Cuando se pierde un paquete que lleva datos de un flujo, solo ese flujo espera la retransmisión. Otros flujos en la misma conexión siguen entregando datos a la aplicación.

Dos advertencias mantienen la afirmación habitual de “cero bloqueo HoL”:

  • El orden aún se preserva dentro de un flujo. Cada flujo es su propio flujo de bytes ordenados, por lo que una pérdida aún retrasa ese flujo.
  • La compresión de cabeceras HTTP/3 puede reintroducir cierto bloqueo. QPACK (RFC 9204) fue diseñado para reducir HoL en comparación con HPACK. Las referencias a su tabla dinámica aún pueden bloquear un flujo si el decodificador no ha recibido la actualización. Las implementaciones limitan esto con la configuración SETTINGS_QPACK_BLOCKED_STREAMS.

Para los túneles, QUIC añade beneficios adicionales:

Propiedad Por qué importa en un túnel
Un socket UDP, una conexión Un solo 4-tupla para que NATs lo rastreen y una sola regla de firewall (UDP 443).
Recuperación de pérdida por flujo Una transferencia bulk atascada no congela servicios no relacionados.
Handshake 1-RTT, reanudación 0-RTT opcional Reconexiones más rápidas. Cuidado con 0-RTT, ya que los datos tempranos pueden ser reproducidos.
IDs de conexión y migración Una conexión puede sobrevivir a cambios en la red del cliente, como Wi-Fi a celular, tras validación de ruta (RFC 9000).
DPLPMTUD incorporado Los tamaños de paquete pueden crecer cuando la ruta lo permite.

IDs de conexión y migración

Las conexiones QUIC se identifican por Connection IDs, no solo por el 4-tuple IP/puerto. Un Connection ID tiene longitud variable, hasta 20 bytes según RFC 9000. No es un valor fijo de 64 bits.

Cuando cambia la ruta de red del agente, el cliente puede explorar la nueva ruta y migrar. Los endpoints realizan primero validación de ruta, por lo que la migración no es instantánea ni automática. Las aplicaciones y middleboxes también pueden interferir.


HTTP/3 Extended CONNECT: qué es

HTTP CONNECT simple abre un túnel TCP a través de un proxy. Extended CONNECT fue definido para HTTP/2 en RFC 8441 y añade un pseudo-header :protocol, para que un solo stream CONNECT pueda transportar algo distinto de TCP puro. RFC 9220 lo lleva a HTTP/3 registrando la configuración SETTINGS_ENABLE_CONNECT_PROTOCOL, valor 0x08, igual que en HTTP/2. Aunque su título (“Bootstrapping WebSockets with HTTP/3”) sugiere otra cosa, el mecanismo es general. Otras especificaciones lo usan:

  • WebSockets sobre HTTP/3 (:protocol = websocket), el caso de uso original.
  • CONNECT-UDP (RFC 9298, “Proxying UDP in HTTP”), que túneles datagramas UDP.
  • CONNECT-IP (RFC 9484, “Proxying IP in HTTP”), que túneles paquetes IP.
  • WebTransport sobre HTTP/3, actualmente en borrador de IETF (draft-ietf-webtrans-http3, revisión 16 en julio 2026), que inicia cada sesión con una solicitud Extended CONNECT.

Una solicitud Extended CONNECT lleva estos pseudo-headers:

Pseudo-header Ejemplo Notas
:method CONNECT
:protocol websocket, connect-udp, webtransport, o un token privado como tunnel-v1 Nombra el protocolo en el stream. tunnel-v1 es un ejemplo para diseño privado, no un valor registrado.
:scheme https Requerido en Extended CONNECT.
:authority service-50.tunnels.example.com Host de destino, para enrutamiento del túnel.
:path / Requerido en Extended CONNECT.

Ambos lados anuncian soporte enviando la configuración en su marco SETTINGS de HTTP/3. Un cliente solo puede enviar una solicitud Extended CONNECT tras recibir la configuración del servidor. quic-go, por ejemplo, verifica esto antes de enviar.


El problema de quién abre el stream

El punto de diseño más importante, y uno fácil de fallar, es quién puede abrir streams.

En HTTP/3, los streams de solicitud son streams bidireccionales iniciados por el cliente. La primera solicitud va en el stream 0, luego en los 4, 8, 12, etc. RFC 9114 dice que HTTP/3 no usa streams bidireccionales iniciados por el servidor, y que un cliente que reciba uno debe tratarlo como error de conexión H3_STREAM_CREATION_ERROR, a menos que se haya negociado una extensión.

Un túnel hace esto incómodo. El agente llama (está detrás de NAT), por lo que es el cliente de QUIC y HTTP/3. El borde es el servidor. Pero las solicitudes públicas llegan al borde, y este necesita enviarlas al agente. En HTTP/3 simple, el borde no puede abrir un stream de solicitud hacia el agente.

Diseños que funcionan:

  1. Streams QUIC en crudo con un protocolo de aplicación personalizado. QUIC permite que cualquiera de los extremos abra streams bidireccionales. El borde abre uno por solicitud pública y usa su propio framing. Es una capacidad general de QUIC, no solo Extended CONNECT. Es la opción más sencilla para túneles, y cloudflared construye su transporte QUIC sobre quic-go.
  2. Un grupo de streams Extended CONNECT preabiertos. El agente abre varios streams Extended CONNECT inactivos, por ejemplo con :protocol = tunnel-v1. El borde los mantiene en reserva. Cuando llega una solicitud pública, reclama uno, envía un preámbulo con el servicio destino, y transmite los bytes. El agente lee el preámbulo, conecta al servicio local, copia en ambas direcciones y repone el grupo. Esto sigue la especificación HTTP/3, con la gestión del pool.
  3. WebTransport sobre HTTP/3. El agente abre una solicitud Extended CONNECT con :protocol = webtransport. Dentro, cualquiera puede abrir streams, porque el borrador lo define sobre HTTP/3 con streams iniciados por el servidor. Aún en borrador, puede cambiar. WebTransport no soporta 0-RTT.
  4. Borradores de HTTP/3 reverso. Algunos borradores describen HTTP/3 con roles invertidos, y “HTTP/3 sobre WebTransport”, para que un servidor envíe solicitudes a un cliente. Son borradores y no están ampliamente desplegados.

Para un túnel, las opciones 1 o 2 son las más prácticas hoy. La opción 3 es atractiva si quieres compatibilidad con navegadores y aceptas el estado de borrador.

Flujo con pool de streams (opción 2)

   Cliente público                Borde (servidor QUIC/H3)               Agente (cliente QUIC/H3)
        |                               |                                   |
        |                               |== handshake QUIC, UDP 443 =======|
        |                               |== SETTINGS (ENABLE_CONNECT) =====|
        |                               |== CONNECT :protocol=tunnel-v1 ===|  stream 0  (en reserva)
        |                               |== CONNECT :protocol=tunnel-v1 ===|  stream 4  (en reserva)
        |  GET https://api.ejemplo.com  |                                   |
        |------------------------------|                                   |
        |                               |-- reclamo stream 0, envío "api" --|
        |                               |                                   |-- conexión a 127.0.0.1:8080
        |---------- respuesta ----------|-------- bytes en stream 0 -------|
        |                               |== agente abre reemplazo =====|  stream 8

Cada solicitud pública mapea a un stream QUIC. Cincuenta servicios, o cincuenta solicitudes concurrentes, comparten un socket UDP y una conexión QUIC.


Qué significa “50+” en la práctica

Cincuenta no es un límite del protocolo. Es un número conveniente que está por debajo de un valor predeterminado común. En quic-go, quic.Config.MaxIncomingStreams por defecto permite 100 streams bidireccionales concurrentes. Si esperas más solicitudes, aumenta ese valor deliberadamente en el lado que recibe los streams.

La documentación de quic-go lista estos valores por defecto en control de flujo:

Configuración Valor predeterminado
InitialStreamReceiveWindow 512 KB
MaxStreamReceiveWindow 6 MB
InitialConnectionReceiveWindow 512 KB
MaxConnectionReceiveWindow 15 MB
MaxIncomingStreams 100

QUIC aplica control de flujo en dos niveles: por stream y por conexión. El límite de streams evita que un servicio consuma toda la memoria del buffer. El límite de conexión limita el total. La ventana de conexión debe dimensionarse para el número de streams que esperas transferir activamente, no para la suma de todos los máximos. Si es muy pequeña, los streams compiten por crédito de conexión y la velocidad disminuye.

Ajustando el host

Las implementaciones de QUIC corren en espacio de usuario sobre UDP, por lo que los buffers del socket UDP del kernel importan. quic-go intenta ampliar sus buffers, pero solo hasta rmem_max y wmem_max, que en Linux son pequeños por defecto. Su recomendación:

sysctl -w net.core.rmem_max=7500000
sysctl -w net.core.wmem_max=7500000

Eso eleva los límites a unos 7.5 MB. Persistir en /etc/sysctl.d/ para que sobrevivan a reinicios. Las herramientas de Cloudflare también indican a los usuarios la misma guía de buffers en quic-go cuando detectan buffers pequeños.

Control de congestión

No asumas que cambiar a BBR es solo ajustar una configuración. tcp_congestion_control en Linux afecta solo TCP, y el control de congestión en QUIC está en la librería QUIC. quic-go usa CUBIC. Sus mantenedores han dicho que no planean implementar BBR, aunque el soporte para BBRv3 está en una tarea pendiente. Si BBR te importa, revisa qué controladores de congestión soporta tu pila QUIC.

Rendimiento versus TCP

QUIC no siempre es más rápido. El procesamiento en espacio de usuario cuesta CPU, y los kernels principales carecen de algunos offloads UDP que TCP sí tiene. En enlaces cableados rápidos y con poca pérdida, HTTP/3 puede no ser más rápido que HTTP/2 y usar más CPU. QUIC ayuda más en caminos con pérdida, alta latencia o móviles. Mide en tu red.


Comparación técnica

Dimensión Reenvío SSH HTTP/2 sobre TCP HTTP/3 sobre QUIC
Transporte TCP TCP UDP (QUIC)
Multiplexación Canales en una conexión TCP, o conexiones separadas Streams en una conexión TCP Streams nativos de QUIC
Pérdida afecta Todos los canales en esa conexión TCP Todos los streams en esa conexión TCP El stream afectado (más dependencia de compresión de cabeceras)
Handshake TCP + intercambio y autenticación SSH TCP + TLS Handshake combinado de transporte y TLS 1.3, 0-RTT en reanudación
Cambio de red La conexión se rompe La conexión se rompe Migración iniciada por el cliente con validación de ruta
Streams iniciados por servidor Sí (a través de canales) No (push en desuso, y Extended CONNECT es cliente-iniciado) Posible en QUIC en crudo. No en HTTP/3 simple. Puede vía WebTransport.
Alcance en firewall TCP TCP Necesita UDP, que algunos redes bloquean

La trampa: UDP no siempre está disponible

Un túnel QUIC solo es útil si UDP pasa. Las estimaciones varían, y las antiguas están desactualizadas. Las primeras mediciones de Google encontraron que aproximadamente 3–5% de redes bloquean QUIC, y las redes corporativas son un punto sensible. Algunos firewalls empresariales bloquean o limitan UDP/443 deliberadamente para que las herramientas de inspección puedan ver el tráfico TCP.

Por ello, los diseños en producción necesitan un fallback TCP. cloudflared en modo auto hace esto: prefiere QUIC y vuelve a HTTP/2 si no puede establecerse UDP. Tu agente también debe hacerlo, y mostrar qué transporte está activo para que los operadores entiendan las diferencias de rendimiento.

Recuerda también que un flujo UDP puede ser descartado por timeouts NAT. Envía keepalives (frames PING de QUIC o un latido de la aplicación) para que los túneles inactivos no mueran silenciosamente.


Seguridad y aislamiento multi-inquilino

Multiplexar muchos servicios en una sola conexión significa que un stream comprometido o mal configurado no debe acceder a recursos de otros inquilinos.

  1. Autentica la conexión, no solo los streams. Usa TLS mutuo o un token bearer al conectar el agente. Mantén la autenticación fuera de 0-RTT, ya que los datos tempranos pueden ser reproducidos.
  2. Vincula el agente a los hostnames que posee. El borde solo debe enrutar tenant-a.ejemplo.com a la conexión autenticada como tenant A. Nunca confíes en un hostname enviado por el agente sin verificar que esté autorizado.
  3. Usa una lista blanca en el agente. El agente debe mapear nombres de servicio a direcciones locales específicas y rechazar todo lo demás. En particular, nunca permitas que un request elija una dirección arbitraria, para evitar ataques de servidor falso a endpoints como 169.254.169.254.
  4. Limita la concurrencia por inquilino. El mecanismo MAX_STREAMS de QUIC limita cuántos streams puede abrir un peer. Añade límites por inquilino y cuotas de bytes en el borde para evitar que un flood en un hostname afecte a otros.
  5. Aisla fallos. Un reset en un stream no debe cerrar toda la conexión. Reserva un cierre a nivel de conexión para violaciones de protocolo.

Contexto de adopción

HTTP/3 ya no es exótico. W3Techs reportó un uso de HTTP/3 en aproximadamente el 38.6% de sitios en marzo de 2026 y 39.7% en julio de 2026. Tómalo como “sitios que soportan”. Las mediciones a nivel de request son menores, y datos de Cloudflare Radar, analizados por terceros, indican cerca del 21% de solicitudes globales en Q1 2026. Para túneles, lo más relevante es que navegadores, CDNs y librerías QUIC principales (quic-go, Google’s QUICHE, otros) son lo suficientemente maduras para usarse.


Conclusión

Ejecutar más de 50 servicios locales en una sola conexión es un problema resuelto. Los túneles maduros ya multiplexan muchos servicios en pocas conexiones, y QUIC añade recuperación de pérdida por stream, un puerto UDP único y migración de conexión en cliente. Los puntos clave son:

  • Los streams de solicitud HTTP/3 son iniciados por el cliente. Un túnel inverso necesita streams QUIC en crudo, un pool de streams Extended CONNECT preabiertos, o WebTransport, no un borde que solo abre streams de solicitud hacia el agente.
  • Extended CONNECT (RFC 8441, RFC 9220) es un mecanismo general. Transporta WebSockets, UDP (RFC 9298), IP (RFC 9484) y WebTransport. Elige o define el token :protocol con cuidado.
  • Planifica que UDP pueda ser bloqueado. Incluye un fallback TCP.
  • Ajusta y mide. Aumenta buffers UDP, dimensiona ventanas de control de flujo para la concurrencia esperada, y prueba con HTTP/2 en tu red antes de asumir que QUIC es superior.

Fuentes

Continue from this article into the most relevant product guides and workflows.

Related Topics

#multiplexed tunnels#multi-tenant tunnels#HTTP/3 Extended CONNECT#HTTP/3 CONNECT method#run multiple services on one port#single TCP port tunneling#cloud ingress stream#microservices tunneling#HTTP/3 multiplexing#local services exposure#reverse proxy tunneling#developer tunneling tools#QUIC protocol tunneling#port multiplexing#bypass port bottlenecks#concurrent local services#HTTP/3 framing#cloud proxy ingress#secure local development#modern tunneling architecture#distributed microservices proxy#scalable tunneling solutions#high-performance tunneling#custom domain tunneling#localhost exposure tool#network address translation traversal#TCP stream multiplexing#zero trust tunneling#edge routing for developers#multi-service port sharing#dynamic service discovery tunnel#low latency tunneling#HTTP/3 transport layer#cloud native networking#containerized service tunneling#enterprise tunneling tools#developer infrastructure#secure ingress proxy#API gateway alternative#local webhooks testing#remote development environments#seamless port forwarding#advanced local tunneling#high concurrency tunnels#HTTP/3 web transport#network optimization tools#cloud tunnel management#developer productivity tools#backend service exposure#scalable cloud ingress#modern network tunneling#enterprise grade tunneling#InstaTunnel features#multi-tenant architecture

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles