Hacia QUIC: lo que subyace a HTTP / 3

Un nuevo hito en la historia de Internet comienza ante nuestros propios ojos: podemos suponer que HTTP / 3 ya ha sido anunciado. A finales de octubre, Mark Nottingham del IETF sugirió que ya se decidiera un nombre para el nuevo protocolo sobre el cual el IETF ha estado construyendo desde 2015. Entonces, en lugar de nombres similares a QUIC, apareció HTTP / 3 ruidoso. Las publicaciones occidentales ya han escrito sobre esto y más de una vez . La historia de QUIC comenzó en las entrañas de Good Corporation en 2012, desde entonces solo los servidores de Google admitían conexiones HTTP sobre QUIC, pero el tiempo pasa y Facebook ya comenzó a implementar esta tecnología (7 de noviembre, Facebook y LiteSpeed hicieron la primera interacción a través de HTTP / 3 ); Actualmente, la proporción de sitios que admiten QUIC es del 1,2%. Finalmente, el grupo de trabajo de WebRTC también está mirando hacia QUIC (además de ver la API de QUIC ), por lo que en el futuro previsible, el video / audio en tiempo real pasará a través de QUIC en lugar de RTP / RTCP. Por lo tanto, decidimos que sería genial revelar los detalles del IETF QUIC: especialmente para Habr, preparamos una traducción del hilo largo punteando i. ¡A disfrutar!

QUIC (Quick UDP Internet Connections) es un nuevo protocolo de capa de transporte predeterminado cifrado que tiene muchas mejoras HTTP: tanto para acelerar el tráfico como para aumentar la seguridad. QUIC también tiene un objetivo a largo plazo: eventualmente reemplazar TCP y TLS. En este artículo, analizaremos los chips QUIC clave y por qué la web se beneficiará de ellos, así como los problemas de soportar este protocolo completamente nuevo.

De hecho, hay dos protocolos con el mismo nombre: Google QUIC (gQUIC), el protocolo original desarrollado por ingenieros de Google hace varios años, que, después de una serie de experimentos, fue adoptado por el Grupo de trabajo de ingeniería de Internet (IETF) para estandarizar.

IETF QUIC (en adelante, simplemente QUIC) ya tiene diferencias tan fuertes con gQUIC que puede considerarse un protocolo separado. Desde el formato del paquete hasta el protocolo de enlace y el mapeo HTTP, QUIC ha mejorado la arquitectura original de gQUIC al colaborar con muchas organizaciones y desarrolladores que tienen un objetivo común: hacer que Internet sea más rápido y seguro.

Entonces, ¿qué mejoras ofrece QUIC?

Seguridad integrada (y rendimiento)


Una de las diferencias más notables entre QUIC y TCP venerable es el objetivo originalmente establecido de ser un protocolo de transporte seguro de forma predeterminada . QUIC logra esto mediante el uso de autenticación y cifrado, que generalmente ocurre en un nivel superior (por ejemplo, en TLS), y no en el protocolo de transporte en sí.

El protocolo de enlace QUIC original combina la comunicación tripartita habitual a través de TCP con el protocolo de enlace TLS 1.3, que proporciona autenticación de los participantes, así como la coordinación de los parámetros criptográficos. Para aquellos que están familiarizados con TLS: QUIC reemplaza el nivel de grabación TLS con su propio formato de trama, pero al mismo tiempo usa apretones de manos TLS.

Esto no solo permite que la conexión esté siempre encriptada y autenticada, sino que también es más rápida para realizar la conexión inicial: un apretón de manos QUIC normal hace el intercambio entre el cliente y el servidor en una pasada, mientras que TCP + TLS 1.3 realiza dos pasadas.


Sin embargo, QUIC va más allá y también cifra los metadatos de conexión que pueden ser fácilmente comprometidos por un tercero. Por ejemplo, los atacantes pueden usar números de paquetes para dirigir a los usuarios a través de múltiples rutas de red cuando se usa la migración de conexión (ver más abajo). QUIC cifra los números de paquete, por lo que no pueden ser corregidos por nadie más que los verdaderos participantes en la conexión.

