Conceptos

QUIC no usa UDP porque UDP sea más rápido: lo usa porque TCP ya no se podía cambiar

Por Equipo Cloud Privado · · 14 min de lectura
Dos pilas de red comparadas: en TCP el transporte está en el kernel; en QUIC, en el espacio de usuario

Un vistazo en 30 segundos

  • La frase «HTTP/3 usa UDP porque UDP es más rápido» se cae en cuanto miras un solo detalle: QUIC reimplementa encima de UDP casi todo lo que TCP le daba gratis. Fiabilidad, orden, control de congestión, control de flujo. Eso no sale gratis en rendimiento.
  • Lo que buscaba QUIC no era velocidad, era poder cambiar el transporte. TCP vive dentro del kernel, y encima hay tres décadas de NAT, cortafuegos, balanceadores y proxies que dan por sentado cómo se comporta. A eso se le llama osificación.
  • Al mover streams, recuperación de pérdidas, congestión y TLS 1.3 al espacio de usuario, una mejora de transporte deja de ser una versión de kernel y pasa a ser una actualización de aplicación.
  • El ejemplo lo dio Cloudflare el 12 de mayo de 2026: un fallo en su implementación dejaba la ventana de congestión clavada en 2.700 bytes, con 999 transiciones entre estados en 6,7 segundos. Lo arreglaron con tres líneas y lo desplegaron ellos.
  • La factura está medida. Un trabajo de la ACM Web Conference 2024 documentó hasta un 45,2 % menos de tasa de datos que TCP+TLS+HTTP/2 en redes rápidas, por el coste de procesar paquetes y confirmaciones en espacio de usuario.
  • De ahí vienen técnicas como UDP GSO, que en las pruebas de Cloudflare bajaron las llamadas al sistema de 904.539 a 18.824 para la misma transferencia.
  • Y el giro: el kernel está volviendo a la ecuación. Windows lleva QUIC en modo kernel (msquic.sys) desde Windows Server 2022, y Linux tiene una implementación de QUIC en revisión para mainline pensada para SMB y NFS.
  • Si operas infraestructura: UDP/443 abierto en los dos sentidos, balanceo consciente del connection ID, tcpdump ya no te cuenta nada del transporte, y el componente QUIC de tu balanceador es superficie de ataque nueva (HAProxy publicó dos CVE de denegación de servicio en febrero de 2026).

Hay una explicación de QUIC que circula desde hace años y que se ha quedado a medio camino: HTTP/3 va sobre UDP porque UDP no tiene handshake, no tiene confirmaciones y por tanto es más rápido. La primera parte es cierta. La conclusión es justo la contraria de lo que pasa.

QUIC no se queda con UDP tal cual. Encima de UDP vuelve a construir la entrega fiable, el orden de los datos, la detección de pérdidas, las retransmisiones, el control de flujo y el control de congestión. Es decir, reconstruye TCP. Con mejor diseño en algunos puntos —varios flujos independientes sin bloqueo en cabeza de línea, migración de conexión, cifrado obligatorio—, pero reconstruyéndolo. Y lo hace en un sitio donde hacer todo eso cuesta más ciclos de CPU, no menos.

Entonces, ¿por qué?

TCP no dejó de funcionar: dejó de poder cambiar

El problema de TCP nunca fue de diseño. Fue de éxito.

La lógica de TCP vive en el kernel del sistema operativo. Eso le da un rendimiento estupendo y una integración fina con el hardware de red, y a cambio convierte cualquier cambio de comportamiento en un problema de despliegue de años: hay que tocar el kernel, esperar a que el cambio llegue a una versión estable, esperar a que esa versión llegue a las distribuciones, y esperar a que alguien actualice sus máquinas. Multiplica eso por los dos extremos de cada conexión.

