La primera mención de QUIC y HTTP/3 en el blog de NGINX fue hace cuatro años (!), y, al igual que usted, esperamos con impaciencia la inminente integración de nuestra implementación de QUIC en la rama principal de NGINX Open Source. Dado su largo periodo de gestación, es comprensible que no haya pensado mucho en QUIC.
Sin embargo, llegados a este punto, como desarrollador o administrador de un sitio web, debe saber que QUIC transfiere la responsabilidad de ciertos aspectos de la red del sistema operativo a NGINX (y a todas las aplicaciones HTTP). Aunque las redes no sean lo suyo, adoptar QUIC implica que preocuparse por la red pasa a formar parte —al menos en cierta medida— de su trabajo.
En este artículo, profundizamos en los principales conceptos de redes y cifrado utilizados en QUIC, simplificando algunos detalles y omitiendo información no esencial en aras de la claridad. Aunque en el proceso puedan perderse algunos matices, nuestra intención es proporcionar información suficiente para que pueda adoptar QUIC de forma eficaz en su entorno o, al menos, ofrecerle una base sobre la que ampliar sus conocimientos.
Si QUIC es algo totalmente nuevo para ti, te recomendamos que primero leas una de nuestras publicaciones anteriores y veas nuestro vídeo introductorio.
 
Para obtener una explicación más detallada y completa de QUIC, recomendamos el excelente documento «Gestionabilidad del protocolo de transporte QUIC» del grupo de trabajo de QUIC del IETC, junto con los materiales adicionales enlazados a lo largo de este documento.
¿Por qué deberían importarte las redes y el cifrado en QUIC?
Hasta ahora, los detalles más engorrosos de la conexión de red entre los clientes y NGINX no han sido especialmente relevantes para la mayoría de los usuarios. Al fin y al cabo, con HTTP/1.x y HTTP/2, el sistema operativo se encarga de establecer la conexión mediante el Protocolo de Control de Transmisión (TCP) entre los clientes y NGINX. NGINX se limita a utilizar la conexión una vez establecida.
Sin embargo, con QUIC, la responsabilidad de crear, validar y gestionar las conexiones pasa del sistema operativo subyacente a NGINX. En lugar de recibir una conexión TCP ya establecida, NGINX recibe ahora un flujo de datagramas del Protocolo de Datagramas de Usuario (UDP), que debe analizar para convertirlos en conexiones y flujos de clientes. NGINX también pasa a encargarse de gestionar la pérdida de paquetes, los reinicios de las conexiones y el control de la congestión.
Además, QUIC combina el inicio de la conexión, la negociación de la versión y el intercambio de claves de cifrado en una única operación de establecimiento de conexión. Y, aunque el cifrado TLS se gestiona de forma muy similar tanto en QUIC+HTTP/3 como en TCP+HTTP/1+2, existen diferencias que podrían ser importantes para dispositivos posteriores, como balanceadores de carga de capa 4, cortafuegos y dispositivos de seguridad.
En última instancia, el efecto global de estos cambios es una experiencia más segura, rápida y fiable para los usuarios, con muy pocos cambios en la configuración o el funcionamiento de NGINX. Sin embargo, los administradores de NGINX deben comprender al menos un poco lo que ocurre con QUIC y NGINX, aunque solo sea para reducir al mínimo el tiempo medio hasta demostrar su inocencia en caso de que surjan problemas.
(Cabe señalar que, aunque esta publicación se centra en las operaciones HTTP porque HTTP/3 requiere QUIC, QUIC también puede utilizarse con otros protocolos. Un buen ejemplo es DNS sobre QUIC, tal como se define en el RFC 9250, «DNS sobre conexiones QUIC dedicadas».)
Una vez hecha esta introducción, profundicemos en algunos aspectos específicos de las redes QUIC.
TCP frente a UDP
QUIC introduce un cambio significativo en el protocolo de red subyacente utilizado para transmitir datos de aplicaciones HTTP entre un cliente y un servidor.
Como ya se ha mencionado, TCP siempre ha sido el protocolo utilizado para transmitir datos de aplicaciones web HTTP. TCP está diseñado para transmitir datos de forma fiable a través de una red IP. Cuenta con un mecanismo bien definido y conocido para establecer conexiones y confirmar la recepción de datos, además de diversos algoritmos y técnicas para gestionar la pérdida y el retraso de paquetes, habituales en redes poco fiables y congestionadas.
Aunque TCP proporciona un transporte fiable, conlleva ciertas contrapartidas en términos de rendimiento y latencia. Además, el cifrado de datos no está integrado en TCP y debe implementarse por separado. También ha resultado difícil mejorar o ampliar TCP ante los cambios en los patrones de tráfico HTTP, ya que el procesamiento de TCP se realiza en el kernel de Linux y cualquier modificación debe diseñarse y probarse cuidadosamente para evitar efectos imprevistos en el rendimiento y la estabilidad generales del sistema.
Otro problema es que, en muchos casos, el tráfico HTTP entre el cliente y el servidor pasa por varios dispositivos que procesan TCP, como cortafuegos o balanceadores de carga (conocidos en conjunto como «dispositivos intermedios»), que pueden tardar en implementar los cambios en los estándares de TCP.
QUIC, en cambio, utiliza UDP como protocolo de transporte. UDP está diseñado para transmitir datos a través de una red IP, al igual que TCP, pero prescinde deliberadamente del establecimiento de conexiones y de la entrega fiable. Esta ausencia de sobrecarga hace que UDP sea adecuado para muchas aplicaciones en las que la eficiencia y la velocidad son más importantes que la fiabilidad.
Sin embargo, para la mayoría de las aplicaciones web, la entrega fiable de datos es esencial. Dado que la capa de transporte UDP subyacente no garantiza una entrega fiable de los datos, QUIC (o la propia aplicación) debe proporcionar estas funciones. Afortunadamente, QUIC presenta un par de ventajas frente a TCP en este sentido:
- El procesamiento de QUIC se realiza en el espacio de usuario de Linux, donde los problemas con una operación concreta suponen un menor riesgo para el sistema en su conjunto. Esto facilita el desarrollo rápido de nuevas funcionalidades.
- Los «middleboxes» mencionados anteriormente suelen realizar un procesamiento mínimo del tráfico UDP, por lo que no limitan las mejoras del protocolo QUIC.
Anatomía simplificada de una red QUIC
QUIC flujos son los objetos lógicos que contienen solicitudes o respuestas HTTP/3 (o cualquier otro dato de la aplicación). Para su transmisión entre puntos finales de red, se encapsulan en varias capas lógicas, tal como se muestra en el diagrama.

