BLOG | NGINX

A Primer on QUIC Networking and Encryption in NGINX (Introducción a las redes QUIC y al cifrado en NGINX)

NGINX - Parte de F5 - horizontal, negro, tipo RGB
Robert Haynes Miniatura
Robert Haynes
Publicado el 19 de abril de 2023

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.

¿Por qué debería importarle la red y el cifrado en QUIC?

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.

TCP frente a UDP

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:

  • El procesamiento de QUIC se realiza en el espacio de usuario de Linux, donde los problemas con una operación particular representan menos riesgo para el sistema en general. Esto hace que sea más factible el desarrollo rápido de nuevas funciones.
  • Los “middleboxes” mencionados anteriormente generalmente realizan un procesamiento mínimo del tráfico UDP y, por lo tanto, no limitan las mejoras al protocolo QUIC.

Una anatomía simplificada de la red QUIC

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.

Figura 1. Anatomía de un flujo QUIC

Empezando desde fuera hacia dentro, las capas y objetos lógicos son:

  • Datagrama UDP : contiene un encabezado que especifica los puertos de origen y destino (junto con datos de longitud y suma de comprobación), seguido de uno o más 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 un encabezado QUIC y uno o más marcos QUIC.
  • Encabezado QUIC : contiene metadatos sobre el paquete. Hay dos tipos de encabezado:

    • El encabezado largo, utilizado durante el establecimiento de la conexión.
    • El encabezado corto, utilizado 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 rastrear qué claves se utilizaron para cifrar el paquete, en apoyo de la rotación de claves). Los números de paquete son únicos (y siempre aumentan) para una conexión y una fase de clave concretas.
  • Marco : contiene el tipo, el ID de la transmisión, el desplazamiento y los datos de la transmisión. Los datos de transmisión se distribuyen en varios cuadros, pero se pueden ensamblar utilizando el ID de conexión, el ID de transmisión y el desplazamiento, que se utiliza para presentar los fragmentos de datos en el orden correcto.
  • Flujo : un flujo de datos unidireccional o bidireccional dentro de una única conexión QUIC. Cada conexión QUIC admite múltiples flujos independientes, cada uno con su propio ID de flujo. Si se pierde un paquete QUIC que contiene varios flujos, esto no afecta el progreso de los flujos no incluidos en el paquete faltante (esto es fundamental para evitar el bloqueo de cabecera de línea que experimenta HTTP/2). Las transmisiones pueden ser bidireccionales y creadas por cualquiera de los puntos finales.

Establecimiento de conexión

El conocido protocolo de enlace de tres vías SYN / SYN-ACK / ACK establece una conexión TCP:

Diagrama que muestra los tres mensajes intercambiados entre el cliente y el servidor en el protocolo de enlace para establecer una conexión TCP
Figura 2. El protocolo de enlace de tres vías que 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.

Diagrama que muestra el protocolo de enlace para establecer una conexión QUIC, sin y con un paquete de repetición
Figura 3. Configuración de la conexión QUIC, con y sin paquete de reintento

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 .

Detección de pérdidas

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.

  • Tanto el cliente como el servidor envían un reconocimiento explícito para cada paquete QUIC que reciben (aunque los paquetes que contienen solo marcos de baja prioridad no se reconocen inmediatamente).
  • 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.

  • Cuando un paquete se considera perdido, los marcos faltantes 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 sólo determina el orden de envío, no cómo deben ensamblarse los paquetes.
  • Dado que el ensamblaje de datos en el receptor es independiente del orden de transmisión, un paquete perdido o retrasado afecta solo a los flujos individuales que contiene, no a todos los flujos de la conexión. Esto elimina el problema de bloqueo de cabecera de línea que afecta a HTTP/ 1.x y HTTP/2 porque los flujos no son parte de la capa de transporte.

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.

Gestión elegante de los cambios de 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 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 .

Cifrado

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.

Figura 4. Comparación de los protocolos de enlace de cifrado para TCP+TLS/1.3 y QUIC

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.

Figura 5. QUIC cifra metadatos más sensibles 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.

Las conexiones de RTT bajo y cero reducen la latencia

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.

Figura 6. Comparación de los mensajes necesarios para restablecer una conexión con TCP+TLS versus QUIC

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 .

Pasar de HTTP/1.1 a HTTP/3 con el encabezado 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).

Figura 7. Cómo se utiliza el encabezado Alt-Svc para convertir una conexión de HTTP/1.1 a HTTP/3

El 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';

CONCLUSIÓN

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.