Y ahí no acaba. Entre tu cliente y tu servidor hay NAT, cortafuegos, balanceadores, proxies transparentes, aceleradores de operador y cajas cuyo fabricante ya no existe. Durante treinta años, todos esos equipos han aprendido cómo suele ser un paquete TCP: qué banderas lleva, cómo avanzan los números de secuencia, cómo empieza un handshake. Algunos inspeccionan. Algunos reescriben. Y unos cuantos, directamente, tiran lo que no entienden.

El resultado es que la red pasó a depender del comportamiento actual de TCP. El protocolo es extensible sobre el papel, pero estrenar una extensión significa descubrir en producción qué proporción de tus usuarios está detrás de una caja que la rompe. Eso es la osificación, y los RFC de QUIC la citan como motivo de diseño, no como anécdota: el RFC 9308 recoge explícitamente que QUIC se puede implementar en espacio de usuario y desplegar sobre la infraestructura UDP que ya existe.

Nosotros hemos escrito aquí sobre el lado feo de esa dependencia: cuando compartir tabla NAT con desconocidos deja de salir gratis, lo que está en juego es exactamente esto, cajas intermedias que saben demasiado de tu transporte.

Dónde vive la lógica, que es la pregunta de verdad

Dónde vive la lógica de transporte en TCP y en QUIC Dos pilas de red comparadas. En la izquierda, con TCP, la aplicación y la biblioteca TLS corren en el espacio de usuario, mientras la fiabilidad, el orden, las retransmisiones y el control de congestión viven dentro del kernel, junto a IP y a las aceleraciones de la tarjeta de red. En la derecha, con QUIC, esa misma lógica de transporte sube al espacio de usuario dentro de la biblioteca que se compila con la aplicación, y al kernel solo le queda un socket UDP sobre IP. La frontera entre kernel y espacio de usuario no se mueve: lo que se mueve es el trabajo, y por eso una mejora de transporte pasa de exigir una versión nueva de kernel a ser una actualización de la aplicación. TCP + TLS + HTTP/2 espacio de usuario HTTP/2 peticiones y respuestas TLS 1.3 OpenSSL y compañía kernel TCP — el transporte orden, pérdidas, congestión IP + NIC TSO, GRO, checksum, kTLS QUIC + HTTP/3 espacio de usuario HTTP/3 peticiones y respuestas QUIC — el transporte orden, pérdidas, congestión, TLS 1.3 kernel UDP puertos y poco más IP + NIC GSO y GRO de UDP Un fallo de congestión: a la izquierda pide kernel nuevo; a la derecha, actualizar el servicio.
Dónde vive la lógica de transporte en TCP y en QUIC Dos pilas de red comparadas. En la izquierda, con TCP, la aplicación y la biblioteca TLS corren en el espacio de usuario, mientras la fiabilidad, el orden, las retransmisiones y el control de congestión viven dentro del kernel, junto a IP y a las aceleraciones de la tarjeta de red. En la derecha, con QUIC, esa misma lógica de transporte sube al espacio de usuario dentro de la biblioteca que se compila con la aplicación, y al kernel solo le queda un socket UDP sobre IP. La frontera entre kernel y espacio de usuario no se mueve: lo que se mueve es el trabajo, y por eso una mejora de transporte pasa de exigir una versión nueva de kernel a ser una actualización de la aplicación. TCP + TLS + HTTP/2 espacio de usuario HTTP/2 peticiones y respuestas TLS 1.3 OpenSSL y compañía kernel TCP — el transporte orden, pérdidas, congestión IP + NIC TSO, GRO, checksum, kTLS QUIC + HTTP/3 espacio de usuario HTTP/3 peticiones y respuestas QUIC — el transporte orden, pérdidas, congestión, TLS kernel UDP puertos y poco más IP + NIC GSO y GRO de UDP
La frontera no se mueve: lo que se mueve es el trabajo. En QUIC, el kernel solo ve un socket UDP.