De fuera hacia dentro, las capas lógicas y los objetos son:
- Datagrama UDP – Contiene una cabecera que especifica los puertos de origen y destino (junto con los datos de longitud y suma de comprobación), seguida de uno o varios paquetes QUIC. El datagrama es la unidad de información que se transmite del cliente al servidor a través de la red.
- Paquete QUIC – Contiene una cabecera QUIC y una o varias tramas QUIC.
- Cabecera QUIC – Contiene metadatos sobre el paquete. Hay dos tipos de cabecera:
- La cabecera larga, utilizada durante el establecimiento de la conexión.
- La cabecera corta, utilizada una vez establecida la conexión. Contiene, entre otros datos, el ID de conexión, el número de paquete y la fase de clave (utilizada para saber qué claves se emplearon para cifrar el paquete y facilitar así la rotación de claves). Los números de paquete son únicos (y siempre aumentan) para una conexión y una fase de clave determinadas.
- Trama – Contiene el tipo, el ID de flujo, el desplazamiento y los datos del flujo. Los datos del flujo se distribuyen entre varias tramas, pero pueden recomponerse mediante el ID de conexión, el ID de flujo y el desplazamiento, que se utiliza para presentar los fragmentos de datos en el orden correcto.
- Flujo – Flujo de datos unidireccional o bidireccional dentro de una única conexión QUIC. Cada conexión QUIC puede admitir varios flujos independientes, cada uno con su propio ID de flujo. Si se pierde un paquete QUIC que contiene algunos flujos, esto no afecta al progreso de los flujos que no estén incluidos en el paquete perdido (esto es fundamental para evitar el bloqueo de cabecera de línea que se produce en HTTP/2). Los flujos pueden ser bidireccionales y cualquiera de los dos extremos puede crearlos.
Establecimiento de la conexión
El conocido protocolo de enlace de tres pasos SYN / SYN-ACK / ACK establece una conexión TCP:
Figura 2. El protocolo de enlace de tres vías que establece una conexión TCP
El establecimiento de una conexión QUIC implica pasos similares, pero es más eficiente. Además, integra la validación de direcciones en el establecimiento de la conexión como parte del protocolo de enlace criptográfico. La validación de direcciones protege frente a ataques de amplificación de tráfico, en los que un agente malintencionado envía al servidor un paquete con información falsificada sobre la dirección de origen de la víctima a la que pretende atacar. El atacante espera que el servidor genere para la víctima más paquetes, o paquetes de mayor tamaño, de los que podría generar por sí solo, lo que provoca un volumen de tráfico abrumador. (Para obtener más información, consulte la Sección 8 de RFC 9000, QUIC: transporte seguro y multiplexado basado en UDP.)
Como parte del establecimiento de la conexión, el cliente y el servidor proporcionan identificadores de conexión independientes que se codifican en la cabecera QUIC, lo que permite identificar fácilmente la conexión con independencia de la dirección IP de origen del cliente.
Sin embargo, dado que el establecimiento inicial de una conexión QUIC también incluye operaciones para el intercambio de claves de cifrado TLS, requiere más recursos computacionales del servidor que la simple respuesta «SYN-ACK» que genera durante el establecimiento de una conexión TCP. Esto también crea un posible vector para ataques de denegación de servicio distribuido (DDoS) porque la dirección IP del cliente no se valida antes de que se lleven a cabo las operaciones de intercambio de claves.
Sin embargo, puede configurar NGINX para que valide la dirección IP del cliente antes de iniciar operaciones criptográficas complejas; para ello, establezca la directiva quic_retry en on. En este caso, NGINX envía al cliente un paquete de reintento que contiene un token que el cliente debe incluir en los paquetes de establecimiento de la conexión.
Figura 3. Establecimiento de una conexión QUIC, sin y con un paquete de reintento
Este mecanismo es similar en cierta medida al protocolo de enlace de tres vías de TCP y, lo que es fundamental, permite comprobar que el cliente es el propietario de la dirección IP de origen que presenta. Sin esta comprobación, los servidores QUIC como NGINX podrían ser vulnerables a ataques DoS sencillos mediante direcciones IP de origen falsificadas. (Otro mecanismo de QUIC que mitiga este tipo de ataques es el requisito de que todos los paquetes iniciales de conexión se rellenen hasta alcanzar un mínimo de 1200 bytes, lo que encarece su envío.)
Además, los paquetes de reintento mitigan un ataque similar al ataque de inundación SYN de TCP (en el que los recursos del servidor se agotan debido a la enorme cantidad de procesos de negociación iniciados, pero no completados, que se almacenan en memoria), ya que codifican los detalles de la conexión en el ID de conexión que envían al cliente. Esto ofrece la ventaja adicional de que no es necesario conservar información en el servidor, puesto que los datos de la conexión pueden reconstruirse a partir del ID de conexión y del token que el cliente presenta posteriormente. Esta técnica es análoga a las cookies SYN de TCP. Además, los servidores QUIC como NGINX pueden proporcionar un token con fecha de caducidad para utilizarlo en futuras conexiones del cliente y agilizar así la reanudación de la conexión.
El uso de identificadores de conexión permite que la conexión sea independiente de la capa de transporte subyacente, de modo que los cambios en la red no provoquen necesariamente la interrupción de las conexiones. Este tema se aborda en Gestión fluida de los cambios en la dirección IP del cliente.
Detección de pérdidas
Una vez establecida la conexión (y habilitado el cifrado, como se explica más adelante a continuación), las solicitudes y respuestas HTTP pueden intercambiarse entre el cliente y NGINX. Los datagramas UDP se envían y reciben. Sin embargo, hay muchos factores que pueden provocar que algunos de estos datagramas se pierdan o se retrasen.
TCP dispone de mecanismos complejos para confirmar la entrega de paquetes, detectar la pérdida o el retraso de paquetes y gestionar la retransmisión de los paquetes perdidos, de modo que los datos lleguen completos y en el orden correcto a la capa de aplicación. UDP carece de esta funcionalidad, por lo que el control de congestión y la detección de pérdidas se implementan en la capa QUIC.
- Tanto el cliente como el servidor envían una confirmación explícita por cada paquete QUIC que reciben (aunque los paquetes que solo contienen tramas de baja prioridad no se confirman inmediatamente).
- Cuando un paquete que contiene tramas que requieren una entrega fiable no recibe confirmación tras un periodo de espera determinado, se considera perdido. Los periodos de espera varían en función del contenido del paquete; por ejemplo, son más cortos para los paquetes necesarios para establecer el cifrado y configurar la conexión, ya que son esenciales para el rendimiento del protocolo de enlace de QUIC.
- Cuando un paquete se considera perdido, las tramas que faltan se retransmiten en un nuevo paquete, que tiene un nuevo número de secuencia.
- El destinatario del paquete utiliza el ID de flujo y el desplazamiento de los paquetes para ensamblar los datos transmitidos en el orden correcto. El número de paquete solo determina el orden de envío, no cómo deben ensamblarse los paquetes.
- Dado que el ensamblado de datos en el receptor es independiente del orden de transmisión, un paquete perdido o retrasado afecta únicamente a los flujos individuales que contiene, no a todos los flujos de la conexión. Esto elimina el problema del bloqueo de cabecera que afecta a HTTP/1.x y HTTP/2, ya que los flujos no forman parte de la capa de transporte.
Una descripción completa de la detección de pérdidas queda fuera del alcance de esta introducción. Consulte RFC 9002, «Detección de pérdidas y control de congestión en QUIC», para obtener información detallada sobre los mecanismos para determinar los tiempos de espera y la cantidad de datos sin confirmar que pueden estar en tránsito.
Gestión fluida de los cambios en la dirección IP del cliente
La dirección IP de un cliente (denominada dirección IP de origen en el contexto de una sesión de aplicación) puede cambiar durante la sesión, por ejemplo, cuando una VPN o una puerta de enlace cambia su dirección pública o cuando el usuario de un smartphone abandona una zona con cobertura Wi-Fi, lo que obliga a cambiar a una red móvil. Además, tradicionalmente los administradores de red han establecido tiempos de espera más cortos para el tráfico UDP que para las conexiones TCP, lo que aumenta la probabilidad de que se produzca una revinculación de la traducción de direcciones de red (NAT).
QUIC proporciona dos mecanismos para reducir las interrupciones que pueden producirse: un cliente puede informar de forma proactiva al servidor de que su dirección va a cambiar, y los servidores pueden gestionar sin problemas un cambio imprevisto en la dirección del cliente. Dado que el ID de conexión se mantiene constante durante la transición, las tramas sin confirmar pueden retransmitirse a la nueva dirección IP.
Los cambios en la dirección IP de origen durante las sesiones QUIC pueden suponer un problema para los balanceadores de carga posteriores (u otros componentes de red de capa 4) que utilizan la dirección IP y el puerto de origen para determinar qué servidor ascendente debe recibir un datagrama UDP concreto. Para garantizar una gestión correcta del tráfico, los proveedores de dispositivos de red de capa 4 deberán actualizarlos para que puedan gestionar los identificadores de conexión QUIC. Para obtener más información sobre el futuro del balanceo de carga y QUIC, consulte el borrador del IETF QUIC‑LB: Generación de identificadores de conexión QUIC enrutables.
Cifrado
En «Establecimiento de la conexión», mencionamos que el protocolo de enlace inicial de QUIC no se limita a establecer una conexión. A diferencia del protocolo de enlace TLS para TCP, con UDP el intercambio de claves y parámetros de cifrado de TLS 1.3 se produce como parte de la conexión inicial. Esta característica elimina varios intercambios y permite un tiempo de ida y vuelta cero (0-RTT) cuando el cliente reanuda una conexión anterior.