El cifrado también puede ser efectivo contra el "estancamiento", un fenómeno que no permite que la flexibilidad del protocolo se use en la práctica debido a suposiciones incorrectas en las implementaciones (osificación: esta es la razón por la que TLS 1.3 presentó durante mucho tiempo . Lo publicamos solo después de algunos cambios que evitar bloqueos no deseados para nuevas revisiones de TLS).

Bloquear el comienzo de la cola (bloqueo de encabezado de línea)


Una de las principales mejoras que nos trajo HTTP / 2 es la capacidad de combinar diferentes solicitudes HTTP en una conexión TCP. Esto permite que las aplicaciones HTTP / 2 procesen solicitudes en paralelo y hagan un mejor uso del canal de red.

Por supuesto, este fue un importante paso adelante. Porque las aplicaciones anteriores necesitaban iniciar muchas conexiones TCP + TLS si querían procesar varias solicitudes HTTP al mismo tiempo (por ejemplo, cuando el navegador necesita recibir CSS y JavaScript para representar la página). Crear nuevas conexiones requiere múltiples apretones de manos, así como inicializar la ventana de sobrecarga: esto significa ralentizar el procesamiento de la página. Las solicitudes HTTP combinadas evitan esto.



Sin embargo, existe un inconveniente: dado que se transmiten múltiples solicitudes / respuestas a través de la misma conexión TCP, todas dependen igualmente de la pérdida de paquetes, incluso si los datos perdidos se refieren solo a una de las solicitudes. Esto se llama "bloquear el comienzo de la cola".

QUIC va más allá y proporciona soporte de primera clase para combinar solicitudes, por ejemplo, diferentes solicitudes HTTP pueden considerarse diferentes solicitudes de transporte QUIC, pero al mismo tiempo todas usarán la misma conexión QUIC, es decir, no se necesitan apretones de manos adicionales, hay uno estado de congestión, las solicitudes QUIC se entregan de forma independiente; como resultado, en la mayoría de los casos, la pérdida de paquetes afecta solo a una solicitud.

Por lo tanto, es posible reducir significativamente el tiempo para, por ejemplo, la representación completa de una página web (CSS, JavaScript, imágenes y otros recursos), especialmente en el caso de una red sobrecargada con alta pérdida de paquetes.

Tan simple, ¿eh?


Para cumplir su promesa, el protocolo QUIC debe superar algunos de los supuestos que muchas aplicaciones de red han dado por sentado. Esto puede complicar la implementación y la implementación de QUIC.

QUIC está diseñado para ser entregado a través de datagramas UDP para facilitar el desarrollo y evitar problemas con los dispositivos de red que descartan paquetes de protocolos desconocidos (porque la mayoría de los dispositivos son compatibles con UDP). También permite que QUIC viva en el espacio del usuario, por lo que, por ejemplo, los navegadores podrán implementar nuevas funciones de protocolo y transmitirlas a los usuarios finales, sin esperar las actualizaciones del sistema operativo.

Sin embargo, el buen objetivo de reducir los problemas de red hace que sea más difícil proteger los paquetes y enrutarlos adecuadamente.

Un NAT para reunir a todos juntos y unirse con una sola voluntad negra


Por lo general, los enrutadores NAT funcionan con conexiones TCP utilizando una tupla de 4 valores (IP de origen y puerto más IP y puerto de destino), además de monitorear los paquetes TCP SYN, ACK y FIN transmitidos por la red; los enrutadores pueden determinar cuándo se establece una nueva conexión y cuándo finaliza. Por lo tanto, es posible una gestión precisa de los enlaces NAT (comunicaciones entre IP y puertos internos y externos).

En el caso de QUIC, esto aún no es posible, porque Los enrutadores NAT modernos aún no conocen QUIC, por lo que generalmente degradan al procesamiento UDP predeterminado y menos preciso, lo que significa tiempos de espera de duración arbitraria (a veces corta) , que pueden afectar las conexiones a largo plazo.

Cuando se produce un nuevo enlace (por ejemplo, debido a un tiempo de espera), el dispositivo fuera del perímetro NAT comienza a recibir paquetes de otra fuente, lo que hace que sea imposible mantener la conexión utilizando solo una tupla de 4 valores.