Conviene decir algo que se malinterpreta mucho: QUIC no se salta el kernel. Los paquetes siguen entrando y saliendo por un socket UDP, y de IP para abajo todo es igual que siempre. Lo que cambia es quién decide cuándo retransmitir, cuánto se puede tener en vuelo, cómo se reparte el ancho de banda entre flujos y cómo se cifra cada paquete: eso se lo lleva una biblioteca que se compila y se despliega con tu aplicación.

Con TCP, ese código lo mantiene quien empaqueta tu kernel. Con QUIC, lo mantiene quien escribe quiche, msquic, ngtcp2, quic-go o el navegador que tenga delante tu usuario.

UDP, en esta historia, no es una elección de rendimiento. Es una elección de despliegue. Cualquier red del mundo sabe encaminar UDP, cualquier NAT sabe seguir un flujo UDP y cualquier sistema operativo trae sockets UDP desde hace décadas. Diseñar un protocolo de transporte nuevo desde cero, con su propio número de protocolo IP, habría sido más limpio y habría tardado quince años en poderse usar.

Lo que se gana: un fallo de transporte con parche en el mismo día

La ventaja se ve mejor con un caso real, y hay uno reciente y muy bien contado.

El 12 de mayo de 2026, Cloudflare publicó el análisis de lo que internamente llamaron la espiral de la muerte de QUIC. El origen es delicioso: en 2017, el kernel de Linux incorporó una optimización de CUBIC para los periodos de inactividad. Si una conexión deja de enviar y luego retoma, la curva de crecimiento de CUBIC calcula un salto de tiempo enorme y abre la ventana de congestión de golpe, que es justo lo que no quieres. La solución del kernel fue desplazar el origen de la curva hacia delante en vez de reiniciarla.

Al portar esa idea a quiche, la comprobación de inactividad se hizo midiendo el tiempo desde el último envío. Y ahí está el fallo: cuando la ventana de congestión ya está en su mínimo —dos paquetes—, se envían los dos, se espera un RTT completo a las confirmaciones, los bytes en vuelo bajan a cero y el código concluye que la conexión ha estado inactiva. No lo estaba: estaba limitada por congestión.

El efecto en su banco de pruebas —descarga de 10 MB, 10 ms de RTT y un 30 % de pérdida durante los dos primeros segundos— era que después de esos dos segundos la pérdida desaparecía y la ventana no crecía nunca. Se quedaba en 2.700 bytes, oscilando entre recuperación y evitación de congestión al ritmo del RTT: 999 transiciones en 6,7 segundos. La prueba de integración fallaba el 61 % de las veces sin que nadie supiera por qué.

El arreglo cabe en un tuit: medir la inactividad desde el último evento real, sea un envío o una confirmación, con max(last_ack_time, last_sent_time). Tres líneas. Tasa de éxito de vuelta al 100 %.

Lo interesante no es el fallo, que es un fallo normal. Es el calendario. Un operador de CDN detectó, diagnosticó, corrigió y desplegó un cambio de control de congestión en su propia flota. El mismo fallo dentro del kernel habría significado esperar a una versión, esperar a que la distribución la empaquetara y esperar a reiniciar máquinas. Cualquiera que haya intentado cambiar de kernel sin apagar las cargas sabe lo que dura esa cadena.

Ese es todo el argumento de QUIC, resumido: no es que el transporte sea mejor, es que se puede arreglar.

Lo que se paga: la CPU que TCP no gasta

Aquí es donde el discurso de marketing suele callarse.

TCP lleva veinticinco años acumulando optimizaciones en el kernel y en las tarjetas de red: segmentación delegada al hardware (TSO), agregación en recepción (GRO), cálculo de sumas de comprobación en la NIC, envío de ficheros sin copias intermedias con sendfile() y, desde hace unos años, cifrado TLS en el propio kernel o en la tarjeta (kTLS; nginx lo usa desde la 1.21.4 con SSL_sendfile()). Nada de eso existía para UDP, porque a nadie le hacía falta mover terabytes por UDP.