Además de integrar el protocolo de enlace de cifrado en el proceso de establecimiento de la conexión, QUIC cifra una mayor parte de los metadatos que TCP+TLS. Incluso antes de que se produzca el intercambio de claves, los paquetes iniciales de la conexión están cifrados; aunque un intruso que intercepte la comunicación aún puede obtener las claves, esto requiere más esfuerzo que con paquetes sin cifrar. De este modo, se protegen mejor datos como la indicación del nombre del servidor (SNI), que resulta de interés tanto para los atacantes como para posibles censores estatales. La figura 5 muestra cómo QUIC cifra más metadatos potencialmente sensibles (en rojo) que TCP+TLS.

Todos los datos de la carga útil de QUIC se cifran mediante TLS 1.3. Esto ofrece dos ventajas: no se permiten conjuntos de cifrado ni algoritmos hash antiguos y vulnerables, y es obligatorio utilizar mecanismos de intercambio de claves con secreto perfecto hacia adelante (FS). El secreto perfecto hacia adelante impide que un atacante descifre los datos, incluso si obtiene la clave privada y una copia del tráfico.
Las conexiones de RTT baja y cero reducen la latencia
Reducir el número de viajes de ida y vuelta que deben producirse entre un cliente y un servidor antes de poder transmitir datos de la aplicación mejora el rendimiento de las aplicaciones, especialmente en redes con mayor latencia.
TLS 1.3 introdujo un único viaje de ida y vuelta para establecer una conexión cifrada y ninguno para reanudar una conexión, pero con TCP esto significa que el protocolo de enlace debe completarse antes del mensaje Client Hello de TLS.
Dado que QUIC combina las operaciones criptográficas con el establecimiento de la conexión, permite restablecer conexiones con un auténtico 0‑RTT, de modo que un cliente puede enviar una solicitud en el primer paquete QUIC. Esto reduce la latencia al eliminar el viaje de ida y vuelta inicial necesario para establecer la conexión antes de la primera solicitud.