¡Y no es solo NAT! Una característica QUIC se llama migración de conexión y permite a los dispositivos transferir conexiones a otras direcciones / rutas IP a su discreción. Por ejemplo, un cliente móvil podrá transferir una conexión QUIC de una red móvil a una red WiFi ya conocida (el usuario ha ingresado a una cafetería favorita, etc.).

QUIC intenta resolver este problema con el concepto de ID de conexión: una información de longitud arbitraria, transmitida en paquetes QUIC y que permite identificar la conexión. Los dispositivos de punto final pueden usar esta ID para rastrear sus conexiones sin reconciliarse con la tupla. En la práctica, debe haber muchas ID que indiquen la misma conexión, por ejemplo, para evitar conectar diferentes rutas cuando se migra la conexión, porque todo el proceso está controlado solo por los dispositivos finales, no por los middleboxes.

Sin embargo, puede haber un problema para los operadores de telecomunicaciones que usan enrutamiento anycast y ECMP, donde una IP puede identificar cientos o miles de servidores. Dado que los enrutadores fronterizos en estas redes aún no saben cómo procesar el tráfico QUIC, puede ocurrir que los paquetes UDP de la misma conexión QUIC, pero con diferentes tuplas, se envíen a diferentes servidores, lo que significa desconexión.



Para evitar esto, los operadores pueden necesitar implementar un equilibrador de nivel más inteligente. Esto se puede lograr mediante programación sin afectar a los enrutadores fronterizos (por ejemplo, vea el proyecto Katran de Facebook).

Qpack


Otra característica útil de HTTP / 2 fue la compresión de encabezado (HPACK) , que permite a los dispositivos finales reducir el tamaño de los datos que se envían al descartar solicitudes y respuestas innecesarias.

En particular, entre otras técnicas, HPACK utiliza tablas dinámicas con encabezados que ya se han enviado / recibido de solicitudes / respuestas HTTP anteriores, lo que permite que los dispositivos remitan nuevas solicitudes / respuestas a encabezados encontrados anteriormente (en lugar de enviarlos nuevamente) .

Las tablas HPACK deben sincronizarse entre el codificador (la parte que envía la solicitud / respuesta) y el decodificador (el lado receptor), de lo contrario, el decodificador simplemente no puede decodificar lo que recibe.

En el caso de HTTP / 2 sobre TCP, esta sincronización es transparente porque la capa de transporte (TCP) entrega solicitudes / respuestas en el mismo orden en que fueron enviadas. Es decir, puede enviar instrucciones al decodificador para actualizar las tablas en una simple solicitud / respuesta. Pero con QUIC, las cosas son mucho más complicadas.

QUIC puede entregar múltiples solicitudes / respuestas HTTP en diferentes direcciones al mismo tiempo, lo que significa que QUIC garantiza el pedido de entrega en una dirección, mientras que no existe tal garantía en el caso de múltiples direcciones.

Por ejemplo, si un cliente envía una solicitud HTTP A en la secuencia A de QUIC, así como una solicitud B en la secuencia B, entonces, debido a la permutación de paquetes o pérdidas de red, el servidor recibirá la solicitud B antes de la solicitud A. Y si la solicitud B se codificó como se indicó en el encabezado de la solicitud A, entonces el servidor simplemente no podrá decodificar la solicitud B, ya que aún no ha visto la solicitud A.

El protocolo gQUIC resolvió este problema simplemente haciendo que todos los encabezados (pero no los cuerpos) de las solicitudes / respuestas HTTP fueran secuenciales dentro de una sola secuencia gQUIC. Esto aseguró que todos los encabezados vengan en el orden correcto, pase lo que pase. Este es un esquema muy simple, con su ayuda, las soluciones existentes pueden continuar usando código que se afina bajo HTTP / 2; Por otro lado, esto aumenta la probabilidad de bloquear el comienzo de la cola, que QUIC está diseñado para reducir. Por lo tanto, el grupo de trabajo IETF QUIC desarrolló una nueva asignación entre HTTP y QUIC (HTTP / QUIC), así como un nuevo principio de compresión de encabezado, QPACK.

En el borrador final de las especificaciones HTTP / QUIC y QPACK, cada intercambio de solicitud / respuesta HTTP utiliza su propio flujo QUIC bidireccional, por lo que no se produce el bloqueo del inicio de la cola. Además, para admitir QPACK, cada participante crea dos secuencias QUIC unidireccionales adicionales, una para enviar actualizaciones de la tabla y la otra para confirmar su recepción. Por lo tanto, el codificador QPACK puede usar el enlace a la tabla dinámica solo después de que el decodificador haya confirmado su recepción.