QUIC llegó a ese terreno y se encontró con la cuenta: cifra cada paquete por separado —no hay forma de delegar eso en la NIC como con TLS sobre TCP—, genera y procesa las confirmaciones en espacio de usuario, y en la versión ingenua hace una llamada al sistema por datagrama.

Las cifras existen. El trabajo QUIC is not Quick Enough over Fast Internet, presentado en la ACM Web Conference 2024, midió hasta un 45,2 % menos de tasa de datos en la pila UDP+QUIC+HTTP/3 frente a TCP+TLS+HTTP/2 en enlaces rápidos, con reducciones de hasta el 9,8 % en el bitrate de vídeo. La causa que señalan es el coste de procesamiento en el receptor: el kernel entrega muchísimos más paquetes uno a uno, con el consiguiente consumo de CPU, porque ninguna de las implementaciones que analizaron usaba UDP GRO. Y el hueco crece cuanto más ancho de banda tienes, que es la parte contraintuitiva.

La respuesta ha sido rehacer para UDP lo que TCP ya tenía. Cloudflare lo documentó en enero de 2020 con UDP GSO: en lugar de una llamada al sistema por paquete, la aplicación entrega un búfer grande y el kernel —o la tarjeta— lo trocea, hasta 64 segmentos por operación con UDP_SEGMENT desde Linux 4.18. En sus mediciones, combinando sendmmsg(), las llamadas al sistema para la misma transferencia pasaron de 904.539 a 18.824.

TCP + TLSQUIC + HTTP/3
Dónde vive el transporteKernelBiblioteca de la aplicación
Cómo se arregla un falloVersión de kernel + reinicioActualizar la aplicación
Aceleración por hardwareTSO, GRO, checksum, kTLS, sendfile()GSO/GRO de UDP; cifrado siempre en CPU
Qué ve un middleboxEstado, banderas, secuenciaIP, UDP y muy pocos metadatos
Diagnósticotcpdump, ss, contadores del kernelqlog, herramientas de la implementación
Superficie de parcheoUn kernel por máquinaUn binario por servicio

Esa última fila es la que más se subestima, y ya la comentamos al hablar de por qué media infraestructura moderna es un binario de Go: cuando la biblioteca va dentro del ejecutable, apt upgrade no arregla nada. Con QUIC, tu pila de transporte es una dependencia de aplicación más, con su CVE y su recompilación.

El giro que casi nadie cuenta: el kernel vuelve

Si el argumento fuera «el espacio de usuario es mejor sitio para el transporte», la historia habría terminado. No ha terminado.

Windows lleva QUIC en el kernel desde hace años. msquic.sys es un driver en modo kernel que da servicio a http.sys para HTTP/3 y a SMB sobre QUIC en Windows Server 2022 y Windows 11. Tiene sus limitaciones —al depender de Schannel para TLS 1.3, el modo kernel no soporta 0-RTT, cosa que sí hace la versión de usuario—, pero está ahí.

Y Linux va por el mismo camino. Xin Long lleva años empujando una implementación de QUIC en el kernel, cuya última tanda de parches se envió a netdev marcada como EXPERIMENTAL y con más de 9.000 líneas solo para la parte baja. El motivo no es servir páginas web: es que subsistemas del propio kernel, como SMB y NFS, puedan hablar QUIC sin subir y bajar datos al espacio de usuario. El diseño es híbrido y bastante elegante: el kernel se queda con toda la lógica del protocolo —congestión, flujo, cifrado de paquetes— y el handshake TLS se procesa arriba, con GnuTLS a través del servicio tlshd. A día de hoy sigue fuera de mainline; en la hoja de ruta del proyecto, «enviar el módulo QUIC al kernel upstream» continúa como tarea pendiente.

Conclusión razonable: el espacio de usuario no era el destino, era el camino. Sirvió para desplegar QUIC sin pedir permiso a nadie y para iterarlo rápido. Ahora que el protocolo se ha estabilizado, cada plataforma decide dónde le compensa ponerlo. Lo mismo que pasó con WireGuard, por cierto, que empezó como módulo y hoy convive con implementaciones de usuario según lo que necesites: montarte una VPN propia no te obliga a elegir bando.