En este caso, el cliente envía una solicitud HTTP cifrada con los parámetros utilizados en una conexión anterior e incluye, para validar la dirección, un token proporcionado por el servidor durante dicha conexión.
Lamentablemente, la reanudación de conexiones 0‑RTT no proporciona secreto hacia adelante, por lo que la solicitud inicial del cliente no está cifrada de forma tan segura como el resto del tráfico del intercambio. Las solicitudes y respuestas posteriores a la primera solicitud están protegidas mediante secreto hacia adelante. Un problema posiblemente más grave es que la solicitud inicial también es vulnerable a ataques de repetición, en los que un atacante puede capturar la solicitud inicial y reenviarla al servidor varias veces.
Para muchas aplicaciones y sitios web, la mejora del rendimiento que ofrece la reanudación de conexiones 0‑RTT compensa estas posibles vulnerabilidades, pero es una decisión que debes tomar por tu cuenta.
Esta función está deshabilitada de forma predeterminada en NGINX. Para habilitarla, establezca la directiva ssl_early_data en on.
Migración de HTTP/1.1 a HTTP/3 mediante la cabecera Alt-Svc Header
Casi todos los clientes (en particular, los navegadores) establecen las conexiones iniciales mediante TCP/TLS. Si un servidor admite QUIC+HTTP/3, se lo indica al cliente devolviendo una respuesta HTTP/1.1 que incluye el parámetro h3 en la cabecera Alt-Svc. A continuación, el cliente decide si utilizar QUIC+HTTP/3 o seguir con una versión anterior de HTTP. (Como dato de interés, la cabecera Alt-Svc, definida en RFC 7838, es anterior a QUIC y también puede utilizarse para otros fines).