Reflejo refractor


Un problema común con los protocolos basados ​​en UDP es su susceptibilidad a los ataques de reflexión, cuando el atacante obliga a un servidor a enviar una gran cantidad de datos a la víctima. El atacante falsifica su IP para que el servidor piense que la solicitud de datos proviene de la dirección de la víctima.


Este tipo de ataque puede ser muy efectivo cuando la respuesta del servidor es incomparablemente mayor que la solicitud. En este caso, hablan de "ganancia".

El TCP generalmente no se usa para tales ataques, porque los paquetes en el protocolo de enlace original (SYN, SYN + ACK, ...) tienen la misma longitud, por lo que no tienen potencial de "amplificación".

Por otro lado, el protocolo de enlace QUIC es muy asimétrico: como en TLS, primero el servidor QUIC envía su cadena de certificados, que puede ser bastante grande, a pesar de que el cliente debe enviar solo unos pocos bytes (un mensaje del cliente ClientHello TLS está integrado en el paquete QUIC ) Por esta razón, el paquete QUIC original debe aumentarse a una cierta longitud mínima, incluso si el contenido del paquete es mucho más pequeño. Sea como fuere, esta medida aún no es muy efectiva, ya que una respuesta típica del servidor contiene varios paquetes y, por lo tanto, puede ser más que un paquete de cliente ampliado.

El protocolo QUIC también define un mecanismo de verificación de origen explícito: el servidor, en lugar de dar una respuesta grande, envía solo un paquete de reintento con un token único, que el cliente luego envía al servidor en un nuevo paquete. Por lo tanto, el servidor tiene más confianza en que el cliente no tiene una dirección IP sustituta y puede finalizar el apretón de manos. Menos de la decisión: el tiempo del apretón de manos aumenta, en lugar de una pasada, ya se requieren dos.

Una solución alternativa es reducir la respuesta del servidor a un tamaño en el que el ataque de reflexión se vuelve menos efectivo, por ejemplo, utilizando certificados ECDSA (generalmente son mucho más pequeños que RSA). También experimentamos con un mecanismo de compresión de certificados TLS utilizando algoritmos de compresión estándar como zlib y brotli; Esta es una característica que apareció por primera vez en gQUIC pero actualmente no es compatible con TLS.

Rendimiento UDP


Uno de los problemas constantes de QUIC es el hardware y software existentes que no pueden funcionar con QUIC. Ya hemos examinado cómo QUIC intenta lidiar con los middleboxes de red como enrutadores, pero otra área potencialmente problemática es el rendimiento de enviar / recibir datos entre dispositivos QUIC a través de UDP. Durante muchos años, se han realizado esfuerzos para optimizar las implementaciones de TCP tanto como sea posible, incluidas las capacidades de descarga integradas en software (por ejemplo, sistemas operativos) y en hardware (interfaces de red), pero nada de esto concierne a UDP.

Sin embargo, es solo cuestión de tiempo antes de que las implementaciones de QUIC superen estas mejoras y beneficios. Eche un vistazo a los esfuerzos recientes para implementar la descarga UDP en Linux , lo que permitiría que las aplicaciones combinen y transmitan múltiples segmentos UDP entre la pila de la red del espacio del usuario y el espacio del núcleo a un costo de aproximadamente un segmento; otro ejemplo es el soporte de zerocopy para sockets en Linux , gracias al cual las aplicaciones podrían evitar el costo de copiar la memoria del espacio del usuario en el espacio del kernel.

Conclusión


Al igual que HTTP / 2 y TLS 1.3, el protocolo QUIC debería aportar un montón de nuevas características que mejorarán el rendimiento y la seguridad de los sitios web y otros participantes en la infraestructura de Internet. El grupo de trabajo de IETF tiene la intención de implementar la primera versión de las especificaciones de QUIC para fin de año, por lo que es hora de pensar en cómo podemos aprovechar al máximo los beneficios de QUIC.

Source: https://habr.com/ru/post/es430436/


All Articles