Qué te cambia esto a ti, que operas la infraestructura

Toda esta historia tiene consecuencias muy terrenales para quien administra servidores, balanceadores y cortafuegos. Estas son las que nos encontramos.

El cortafuegos: UDP/443 en los dos sentidos

QUIC habla por UDP, casi siempre en el puerto 443. Si tu política de salida permite TCP/443 y bloquea UDP/443 —que es la configuración por defecto de muchas organizaciones—, los navegadores no se quedan sin Internet: reintentan por TCP. Lo que se pierde es cualquier ventaja de HTTP/3 y se gana un pequeño retraso en cada conexión mientras se descubre que UDP no pasa.

Decidirlo está bien. Que pase por accidente, no. Y si lo que publicas es un servicio con HTTP/3 activo, comprueba que el UDP entra de verdad hasta el balanceador, porque el fallback silencioso hace que todo «funcione» y nadie se entere de que la mitad del diseño no se está usando.

El balanceo: la conexión ya no es una 5-tupla

Un balanceador de capa 4 reparte por IP y puerto de origen y destino. QUIC identifica cada conexión con un connection ID propio precisamente para sobrevivir a que esa 5-tupla cambie: es lo que permite que un móvil pase de wifi a datos móviles sin cortar la descarga.

Traducido a tu instalación: si repartes por hash de 5-tupla, un cambio de red del cliente puede mandar sus paquetes a un backend que no tiene ni idea de esa conexión. Los balanceadores serios lo resuelven enrutando por connection ID, pero hay que configurarlo, y conviene saber que el estado de conexión ya no está donde estaba.

La observabilidad: tcpdump deja de contarte la película

En TCP puedes ver un handshake, seguir números de secuencia, detectar retransmisiones y deducir el estado de la congestión con una captura. QUIC cifra casi todos sus metadatos de transporte, y eso es intencionado: es la vacuna contra la osificación, evitar que las cajas intermedias vuelvan a construir suposiciones sobre lo que ven.

El precio lo pagas tú cuando algo va mal. Para diagnosticar hace falta instrumentar el extremo: qlog en la implementación, claves exportadas para descifrar la captura, métricas de la propia biblioteca. Si tu procedimiento de incidencias empieza con «pon un tcpdump en el balanceador», con HTTP/3 necesitas un procedimiento nuevo.

La seguridad: superficie nueva, y en tu lado

Que el transporte sea código de aplicación significa que los fallos de transporte son fallos de tu aplicación. En febrero de 2026, HAProxy publicó dos vulnerabilidades del componente QUIC —CVE-2026-26080 y CVE-2026-26081, ambas CVSS 7,5— que permitían a un atacante remoto sin autenticar tumbar el proceso con un paquete Initial malformado o dejar el analizador de tramas en bucle infinito con un varint truncado. La mitigación provisional era desactivar QUIC (tune.quic.listen off o no-quic, según versión) mientras se actualizaba.

No es un argumento contra QUIC; es la factura normal del código joven. Pero cambia dónde miras: tu inventario de parches tiene que incluir la biblioteca QUIC de cada servicio expuesto, no solo el kernel.

La decisión: activarlo o no

Para un sitio público con usuarios en móvil y redes malas, HTTP/3 compensa: se nota en establecimiento de conexión, en pérdida de paquetes y en cambios de red. Según W3Techs, en agosto de 2026 lo soporta el 40,3 % de los sitios web, aunque conviene leer ese número con cuidado, porque soportar no es servir: la proporción de peticiones que realmente viajan por HTTP/3 es bastante menor y depende mucho de si hay un CDN delante.

