La primera mención de QUIC y HTTP/3 en el blog de NGINX fue hace cuatro años (!), y al igual que usted, ahora estamos esperando ansiosamente la inminente fusión de nuestra implementación de QUIC en la rama principal de código abierto de NGINX. Dada la larga gestación, es comprensible que no hayas pensado mucho en ello.
En este punto, sin embargo, como desarrollador o administrador del sitio debes tener en cuenta cómo QUIC transfiere la responsabilidad de algunos detalles de red del sistema operativo a NGINX (y todas las aplicaciones HTTP). Incluso si la creación de redes no es lo tuyo, adoptar QUIC significa que preocuparte por la red ahora es (al menos un poco) parte de tu trabajo.
En esta publicación, profundizamos en conceptos clave de redes y cifrado utilizados en QUIC, simplificando algunos detalles y omitiendo información no esencial en busca de claridad. Aunque es posible que se pierdan algunos matices en el proceso, nuestra intención es brindarle suficiente información para que pueda adoptar QUIC de manera efectiva en su entorno, o al menos una base sobre la cual construir su conocimiento.
Si QUIC es totalmente nuevo para usted, le recomendamos que primero lea una de nuestras publicaciones anteriores y vea nuestro video de descripción general.
Para una explicación más detallada y completa de QUIC, recomendamos el excelente documento Manageability of the QUIC Transport Protocol del grupo de trabajo IETC QUIC, junto con los materiales adicionales vinculados a lo largo de este documento.
Los detalles sucios de la conexión de red entre los clientes y NGINX no han sido particularmente relevantes para la mayoría de los usuarios hasta ahora. Después de todo, con HTTP/ 1.x y HTTP/2, el sistema operativo se encarga de establecer la conexión TCP entre los clientes y NGINX. NGINX simplemente utiliza la conexión una vez establecida.
Sin embargo, con QUIC, la responsabilidad de la creación, validación y gestión de conexiones se traslada del sistema operativo subyacente a NGINX. En lugar de recibir una conexión TCP establecida, NGINX ahora recibe un flujo de datagramas del Protocolo de Datagramas de Usuario (UDP), que debe analizar para obtener conexiones y flujos de cliente. NGINX ahora también es responsable de gestionar la pérdida de paquetes, los reinicios de conexión 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 maneja de una manera bastante similar para QUIC+HTTP/3 y TCP+HTTP/1+2, hay diferencias que podrían ser significativas para dispositivos posteriores como balanceadores de carga de capa 4, firewalls y dispositivos de seguridad.
En última instancia, el efecto general de estos cambios es una experiencia más segura, más rápida y más confiable para los usuarios, con muy pocos cambios en la configuración o las operaciones de NGINX. Sin embargo, los administradores de NGINX necesitan entender al menos un poco de lo que está pasando con QUIC y NGINX, aunque solo sea para mantener su tiempo medio de inocencia lo más breve posible en caso de que surjan problemas.
(Vale la pena señalar que si bien esta publicación se centra en las operaciones HTTP porque HTTP/3 requiere QUIC, QUIC también se puede utilizar para otros protocolos. Un buen ejemplo es DNS sobre QUIC, tal como se define en RFC 9250 , DNS sobre conexiones QUIC dedicadas .)
Ahora que ya hemos dejado esa introducción hecha, profundicemos en algunos aspectos específicos de la red QUIC.
QUIC introduce un cambio significativo en el protocolo de red subyacente utilizado para transmitir datos de aplicação HTTP entre un cliente y un servidor.
Como se mencionó, TCP siempre ha sido el protocolo para transmitir datos de aplicação web HTTP. TCP está diseñado para entregar datos de manera confiable a través de una red IP. Tiene un mecanismo bien definido y comprendido para establecer conexiones y reconocer la recepción de datos, junto con una variedad de algoritmos y técnicas para gestionar la pérdida de paquetes y el retraso que son comunes en redes poco confiables y congestionadas.
Si bien TCP proporciona un transporte confiable, existen desventajas 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 sido difícil mejorar o ampliar TCP frente a los patrones cambiantes del tráfico HTTP; debido a que el procesamiento de TCP se realiza en el kernel de Linux, cualquier cambio debe diseñarse y probarse cuidadosamente para evitar efectos imprevistos en el rendimiento y la estabilidad general del sistema.
Otro problema es que en muchos escenarios, el tráfico HTTP entre el cliente y el servidor pasa a través de múltiples dispositivos de procesamiento TCP, como firewalls o balanceadores de carga (conocidos colectivamente como “middleboxes”), que pueden tardar en implementar cambios en los estándares TCP.
QUIC en cambio utiliza UDP como protocolo de transporte. UDP está diseñado para transmitir datos a través de una red IP como TCP, pero elimina intencionalmente el establecimiento de la conexión y la entrega confiable. Esta falta de sobrecarga hace que UDP sea adecuado para muchas aplicações donde la eficiencia y la velocidad son más importantes que la confiabilidad.
Sin embargo, para la mayoría de las aplicações web, la entrega confiable de datos es esencial. Dado que la capa de transporte UDP subyacente no proporciona una entrega de datos confiable, estas funciones deben ser proporcionadas por QUIC (o la aplicação misma). Afortunadamente, QUIC tiene un par de ventajas sobre TCP en este sentido:
Los flujos QUIC son objetos lógicos que contienen solicitudes o respuestas HTTP/3 (o cualquier otro dato de aplicação ). Para la transmisión entre puntos finales de la red, se envuelven dentro de múltiples capas lógicas como se muestra en el diagrama.
Empezando desde fuera hacia dentro, las capas y objetos lógicos son:
Encabezado QUIC : contiene metadatos sobre el paquete. Hay dos tipos de encabezado:
El conocido protocolo de enlace de tres vías SYN
/ SYN-ACK
/ ACK
establece una conexión TCP:
Establecer una conexión QUIC implica pasos similares, pero es más eficiente. También incorpora la validación de direcciones en la configuración de la conexión como parte del protocolo de enlace criptográfico. La validación de direcciones defiende contra ataques de amplificación de tráfico, en los que un actor malicioso envía al servidor un paquete con información de dirección de origen falsificada para la víctima del ataque previsto. El atacante espera que el servidor genere más paquetes o paquetes más grandes para la víctima de los que el atacante puede generar por sí solo, lo que genera una cantidad abrumadora de tráfico. (Para más detalles, consulte la Sección 8 del RFC 9000, QUIC: Un 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 están codificados en el encabezado QUIC, lo que proporciona una identificación simple de la conexión, independientemente de la dirección IP de origen del cliente.
Sin embargo, como el establecimiento inicial de una conexión QUIC también incluye operaciones de intercambio de claves de cifrado TLS, es computacionalmente más costoso para el servidor que la simple respuesta SYN-ACK
que genera durante el establecimiento de una conexión TCP. También crea un vector potencial para ataques distribuidos de denegación de servicio (DDoS) , porque la dirección IP del cliente no se valida antes de que se realicen las operaciones de intercambio de claves.
Pero puede configurar NGINX para validar la dirección IP del cliente antes de que comiencen operaciones criptográficas complejas, estableciendo 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 configuración de conexión.
Este mecanismo es similar al protocolo de enlace TCP de tres vías y, fundamentalmente, establece que el cliente es el propietario de la dirección IP de origen que está presentando. Sin esta verificación, los servidores QUIC como NGINX podrían ser vulnerables a ataques DoS fáciles con direcciones IP de origen falsificadas. (Otro mecanismo de QUIC que mitiga tales ataques es el requisito de que todos los paquetes de conexión iniciales deben tener un mínimo de 1200 bytes, lo que hace que enviarlos sea una operación más costosa).
Además, los paquetes de reintento mitigan un ataque similar al ataque de inundación TCP SYN
(donde los recursos del servidor se agotan por una enorme cantidad de protocolos de enlace abiertos pero no completados almacenados en la memoria), al codificar los detalles de la conexión en el ID de conexión que envía al cliente; esto tiene el beneficio adicional de que no es necesario retener información del lado del servidor, ya que la información de la conexión se puede reconstituir a partir del ID de conexión y el token que posteriormente presenta el cliente. Esta técnica es análoga a las cookies TCP SYN
. Además, los servidores QUIC como NGINX pueden proporcionar un token que caduca para ser utilizado en futuras conexiones del cliente, para acelerar 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 necesariamente provoquen la interrupción de las conexiones. Esto se analiza en Cómo gestionar con elegancia los cambios de dirección IP del cliente .
Con una conexión establecida (y el cifrado habilitado, como se explica más adelante ), las solicitudes y respuestas HTTP pueden fluir entre el cliente y NGINX. Se envían y reciben datagramas UDP. Sin embargo, hay muchos factores que podrían provocar que algunos de estos datagramas se pierdan o se retrasen.
TCP tiene mecanismos complejos para reconocer la entrega de paquetes, detectar la pérdida o el retraso de paquetes y gestionar la retransmisión de paquetes perdidos, entregando datos completos y secuenciados adecuadamente a la capa de aplicação . UDP carece de esta facilidad y, por lo tanto, el control de congestión y la detección de pérdidas se implementan en la capa QUIC.
Cuando un paquete que contiene tramas que requieren una entrega confiable no ha sido reconocido luego de un período de tiempo establecido, se considera perdido.
Los períodos de tiempo de espera varían según el contenido del paquete; por ejemplo, el tiempo de espera es más corto para los paquetes que se necesitan para establecer el cifrado y configurar la conexión, porque son esenciales para el rendimiento del protocolo de enlace QUIC.
Una descripción completa de la detección de pérdidas está más allá del alcance de este manual. Consulte RFC 9002 , Detección de pérdida y control de congestión QUIC , para obtener detalles sobre los mecanismos para determinar los tiempos de espera y la cantidad de datos no reconocidos que se permite que estén en tránsito.
La dirección IP de un cliente (denominada dirección IP de origen en el contexto de una sesión de aplicação ) está sujeta a cambios durante la sesión, por ejemplo, cuando una VPN o puerta de enlace cambia su dirección pública o un usuario de teléfono inteligente abandona una ubicación cubierta por WiFi, lo que obliga a cambiar a una red celular. Además, los administradores de red tradicionalmente han establecido tiempos de espera más bajos para el tráfico UDP que para las conexiones TCP, lo que genera una mayor probabilidad de 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 manera proactiva al servidor que su dirección va a cambiar, y los servidores pueden manejar con elegancia un cambio no planificado en la dirección del cliente. Dado que el ID de conexión permanece constante durante la transición, los marcos no reconocidos se pueden retransmitir a la nueva dirección IP.
Los cambios en la dirección IP de origen durante las sesiones QUIC pueden representar un problema para los balanceadores de carga descendentes (u otros componentes de red de capa 4) que usan la dirección IP de origen y el puerto para determinar qué servidor ascendente recibirá un datagrama UDP particular. Para garantizar una gestión correcta del tráfico, los proveedores de dispositivos de red de capa 4 deberán actualizarlos para manejar los identificadores de conexión QUIC. Para obtener más información sobre el futuro del equilibrio de carga y QUIC, consulte el borrador QUIC-LB del IETF: Generación de identificadores de conexión QUIC enrutables .
En Establecimiento de conexión , hicimos alusión al hecho de que el protocolo de enlace QUIC inicial hace más que simplemente establecer una conexión. A diferencia del protocolo de enlace TLS para TCP, con UDP el intercambio de claves y parámetros de cifrado TLS 1.3 ocurre como parte de la conexión inicial. Esta función 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 porción mayor de los metadatos que TCP+TLS. Incluso antes de que se produzca el intercambio de claves, los paquetes de conexión iniciales están cifrados; aunque un espía todavía puede obtener las claves, requiere más esfuerzo que con paquetes no cifrados. Esto protege mejor datos como el Indicador de nombre de servidor (SNI), que es relevante tanto para los atacantes como para los potenciales censores a nivel estatal. La figura 5 ilustra cómo QUIC cifra metadatos potencialmente más sensibles (en rojo) que TCP+TLS.
Todos los datos de la carga útil QUIC están encriptados mediante TLS 1.3. Hay dos ventajas: no se permiten conjuntos de cifrados y algoritmos hash más antiguos y vulnerables y los mecanismos de intercambio de claves de secreto directo (FS) son obligatorios. El secreto hacia adelante impide que un atacante descifre los datos incluso si captura la clave privada y una copia del tráfico.
Reducir la cantidad de viajes de ida y vuelta que deben ocurrir entre un cliente y un servidor antes de que se puedan transmitir datos de la aplicação mejora el rendimiento de las aplicações, particularmente en redes con mayor latencia.
TLS 1.3 introdujo un único viaje de ida y vuelta para establecer una conexión cifrada y cero viajes de ida y vuelta para reanudar una conexión, pero con TCP esto significa que el protocolo de enlace debe ocurrir antes del saludo del cliente TLS.
Debido a que QUIC combina operaciones criptográficas con la configuración de la conexión, proporciona un verdadero restablecimiento de la conexión 0-RTT, donde un cliente puede enviar una solicitud en el primer paquete QUIC. Esto reduce la latencia al eliminar el viaje de ida y vuelta inicial para el establecimiento de 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 y, para fines de validación de dirección, incluye un token suministrado por el servidor durante la conexión anterior.
Lamentablemente, la reanudación de la conexión 0-RTT no proporciona confidencialidad hacia adelante, por lo que la solicitud inicial del cliente no está cifrada de forma tan segura como el resto del tráfico en el intercambio. Las solicitudes y respuestas posteriores a la primera solicitud están protegidas por el secreto de reenvío. Posiblemente lo más problemático es que la solicitud inicial también es vulnerable a ataques de repetición , donde un atacante puede capturar la solicitud inicial y reproducirla en el servidor varias veces.
Para muchas aplicações y sitios web, la mejora del rendimiento derivada de la reanudación de la conexión 0-RTT supera estas posibles vulnerabilidades, pero es una decisión que debe tomar usted mismo.
Esta función está deshabilitada por defecto en NGINX. Para habilitarla, configure la directiva ssl_early_data
como activada
.
Alt-Svc
Casi todos los clientes (en particular los navegadores) realizan conexiones iniciales a través de TCP/TLS. Si un servidor admite QUIC+HTTP/3, lo señala al cliente devolviendo una respuesta HTTP/1.1 que incluye el parámetro h3
en el encabezado Alt-Svc
. A continuación, el cliente elige si desea utilizar QUIC+HTTP/3 o seguir con una versión anterior de HTTP. (Cabe destacar que el encabezado Alt-Svc
, definido en RFC 7838 , es anterior a QUIC y puede usarse también para otros fines).
Alt-Svc
para convertir una conexión de HTTP/1.1 a HTTP/3El encabezado Alt-Svc
le dice a un cliente que el mismo servicio está disponible en un host, protocolo o puerto alternativo (o una combinación de ellos). Además, se puede informar a los clientes durante cuánto tiempo es seguro asumir que este servicio seguirá estando disponible.
Algunos ejemplos:
Servicio alternativo: h3=":443" |
HTTP/3 está disponible en este servidor en el puerto 443 |
Alt-Svc: h3="nuevo.ejemplo.com:8443" |
HTTP/3 está disponible en el servidor new.example.com en el puerto 8443 |
Servicio alternativo: h3=":8443"; ma=600 |
HTTP/3 está disponible en este servidor en el puerto 8443 y estará disponible 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 incluir el encabezado Alt-Svc
, utilice la directiva add_header
. En este ejemplo, la variable $server_port
significa que NGINX acepta conexiones QUIC en el puerto al que el cliente envió su solicitud TCP+TLS, y 86,400 son 24 horas:
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
Este blog ofrece una introducción simplificada a QUIC y, con suerte, le brindará una descripción general suficiente para comprender las operaciones de red y cifrado clave que se utilizan con QUIC.
Para obtener una visión más completa sobre la configuración de NGINX para QUIC + HTTP/3, lea Paquetes binarios ahora disponibles para la vista previa de la implementación de NGINX QUIC+HTTP/3 en nuestro blog o mire nuestro seminario web, Póngase en práctica con NGINX y QUIC+HTTP/3 . Para obtener detalles sobre todas las directivas NGINX para QUIC+HTTP/3 e instrucciones completas para instalar binarios precompilados o compilar desde la fuente, consulte la página web NGINX QUIC .
"Esta publicación de blog puede hacer referencia a productos que ya no están disponibles o que ya no reciben soporte. Para obtener la información más actualizada sobre los productos y soluciones F5 NGINX disponibles, explore nuestra familia de productos NGINX . NGINX ahora es parte de F5. Todos los enlaces anteriores de NGINX.com redirigirán a contenido similar de NGINX en F5.com.