Alt-Svc para convertir una conexión de HTTP/1.1 a HTTP/3La cabecera «Alt-Svc» indica al cliente que el mismo servicio está disponible en un host, protocolo o puerto alternativo (o en una combinación de estos). Además, se puede informar a los clientes de durante cuánto tiempo pueden dar por hecho que este servicio seguirá estando disponible.
Algunos ejemplos:
Alt-Svc: h3=":443" HTTP/3 está disponible en este servidor en el puerto 443Alt-Svc: h3="new.example.com:8443" HTTP/3 está disponible en el servidor new.example.com en el puerto 8443Alt-Svc: h3=":8443"; ma=600 HTTP/3 está disponible en este servidor en el puerto 8443 y seguirá estándolo durante al menos 10 minutos
Aunque no es obligatorio, en la mayoría de los casos los servidores están configurados para responder a las conexiones QUIC en el mismo puerto que TCP+TLS.
Para configurar NGINX para que incluya la cabecera Alt-Svc, utilice la directiva add_header. En este ejemplo, la variable $server_port indica que NGINX acepta conexiones QUIC en el puerto al que el cliente envió su solicitud TCP+TLS, y 86 400 equivale a 24 horas:
add_header Alt-Svc 'h3=":$server_port"; ma=86400';Conclusión
Este blog ofrece una introducción simplificada a QUIC y esperamos que proporcione una visión general suficiente para comprender las principales operaciones de red y cifrado utilizadas con QUIC.
Para obtener información más completa sobre cómo configurar NGINX para QUIC + HTTP/3, lea Ya están disponibles los paquetes binarios de la versión preliminar de la implementación de QUIC+HTTP/3 en NGINX en nuestro blog o vea nuestro seminario web, Pruebe NGINX y QUIC+HTTP/3 de forma práctica. Para obtener información detallada sobre todas las directivas de NGINX para QUIC+HTTP/3 e instrucciones completas para instalar archivos binarios precompilados o compilar desde el código fuente, consulte la página web de NGINX QUIC.
Sobre el autor

Artículos relacionados del blog
Únete a F5 NGINX en AppWorld 2024
Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.
Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.
Exposición de APIs en Kubernetes
La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».
NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.
Presentamos NGINX Plus R22
NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.
Presentamos NGINX Plus R17
NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.