Para tráfico interno entre nodos de tu propia plataforma —réplicas de base de datos, colas, almacenamiento— el cálculo se invierte. Ahí controlas la red, no hay middleboxes hostiles, no hay clientes cambiando de wifi a 5G, y lo que te importa es exprimir la CPU. Por eso etcd, Kafka y compañía siguen hablando TCP entre ellos, y por eso el soporte de HTTP/3 en nginx, disponible desde la rama 1.25, sigue descrito por la propia documentación del proyecto como experimental.

Lo que nos llevamos

La lección de QUIC no va de UDP. Va de qué pasa cuando una pieza de infraestructura tiene tanto éxito que la propia red se organiza alrededor de su comportamiento y deja de poder evolucionar.

La respuesta no fue convencer al mundo de que cambiara TCP. Fue construir el transporte en un sitio donde cambiarlo dependiera de menos gente, aceptando a cambio pagar en CPU lo que TCP tenía resuelto en silicio. Y como el problema era de despliegue y no de arquitectura, en cuanto el protocolo se ha asentado, el kernel ha empezado a reclamar su parte.

En las plataformas que gestionamos, esto se traduce en cosas concretas y aburridas: saber qué puertos UDP están abiertos y hacia dónde, saber qué biblioteca QUIC lleva cada servicio expuesto y quién la parchea, y tener un procedimiento de diagnóstico que no dependa de leer el transporte en claro. Si estás montando infraestructura propia y quieres que alguien revise contigo esa parte antes de que te la encuentres a las tres de la mañana, cuéntanos cómo lo tienes.

Preguntas frecuentes

¿HTTP/3 es más rápido que HTTP/2?

Depende de la red. En conexiones con pérdida de paquetes, latencia alta o cambios de red —típicamente móviles— QUIC gana porque establece la conexión en menos viajes y porque la pérdida en un flujo no bloquea a los demás. En redes rápidas y estables puede perder: un trabajo de la ACM Web Conference 2024 midió hasta un 45,2 % menos de tasa de datos frente a TCP+TLS+HTTP/2, por el coste de procesar los paquetes en espacio de usuario.

¿Por qué QUIC va sobre UDP y no sobre un protocolo nuevo?

Por despliegue. Un protocolo IP nuevo habría requerido que cortafuegos, NAT y sistemas operativos de todo el mundo lo soportaran antes de poder usarlo. UDP ya está en todas partes, así que QUIC lo usa como envoltorio y construye encima la fiabilidad, el orden y el control de congestión que TCP daba hecho.

¿QUIC se salta el kernel?

No. Los paquetes siguen pasando por el socket UDP del kernel y por la pila IP. Lo que se ejecuta en espacio de usuario es la lógica de transporte: streams, retransmisiones, control de congestión, control de flujo y TLS 1.3. De hecho, Windows implementa QUIC en modo kernel con msquic.sys y Linux tiene una implementación de kernel en revisión pensada para SMB y NFS.

¿Tengo que abrir el puerto UDP 443 en el cortafuegos?

Sí, si quieres que HTTP/3 se use de verdad, y en los dos sentidos. Si UDP/443 está bloqueado, los clientes vuelven a TCP y todo sigue funcionando, con lo cual el bloqueo pasa desapercibido y el servicio nunca usa HTTP/3 aunque lo tengas configurado.

¿Cómo se diagnostica un problema de QUIC si va todo cifrado?

Instrumentando los extremos. La captura de red te da poco más que IP y UDP, así que se recurre a qlog en la implementación, a las métricas de la propia biblioteca y, cuando hace falta mirar el contenido, a exportar las claves de sesión para descifrar la captura en laboratorio.

¿Merece la pena QUIC para tráfico interno entre servidores?

Casi nunca. Dentro de una red que controlas no hay middleboxes que rompan TCP ni clientes cambiando de red, y sí importa mucho el consumo de CPU, donde TCP juega con ventaja gracias a las aceleraciones del kernel y de la tarjeta de red. Por eso los sistemas distribuidos habituales siguen usando TCP entre nodos.

Fuentes