SSU2

Proposal 159
Cerrado
Author eyedeekay, orignal, zlatinb, zzz
Created 2021-09-12
Last Updated 2025-03-05
Target Version 0.9.56

Estado

Plan de implementación:

FeatureTesting (not default)Enabled by default
Local test code2022-02
Joint test code2022-03
Joint test in-net0.9.54 2022-05
Freeze basic protocol0.9.54 2022-05
Basic Session0.9.55 2022-080.9.56 2022-11
Address Validation (Retry)0.9.55 2022-080.9.56 2022-11
Fragmented RI in handshake0.9.55 2022-080.9.56 2022-11
New Token0.9.55 2022-080.9.57 2022-11
Freeze extended protocol0.9.55 2022-08
Relay0.9.55 2022-080.9.56 2022-11
Peer Test0.9.55 2022-080.9.56 2022-11
Enable for random 2%0.9.55 2022-08
Path Validation0.9.55+ dev0.9.56 2022-11
Connection Migration0.9.55+ dev0.9.56 2022-11
Immediate ACK flag0.9.55+ dev0.9.56 2022-11
Key Rotation0.9.57 2023-020.9.58 2023-05
Disable SSU 1 (i2pd)0.9.56 2022-11
Disable SSU 1 (Java I2P)0.9.58 2023-050.9.61 2023-12
La Sesión Básica incluye la fase de handshake y datos. El protocolo extendido incluye relay y peer test.

Resumen

Esta propuesta describe un protocolo de acuerdo de claves autenticado para mejorar la resistencia de SSU a varias formas de identificación automatizada y ataques.

La propuesta está organizada de la siguiente manera: se presentan los objetivos de seguridad, seguidos de una discusión del protocolo básico. A continuación, se proporciona una especificación completa de todos los mensajes del protocolo. Finalmente, se discuten las direcciones de router y la identificación de versión.

Al igual que con otros transportes I2P, SSU2 está definido para el transporte punto a punto (router a router) de mensajes I2NP. No es una tubería de datos de propósito general. Como SSU, también proporciona dos servicios adicionales: Relaying para atravesar NAT, y Peer Testing para la determinación de accesibilidad entrante. También proporciona un tercer servicio, que no está en SSU, para migración de conexiones cuando un peer cambia de IP o puerto.

Motivación

SSU es la única capa de protocolo restante que requiere ElGamal, que es muy lenta. El control de flujo para SSU es complejo y no funciona bien. Partes de SSU son vulnerables a ataques de suplantación de direcciones. El handshake no utiliza Noise.

Objetivos de Diseño

  • Reduce el uso de CPU eliminando ElGamal. Usa X25519 para el DH.

  • Mantener las funciones Peer Test y Relay, y aumentar la seguridad para ellas.

  • Facilitar la implementación al permitir algoritmos de control de flujo estándar.

  • Reducir la latencia de configuración. El tiempo medio de configuración es actualmente de unos 135 ms para NTCP2 y 187 ms para SSU, aunque NTCP2 tiene un viaje de ida y vuelta adicional; reemplazar ElGamal en SSU2 debería reducirlo, pero otros cambios también podrían ayudar.

  • Mantener o aumentar el rendimiento máximo comparado con SSU 1, según se mide en un rango de latencias simuladas y porcentajes de pérdida de paquetes en una testnet.

  • Prevenir ataques de amplificación de tráfico y enrutamiento incorrecto desde direcciones de origen falsificadas mediante “validación de direcciones”.

  • Facilitar la identificación de paquetes, para reducir la dependencia de mecanismos de respaldo y heurísticas que hacen el código excesivamente complejo.

  • Formalizar y mejorar la migración de conexiones cuando la IP o puerto del peer cambia. No migrar conexiones hasta que la validación de dirección esté completa, para prevenir ataques. Algunas implementaciones de SSU 1 usan heurísticas costosas para manejar cambios de puerto debido a reenlace NAT. Ninguna implementación conocida de SSU 1 puede manejar cambios de IP en absoluto.

  • Compatible con SSU 1 y 2 en un solo puerto, detección automática, y publicado como un solo “transport” (es decir, RouterAddress) en la NetDB.

  • Publicar soporte para versión 1 solamente, 2 solamente, o 1+2 en la NetDB en un campo separado, y usar por defecto versión 1 solamente (no vincular el soporte de versión a una versión particular del router)

  • Asegurar que todas las implementaciones (Java/i2pd/Go) puedan añadir soporte para la versión 2 (o no) en sus propios cronogramas

  • Agregar relleno aleatorio a todos los mensajes incluyendo mensajes de handshake y de datos. Todo el relleno debe estar cubierto por el MAC, a diferencia del relleno de fin de paquete en SSU 1. Proporcionar mecanismo de opciones para que ambos lados soliciten relleno mínimo y máximo y/o distribución de relleno. Los detalles específicos de la distribución de relleno dependen de la implementación y pueden o no estar especificados en el protocolo mismo.

  • Ofuscar los encabezados y contenidos de mensajes que no están completamente cifrados lo suficiente para que los equipos DPI y las firmas AV no puedan clasificarlos fácilmente. También asegurar que los mensajes dirigidos a un solo peer o conjunto de peers no tengan un patrón similar de bits.

  • Corregir pérdida de bits en DH debido al formato Java Ticket1112, y acelerar el DH cambiando a X25519.

  • Cambiar a una función de derivación de claves (KDF) real en lugar de usar el resultado DH tal como está

  • Agregar “resistencia a sondeo” (como lo llama Tor); esto incluye resistencia a repetición.

  • Mantener intercambio de claves autenticado bidireccional (2W-AKE). 1W-AKE no es suficiente para nuestra aplicación.

  • Depender de la clave pública estática publicada en el RouterInfo como otra parte de la autenticación.

  • Agregar options/version en el handshake para extensibilidad futura.

  • No añadir significativamente a la CPU requerida para el establecimiento de conexión; si es posible, reducirla significativamente.

  • Eliminar el requisito de relleno a un múltiplo de 16 bytes impuesto por el cifrado AES en SSU 1.

  • Usar ChaCha/Poly1305 estándar para cifrado y MAC, reemplazando el cifrado AES y el MAC HMAC-MD5-128 no estándar usado en SSU 1.

  • Usar claves de cifrado separadas para envío y recepción, en lugar de las claves comunes para ambas direcciones utilizadas en SSU 1.

  • Usa un handshake de 3 mensajes en un solo viaje de ida y vuelta, como en NTCP2. Elimina la demora de esperar mensajes de datos que hace que SSU sea efectivamente un handshake de dos viajes de ida y vuelta.

  • Mejorar drásticamente la eficiencia de los ACKs y NACKs, que es horrible en SSU 1. Reducir el ancho de banda requerido para ACKs y NACKs, e incrementar el tamaño de paquete disponible para datos. Codificar eficientemente los NACKs para una ráfaga de mensajes perdidos, lo cual es común en WiFi.

  • Reducir la complejidad requerida para implementar la fragmentación de mensajes I2NP. Omitir los mecanismos de fragmentación y codificación para mensajes I2NP completos.

  • Minimizar la sobrecarga del protocolo antes del relleno, especialmente para los ACK. Aunque se añadirá relleno, la sobrecarga antes del relleno sigue siendo sobrecarga. Los nodos de ancho de banda bajo deben poder usar SSU2.

  • Mantener marcas de tiempo para la detección de repetición y desviación.

  • Evitar cualquier problema del año 2038 en las marcas de tiempo, debe funcionar hasta al menos 2106.

  • Aumentar el MTU mínimo de 620 a 1280 para mayor eficiencia, facilidad de implementación, y aumentar el tamaño máximo de mensaje I2NP. La fragmentación y reensamblaje es bastante costosa. Al proporcionar espacio para mensajes de túnel de 1028 bytes, una gran mayoría de mensajes I2NP no requerirán fragmentación.

  • Aumentar el MTU máximo de 1488 (1484 para IPv6) a 1500 para mayor eficiencia. Eliminar el requisito de que el MTU sea múltiplo de 16.

  • Aumentar el tamaño máximo del mensaje I2NP de aproximadamente 32K en SSU 1 a aproximadamente 64 KB como en NTCP2.

  • Eliminar la firma de los campos de IP y puerto del handshake, para que los routers que no conocen su IP externa y puerto puedan conectarse.

  • Conservar el mecanismo de descubrimiento de IP/puerto de SSU 1 en el handshake, para que los routers puedan conocer su IP y puerto externos.

  • Incluir representantes de los desarrolladores de router de Java, C++, y Go en el diseño.

Non-Goals

  • Resistencia a DPI a prueba de balas… eso serían los transportes conectables, Propuesta 109.

  • Un transporte basado en TLS (o similar a HTTPS)… que sería la Propuesta 104.

  • Resistencia a DPI basada en temporización (el tiempo/retrasos entre mensajes puede depender de la implementación; los retrasos intra-mensaje pueden introducirse en cualquier punto, incluyendo antes de enviar el relleno aleatorio, por ejemplo). Los retrasos artificiales (lo que obfs4 llama IAT o tiempo entre llegadas) son independientes del protocolo en sí.

  • Negabilidad de participar en una sesión (hay firmas ahí dentro).

No objetivos que pueden ser parcialmente reconsiderados o discutidos:

  • El grado de protección contra la Inspección Profunda de Paquetes (DPI)

  • Seguridad Post-Cuántica (PQ)

  • Negación plausible

Security Goals

Consideramos tres partes:

  • Alice, quien desea establecer una nueva sesión.
  • Bob, con quien Alice desea establecer una sesión.
  • Mallory, el “hombre en el medio” entre Alice y Bob.

Como máximo dos participantes pueden participar en ataques activos.

Alice y Bob poseen cada uno un par de claves estáticas, que está contenido en su RouterIdentity.

El protocolo propuesto intenta permitir que Alice y Bob acuerden una clave secreta compartida (K) bajo los siguientes requisitos:

  1. Seguridad de clave privada: ni Bob ni Mallory aprenden nada sobre la clave privada estática de Alice. Simétricamente, Alice no aprende nada sobre la clave privada estática de Bob.

  2. La clave de sesión K solo es conocida por Alice y Bob.

  3. Secreto perfecto hacia adelante: la clave de sesión acordada permanece secreta en el futuro, incluso cuando las claves privadas estáticas de Alice y/o Bob se revelan después de que la clave haya sido acordada.

  4. Autenticación bidireccional: Alice tiene la certeza de que ha establecido una sesión con Bob, y viceversa.

  5. Protección contra DPI en línea: Asegurar que no sea trivial detectar que Alice y Bob están participando en el protocolo usando únicamente técnicas sencillas de inspección profunda de paquetes (DPI). Ver a continuación.

  6. Negación limitada: ni Alice ni Bob pueden negar su participación en el protocolo, pero si cualquiera de los dos filtra la clave compartida, la otra parte puede negar la autenticidad del contenido de los datos transmitidos.

La presente propuesta intenta proporcionar los cinco requisitos basándose en el protocolo Station-To-Station (STS). Nótese que este protocolo también es la base para el protocolo SSU.

Additional DPI Discussion

Asumimos dos componentes DPI:

Online DPI

DPI en línea inspeccionando todos los flujos en tiempo real. Las conexiones pueden ser bloqueadas o manipuladas de otra manera. Los datos de conexión o metadatos pueden ser identificados y almacenados para análisis fuera de línea. El DPI en línea no tiene acceso a la base de datos de red de I2P. El DPI en línea tiene solo capacidad computacional limitada en tiempo real, incluyendo cálculo de longitud, inspección de campos y cálculos simples como XOR. El DPI en línea sí tiene la capacidad de funciones criptográficas rápidas en tiempo real como ChaCha20, AEAD y hashing, pero estas serían demasiado costosas para aplicar a la mayoría o todos los flujos. Cualquier aplicación de estas operaciones criptográficas se aplicaría solo a flujos en combinaciones IP/Puerto previamente identificadas por análisis fuera de línea. El DPI en línea no tiene la capacidad de funciones criptográficas de alto overhead como DH o elligator2. El DPI en línea no está diseñado específicamente para detectar I2P, aunque puede tener reglas de clasificación limitadas para ese propósito.

Es un objetivo prevenir la identificación del protocolo por un DPI en línea.

La noción de DPI en línea o “directa” se entiende aquí que incluye las siguientes capacidades del adversario:

  1. La capacidad de inspeccionar todos los datos enviados o recibidos por el objetivo.

  2. La capacidad de realizar operaciones sobre los datos observados, como aplicar cifrados por bloques o funciones hash.

  3. La capacidad de almacenar y comparar con mensajes enviados anteriormente.

  4. La capacidad de modificar, retrasar o fragmentar paquetes.

Sin embargo, se asume que el DPI en línea tiene las siguientes restricciones:

  1. La incapacidad de mapear direcciones IP a hashes de router. Aunque esto es trivial con acceso en tiempo real a la base de datos de red, requeriría un sistema DPI específicamente diseñado para atacar I2P.

  2. La incapacidad de usar información de temporización para detectar el protocolo.

  3. En términos generales, la caja de herramientas de DPI en línea no contiene ninguna herramienta incorporada que esté específicamente diseñada para la detección de I2P. Esto incluye la creación de “honeypots”, que por ejemplo incluirían relleno no aleatorio en sus mensajes. Nótese que esto no excluye sistemas de aprendizaje automático o herramientas de DPI altamente configurables siempre que cumplan con los otros requisitos.

Para contrarrestar el análisis de carga útil, se asegura que todos los mensajes sean indistinguibles de datos aleatorios. Esto también requiere que su longitud sea aleatoria, lo cual es más complicado que simplemente agregar relleno aleatorio. De hecho, en el Apéndice A, los autores argumentan que un esquema de relleno ingenuo (es decir, uniforme) no resuelve el problema. Por lo tanto, el Apéndice A propone incluir retrasos aleatorios o desarrollar un esquema de relleno alternativo que pueda proporcionar protección razonable contra el ataque propuesto.

Para protegerse contra la sexta entrada mencionada anteriormente, las implementaciones deberían incluir retrasos aleatorios en el protocolo. Tales técnicas no están cubiertas por esta propuesta, pero también podrían resolver los problemas de longitud de relleno. En resumen, la propuesta proporciona buena protección contra el análisis de carga útil (cuando se tienen en cuenta las consideraciones del Apéndice A), pero solo protección limitada contra el análisis de flujo.

Offline DPI

DPI offline inspeccionando datos almacenados por el DPI online para análisis posterior. El DPI offline puede estar diseñado específicamente para detectar I2P. El DPI offline sí tiene acceso en tiempo real a la base de datos de red de I2P. El DPI offline sí tiene acceso a esta y otras especificaciones de I2P. El DPI offline tiene capacidad computacional ilimitada, incluyendo todas las funciones criptográficas definidas en esta especificación.

El DPI offline no tiene la capacidad de bloquear conexiones existentes. El DPI offline sí tiene la capacidad de realizar envío en tiempo casi real (dentro de minutos de configuración) a host/puerto de las partes mediante inyección de paquetes. El DPI offline sí tiene la capacidad de realizar reproducción en tiempo casi real (dentro de minutos de configuración) de mensajes previos (modificados o no) para “sondeo” u otras razones.

No es un objetivo prevenir la identificación del protocolo por parte de un DPI fuera de línea. Toda la decodificación de datos ofuscados en los primeros dos mensajes, que es implementada por los routers I2P, también puede ser implementada por el DPI fuera de línea.

Es un objetivo rechazar los intentos de conexión que utilicen la repetición de mensajes anteriores.

Address Validation

Lo siguiente está copiado de QUIC RFC 9000. Para cada sección, revisar y editar.

La validación de direcciones asegura que un endpoint no pueda ser utilizado para un ataque de amplificación de tráfico. En tal ataque, se envía un paquete a un servidor con información de dirección de origen falsificada que identifica a una víctima. Si un servidor genera más paquetes o paquetes más grandes en respuesta a ese paquete, el atacante puede usar el servidor para enviar más datos hacia la víctima de los que sería capaz de enviar por sí mismo.

La defensa principal contra los ataques de amplificación es verificar que un peer sea capaz de recibir paquetes en la dirección de transporte que declara. Por lo tanto, después de recibir paquetes de una dirección que aún no está validada, un endpoint DEBE limitar la cantidad de datos que envía a la dirección no validada a tres veces la cantidad de datos recibidos de esa dirección. Esta limitación en el tamaño de las respuestas se conoce como el límite anti-amplificación.

La validación de direcciones se realiza tanto durante el establecimiento de la conexión (ver Sección 8.1) como durante la migración de la conexión (ver Sección 8.2).

Address Validation during Connection Establishment

El establecimiento de conexión proporciona implícitamente validación de direcciones para ambos extremos. En particular, la recepción de un paquete protegido con claves de Handshake confirma que el peer procesó exitosamente un paquete Initial. Una vez que un extremo ha procesado exitosamente un paquete Handshake del peer, puede considerar que la dirección del peer ha sido validada.

Además, un endpoint PUEDE considerar la dirección del peer validada si el peer utiliza un ID de conexión elegido por el endpoint y el ID de conexión contiene al menos 64 bits de entropía.

Para el cliente, el valor del campo Destination Connection ID en su primer paquete Initial le permite validar la dirección del servidor como parte del procesamiento exitoso de cualquier paquete. Los paquetes Initial del servidor están protegidos con claves que se derivan de este valor (ver Sección 5.2 de QUIC-TLS). Alternativamente, el valor es devuelto por el servidor en paquetes Version Negotiation (Sección 6) o incluido en el Integrity Tag en paquetes Retry (Sección 5.8 de QUIC-TLS).

Antes de validar la dirección del cliente, los servidores NO DEBEN enviar más de tres veces la cantidad de bytes que el número de bytes que han recibido. Esto limita la magnitud de cualquier ataque de amplificación que pueda montarse utilizando direcciones de origen falsificadas. Con el propósito de evitar la amplificación antes de la validación de la dirección, los servidores DEBEN contar todos los bytes de carga útil recibidos en datagramas que se atribuyen de manera única a una sola conexión. Esto incluye datagramas que contienen paquetes que se procesan exitosamente y datagramas que contienen paquetes que se descartan por completo.

Los clientes DEBEN asegurar que los datagramas UDP que contienen paquetes Initial tengan cargas útiles UDP de al menos 1200 bytes, agregando tramas PADDING según sea necesario. Un cliente que envía datagramas con relleno permite al servidor enviar más datos antes de completar la validación de dirección.

La pérdida de un paquete Initial o Handshake del servidor puede causar un deadlock si el cliente no envía paquetes Initial o Handshake adicionales. Un deadlock podría ocurrir cuando el servidor alcanza su límite anti-amplificación y el cliente ha recibido confirmaciones para todos los datos que ha enviado. En este caso, cuando el cliente no tiene razón para enviar paquetes adicionales, el servidor será incapaz de enviar más datos porque no ha validado la dirección del cliente. Para prevenir este deadlock, los clientes DEBEN enviar un paquete en un Probe Timeout (PTO); ver Sección 6.2 de QUIC-RECOVERY. Específicamente, el cliente DEBE enviar un paquete Initial en un datagrama UDP que contenga al menos 1200 bytes si no tiene claves Handshake, y de lo contrario enviar un paquete Handshake.

Un servidor podría desear validar la dirección del cliente antes de iniciar el intercambio criptográfico. QUIC utiliza un token en el paquete Initial para proporcionar validación de dirección antes de completar el handshake. Este token se entrega al cliente durante el establecimiento de la conexión con un paquete Retry (ver Sección 8.1.2) o en una conexión previa utilizando el frame NEW_TOKEN (ver Sección 8.1.3).

Además de los límites de envío impuestos antes de la validación de direcciones, los servidores también están limitados en lo que pueden enviar por los límites establecidos por el controlador de congestión. Los clientes solo están limitados por el controlador de congestión.

Token Construction

Un token enviado en una trama NEW_TOKEN o un paquete Retry DEBE construirse de manera que permita al servidor identificar cómo se proporcionó a un cliente. Estos tokens se transportan en el mismo campo pero requieren un manejo diferente por parte de los servidores.

Address Validation Using Retry Packets

Al recibir el paquete Initial del cliente, el servidor puede solicitar validación de dirección enviando un paquete Retry (Sección 17.2.5) que contenga un token. Este token DEBE ser repetido por el cliente en todos los paquetes Initial que envíe para esa conexión después de recibir el paquete Retry.

En respuesta al procesamiento de un paquete Initial que contiene un token que fue proporcionado en un paquete Retry, un servidor no puede enviar otro paquete Retry; solo puede rechazar la conexión o permitir que proceda.

Siempre que no sea posible para un atacante generar un token válido para su propia dirección (ver Sección 8.1.4) y el cliente sea capaz de devolver ese token, esto demuestra al servidor que recibió el token.

Un servidor también puede usar un paquete Retry para diferir los costos de estado y procesamiento del establecimiento de conexión. Requerir que el servidor proporcione un ID de conexión diferente, junto con el parámetro de transporte original_destination_connection_id definido en la Sección 18.2, obliga al servidor a demostrar que él, o una entidad con la que coopera, recibió el paquete Initial original del cliente. Proporcionar un ID de conexión diferente también otorga al servidor cierto control sobre cómo se enrutan los paquetes subsiguientes. Esto se puede usar para dirigir conexiones a una instancia de servidor diferente.

Si un servidor recibe un Initial de cliente que contiene un token de Retry inválido pero que por lo demás es válido, sabe que el cliente no aceptará otro token de Retry. El servidor puede descartar dicho paquete y permitir que el cliente agote el tiempo de espera para detectar el fallo del handshake, pero eso podría imponer una penalización de latencia significativa en el cliente. En su lugar, el servidor DEBERÍA cerrar inmediatamente (Sección 10.2) la conexión con un error INVALID_TOKEN. Tenga en cuenta que un servidor no ha establecido ningún estado para la conexión en este punto y por lo tanto no entra en el período de cierre.

Se muestra un flujo que demuestra el uso de un paquete Retry en la Figura 9.

Client                                                  Server

Initial[0]: CRYPTO[CH] ->

                                                <- Retry+Token

Initial+Token[1]: CRYPTO[CH] ->

                                 Initial[0]: CRYPTO[SH] ACK[1]
                       Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
                                 <- 1-RTT[0]: STREAM[1, "..."]

                Figure 9: Example Handshake with Retry

Address Validation for Future Connections

Un servidor PUEDE proporcionar a los clientes un token de validación de dirección durante una conexión que puede ser usado en una conexión posterior. La validación de dirección es especialmente importante con 0-RTT porque un servidor potencialmente envía una cantidad significativa de datos a un cliente en respuesta a datos 0-RTT.

El servidor utiliza el frame NEW_TOKEN (Sección 19.7) para proporcionar al cliente un token de validación de dirección que puede usarse para validar conexiones futuras. En una conexión futura, el cliente incluye este token en los paquetes Initial para proporcionar validación de dirección. El cliente DEBE incluir el token en todos los paquetes Initial que envíe, a menos que un Retry reemplace el token con uno más reciente. El cliente NO DEBE usar el token proporcionado en un Retry para conexiones futuras. Los servidores PUEDEN descartar cualquier paquete Initial que no contenga el token esperado.

A diferencia del token que se crea para un paquete Retry, que se usa inmediatamente, el token enviado en el frame NEW_TOKEN puede usarse después de que haya transcurrido cierto período de tiempo. Por lo tanto, un token DEBERÍA tener un tiempo de expiración, que podría ser ya sea un tiempo de expiración explícito o una marca de tiempo de emisión que pueda usarse para calcular dinámicamente el tiempo de expiración. Un servidor puede almacenar el tiempo de expiración o incluirlo en forma encriptada en el token.

Un token emitido con NEW_TOKEN NO DEBE incluir información que permita que un observador vincule los valores con la conexión en la que fue emitido. Por ejemplo, no puede incluir el ID de conexión anterior o información de direccionamiento, a menos que los valores estén cifrados. Un servidor DEBE asegurar que cada frame NEW_TOKEN que envía sea único entre todos los clientes, con excepción de aquellos enviados para reparar pérdidas de frames NEW_TOKEN enviados previamente. La información que permite al servidor distinguir entre tokens de Retry y NEW_TOKEN PUEDE ser accesible a entidades distintas del servidor.

Es poco probable que el número de puerto del cliente sea el mismo en dos conexiones diferentes; por lo tanto, es poco probable que la validación del puerto sea exitosa.

Un token recibido en un frame NEW_TOKEN es aplicable a cualquier servidor para el que la conexión se considere autoritativa (por ejemplo, nombres de servidor incluidos en el certificado). Al conectarse a un servidor para el cual el cliente conserva un token aplicable y sin usar, DEBERÍA incluir ese token en el campo Token de su paquete Initial. Incluir un token podría permitir que el servidor valide la dirección del cliente sin un viaje de ida y vuelta adicional. Un cliente NO DEBE incluir un token que no sea aplicable al servidor al que se está conectando, a menos que el cliente tenga conocimiento de que el servidor que emitió el token y el servidor al que se conecta el cliente están gestionando conjuntamente los tokens. Un cliente PUEDE usar un token de cualquier conexión previa a ese servidor.

Un token permite a un servidor correlacionar la actividad entre la conexión donde se emitió el token y cualquier conexión donde se utiliza. Los clientes que desean romper la continuidad de identidad con un servidor pueden descartar los tokens proporcionados usando el frame NEW_TOKEN. En comparación, un token obtenido en un paquete Retry DEBE ser usado inmediatamente durante el intento de conexión y no puede ser utilizado en intentos de conexión posteriores.

Un cliente NO DEBERÍA reutilizar un token de una trama NEW_TOKEN para diferentes intentos de conexión. Reutilizar un token permite que las conexiones sean vinculadas por entidades en la ruta de red; ver Sección 9.5.

Los clientes pueden recibir múltiples tokens en una sola conexión. Aparte de prevenir la vinculación, cualquier token puede usarse en cualquier intento de conexión. Los servidores pueden enviar tokens adicionales para habilitar la validación de direcciones para múltiples intentos de conexión o reemplazar tokens más antiguos que podrían volverse inválidos. Para un cliente, esta ambigüedad significa que enviar el token no utilizado más reciente es más probable que sea efectivo. Aunque guardar y usar tokens más antiguos no tiene consecuencias negativas, los clientes pueden considerar que los tokens más antiguos tienen menos probabilidades de ser útiles para el servidor en la validación de direcciones.

Cuando un servidor recibe un paquete Initial con un token de validación de dirección, DEBE intentar validar el token, a menos que ya haya completado la validación de dirección. Si el token es inválido, entonces el servidor DEBERÍA proceder como si el cliente no tuviera una dirección validada, incluyendo potencialmente enviar un paquete Retry. Los tokens proporcionados con marcos NEW_TOKEN y paquetes Retry pueden ser distinguidos por los servidores (ver Sección 8.1.1), y estos últimos pueden ser validados de manera más estricta. Si la validación tiene éxito, el servidor DEBERÍA entonces permitir que el handshake proceda.

Nota: La razón para tratar al cliente como no validado en lugar de descartar el paquete es que el cliente podría haber recibido el token en una conexión anterior usando el frame NEW_TOKEN, y si el servidor ha perdido el estado, podría ser incapaz de validar el token en absoluto, lo que llevaría a una falla de conexión si el paquete es descartado.

En un diseño sin estado, un servidor puede usar tokens cifrados y autenticados para pasar información a los clientes que el servidor puede recuperar más tarde y usar para validar una dirección de cliente. Los tokens no están integrados en el handshake criptográfico, y por lo tanto no están autenticados. Por ejemplo, un cliente podría ser capaz de reutilizar un token. Para evitar ataques que exploten esta propiedad, un servidor puede limitar su uso de tokens solo a la información necesaria para validar direcciones de cliente.

Los clientes PUEDEN usar tokens obtenidos en una conexión para cualquier intento de conexión usando la misma versión. Al seleccionar un token para usar, los clientes no necesitan considerar otras propiedades de la conexión que se está intentando, incluyendo la elección de posibles protocolos de aplicación, tickets de sesión, u otras propiedades de conexión.

Address Validation Token Integrity

Un token de validación de dirección DEBE ser difícil de adivinar. Incluir un valor aleatorio con al menos 128 bits de entropía en el token sería suficiente, pero esto depende de que el servidor recuerde el valor que envía a los clientes.

Un esquema basado en tokens permite al servidor transferir cualquier estado asociado con la validación al cliente. Para que este diseño funcione, el token DEBE estar cubierto por protección de integridad contra modificación o falsificación por parte de los clientes. Sin protección de integridad, clientes maliciosos podrían generar o adivinar valores para tokens que serían aceptados por el servidor. Solo el servidor requiere acceso a la clave de protección de integridad para tokens.

No es necesario un formato único bien definido para el token porque el servidor que genera el token también lo consume. Los tokens enviados en paquetes Retry DEBERÍAN incluir información que permita al servidor verificar que la dirección IP de origen y el puerto en los paquetes del cliente permanezcan constantes.

Los tokens enviados en marcos NEW_TOKEN DEBEN incluir información que permita al servidor verificar que la dirección IP del cliente no ha cambiado desde que se emitió el token. Los servidores pueden usar tokens de marcos NEW_TOKEN para decidir no enviar un paquete Retry, incluso si la dirección del cliente ha cambiado. Si la dirección IP del cliente ha cambiado, el servidor DEBE cumplir con el límite anti-amplificación; ver Sección 8. Tenga en cuenta que en presencia de NAT, este requisito podría ser insuficiente para proteger otros hosts que comparten el NAT de ataques de amplificación.

Los atacantes podrían reutilizar tokens para usar servidores como amplificadores en ataques DDoS. Para protegerse contra tales ataques, los servidores DEBEN asegurar que la reutilización de tokens sea prevenida o limitada. Los servidores DEBERÍAN asegurar que los tokens enviados en paquetes Retry sean aceptados solo por un corto tiempo, ya que son devueltos inmediatamente por los clientes. Los tokens que se proporcionan en frames NEW_TOKEN (Sección 19.7) necesitan ser válidos por más tiempo pero NO DEBERÍAN ser aceptados múltiples veces. Se recomienda a los servidores permitir que los tokens sean usados solo una vez, si es posible; los tokens PUEDEN incluir información adicional sobre los clientes para estrechar aún más la aplicabilidad o reutilización.

DPI en línea

La validación de ruta es utilizada por ambos peers durante la migración de conexión (ver Sección 9) para verificar la accesibilidad después de un cambio de dirección. En la validación de ruta, los endpoints prueban la accesibilidad entre una dirección local específica y una dirección de peer específica, donde una dirección es la tupla de 2 elementos compuesta por la dirección IP y el puerto.

Las pruebas de validación de ruta verifican que los paquetes enviados en una ruta a un peer sean recibidos por ese peer. La validación de ruta se utiliza para asegurar que los paquetes recibidos de un peer en migración no contengan una dirección de origen falsificada.

La validación de ruta no valida que un peer pueda enviar en la dirección de retorno. Los reconocimientos no pueden usarse para la validación de ruta de retorno porque contienen entropía insuficiente y podrían ser falsificados. Los endpoints determinan independientemente la accesibilidad en cada dirección de una ruta, y por lo tanto la accesibilidad de retorno solo puede ser establecida por el peer.

La validación de ruta puede ser utilizada en cualquier momento por cualquiera de los endpoints. Por ejemplo, un endpoint podría verificar que un peer todavía esté en posesión de su dirección después de un período de inactividad.

La validación de rutas no está diseñada como un mecanismo de traversal de NAT. Aunque el mecanismo descrito aquí podría ser efectivo para la creación de enlaces NAT que soporten el traversal de NAT, la expectativa es que un endpoint sea capaz de recibir paquetes sin haber enviado primero un paquete en esa ruta. El traversal efectivo de NAT necesita mecanismos de sincronización adicionales que no se proporcionan aquí.

Un endpoint PUEDE incluir otros frames con los frames PATH_CHALLENGE y PATH_RESPONSE utilizados para la validación de rutas. En particular, un endpoint puede incluir frames PADDING con un frame PATH_CHALLENGE para el Descubrimiento de Unidad Máxima de Transmisión de Ruta (PMTUD); ver Sección 14.2.1. Un endpoint también puede incluir su propio frame PATH_CHALLENGE al enviar un frame PATH_RESPONSE.

Un endpoint utiliza un nuevo ID de conexión para las sondas enviadas desde una nueva dirección local; ver Sección 9.5. Al sondear una nueva ruta, un endpoint puede asegurar que su par tenga un ID de conexión no utilizado disponible para las respuestas. Enviar frames NEW_CONNECTION_ID y PATH_CHALLENGE en el mismo paquete, si el active_connection_id_limit del par lo permite, asegura que un ID de conexión no utilizado estará disponible para el par al enviar una respuesta.

Un endpoint puede elegir sondear múltiples rutas simultáneamente. El número de rutas simultáneas utilizadas para sondeos está limitado por el número de IDs de conexión adicionales que su peer ha proporcionado previamente, ya que cada nueva dirección local utilizada para un sondeo requiere un ID de conexión previamente no utilizado.

DPI sin conexión

Para iniciar la validación de ruta, un endpoint envía una trama PATH_CHALLENGE que contiene una carga útil impredecible en la ruta a validar.

Un endpoint PUEDE enviar múltiples tramas PATH_CHALLENGE para protegerse contra la pérdida de paquetes. Sin embargo, un endpoint NO DEBERÍA enviar múltiples tramas PATH_CHALLENGE en un solo paquete.

Un endpoint NO DEBERÍA sondear una nueva ruta con paquetes que contengan un frame PATH_CHALLENGE con más frecuencia de la que enviaría un paquete Initial. Esto asegura que la migración de conexión no genere más carga en una nueva ruta que el establecimiento de una nueva conexión.

El endpoint DEBE usar datos impredecibles en cada frame PATH_CHALLENGE para que pueda asociar la respuesta del peer con el PATH_CHALLENGE correspondiente.

Un endpoint DEBE expandir los datagramas que contengan un frame PATH_CHALLENGE a al menos el tamaño máximo de datagrama más pequeño permitido de 1200 bytes, a menos que el límite de anti-amplificación para la ruta no permita enviar un datagrama de este tamaño. El envío de datagramas UDP de este tamaño asegura que la ruta de red desde el endpoint hasta el peer pueda ser utilizada para QUIC; véase la Sección 14.

Cuando un endpoint no puede expandir el tamaño del datagrama a 1200 bytes debido al límite anti-amplificación, el MTU de la ruta no será validado. Para asegurar que el MTU de la ruta sea lo suficientemente grande, el endpoint DEBE realizar una segunda validación de ruta enviando un frame PATH_CHALLENGE en un datagrama de al menos 1200 bytes. Esta validación adicional puede realizarse después de que se reciba exitosamente un PATH_RESPONSE o cuando se hayan recibido suficientes bytes en la ruta para que el envío del datagrama más grande no resulte en exceder el límite anti-amplificación.

A diferencia de otros casos donde los datagramas se expanden, los endpoints NO DEBEN descartar datagramas que parecen ser demasiado pequeños cuando contienen PATH_CHALLENGE o PATH_RESPONSE.

Path Validation Responses

Al recibir un frame PATH_CHALLENGE, un endpoint DEBE responder enviando de vuelta los datos contenidos en el frame PATH_CHALLENGE en un frame PATH_RESPONSE. Un endpoint NO DEBE retrasar la transmisión de un paquete que contenga un frame PATH_RESPONSE a menos que esté limitado por el control de congestión.

Un frame PATH_RESPONSE DEBE ser enviado en la ruta de red donde se recibió el frame PATH_CHALLENGE. Esto asegura que la validación de ruta por parte de un peer solo tenga éxito si la ruta es funcional en ambas direcciones. Este requisito NO DEBE ser aplicado por el endpoint que inicia la validación de ruta, ya que eso habilitaría un ataque sobre la migración; ver Sección 9.3.3.

Un endpoint DEBE expandir los datagramas que contienen un frame PATH_RESPONSE hasta al menos el tamaño máximo de datagrama permitido más pequeño de 1200 bytes. Esto verifica que la ruta es capaz de transportar datagramas de este tamaño en ambas direcciones. Sin embargo, un endpoint NO DEBE expandir el datagrama que contiene el PATH_RESPONSE si los datos resultantes exceden el límite de anti-amplificación. Se espera que esto ocurra únicamente si el PATH_CHALLENGE recibido no fue enviado en un datagrama expandido.

Un endpoint NO DEBE enviar más de un frame PATH_RESPONSE en respuesta a un frame PATH_CHALLENGE; ver Sección 13.3. Se espera que el peer envíe más frames PATH_CHALLENGE según sea necesario para provocar frames PATH_RESPONSE adicionales.

Validación de Direcciones durante el Establecimiento de Conexión

La validación de ruta tiene éxito cuando se recibe un frame PATH_RESPONSE que contiene los datos que fueron enviados en un frame PATH_CHALLENGE previo. Un frame PATH_RESPONSE recibido en cualquier ruta de red valida la ruta en la que se envió el PATH_CHALLENGE.

Si un endpoint envía un frame PATH_CHALLENGE en un datagrama que no se expande a al menos 1200 bytes y si la respuesta valida la dirección del peer, la ruta se valida pero no el MTU de la ruta. Como resultado, el endpoint ahora puede enviar más de tres veces la cantidad de datos que ha recibido. Sin embargo, el endpoint DEBE iniciar otra validación de ruta con un datagrama expandido para verificar que la ruta soporta el MTU requerido.

La recepción de un acuse de recibo para un paquete que contiene una trama PATH_CHALLENGE no es una validación adecuada, ya que el acuse de recibo puede ser falsificado por un peer malicioso.

Construcción de Tokens

La validación de ruta solo falla cuando el extremo que intenta validar la ruta abandona su intento de validar la ruta.

Los endpoints DEBERÍAN abandonar la validación de ruta basada en un temporizador. Al configurar este temporizador, se advierte a las implementaciones que la nueva ruta podría tener un tiempo de ida y vuelta más largo que la original. Se RECOMIENDA un valor de tres veces el mayor entre el PTO actual o el PTO para la nueva ruta (usando kInitialRtt, como se define en QUIC-RECOVERY).

Este timeout permite que múltiples PTOs expiren antes de fallar la validación de ruta, de modo que la pérdida de un solo frame PATH_CHALLENGE o PATH_RESPONSE no cause falla en la validación de ruta.

Tenga en cuenta que el endpoint podría recibir paquetes que contengan otros frames en la nueva ruta, pero se requiere un frame PATH_RESPONSE con los datos apropiados para que la validación de la ruta sea exitosa.

Cuando un endpoint abandona la validación de ruta, determina que la ruta es inutilizable. Esto no implica necesariamente un fallo de la conexión – los endpoints pueden continuar enviando paquetes por otras rutas según sea apropiado. Si no hay rutas disponibles, un endpoint puede esperar a que una nueva ruta esté disponible o cerrar la conexión. Un endpoint que no tiene una ruta de red válida a su peer PUEDE señalar esto usando el error de conexión NO_VIABLE_PATH, notando que esto solo es posible si la ruta de red existe pero no soporta el MTU requerido (Sección 14).

Una validación de ruta podría ser abandonada por otras razones además del fallo. Principalmente, esto ocurre si se inicia una migración de conexión a una nueva ruta mientras una validación de ruta en la ruta anterior está en progreso.

Connection Migration

Lo siguiente se copia de QUIC RFC 9000. Para cada sección, revisar y editar.

El uso de un ID de conexión permite que las conexiones sobrevivan a cambios en las direcciones de punto final (dirección IP y puerto), como aquellos causados por un punto final que migra a una nueva red. Esta sección describe el proceso por el cual un punto final migra a una nueva dirección.

El diseño de QUIC depende de que los endpoints mantengan una dirección estable durante la duración del handshake. Un endpoint NO DEBE iniciar migración de conexión antes de que el handshake sea confirmado, como se define en la Sección 4.1.2 de QUIC-TLS.

Si el par envió el parámetro de transporte disable_active_migration, un endpoint también DEBE NO enviar paquetes (incluyendo paquetes de sondeo; ver Sección 9.1) desde una dirección local diferente a la dirección que el par usó durante el handshake, a menos que el endpoint haya actuado sobre un parámetro de transporte preferred_address del par. Si el par viola este requisito, el endpoint DEBE ya sea descartar los paquetes entrantes en esa ruta sin generar un Stateless Reset o proceder con la validación de ruta y permitir que el par migre. Generar un Stateless Reset o cerrar la conexión permitiría a terceros en la red causar que las conexiones se cierren mediante spoofing o manipulando de otra manera el tráfico observado.

No todos los cambios de dirección de peers son migraciones intencionales o activas. El peer podría experimentar un reenlazado NAT: un cambio de dirección debido a un middlebox, usualmente un NAT, que asigna un nuevo puerto de salida o incluso una nueva dirección IP de salida para un flujo. Un endpoint DEBE realizar validación de ruta (Sección 8.2) si detecta cualquier cambio en la dirección de un peer, a menos que haya validado previamente esa dirección.

Cuando un endpoint no tiene una ruta validada en la cual enviar paquetes, PUEDE descartar el estado de la conexión. Un endpoint capaz de migración de conexión PUEDE esperar a que una nueva ruta esté disponible antes de descartar el estado de la conexión.

Este documento limita la migración de conexiones a nuevas direcciones de cliente, excepto como se describe en la Sección 9.6. Los clientes son responsables de iniciar todas las migraciones. Los servidores no envían paquetes que no sean de sondeo (ver Sección 9.1) hacia una dirección de cliente hasta que vean un paquete que no sea de sondeo desde esa dirección. Si un cliente recibe paquetes desde una dirección de servidor desconocida, el cliente DEBE descartar estos paquetes.

Validación de Direcciones Usando Paquetes de Reintento

Un endpoint PUEDE sondear la accesibilidad del peer desde una nueva dirección local usando validación de ruta (Sección 8.2) antes de migrar la conexión a la nueva dirección local. El fallo de la validación de ruta simplemente significa que la nueva ruta no es utilizable para esta conexión. El fallo al validar una ruta no causa que la conexión termine a menos que no haya rutas alternativas válidas disponibles.

Los frames PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID y PADDING son “frames de sondeo”, y todos los demás frames son “frames de no sondeo”. Un paquete que contiene solo frames de sondeo es un “paquete de sondeo”, y un paquete que contiene cualquier otro frame es un “paquete de no sondeo”.

Validación de Direcciones para Conexiones Futuras

Un endpoint puede migrar una conexión a una nueva dirección local enviando paquetes que contengan frames que no sean de sondeo desde esa dirección.

Cada endpoint valida la dirección de su peer durante el establecimiento de la conexión. Por lo tanto, un endpoint que está migrando puede enviar a su peer sabiendo que el peer está dispuesto a recibir en la dirección actual del peer. Así, un endpoint puede migrar a una nueva dirección local sin validar primero la dirección del peer.

Para establecer la accesibilidad en la nueva ruta, un endpoint inicia la validación de ruta (Sección 8.2) en la nueva ruta. Un endpoint PUEDE diferir la validación de ruta hasta después de que un peer envíe el siguiente frame que no sea de sondeo a su nueva dirección.

Al migrar, la nueva ruta podría no soportar la velocidad de envío actual del endpoint. Por lo tanto, el endpoint reinicia su controlador de congestión y estimación de RTT, como se describe en la Sección 9.4.

La nueva ruta podría no tener la misma capacidad ECN. Por lo tanto, el endpoint valida la capacidad ECN como se describe en la Sección 13.4.

Integridad del Token de Validación de Dirección

Recibir un paquete de una nueva dirección de peer que contiene un frame que no es de sondeo indica que el peer ha migrado a esa dirección.

Si el destinatario permite la migración, DEBE enviar paquetes posteriores a la nueva dirección del peer y DEBE iniciar la validación de ruta (Sección 8.2) para verificar la propiedad de la dirección por parte del peer si la validación no está ya en curso. Si el destinatario no tiene IDs de conexión no utilizados del peer, no podrá enviar nada en la nueva ruta hasta que el peer proporcione uno; ver Sección 9.5.

Un endpoint solo cambia la dirección a la cual envía paquetes en respuesta al paquete no exploratorio con el número más alto. Esto garantiza que un endpoint no envíe paquetes a una dirección de peer antigua en caso de que reciba paquetes reordenados.

Un endpoint PUEDE enviar datos a una dirección de peer no validada, pero DEBE protegerse contra ataques potenciales como se describe en las Secciones 9.3.1 y 9.3.2. Un endpoint PUEDE omitir la validación de una dirección de peer si esa dirección ha sido vista recientemente. En particular, si un endpoint regresa a una ruta previamente validada después de detectar alguna forma de migración espuria, omitir la validación de dirección y restaurar el estado de detección de pérdidas y congestión puede reducir el impacto en el rendimiento del ataque.

Después de cambiar la dirección a la cual envía paquetes que no son de sondeo, un endpoint puede abandonar cualquier validación de ruta para otras direcciones.

Recibir un paquete desde una nueva dirección de peer podría ser el resultado de un reenlace NAT en el peer.

Después de verificar una nueva dirección de cliente, el servidor DEBERÍA enviar nuevos tokens de validación de dirección (Sección 8) al cliente.

Validación de Ruta

Es posible que un peer esté suplantando su dirección de origen para hacer que un endpoint envíe cantidades excesivas de datos a un host que no desea recibirlos. Si el endpoint envía significativamente más datos que el peer suplantador, la migración de conexión podría utilizarse para amplificar el volumen de datos que un atacante puede generar hacia una víctima.

Como se describe en la Sección 9.3, se requiere que un endpoint valide la nueva dirección de un peer para confirmar la posesión de la nueva dirección por parte del peer. Hasta que la dirección de un peer se considere válida, un endpoint limita la cantidad de datos que envía a esa dirección; ver Sección 8. En ausencia de este límite, un endpoint corre el riesgo de ser utilizado para un ataque de denegación de servicio contra una víctima desprevenida.

Si un endpoint omite la validación de una dirección de peer como se describe arriba, no necesita limitar su velocidad de envío.

Iniciando la Validación de Rutas

Un atacante en la ruta podría causar una migración de conexión falsa copiando y reenviando un paquete con una dirección falsificada de tal manera que llegue antes que el paquete original. El paquete con la dirección falsificada será visto como proveniente de una conexión que está migrando, y el paquete original será visto como duplicado y descartado. Después de una migración falsa, la validación de la dirección de origen fallará porque la entidad en la dirección de origen no tiene las claves criptográficas necesarias para leer o responder al frame PATH_CHALLENGE que se le envía, incluso si quisiera hacerlo.

Para proteger la conexión de fallar debido a tal migración espuria, un endpoint DEBE revertir al uso de la última dirección de par validada cuando falla la validación de una nueva dirección de par. Además, la recepción de paquetes con números de paquete más altos desde la dirección legítima del par activará otra migración de conexión. Esto causará que se abandone la validación de la dirección de la migración espuria, conteniendo así las migraciones iniciadas por el atacante inyectando un solo paquete.

Si un endpoint no tiene estado sobre la última dirección de peer validada, DEBE cerrar la conexión silenciosamente descartando todo el estado de la conexión. Esto resulta en que los nuevos paquetes de la conexión sean manejados de manera genérica. Por ejemplo, un endpoint PUEDE enviar un Stateless Reset en respuesta a cualquier paquete entrante adicional.

Respuestas de Validación de Ruta

Un atacante fuera de ruta que pueda observar paquetes podría reenviar copias de paquetes genuinos a los endpoints. Si el paquete copiado llega antes que el paquete genuino, esto aparecerá como un reenlace NAT. Cualquier paquete genuino será descartado como duplicado. Si el atacante es capaz de continuar reenviando paquetes, podría ser capaz de causar migración a una ruta a través del atacante. Esto coloca al atacante en la ruta, dándole la capacidad de observar o descartar todos los paquetes subsecuentes.

Este estilo de ataque depende de que el atacante utilice una ruta que tenga aproximadamente las mismas características que la ruta directa entre los puntos finales. El ataque es más confiable si se envían relativamente pocos paquetes o si la pérdida de paquetes coincide con el intento de ataque.

Un paquete que no sea de sondeo recibido en la ruta original que incremente el número máximo de paquete recibido causará que el endpoint regrese a esa ruta. Provocar paquetes en esta ruta aumenta la probabilidad de que el ataque no tenga éxito. Por lo tanto, la mitigación de este ataque depende de activar el intercambio de paquetes.

En respuesta a una migración aparente, los endpoints DEBEN validar la ruta previamente activa usando un frame PATH_CHALLENGE. Esto induce el envío de nuevos paquetes en esa ruta. Si la ruta ya no es viable, el intento de validación expirará y fallará; si la ruta es viable pero ya no es deseada, la validación tendrá éxito pero solo resultará en que se envíen paquetes de sondeo en la ruta.

Un endpoint que recibe un PATH_CHALLENGE en una ruta activa DEBERÍA enviar un paquete no de sondeo en respuesta. Si el paquete no de sondeo llega antes que cualquier copia hecha por un atacante, esto resulta en que la conexión sea migrada de vuelta a la ruta original. Cualquier migración subsecuente a otra ruta reinicia todo este proceso.

Esta defensa es imperfecta, pero esto no se considera un problema serio. Si la ruta a través del ataque es consistentemente más rápida que la ruta original a pesar de múltiples intentos de usar esa ruta original, no es posible distinguir entre un ataque y una mejora en el enrutamiento.

Un endpoint también podría usar heurísticas para mejorar la detección de este estilo de ataque. Por ejemplo, el rebinding de NAT es improbable si se recibieron paquetes recientemente en la ruta antigua; de manera similar, el rebinding es raro en rutas IPv6. Los endpoints también pueden buscar paquetes duplicados. Por el contrario, un cambio en el ID de conexión es más probable que indique una migración intencional en lugar de un ataque.

Validación de Ruta Exitosa

La capacidad disponible en la nueva ruta podría no ser la misma que en la ruta anterior. Los paquetes enviados en la ruta anterior NO DEBEN contribuir al control de congestión o estimación de RTT para la nueva ruta.

Al confirmar la propiedad de un peer de su nueva dirección, un endpoint DEBE restablecer inmediatamente el controlador de congestión y el estimador de tiempo de ida y vuelta para la nueva ruta a valores iniciales (ver Apéndices A.3 y B.3 de QUIC-RECOVERY) a menos que el único cambio en la dirección del peer sea su número de puerto. Debido a que los cambios solo de puerto son comúnmente el resultado de reenlace NAT u otra actividad de middlebox, el endpoint PUEDE en su lugar retener su estado de control de congestión y estimación de tiempo de ida y vuelta en esos casos en lugar de revertir a valores iniciales. En casos donde el estado de control de congestión retenido de una ruta antigua se usa en una nueva ruta con características sustancialmente diferentes, un emisor podría transmitir de manera demasiado agresiva hasta que el controlador de congestión y el estimador RTT se hayan adaptado. En general, se aconseja a las implementaciones ser cautelosas al usar valores previos en una nueva ruta.

Podría haber un reordenamiento aparente en el receptor cuando un endpoint envía datos y sondeos desde/hacia múltiples direcciones durante el período de migración, ya que las dos rutas resultantes podrían tener diferentes tiempos de ida y vuelta. Un receptor de paquetes en múltiples rutas seguirá enviando tramas ACK que cubran todos los paquetes recibidos.

Aunque se podrían usar múltiples rutas durante la migración de conexión, un único contexto de control de congestión y un único contexto de recuperación de pérdidas (como se describe en QUIC-RECOVERY) podrían ser adecuados. Por ejemplo, un endpoint podría retrasar el cambio a un nuevo contexto de control de congestión hasta que se confirme que una ruta antigua ya no es necesaria (como el caso descrito en la Sección 9.3.3).

Un remitente puede hacer excepciones para los paquetes de sonda de modo que su detección de pérdidas sea independiente y no cause indebidamente que el controlador de congestión reduzca su tasa de envío. Un endpoint podría establecer un temporizador separado cuando se envía un PATH_CHALLENGE, el cual se cancela si se recibe el PATH_RESPONSE correspondiente. Si el temporizador se activa antes de que se reciba el PATH_RESPONSE, el endpoint podría enviar un nuevo PATH_CHALLENGE y reiniciar el temporizador por un período de tiempo más largo. Este temporizador DEBERÍA establecerse como se describe en la Sección 6.2.1 de QUIC-RECOVERY y NO DEBE ser más agresivo.

Validación de Ruta Fallida

Usar un ID de conexión estable en múltiples rutas de red permitiría a un observador pasivo correlacionar la actividad entre esas rutas. Un endpoint que se mueve entre redes podría no desear que su actividad sea correlacionada por ninguna entidad que no sea su peer, por lo que se utilizan diferentes IDs de conexión al enviar desde diferentes direcciones locales, como se discute en la Sección 5.1. Para que esto sea efectivo, los endpoints necesitan asegurar que los IDs de conexión que proporcionan no puedan ser vinculados por ninguna otra entidad.

En cualquier momento, los endpoints PUEDEN cambiar el Destination Connection ID que transmiten a un valor que no haya sido utilizado en otra ruta.

Un endpoint NO DEBE reutilizar un connection ID cuando envía desde más de una dirección local – por ejemplo, cuando inicia una migración de conexión como se describe en la Sección 9.2 o cuando sondea una nueva ruta de red como se describe en la Sección 9.1.

De manera similar, un endpoint NO DEBE reutilizar un connection ID cuando envía a más de una dirección de destino. Debido a cambios de red fuera del control de su peer, un endpoint podría recibir paquetes desde una nueva dirección de origen con el mismo valor del campo Destination Connection ID, en cuyo caso PUEDE continuar usando el connection ID actual con la nueva dirección remota mientras sigue enviando desde la misma dirección local.

Estos requisitos sobre la reutilización del ID de conexión se aplican únicamente al envío de paquetes, ya que son posibles cambios no intencionados en la ruta sin un cambio en el ID de conexión. Por ejemplo, después de un período de inactividad de red, la reasignación de NAT podría causar que los paquetes se envíen por una nueva ruta cuando el cliente reanude el envío. Un endpoint responde a tal evento como se describe en la Sección 9.3.

El uso de diferentes IDs de conexión para paquetes enviados en ambas direcciones en cada nueva ruta de red elimina el uso del ID de conexión para vincular paquetes de la misma conexión a través de diferentes rutas de red. La protección de encabezados asegura que los números de paquete no puedan ser utilizados para correlacionar actividad. Esto no previene que otras propiedades de los paquetes, como el tiempo y el tamaño, sean utilizadas para correlacionar actividad.

Un endpoint NO DEBERÍA iniciar migración con un peer que ha solicitado un connection ID de longitud cero, porque el tráfico sobre la nueva ruta podría ser trivialmente enlazable al tráfico sobre la anterior. Si el servidor es capaz de asociar paquetes con un connection ID de longitud cero a la conexión correcta, significa que el servidor está usando otra información para demultiplexar paquetes. Por ejemplo, un servidor podría proporcionar una dirección única a cada cliente – por ejemplo, usando servicios alternativos HTTP ALTSVC. La información que podría permitir el enrutamiento correcto de paquetes a través de múltiples rutas de red también permitirá que la actividad en esas rutas sea enlazada por entidades distintas al peer.

Un cliente podría desear reducir la vinculabilidad cambiando a un nuevo ID de conexión, puerto UDP de origen o dirección IP (véase RFC8981) al enviar tráfico después de un período de inactividad. Cambiar la dirección desde la cual envía paquetes al mismo tiempo podría hacer que el servidor detecte una migración de conexión. Esto asegura que los mecanismos que soportan la migración se ejerciten incluso para clientes que no experimentan revinculaciones NAT o migraciones genuinas. Cambiar la dirección puede hacer que un peer reinicie su estado de control de congestión (véase Sección 9.4), por lo que las direcciones DEBERÍAN cambiarse solo de forma infrecuente.

Un endpoint que agota los ID de conexión disponibles no puede sondear nuevas rutas o iniciar migración, ni puede responder a sondeos o intentos de su peer de migrar. Para asegurar que la migración sea posible y que los paquetes enviados en diferentes rutas no puedan correlacionarse, los endpoints DEBERÍAN proporcionar nuevos ID de conexión antes de que los peers migren; ver Sección 5.1.1. Si un peer podría haber agotado los ID de conexión disponibles, un endpoint que migra podría incluir un frame NEW_CONNECTION_ID en todos los paquetes enviados en una nueva ruta de red.

Server’s Preferred Address

QUIC permite a los servidores aceptar conexiones en una dirección IP e intentar transferir estas conexiones a una dirección más preferida poco después del handshake. Esto es particularmente útil cuando los clientes se conectan inicialmente a una dirección compartida por múltiples servidores pero preferirían usar una dirección unicast para asegurar la estabilidad de la conexión. Esta sección describe el protocolo para migrar una conexión a una dirección de servidor preferida.

La migración de una conexión a una nueva dirección de servidor durante la conexión no es compatible con la versión de QUIC especificada en este documento. Si un cliente recibe paquetes de una nueva dirección de servidor cuando el cliente no ha iniciado una migración a esa dirección, el cliente DEBERÍA descartar estos paquetes.

Sondeo de una Nueva Ruta

Un servidor transmite una dirección preferida incluyendo el parámetro de transporte preferred_address en el handshake TLS.

Los servidores PUEDEN comunicar una dirección preferida de cada familia de direcciones (IPv4 e IPv6) para permitir que los clientes elijan la más adecuada para su conexión de red.

Una vez que se confirma el handshake, el cliente DEBERÍA seleccionar una de las dos direcciones proporcionadas por el servidor e iniciar la validación de ruta (ver Sección 8.2). Un cliente construye paquetes usando cualquier ID de conexión activo no utilizado previamente, tomado del parámetro de transporte preferred_address o de una trama NEW_CONNECTION_ID.

Tan pronto como la validación de ruta tenga éxito, el cliente DEBERÍA comenzar a enviar todos los paquetes futuros a la nueva dirección del servidor usando el nuevo ID de conexión y descontinuar el uso de la dirección del servidor anterior. Si la validación de ruta falla, el cliente DEBE continuar enviando todos los paquetes futuros a la dirección IP original del servidor.

Iniciando la Migración de Conexión

Un cliente que migra a una dirección preferida DEBE validar la dirección que elige antes de migrar; ver Sección 21.5.3.

Un servidor podría recibir un paquete dirigido a su dirección IP preferida en cualquier momento después de que acepta una conexión. Si este paquete contiene un frame PATH_CHALLENGE, el servidor envía un paquete que contiene un frame PATH_RESPONSE según la Sección 8.2. El servidor DEBE enviar paquetes que no sean de sondeo desde su dirección original hasta que reciba un paquete que no sea de sondeo del cliente en su dirección preferida y hasta que el servidor haya validado la nueva ruta.

El servidor DEBE sondear en la ruta hacia el cliente desde su dirección preferida. Esto ayuda a proteger contra la migración espuria iniciada por un atacante.

Una vez que el servidor ha completado su validación de ruta y ha recibido un paquete no de sondeo con un nuevo número de paquete más grande en su dirección preferida, el servidor comienza a enviar paquetes no de sondeo al cliente exclusivamente desde su dirección IP preferida. El servidor DEBERÍA descartar paquetes más nuevos para esta conexión que se reciban en la dirección IP antigua. El servidor PUEDE continuar procesando paquetes retrasados que se reciban en la dirección IP antigua.

Las direcciones que un servidor proporciona en el parámetro de transporte preferred_address solo son válidas para la conexión en la que se proporcionan. Un cliente NO DEBE usar estas para otras conexiones, incluyendo conexiones que se reanudan desde la conexión actual.

Respondiendo a la Migración de Conexiones

Un cliente podría necesitar realizar una migración de conexión antes de haber migrado a la dirección preferida del servidor. En este caso, el cliente DEBERÍA realizar validación de ruta tanto a la dirección original como a la preferida del servidor desde la nueva dirección del cliente de forma concurrente.

Si la validación de ruta de la dirección preferida del servidor tiene éxito, el cliente DEBE abandonar la validación de la dirección original y migrar al uso de la dirección preferida del servidor. Si la validación de ruta de la dirección preferida del servidor falla pero la validación de la dirección original del servidor tiene éxito, el cliente PUEDE migrar a su nueva dirección y continuar enviando a la dirección original del servidor.

Si los paquetes recibidos en la dirección preferida del servidor tienen una dirección de origen diferente a la observada desde el cliente durante el handshake, el servidor DEBE protegerse contra posibles ataques como se describe en las Secciones 9.3.1 y 9.3.2. Además de la migración simultánea intencional, esto también podría ocurrir porque la red de acceso del cliente utilizó una vinculación NAT diferente para la dirección preferida del servidor.

Los servidores DEBERÍAN iniciar la validación de ruta a la nueva dirección del cliente al recibir un paquete de sondeo desde una dirección diferente; consulte la Sección 8.

Un cliente que migra a una nueva dirección DEBERÍA usar una dirección preferida de la misma familia de direcciones para el servidor.

El ID de conexión proporcionado en el parámetro de transporte preferred_address no es específico para las direcciones que se proporcionan. Este ID de conexión se proporciona para asegurar que el cliente tenga un ID de conexión disponible para migración, pero el cliente PUEDE usar este ID de conexión en cualquier ruta.

Suplantación de Dirección de Peer

QUIC recomienda que los endpoints que envían datos usando IPv6 DEBERÍAN aplicar una etiqueta de flujo IPv6 en cumplimiento con RFC 6437, a menos que la API local no permita establecer etiquetas de flujo IPv6.

Desafortunadamente, la API de Java no permite establecer etiquetas de flujo IPv6.

Objetivos Excluidos

Lo siguiente está copiado de QUIC RFC 9000. Para cada sección, revisar y editar.

El objetivo de QUIC es proporcionar una conexión de transporte segura. La Sección 21.1 proporciona una descripción general de esas propiedades; las secciones posteriores discuten restricciones y advertencias con respecto a estas propiedades, incluyendo descripciones de ataques conocidos y contramedidas.

Suplantación de Dirección en el Camino

Un análisis de seguridad completo de QUIC está fuera del alcance de este documento. Esta sección proporciona una descripción informal de las propiedades de seguridad deseadas como ayuda para los implementadores y para guiar el análisis del protocolo.

QUIC asume el modelo de amenazas descrito en SEC-CONS y proporciona protecciones contra muchos de los ataques que surgen de ese modelo.

Para este propósito, los ataques se dividen en ataques pasivos y activos. Los atacantes pasivos tienen la capacidad de leer paquetes de la red, mientras que los atacantes activos también tienen la capacidad de escribir paquetes en la red. Sin embargo, un ataque pasivo podría involucrar a un atacante con la capacidad de causar un cambio de enrutamiento u otra modificación en la ruta tomada por los paquetes que comprenden una conexión.

Los atacantes se categorizan adicionalmente como atacantes en ruta o atacantes fuera de ruta. Un atacante en ruta puede leer, modificar o eliminar cualquier paquete que observe de tal manera que el paquete ya no llegue a su destino, mientras que un atacante fuera de ruta observa los paquetes pero no puede evitar que el paquete original llegue a su destino previsto. Ambos tipos de atacantes también pueden transmitir paquetes arbitrarios. Esta definición difiere de la de la Sección 3.5 de SEC-CONS en que un atacante fuera de ruta es capaz de observar paquetes.

Las propiedades del handshake, los paquetes protegidos y la migración de conexión se consideran por separado.

Reenvío de Paquetes Fuera de Ruta

El handshake de QUIC incorpora el handshake de TLS 1.3 y hereda las propiedades criptográficas descritas en el Apéndice E.1 de TLS13. Muchas de las propiedades de seguridad de QUIC dependen de que el handshake de TLS proporcione estas propiedades. Cualquier ataque al handshake de TLS podría afectar a QUIC.

Cualquier ataque al handshake TLS que comprometa el secreto o la unicidad de las claves de sesión, o la autenticación de los pares participantes, afecta otras garantías de seguridad proporcionadas por QUIC que dependen de esas claves. Por ejemplo, la migración (Sección 9) depende de la eficacia de las protecciones de confidencialidad, tanto para la negociación de claves usando el handshake TLS como para la protección de paquetes QUIC, para evitar la vinculabilidad a través de rutas de red.

Un ataque a la integridad del handshake TLS podría permitir que un atacante afecte la selección del protocolo de aplicación o la versión de QUIC.

Además de las propiedades proporcionadas por TLS, el handshake QUIC proporciona cierta defensa contra ataques DoS en el handshake.

Detección de Pérdidas y Control de Congestión

La validación de direcciones (Sección 8) se utiliza para verificar que una entidad que reclama una dirección determinada es capaz de recibir paquetes en esa dirección. La validación de direcciones limita los objetivos de ataques de amplificación a direcciones para las cuales un atacante puede observar paquetes.

Antes de la validación de direcciones, los endpoints están limitados en lo que pueden enviar. Los endpoints no pueden enviar datos hacia una dirección no validada que excedan tres veces los datos recibidos desde esa dirección.

Nota: El límite anti-amplificación solo se aplica cuando un endpoint responde a paquetes recibidos desde una dirección no validada. El límite anti-amplificación no se aplica a los clientes cuando establecen una nueva conexión o cuando inician la migración de conexión.

Implicaciones de Privacidad de la Migración de Conexiones

Calcular el primer vuelo del servidor para un handshake completo es potencialmente costoso, requiriendo tanto un cálculo de firma como de intercambio de claves. Para prevenir ataques DoS computacionales, el paquete Retry proporciona un mecanismo de intercambio de tokens económico que permite a los servidores validar la dirección IP de un cliente antes de realizar cualquier cálculo costoso al costo de un solo viaje de ida y vuelta. Después de un handshake exitoso, los servidores pueden emitir nuevos tokens a un cliente, lo que permitirá el establecimiento de nuevas conexiones sin incurrir en este costo.

Dirección Preferida del Servidor

Un atacante en la ruta o fuera de la ruta puede forzar que falle un handshake reemplazando o compitiendo con los paquetes Initial. Una vez que se han intercambiado paquetes Initial válidos, los paquetes Handshake posteriores están protegidos con las claves de Handshake, y un atacante en la ruta no puede forzar el fallo del handshake más que descartando paquetes para hacer que los endpoints abandonen el intento.

Un atacante en la ruta también puede reemplazar las direcciones de los paquetes en cualquiera de los lados y por lo tanto hacer que el cliente o servidor tenga una vista incorrecta de las direcciones remotas. Este tipo de ataque es indistinguible de las funciones realizadas por un NAT.

Comunicando una Dirección Preferida

Todo el handshake está protegido criptográficamente, con los paquetes Initial siendo cifrados con claves por versión y los paquetes Handshake y posteriores siendo cifrados con claves derivadas del intercambio de claves TLS. Además, la negociación de parámetros se incorpora en la transcripción TLS y por tanto proporciona las mismas garantías de integridad que la negociación TLS ordinaria. Un atacante puede observar los parámetros de transporte del cliente (siempre que conozca el salt específico de la versión) pero no puede observar los parámetros de transporte del servidor y no puede influir en la negociación de parámetros.

Los IDs de conexión no están cifrados pero tienen protección de integridad en todos los paquetes.

Esta versión de QUIC no incorpora un mecanismo de negociación de versiones; las implementaciones de versiones incompatibles simplemente fallarán al establecer una conexión.

Migración a una Dirección Preferida

La protección de paquetes (Sección 12.1) aplica cifrado autenticado a todos los paquetes excepto los paquetes de Negociación de Versión, aunque los paquetes Initial y Retry tienen protección limitada debido al uso de material de claves específico de la versión; consulte QUIC-TLS para más detalles. Esta sección considera ataques pasivos y activos contra paquetes protegidos.

Tanto los atacantes en ruta como fuera de ruta pueden montar un ataque pasivo en el que guardan los paquetes observados para un ataque offline contra la protección de paquetes en el futuro; esto es cierto para cualquier observador de cualquier paquete en cualquier red.

Un atacante que inyecta paquetes sin poder observar paquetes válidos para una conexión es poco probable que tenga éxito, ya que la protección de paquetes asegura que los paquetes válidos solo son generados por endpoints que poseen el material de clave establecido durante el handshake; ver Secciones 7 y 21.1.1. De manera similar, cualquier atacante activo que observe paquetes e intente insertar nuevos datos o modificar datos existentes en esos paquetes no debería poder generar paquetes considerados válidos por el endpoint receptor, excepto por los paquetes Initial.

Un ataque de spoofing, en el cual un atacante activo reescribe partes no protegidas de un paquete que reenvía o inyecta, como la dirección de origen o destino, solo es efectivo si el atacante puede reenviar paquetes al endpoint original. La protección de paquetes asegura que las cargas útiles de los paquetes solo puedan ser procesadas por los endpoints que completaron el handshake, y los paquetes inválidos son ignorados por esos endpoints.

Un atacante también puede modificar los límites entre paquetes y datagramas UDP, causando que múltiples paquetes se fusionen en un solo datagrama o dividiendo paquetes fusionados en múltiples datagramas. Aparte de los datagramas que contienen paquetes Initial, que requieren relleno, la modificación de cómo se organizan los paquetes en datagramas no tiene efecto funcional en una conexión, aunque podría cambiar algunas características de rendimiento.

Interacción entre la Migración de Cliente y la Dirección Preferida

La migración de conexiones (Sección 9) proporciona a los endpoints la capacidad de hacer transiciones entre direcciones IP y puertos en múltiples rutas, utilizando una ruta a la vez para la transmisión y recepción de frames no exploratorios. La validación de rutas (Sección 8.2) establece que un peer está tanto dispuesto como capacitado para recibir paquetes enviados en una ruta particular. Esto ayuda a reducir los efectos del spoofing de direcciones al limitar el número de paquetes enviados a una dirección falsificada.

Esta sección describe las propiedades de seguridad previstas de la migración de conexiones bajo varios tipos de ataques DoS.

Uso de la Etiqueta de Flujo IPv6 y Migración

Un atacante que puede hacer que un paquete que observa ya no llegue a su destino previsto se considera un atacante en la ruta. Cuando un atacante está presente entre un cliente y un servidor, los endpoints están obligados a enviar paquetes a través del atacante para establecer conectividad en una ruta determinada.

Un atacante en la ruta puede:

  • Inspeccionar paquetes

  • Modificar encabezados de paquetes IP y UDP

  • Inyectar nuevos paquetes

  • Retrasar paquetes

  • Reordenar paquetes

  • Descartar paquetes

  • Dividir y fusionar datagramas a lo largo de los límites de paquetes

Un atacante en la ruta no puede:

  • Modificar una porción autenticada de un paquete y hacer que el destinatario acepte ese paquete

Un atacante en la ruta tiene la oportunidad de modificar los paquetes que observa; sin embargo, cualquier modificación a una porción autenticada de un paquete causará que sea descartado por el endpoint receptor como inválido, ya que las cargas útiles de los paquetes están tanto autenticadas como cifradas.

QUIC tiene como objetivo restringir las capacidades de un atacante en la ruta de la siguiente manera:

  1. Un atacante en la ruta puede impedir el uso de una ruta para una conexión, causando que la conexión falle si no puede usar una ruta diferente que no contenga al atacante. Esto se puede lograr descartando todos los paquetes, modificándolos para que no se puedan descifrar, u otros métodos.

  2. Un atacante en la ruta puede prevenir la migración a una nueva ruta en la cual el atacante también esté en la ruta causando que la validación de ruta falle en la nueva ruta.

  3. Un atacante en la ruta no puede impedir que un cliente migre a una ruta en la cual el atacante no esté en la ruta.

  4. Un atacante en la ruta puede reducir el rendimiento de una conexión retrasando paquetes o descartándolos.

  5. Un atacante en la ruta no puede hacer que un endpoint acepte un paquete para el cual ha modificado una porción autenticada de ese paquete.

Off-Path Active Attacks

Un atacante fuera del camino (off-path) no está directamente en la ruta entre un cliente y servidor, pero podría ser capaz de obtener copias de algunos o todos los paquetes enviados entre el cliente y el servidor. También es capaz de enviar copias de esos paquetes a cualquiera de los extremos.

Un atacante fuera de la ruta puede:

  • Inspeccionar paquetes

  • Inyectar nuevos paquetes

  • Reordenar paquetes inyectados

Un atacante fuera de ruta no puede:

  • Modificar paquetes enviados por endpoints

  • Retrasar paquetes

  • Descartar paquetes

  • Reordenar paquetes originales

Un atacante fuera de ruta puede crear copias modificadas de los paquetes que ha observado e inyectar esas copias en la red, potencialmente con direcciones de origen y destino falsificadas.

Para los propósitos de esta discusión, se asume que un atacante fuera de ruta tiene la capacidad de inyectar una copia modificada de un paquete en la red que llegará al endpoint de destino antes de la llegada del paquete original observado por el atacante. En otras palabras, un atacante tiene la capacidad de consistentemente “ganar” una carrera con los paquetes legítimos entre los endpoints, potencialmente causando que el paquete original sea ignorado por el destinatario.

También se asume que un atacante tiene los recursos necesarios para afectar el estado NAT. En particular, un atacante puede hacer que un endpoint pierda su vinculación NAT y luego obtener el mismo puerto para usarlo con su propio tráfico.

QUIC tiene como objetivo limitar las capacidades de un atacante fuera de ruta de la siguiente manera:

  1. Un atacante fuera de ruta puede competir con los paquetes e intentar convertirse en un atacante “limitado” en ruta.

  2. Un atacante fuera del camino puede hacer que la validación de ruta tenga éxito para paquetes reenviados con la dirección de origen listada como el atacante fuera del camino siempre que pueda proporcionar conectividad mejorada entre el cliente y el servidor.

  3. Un atacante fuera de ruta no puede causar que una conexión se cierre una vez que el handshake se ha completado.

  4. Un atacante fuera de la ruta no puede causar que la migración a una nueva ruta falle si no puede observar la nueva ruta.

  5. Un atacante fuera de la ruta puede convertirse en un atacante limitado dentro de la ruta durante la migración a una nueva ruta para la cual también es un atacante fuera de la ruta.

  6. Un atacante fuera de ruta puede convertirse en un atacante limitado dentro de la ruta al afectar el estado NAT compartido de tal manera que envíe paquetes al servidor desde la misma dirección IP y puerto que el cliente utilizó originalmente.

Resumen de las Propiedades de Seguridad

Un atacante limitado en ruta es un atacante fuera de ruta que ha ofrecido enrutamiento mejorado de paquetes duplicando y reenviando paquetes originales entre el servidor y el cliente, causando que esos paquetes lleguen antes que las copias originales de tal manera que los paquetes originales sean descartados por el punto final de destino.

Un atacante limitado en ruta difiere de un atacante en ruta en que no se encuentra en la ruta original entre los endpoints, y por lo tanto los paquetes originales enviados por un endpoint aún están llegando a su destino. Esto significa que una futura falla al enrutar paquetes copiados al destino más rápido que su ruta original no evitará que los paquetes originales lleguen al destino.

Un atacante limitado en la ruta puede:

  • Inspeccionar paquetes

  • Inyectar nuevos paquetes

  • Modificar cabeceras de paquetes no cifrados

  • Reordenar paquetes

Un atacante limitado en la ruta no puede:

  • Retrasar paquetes para que lleguen más tarde que los paquetes enviados en la ruta original

  • Descartar paquetes

  • Modificar la porción autenticada y cifrada de un paquete y hacer que el destinatario acepte ese paquete

Un atacante limitado en la ruta solo puede retrasar paquetes hasta el punto en que los paquetes originales lleguen antes que los paquetes duplicados, lo que significa que no puede ofrecer enrutamiento con peor latencia que la ruta original. Si un atacante limitado en la ruta descarta paquetes, la copia original aún llegará al punto final de destino.

QUIC tiene como objetivo restringir las capacidades de un atacante limitado fuera de la ruta de la siguiente manera:

  1. Un atacante limitado en la ruta no puede provocar que una conexión se cierre una vez que el handshake se ha completado.

  2. Un atacante limitado en la ruta no puede causar que una conexión inactiva se cierre si el cliente es el primero en reanudar la actividad.

  3. Un atacante limitado en la ruta puede hacer que una conexión inactiva sea considerada perdida si el servidor es el primero en reanudar la actividad.

Tenga en cuenta que estas garantías son las mismas garantías proporcionadas para cualquier NAT, por las mismas razones.

Handshake

Como transporte cifrado y autenticado, QUIC proporciona una gama de protecciones contra ataques de denegación de servicio. Una vez completado el handshake criptográfico, los endpoints QUIC descartan la mayoría de paquetes que no están autenticados, limitando considerablemente la capacidad de un atacante para interferir con conexiones existentes.

Una vez que se establece una conexión, los endpoints QUIC podrían aceptar algunos paquetes ICMP no autenticados (véase la Sección 14.2.1), pero el uso de estos paquetes está extremadamente limitado. El único otro tipo de paquete que un endpoint podría aceptar es un reinicio sin estado (Sección 10.3), que depende de que el token se mantenga en secreto hasta que se use.

Durante la creación de una conexión, QUIC solo proporciona protección contra ataques desde fuera de la ruta de red. Todos los paquetes QUIC contienen prueba de que el destinatario vio un paquete anterior de su par.

Las direcciones no pueden cambiar durante el handshake, por lo que los endpoints pueden descartar los paquetes que se reciben en una ruta de red diferente.

Los campos Source and Destination Connection ID son el medio principal de protección contra un ataque fuera de la ruta durante el handshake; ver Sección 8.1. Estos deben coincidir con los establecidos por un peer. Excepto para Initial y Stateless Resets, un endpoint solo acepta paquetes que incluyan un campo Destination Connection ID que coincida con un valor que el endpoint eligió previamente. Esta es la única protección ofrecida para los paquetes Version Negotiation.

El campo Destination Connection ID en un paquete Initial es seleccionado por un cliente para ser impredecible, lo cual sirve a un propósito adicional. Los paquetes que transportan el handshake criptográfico están protegidos con una clave que se deriva de este connection ID y un salt específico para la versión de QUIC. Esto permite a los endpoints usar el mismo proceso para autenticar los paquetes que reciben como el que usan después de que el handshake criptográfico se complete. Los paquetes que no pueden ser autenticados son descartados. Proteger los paquetes de esta manera proporciona una fuerte garantía de que el remitente del paquete vio el paquete Initial y lo entendió.

Estas protecciones no están destinadas a ser efectivas contra un atacante que sea capaz de recibir paquetes QUIC antes de que se establezca la conexión. Dicho atacante puede potencialmente enviar paquetes que serán aceptados por los endpoints QUIC. Esta versión de QUIC intenta detectar este tipo de ataque, pero espera que los endpoints fallen al establecer una conexión en lugar de recuperarse. En su mayor parte, el protocolo de handshake criptográfico QUIC-TLS es responsable de detectar manipulaciones durante el handshake.

Los endpoints tienen permitido usar otros métodos para detectar e intentar recuperarse de la interferencia con el handshake. Los paquetes inválidos pueden ser identificados y descartados usando otros métodos, pero ningún método específico es obligatorio en este documento.

Anti-Amplificación

Un atacante podría ser capaz de recibir un token de validación de dirección (Sección 8) de un servidor y luego liberar la dirección IP que utilizó para adquirir ese token. En un momento posterior, el atacante puede iniciar una conexión 0-RTT con un servidor falsificando esta misma dirección, que ahora podría dirigirse a un endpoint diferente (víctima). El atacante puede así potencialmente causar que el servidor envíe datos equivalentes a una ventana de congestión inicial hacia la víctima.

Los servidores DEBERÍAN proporcionar mitigaciones para este ataque limitando el uso y tiempo de vida de los tokens de validación de direcciones; ver Sección 8.1.3.

DoS del Lado del Servidor

Un endpoint que reconoce paquetes que no ha recibido podría causar que un controlador de congestión permita el envío a velocidades superiores a las que la red soporta. Un endpoint PUEDE omitir números de paquete al enviar paquetes para detectar este comportamiento. Un endpoint puede entonces cerrar inmediatamente la conexión con un error de conexión de tipo PROTOCOL_VIOLATION; ver Sección 10.2.

Terminación de Handshake en la Ruta

Un ataque de falsificación de solicitud ocurre cuando un endpoint hace que su par emita una solicitud hacia una víctima, con la solicitud controlada por el endpoint. Los ataques de falsificación de solicitud tienen como objetivo proporcionar al atacante acceso a las capacidades de su par que de otro modo podrían no estar disponibles para el atacante. Para un protocolo de red, un ataque de falsificación de solicitud se utiliza a menudo para explotar cualquier autorización implícita conferida al par por la víctima debido a la ubicación del par en la red.

Para que la falsificación de solicitudes sea efectiva, un atacante necesita poder influir en qué paquetes envía el peer y hacia dónde se envían estos paquetes. Si un atacante puede dirigirse a un servicio vulnerable con una carga útil controlada, ese servicio podría realizar acciones que se atribuyen al peer del atacante pero que son decididas por el atacante.

Por ejemplo, los exploits de falsificación de solicitudes entre sitios CSRF en la Web causan que un cliente emita solicitudes que incluyen cookies de autorización COOKIE, permitiendo a un sitio acceder a información y acciones que están destinadas a estar restringidas a un sitio diferente.

Como QUIC se ejecuta sobre UDP, la modalidad de ataque principal que preocupa es una donde un atacante puede seleccionar la dirección a la cual su par envía datagramas UDP y puede controlar parte del contenido no protegido de esos paquetes. Como gran parte de los datos enviados por los endpoints de QUIC están protegidos, esto incluye control sobre el texto cifrado. Un ataque es exitoso si un atacante puede hacer que un par envíe un datagrama UDP a un host que realizará alguna acción basada en el contenido del datagrama.

Esta sección discute las formas en que QUIC podría ser usado para ataques de falsificación de solicitudes.

Esta sección también describe contramedidas limitadas que pueden ser implementadas por endpoints QUIC. Estas mitigaciones pueden ser empleadas unilateralmente por una implementación o despliegue QUIC, sin que los objetivos potenciales de ataques de falsificación de solicitudes tomen acción. Sin embargo, estas contramedidas podrían ser insuficientes si los servicios basados en UDP no autorizan adecuadamente las solicitudes.

Debido a que el ataque de migración descrito en la Sección 21.5.4 es bastante poderoso y no tiene contramedidas adecuadas, las implementaciones de servidor QUIC deben asumir que los atacantes pueden hacer que generen cargas útiles UDP arbitrarias hacia destinos arbitrarios. Los servidores QUIC NO DEBERÍAN desplegarse en redes que no implementen filtrado de ingreso BCP38 y que también tengan endpoints UDP inadecuadamente asegurados.

Aunque generalmente no es posible garantizar que los clientes no estén ubicados junto con endpoints vulnerables, esta versión de QUIC no permite que los servidores migren, evitando así ataques de migración falsificada contra los clientes. Cualquier extensión futura que permita la migración de servidores DEBE también definir contramedidas para ataques de falsificación.

Negociación de Parámetros

QUIC ofrece algunas oportunidades para que un atacante influya o controle hacia dónde su par envía datagramas UDP:

  • establecimiento de conexión inicial (Sección 7), donde un servidor puede elegir dónde un cliente envía datagramas – por ejemplo, poblando registros DNS;

  • direcciones preferidas (Sección 9.6), donde un servidor es capaz de elegir dónde un cliente envía datagramas;

  • migraciones de conexión falsificadas (Sección 9.3.1), donde un cliente es capaz de usar spoofing de dirección de origen para seleccionar dónde un servidor envía datagramas posteriores; y

  • paquetes falsificados que hacen que un servidor envíe un paquete de Negociación de Versión (Sección 21.5.5).

En todos los casos, el atacante puede hacer que su peer envíe datagramas a una víctima que podría no entender QUIC. Es decir, estos paquetes son enviados por el peer antes de la validación de dirección; ver Sección 8.

Fuera de la porción encriptada de los paquetes, QUIC ofrece a un endpoint varias opciones para controlar el contenido de los datagramas UDP que envía su peer. El campo Destination Connection ID ofrece control directo sobre los bytes que aparecen temprano en los paquetes enviados por el peer; véase la Sección 5.1. El campo Token en los paquetes Initial ofrece a un servidor control sobre otros bytes de los paquetes Initial; véase la Sección 17.2.2.

No existen medidas en esta versión de QUIC para prevenir el control indirecto sobre las porciones cifradas de los paquetes. Es necesario asumir que los endpoints son capaces de controlar el contenido de los frames que un peer envía, especialmente aquellos frames que transmiten datos de aplicación, como los frames STREAM. Aunque esto depende en cierto grado de los detalles del protocolo de aplicación, es posible ejercer cierto control en muchos contextos de uso del protocolo. Como el atacante tiene acceso a las claves de protección de paquetes, es probable que sea capaz de predecir cómo un peer cifrará futuros paquetes. El control exitoso sobre el contenido del datagrama entonces solo requiere que el atacante sea capaz de predecir el número de paquete y la ubicación de los frames en los paquetes con cierta confiabilidad.

Esta sección asume que limitar el control sobre el contenido del datagrama no es factible. El enfoque de las mitigaciones en las secciones posteriores está en limitar las formas en que los datagramas que se envían antes de la validación de dirección pueden usarse para la falsificación de solicitudes.

Paquetes Protegidos

Un atacante que actúa como servidor puede elegir la dirección IP y el puerto en el que anuncia su disponibilidad, por lo que se asume que los paquetes Initial de los clientes están disponibles para usar en este tipo de ataque. La validación de direcciones implícita en el handshake garantiza que – para una nueva conexión – un cliente no enviará otros tipos de paquetes a un destino que no entiende QUIC o no está dispuesto a aceptar una conexión QUIC.

La protección inicial de paquetes (Sección 5.2 de QUIC-TLS) hace que sea difícil para los servidores controlar el contenido de los paquetes Initial enviados por los clientes. Un cliente que elige un Destination Connection ID impredecible asegura que los servidores no puedan controlar ninguna parte de la porción cifrada de los paquetes Initial de los clientes.

Sin embargo, el campo Token está abierto al control del servidor y permite que un servidor use clientes para montar ataques de falsificación de solicitudes. El uso de tokens proporcionados con el frame NEW_TOKEN (Sección 8.1.3) ofrece la única opción para la falsificación de solicitudes durante el establecimiento de conexión.

Los clientes, sin embargo, no están obligados a usar la trama NEW_TOKEN. Los ataques de falsificación de solicitudes que dependen del campo Token pueden evitarse si los clientes envían un campo Token vacío cuando la dirección del servidor ha cambiado desde que se recibió la trama NEW_TOKEN.

Los clientes podrían evitar usar NEW_TOKEN si la dirección del servidor cambia. Sin embargo, no incluir un campo Token podría afectar negativamente el rendimiento. Los servidores podrían depender de NEW_TOKEN para habilitar el envío de datos que exceda el límite de tres veces en el envío de datos; ver Sección 8.1. En particular, esto afecta los casos donde los clientes usan 0-RTT para solicitar datos de los servidores.

Enviar un paquete Retry (Sección 17.2.5) ofrece al servidor la opción de cambiar el campo Token. Después de enviar un Retry, el servidor también puede controlar el campo Destination Connection ID de los paquetes Initial posteriores del cliente. Esto también podría permitir control indirecto sobre el contenido cifrado de los paquetes Initial. Sin embargo, el intercambio de un paquete Retry valida la dirección del servidor, evitando así el uso de paquetes Initial posteriores para falsificación de solicitudes.

Migración de Conexión

Los servidores pueden especificar una dirección preferida, a la cual los clientes migran después de confirmar el handshake; ver Sección 9.6. El campo Destination Connection ID de los paquetes que el cliente envía a una dirección preferida puede ser utilizado para falsificación de solicitudes.

Un cliente NO DEBE enviar tramas que no sean de sondeo a una dirección preferida antes de validar esa dirección; ver Sección 8. Esto reduce considerablemente las opciones que tiene un servidor para controlar la porción cifrada de los datagramas.

Este documento no ofrece ninguna contramedida adicional que sea específica para el uso de direcciones preferidas y que pueda ser implementada por los endpoints. Las medidas genéricas descritas en la Sección 21.5.6 podrían utilizarse como mitigación adicional.

Ataques Activos en la Ruta

Los clientes pueden presentar una dirección de origen falsificada como parte de una aparente migración de conexión para hacer que un servidor envíe datagramas a esa dirección.

El campo Destination Connection ID en cualquier paquete que un servidor envíe posteriormente a esta dirección falsificada puede ser utilizado para la falsificación de solicitudes. Un cliente también podría ser capaz de influir en el texto cifrado.

Un servidor que solo envía paquetes de sondeo (Sección 9.1) a una dirección antes de la validación de dirección proporciona a un atacante solo un control limitado sobre la porción cifrada de los datagramas. Sin embargo, particularmente para el reenlace NAT, esto puede afectar negativamente el rendimiento. Si el servidor envía tramas que transportan datos de aplicación, un atacante podría ser capaz de controlar la mayor parte del contenido de los datagramas.

Este documento no ofrece contramedidas específicas que puedan ser implementadas por los endpoints, aparte de las medidas genéricas descritas en la Sección 21.5.6. Sin embargo, las contramedidas para la suplantación de direcciones a nivel de red – en particular, el filtrado de ingreso BCP38 – son especialmente efectivas contra ataques que utilizan suplantación y se originan desde una red externa.

Ataques Activos Fuera de Ruta

Los clientes que pueden presentar una dirección de origen falsificada en un paquete pueden hacer que un servidor envíe un paquete de Negociación de Versión (Sección 17.2.1) a esa dirección.

La ausencia de restricciones de tamaño en los campos de ID de conexión para paquetes de una versión desconocida aumenta la cantidad de datos que el cliente controla del datagrama resultante. El primer byte de este paquete no está bajo control del cliente y los siguientes cuatro bytes son cero, pero el cliente puede controlar hasta 512 bytes comenzando desde el quinto byte.

No se proporcionan contramedidas específicas para este ataque, aunque las protecciones genéricas (Sección 21.5.6) podrían aplicar. En este caso, el filtrado de ingreso BCP38 también es efectivo.

Ataques Activos Limitados en la Ruta

La defensa más efectiva contra los ataques de falsificación de solicitudes es modificar los servicios vulnerables para usar autenticación fuerte. Sin embargo, esto no siempre está bajo el control de un despliegue QUIC. Esta sección describe algunos otros pasos que los endpoints QUIC podrían tomar unilateralmente. Todos estos pasos adicionales son discrecionales porque, dependiendo de las circunstancias, podrían interferir con o prevenir usos legítimos.

Los servicios ofrecidos a través de interfaces de loopback a menudo carecen de autenticación adecuada. Los endpoints PUEDEN prevenir intentos de conexión o migración a una dirección de loopback. Los endpoints NO DEBERÍAN permitir conexiones o migración a una dirección de loopback si el mismo servicio estaba previamente disponible en una interfaz diferente o si la dirección fue proporcionada por un servicio en una dirección que no es de loopback. Los endpoints que dependen de estas capacidades podrían ofrecer una opción para desactivar estas protecciones.

De manera similar, los endpoints podrían considerar un cambio de dirección a una dirección link-local RFC4291 o una dirección en un rango de uso privado RFC1918 desde una dirección global, unique-local RFC4193, o no privada como un posible intento de falsificación de solicitud. Los endpoints podrían rechazar usar estas direcciones completamente, pero eso conlleva un riesgo significativo de interferir con usos legítimos. Los endpoints NO DEBERÍAN rechazar usar una dirección a menos que tengan conocimiento específico sobre la red que indique que enviar datagramas a direcciones no validadas en un rango dado no es seguro.

Los endpoints PUEDEN elegir reducir el riesgo de falsificación de solicitudes no incluyendo valores de tramas NEW_TOKEN en paquetes Initial o enviando únicamente tramas de sondeo en paquetes antes de completar la validación de dirección. Tenga en cuenta que esto no impide que un atacante use el campo Destination Connection ID para un ataque.

No se espera que los endpoints tengan información específica sobre la ubicación de servidores que podrían ser objetivos vulnerables de un ataque de falsificación de solicitudes. Sin embargo, podría ser posible con el tiempo identificar puertos UDP específicos que son objetivos comunes de ataques o patrones particulares en datagramas que se utilizan para ataques. Los endpoints PUEDEN elegir evitar enviar datagramas a estos puertos o no enviar datagramas que coincidan con estos patrones antes de validar la dirección de destino. Los endpoints PUEDEN retirar IDs de conexión que contengan patrones conocidos como problemáticos sin utilizarlos.

Nota: Modificar los endpoints para aplicar estas protecciones es más eficiente que desplegar protecciones basadas en red, ya que los endpoints no necesitan realizar ningún procesamiento adicional al enviar a una dirección que ha sido validada.

Denegación de Servicio de Handshake

Los ataques comúnmente conocidos como Slowloris SLOWLORIS intentan mantener muchas conexiones abiertas al endpoint objetivo y mantenerlas abiertas durante el mayor tiempo posible. Estos ataques pueden ejecutarse contra un endpoint QUIC generando la cantidad mínima de actividad necesaria para evitar ser cerrado por inactividad. Esto podría involucrar el envío de pequeñas cantidades de datos, abrir gradualmente ventanas de control de flujo para controlar la velocidad del remitente, o fabricar tramas ACK que simulen una alta tasa de pérdida.

Las implementaciones QUIC DEBERÍAN proporcionar mitigaciones para los ataques Slowloris, como aumentar el número máximo de clientes que el servidor permitirá, limitar el número de conexiones que una sola dirección IP puede realizar, imponer restricciones en la velocidad mínima de transferencia que se permite a una conexión, y restringir la duración de tiempo que se permite a un endpoint permanecer conectado.

Ataque de Amplificación

Un remitente adversarial podría intencionalmente no enviar porciones de los datos del flujo, causando que el receptor comprometa recursos para los datos no enviados. Esto podría causar un compromiso de memoria del búfer de recepción desproporcionado y/o la creación de una estructura de datos grande e ineficiente en el receptor.

Un receptor adversario podría intencionalmente no reconocer paquetes que contengan datos de flujo en un intento de forzar al emisor a almacenar los datos de flujo no reconocidos para retransmisión.

El ataque a los receptores se mitiga si las ventanas de control de flujo corresponden a la memoria disponible. Sin embargo, algunos receptores sobreasignarán memoria y anunciarán desplazamientos de control de flujo en el agregado que exceden la memoria real disponible. La estrategia de sobreasignación puede llevar a un mejor rendimiento cuando los endpoints se comportan bien, pero hace que los endpoints sean vulnerables al ataque de fragmentación de flujo.

Las implementaciones QUIC DEBERÍAN proporcionar mitigaciones para ataques de fragmentación de flujo. Las mitigaciones podrían consistir en evitar el sobrecompromiso de memoria, limitar el tamaño de las estructuras de datos de seguimiento, retrasar el reensamblaje de tramas STREAM, implementar heurísticas basadas en la antigüedad y duración de los huecos de reensamblaje, o alguna combinación de estas.

Ataque de ACK Optimista

Un endpoint adversario puede abrir una gran cantidad de streams, agotando el estado en un endpoint. El endpoint adversario podría repetir el proceso en un gran número de conexiones, de manera similar a los ataques de SYN flooding en TCP.

Normalmente, los clientes abrirán streams secuencialmente, como se explica en la Sección 2.1. Sin embargo, cuando varios streams se inician en intervalos cortos, la pérdida o el reordenamiento pueden causar que los frames STREAM que abren streams se reciban fuera de secuencia. Al recibir un ID de stream numerado más alto, un receptor debe abrir todos los streams intermedios del mismo tipo; ver Sección 3.2. Por lo tanto, en una nueva conexión, abrir el stream 4000000 abre 1 millón y 1 streams bidireccionales iniciados por el cliente.

El número de streams activos está limitado por los parámetros de transporte initial_max_streams_bidi e initial_max_streams_uni según se actualicen por cualquier frame MAX_STREAMS recibido, como se explica en la Sección 4.6. Si se eligen juiciosamente, estos límites mitigan el efecto del ataque de compromiso de stream. Sin embargo, establecer el límite demasiado bajo podría afectar el rendimiento cuando las aplicaciones esperan abrir un gran número de streams.

Ataques de Falsificación de Solicitudes

QUIC y TLS contienen marcos o mensajes que tienen usos legítimos en algunos contextos, pero estos marcos o mensajes pueden ser abusados para causar que un par gaste recursos de procesamiento sin tener ningún impacto observable en el estado de la conexión.

Los mensajes también se pueden usar para cambiar y revertir el estado de maneras pequeñas o intrascendentes, como enviando pequeños incrementos a los límites de control de flujo.

Si los costos de procesamiento son desproporcionadamente grandes en comparación con el consumo de ancho de banda o el efecto en el estado, entonces esto podría permitir que un peer malicioso agote la capacidad de procesamiento.

Aunque existen usos legítimos para todos los mensajes, las implementaciones DEBERÍAN rastrear el costo de procesamiento relativo al progreso y tratar cantidades excesivas de cualquier paquete no productivo como indicativo de un ataque. Los endpoints PUEDEN responder a esta condición con un error de conexión o descartando paquetes.

Opciones de Control para Endpoints

Un atacante en la ruta podría manipular el valor de los campos ECN en el encabezado IP para influir en la tasa del remitente. RFC3168 discute las manipulaciones y sus efectos con mayor detalle.

Un atacante limitado en la ruta puede duplicar y enviar paquetes con campos ECN modificados para afectar la velocidad del remitente. Si los paquetes duplicados son descartados por un receptor, un atacante necesitará competir el paquete duplicado contra el original para ser exitoso en este ataque. Por lo tanto, los endpoints QUIC ignoran el campo ECN en un paquete IP a menos que al menos un paquete QUIC en ese paquete IP sea procesado exitosamente; ver Sección 13.4.

Falsificación de Solicitudes con Paquetes Iniciales del Cliente

Los reinicios sin estado crean un posible ataque de denegación de servicio análogo a una inyección de reset TCP. Este ataque es posible si un atacante puede hacer que se genere un token de reinicio sin estado para una conexión con un ID de conexión seleccionado. Un atacante que pueda hacer que se genere este token puede reiniciar una conexión activa con el mismo ID de conexión.

Si un paquete puede ser enrutado a diferentes instancias que comparten una clave estática – por ejemplo, al cambiar una dirección IP o puerto – entonces un atacante puede hacer que el servidor envíe un reinicio sin estado. Para defenderse contra este tipo de denegación de servicio, los endpoints que comparten una clave estática para reinicios sin estado (ver Sección 10.3.2) DEBEN organizarse de manera que los paquetes con un ID de conexión dado siempre lleguen a una instancia que tenga estado de conexión, a menos que esa conexión ya no esté activa.

Más en general, los servidores NO DEBEN generar un restablecimiento sin estado si una conexión con el ID de conexión correspondiente podría estar activa en cualquier endpoint que use la misma clave estática.

En el caso de un clúster que utiliza balanceamiento de carga dinámico, es posible que ocurra un cambio en la configuración del balanceador de carga mientras una instancia activa mantiene el estado de la conexión. Incluso si una instancia mantiene el estado de la conexión, el cambio en el enrutamiento y el reinicio sin estado resultante provocarán que la conexión sea terminada. Si no hay posibilidad de que el paquete sea enrutado a la instancia correcta, es mejor enviar un reinicio sin estado que esperar a que la conexión expire. Sin embargo, esto es aceptable solo si el enrutamiento no puede ser influenciado por un atacante.

Falsificación de Solicitudes con Direcciones Preferidas

Este documento define los paquetes de Negociación de Versión QUIC (Sección 6), que pueden usarse para negociar la versión QUIC utilizada entre dos endpoints. Sin embargo, este documento no especifica cómo se realizará esta negociación entre esta versión y las versiones futuras subsiguientes. En particular, los paquetes de Negociación de Versión no contienen ningún mecanismo para prevenir ataques de degradación de versión. Las versiones futuras de QUIC que usen paquetes de Negociación de Versión DEBEN definir un mecanismo que sea robusto contra ataques de degradación de versión.

Falsificación de Solicitud con Migración Falsificada

Las implementaciones deben limitar la capacidad de un atacante para dirigir una nueva conexión a una instancia de servidor particular. Idealmente, las decisiones de enrutamiento se toman independientemente de los valores seleccionados por el cliente, incluidas las direcciones. Una vez que se selecciona una instancia, se puede seleccionar un ID de conexión para que los paquetes posteriores se enruten a la misma instancia.

Falsificación de Solicitud con Negociación de Versión

La longitud de los paquetes QUIC puede revelar información sobre la longitud del contenido de esos paquetes. Se proporciona el frame PADDING para que los endpoints tengan cierta capacidad de ocultar la longitud del contenido del paquete; ver Sección 19.1.

Derrotar el análisis de tráfico es desafiante y es objeto de investigación activa. La longitud no es la única manera en que la información podría filtrarse. Los endpoints también podrían revelar información sensible a través de otros canales laterales, como el tiempo de los paquetes.

Relay Security

A continuación se presenta un análisis de Relay Request, Relay Response, Relay Intro y Hole Punch en SSU1.

Restricciones: Es importante que los Relays sean rápidos. Los viajes de ida y vuelta deben minimizarse. El ancho de banda y la CPU no son tan importantes.

SSU 1: Alice primero se conecta al introducer Bob, quien retransmite la solicitud a Charlie (que está detrás de un firewall). Después del hole punch, la sesión se establece entre Alice y Charlie como en un establecimiento directo.

Alice                         Bob                  Charlie
1. RelayRequest ---------------------->
2.      <-------------- RelayResponse    RelayIntro ----------->
3.      <-------------------------------------------- HolePunch
4. SessionRequest -------------------------------------------->
5.      <-------------------------------------------- SessionCreated
6. SessionConfirmed ------------------------------------------>

Autenticación: Relay Request y Relay Response no están autenticados de forma segura, ya que Alice y Bob normalmente no tienen una sesión existente; estos mensajes usan claves de introducción publicadas. El Relay Request/Response durante la sesión está permitido y es preferible si existe una sesión.

Relay Intro de Bob a Charlie debe estar en una sesión existente, por lo que se presume seguro.

Bob puede falsificar Relay Intros o cambiar IP/puerto desde el Relay Request. No hay mecanismos para vincular criptográficamente las solicitudes a las intros o prevenir o detectar de otra manera a Bobs maliciosos.

El hash del router de Bob no está publicado actualmente en el Router Info de Charlie, por lo que debe agregarse si queremos que los mensajes Alice-Bob sean autenticados. Además, otros parámetros SSU2 tendrían que publicarse en el Router Info de Charlie, o Alice tendría que buscar el Router Info de Bob en la base de datos de red, agregando retraso adicional. La autenticación agregaría un viaje de ida y vuelta entre Alice y Bob.

Al reenviar el hash del router de Alice a Charlie, Charlie podría determinar más fácilmente si desea recibir una conexión de Alice, verificando una lista de bloqueo local. No existe un mecanismo para que Charlie rechace el relay enviando un rechazo a través de Bob hacia Alice. No existe un mecanismo para que Charlie acepte el relay enviando una aceptación a través de Bob hacia Alice. Alice debe esperar el HolePunch, o simplemente enviar el SessionRequest a ciegas. El HolePunch puede provenir de un puerto diferente al que Alice esperaba, debido a NAT, lo que puede hacer más difícil reconocer de qué router provino el HolePunch.

Alice podría enviar su Router Info completo en la Relay Request a Bob, y reenviarlo a Charlie en la Relay Intro.

La Relay Request no contiene una marca de tiempo, por lo que no tiene prevención de reproducción. La IP de origen puede ser falsificada, para hacer que Charlie envíe un Hole Punch a cualquier IP/puerto. La Relay Request no está firmada, e incluso si estuviera firmada y marcada con tiempo, Charlie no tiene la Router Identity completa para poder verificar la firma.

El protocolo define un campo de desafío de longitud variable de 0-255 bytes. El desafío en el Relay Request se pasa a Charlie en el Relay Intro. Sin embargo, el protocolo no especifica cómo crear, usar o verificar el desafío, y no está implementado. Si el HolePunch contuviera el desafío, Alice podría correlacionar fácilmente el HolePunch con Charlie.

El nonce de cuatro bytes puede necesitar ser reemplazado o complementado por un ID de conexión de 8 bytes.

El mensaje vacío de Hole Punch es único y puede ser utilizado por observadores en el camino para identificar el protocolo, esto debería cambiarse.

Discusión Adicional sobre DPI

A continuación se presenta un análisis del Peer Test en SSU1.

Restricciones: No es particularmente importante que las Pruebas de Pares sean rápidas, o de bajo ancho de banda, o de bajo uso de CPU, excepto quizás en el arranque del router, donde preferimos que el router descubra su accesibilidad bastante rápidamente.

SSU 1:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
2.                          PeerTest-------------------->
3.                             <-------------------PeerTest
4.      <-------------------PeerTest

5.      <------------------------------------------PeerTest
6. PeerTest------------------------------------------>
7.      <------------------------------------------PeerTest

Debido a que la especificación de SSU1 es difícil de seguir, documentamos el contenido de los mensajes a continuación.

MessagePathAlice IP incl?Intro Key
1A->B sessionnoAlice
2B->C sessionyesAlice
3C->B sessionyesCharlie
4B->A sessionyesCharlie
5C->AyesCharlie
6A->CnoAlice
7C->AyesCharlie
Autenticación: Alice siempre elegirá un Bob con una sesión existente. Bob rechazará PeerTests de peers sin una sesión establecida. El mensaje 1 se envía dentro de la sesión. Por lo tanto, el mensaje 1 es seguro y autenticado.

Bob selecciona un Charlie con quien tiene una sesión existente. Los mensajes 2 y 3 se envían dentro de la sesión. Por lo tanto, los mensajes 2 y 3 son seguros y autenticados.

El Mensaje 4 debería enviarse dentro de la sesión; sin embargo, la especificación de SSU 1 anteriormente indicaba que se envía con la clave de introducción publicada de Alice, lo que significa que no está dentro de la sesión. Antes de la versión 0.9.52, Java I2P sí enviaba con la clave de introducción. A partir de la versión 0.9.52, la especificación establece que se debe usar la clave de sesión, y Java I2P envía el mensaje dentro de la sesión desde la versión 0.9.52.

Alice no debe tener una sesión existente con Charlie para que la prueba proceda; Alice aborta la prueba si Bob elige un Charlie que tiene una sesión con Alice. Por lo tanto, los mensajes 5-7 no son seguros y autenticados.

Todos los mensajes de Peer Test contienen un nonce de 4 bytes que es elegido por Alice. Este nonce no se usa criptográficamente.

Ataques posibles en los mensajes 5-7: por investigar.

El hash del router de Alice no es conocido por Charlie. El hash del router de Charlie no es conocido por Alice. Estos deben agregarse al protocolo si queremos que los mensajes de Alice-Charlie sean autenticados. Además, otros parámetros SSU2 tendrían que proporcionarse en los mensajes Peer Test, o Charlie tendría que buscar la Router Info de Alice en la base de datos de red, agregando retraso adicional. La autenticación agregaría un intercambio completo entre Charlie y Alice.

Al reenviar el hash del router de Alice a Charlie, Charlie podría determinar más fácilmente si desea participar en un Peer Test con Alice, verificando una lista de prohibiciones local.

El nonce de cuatro bytes puede necesitar ser reemplazado o complementado por un ID de conexión de 8 bytes.

Relay and Peer Test Design Goals

Relay y Peer Test tienen construcciones similares. En ambos casos, Alice solicita a Bob que reenvíe una petición de servicio a Charlie, y Charlie luego actúa sobre esa petición.

Problemas actuales de SSU1 Peer Test:

  • Peer Test no tiene protecciones contra un Bob malicioso
  • Peer Test no tiene forma de que Bob o Charlie rechacen una solicitud
  • Peer Test no tiene forma de que Alice conozca la identidad de Charlie o de que Alice rechace a un Charlie
  • Peer Test no tiene forma de que Charlie conozca la identidad de Alice o de que Charlie rechace a una Alice
  • Peer Test tiene su propio esquema de retransmisión ad-hoc
  • Peer Test requiere una máquina de estados compleja para saber qué mensaje corresponde a qué estado
  • Sin saber que Charlie la ha rechazado, Alice tratará la prueba como un fallo.

Problemas actuales de SSU1 Relay:

La mayoría de los problemas de Peer Test listados arriba también se aplican a Peer Test.

Tenemos los siguientes objetivos para mejorar la seguridad de Relay y Peer Test:

  • Charlie debe publicar suficiente información sobre sus introducers (Bobs) en la netdb para que Alice pueda validar la información si es necesario. Por ejemplo, publicar un hash de router para cada introducer permitiría a Alice, si el tiempo lo permite, obtener la información del router desde la netdb.

  • Proteger contra la suplantación de direcciones o amenazas en el camino que pueden suplantar, alterar, falsificar o repetir solicitudes de Alice a Bob. Bob debe asegurar que Alice es un router I2P real y que la solicitud y dirección de prueba presentadas son válidas.

  • Proteger contra Bobs maliciosos que pueden suplantar, alterar, falsificar o reproducir solicitudes reenviadas a Charlie. Charlie debe asegurar que tanto Alice como Bob son routers I2P reales y que la solicitud y dirección de prueba presentadas son válidas.

  • Bob debe recibir suficiente información de Alice para poder validar la solicitud y luego aceptarla o rechazarla. Bob debe tener un mecanismo para enviar la aceptación o el rechazo de vuelta a Alice. Bob nunca debe estar obligado a realizar la acción solicitada.

  • Charlie debe recibir suficiente información de Bob para poder validar la solicitud y luego aceptarla o rechazarla. Charlie debe tener un mecanismo para enviar la aceptación o rechazo de vuelta a Bob, para ser reenviado a Alice. Charlie nunca debe estar obligado a realizar la acción solicitada.

  • Alice debe poder validar que la respuesta reenviada a través de Bob realmente se originó desde Charlie.

  • Alice y Charlie deben poder validar que sus mensajes directos posteriores (no retransmitidos vía Bob) provienen de la fuente esperada y son routers I2P reales.

Los siguientes mecanismos pueden ayudar a lograr estos objetivos:

  • Marcas de tiempo

  • Firmas que utilizan la clave de firma del router

  • Usando datos de desafío incluidos en la solicitud

  • Cifrado usando la clave de cifrado del router

  • Envío de hashes de router, Router Identities o Router Infos, no solo IPs y puertos.

  • Validación de la información del router consultando la base de datos de red

  • Verificando información del router, IPs y puertos contra listas de bloqueo

  • Limitación de velocidad

  • Requiere el establecimiento de sesión

Estos posibles mecanismos pueden aumentar el tiempo de procesamiento y la latencia de las funciones de Relay o Peer Test. Todos los efectos deben ser evaluados.

El relaying entre versiones y las pruebas de peer también deberían ser soportados si es posible. Esto facilitará una transición gradual de SSU 1 a SSU 2. Las posibles combinaciones de versiones son:

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121Relay: yes? Peer Test: no
122no, use 1/2/1
211Relay: yes? Peer Test: no
212Relay: yes? Peer Test: no
221no, use 2/2/2
222yes

Objetivos de Seguridad

Summary

Dependemos de varios protocolos existentes, tanto dentro de I2P como de estándares externos, para obtener inspiración, orientación y reutilización de código:

  • Modelos de amenazas: De NTCP2 NTCP2, con amenazas adicionales significativas relevantes al transporte UDP según el análisis de QUIC RFC 9000 RFC 9001.

  • Opciones criptográficas: De NTCP2.

  • Handshake: Noise XK de NTCP2 y NOISE. Son posibles simplificaciones significativas a NTCP2 debido a la encapsulación (límites de mensaje inherentes) proporcionada por UDP.

  • Ofuscación de clave efímera de handshake: Adaptado de NTCP2 pero usando ChaCha20 de ECIES en lugar de AES.

  • Encabezados de paquete: Adaptado de WireGuard WireGuard y QUIC RFC 9000 RFC 9001.

  • Ofuscación de encabezados de paquetes: Adaptada de NTCP2 pero usando ChaCha20 de ECIES en lugar de AES.

  • Protección de cabeceras de paquetes: Adaptado de QUIC RFC 9001 y Nonces

  • Headers utilizados como datos asociados AEAD como en ECIES.

  • Numeración de paquetes: Adaptado de WireGuard WireGuard y QUIC RFC 9000 RFC 9001.

  • Mensajes: Adaptado de SSU

  • Fragmentación I2NP: Adaptado de SSU

  • Relay y Peer Testing: Adaptado de SSU

  • Firmas de datos de Relay y Peer Test: De la especificación de estructuras comunes Common

  • Formato de bloque: De NTCP2 y ECIES.

  • Relleno y opciones: De NTCP2 y ECIES.

  • Acks, nacks: Adaptado de QUIC RFC 9000.

  • Control de flujo: TBD

No hay primitivas criptográficas nuevas que no hayan sido utilizadas anteriormente en I2P.

Validación de Direcciones

Al igual que con otros transportes de I2P NTCP, NTCP2 y SSU 1, este transporte no es una facilidad de propósito general para la entrega de un flujo ordenado de bytes. Está diseñado para el transporte de mensajes I2NP. No se proporciona abstracción de “flujo”.

Además, al igual que SSU, contiene facilidades adicionales para el traversal de NAT facilitado por pares y pruebas de alcanzabilidad (conexiones entrantes).

En cuanto a SSU 1, NO proporciona entrega en orden de mensajes I2NP. Tampoco proporciona entrega garantizada de mensajes I2NP. Por eficiencia, o debido a la entrega fuera de orden de datagramas UDP o la pérdida de esos datagramas, los mensajes I2NP pueden ser entregados al extremo remoto fuera de orden, o pueden no ser entregados en absoluto. Un mensaje I2NP puede ser retransmitido múltiples veces si es necesario, pero la entrega puede eventualmente fallar sin causar que toda la conexión sea desconectada. Además, nuevos mensajes I2NP pueden continuar siendo enviados incluso mientras la retransmisión (recuperación de pérdidas) está ocurriendo para otros mensajes I2NP.

Este protocolo NO previene completamente la entrega duplicada de mensajes I2NP. El router debe hacer cumplir la expiración de I2NP y usar un filtro Bloom u otro mecanismo basado en el ID del mensaje I2NP. Consulte la sección Duplicación de Mensajes I2NP a continuación.

Noise Protocol Framework

Esta propuesta proporciona los requisitos basados en el Noise Protocol Framework NOISE (Revisión 33, 2017-10-04). Noise tiene propiedades similares al protocolo Station-To-Station (STS), que es la base del protocolo SSU. En la terminología de Noise, Alice es el iniciador, y Bob es el respondedor.

SSU2 se basa en el protocolo Noise Noise_XK_25519_ChaChaPoly_SHA256. (El identificador real para la función de derivación de clave inicial es “Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256” para indicar las extensiones I2P - ver sección KDF 1 a continuación)

NOTA: Este identificador es diferente al usado para NTCP2, porque los tres mensajes de handshake usan el encabezado como datos asociados.

Este protocolo Noise utiliza las siguientes primitivas:

  • Patrón de Handshake: XK Alice transmite su clave a Bob (X) Alice ya conoce la clave estática de Bob (K)

  • DH Function: X25519 X25519 DH con una longitud de clave de 32 bytes según se especifica en RFC 7748.

  • Función de Cifrado: ChaChaPoly AEAD_CHACHA20_POLY1305 según se especifica en RFC 7539 sección 2.8. Nonce de 12 bytes, con los primeros 4 bytes establecidos en cero.

  • Función Hash: SHA256 Hash estándar de 32 bytes, ya utilizado extensivamente en I2P.

Additions to the Framework

Esta propuesta define las siguientes mejoras a Noise_XK_25519_ChaChaPoly_SHA256. Estas generalmente siguen las pautas en NOISE sección 13.

  1. Los mensajes de handshake (Session Request, Created, Confirmed) incluyen un header de 16 o 32 bytes.

  2. Las cabeceras para los mensajes de handshake (Session Request, Created, Confirmed) se utilizan como entrada a mixHash() antes del cifrado/descifrado para vincular las cabeceras al mensaje.

  3. Los encabezados están cifrados y protegidos.

  4. Las claves efímeras en texto plano se ofuscan con cifrado ChaCha20 usando una clave e IV conocidos. Esto es más rápido que elligator2.

  5. El formato de carga útil está definido para los mensajes 1, 2, y la fase de datos. Por supuesto, esto no está definido en Noise.

La fase de datos utiliza un cifrado similar al de la fase de datos de Noise, pero no es compatible con ella.

Processing overhead estimate

Por determinar

Definitions

Definimos las siguientes funciones correspondientes a los bloques de construcción criptográficos utilizados.

ZEROLEN

zero-length byte array

H(p, d)

SHA-256 hash function that takes a personalization string p and data d, and
produces an output of length 32 bytes.
As defined in [NOISE](https://noiseprotocol.org/noise.html).
|| below means append.

Use SHA-256 as follows::

    H(p, d) := SHA-256(p || d)

MixHash(d)

SHA-256 hash function that takes a previous hash h and new data d,
and produces an output of length 32 bytes.
|| below means append.

Use SHA-256 as follows::

    MixHash(d) := h = SHA-256(h || d)

STREAM

The ChaCha20/Poly1305 AEAD as specified in [RFC 7539](https://tools.ietf.org/html/rfc7539).
S_KEY_LEN = 32 and S_IV_LEN = 12.

ENCRYPT(k, n, plaintext, ad)
    Encrypts plaintext using the cipher key k, and nonce n which MUST be unique for
    the key k.
    Associated data ad is optional.
    Returns a ciphertext that is the size of the plaintext + 16 bytes for the HMAC.

    The entire ciphertext must be indistinguishable from random if the key is secret.

DECRYPT(k, n, ciphertext, ad)
    Decrypts ciphertext using the cipher key k, and nonce n.
    Associated data ad is optional.
    Returns the plaintext.

DH

X25519 public key agreement system. Private keys of 32 bytes, public keys of 32
bytes, produces outputs of 32 bytes. It has the following
functions:

GENERATE_PRIVATE()
    Generates a new private key.

DERIVE_PUBLIC(privkey)
    Returns the public key corresponding to the given private key.

DH(privkey, pubkey)
    Generates a shared secret from the given private and public keys.

HKDF(salt, ikm, info, n)

A cryptographic key derivation function which takes some input key material ikm (which
should have good entropy but is not required to be a uniformly random string), a salt
of length 32 bytes, and a context-specific 'info' value, and produces an output
of n bytes suitable for use as key material.

Use HKDF as specified in [RFC 5869](https://tools.ietf.org/html/rfc5869), using the HMAC hash function SHA-256
as specified in [RFC 2104](https://tools.ietf.org/html/rfc2104). This means that SALT_LEN is 32 bytes max.

MixKey(d)

Use HKDF() with a previous chainKey and new data d, and
sets the new chainKey and k.
As defined in [NOISE](https://noiseprotocol.org/noise.html).

Use HKDF as follows::

    MixKey(d) := output = HKDF(chainKey, d, "", 64)
                 chainKey = output[0:31]
                 k = output[32:63]

Messages

Cada datagrama UDP contiene exactamente un mensaje. La longitud del datagrama (después de las cabeceras IP y UDP) es la longitud del mensaje. El relleno, si lo hay, se encuentra contenido en un bloque de relleno dentro del mensaje. En este documento, usamos los términos “datagrama” y “paquete” mayormente de manera intercambiable. Cada datagrama (o paquete) contiene un solo mensaje (a diferencia de QUIC, donde un datagrama puede contener múltiples paquetes QUIC). La “cabecera del paquete” es la parte después de la cabecera IP/UDP.

Excepción: El mensaje Session Confirmed es único en el sentido de que puede fragmentarse a través de múltiples paquetes. Consulte la sección Session Confirmed Fragmentation a continuación para obtener más información.

Todos los mensajes SSU2 tienen al menos 40 bytes de longitud. Cualquier mensaje de longitud 1-39 bytes es inválido. Todos los mensajes SSU2 tienen una longitud menor o igual a 1472 (IPv4) o 1452 (IPv6) bytes. El formato del mensaje se basa en mensajes Noise, con modificaciones para el encuadre y la indistinguibilidad. Las implementaciones que utilizan bibliotecas Noise estándar deben preprocesar los mensajes recibidos al formato de mensaje Noise estándar. Todos los campos cifrados son textos cifrados AEAD.

Los siguientes mensajes están definidos:

TypeMessageHeader LengthHeader Encr. Length
0SessionRequest3264
1SessionCreated3264
2SessionConfirmed1616
6Data1616
7PeerTest3232
9Retry3232
10Token Request3232
11HolePunch3232

Session Establishment

La secuencia de establecimiento estándar, cuando Alice tiene un token válido recibido previamente de Bob, es la siguiente:

Alice                           Bob

SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Cuando Alice no tiene un token válido, la secuencia de establecimiento es la siguiente:

Alice                           Bob

TokenRequest --------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Cuando Alice cree que tiene un token válido, pero Bob lo rechaza (quizás porque Bob se reinició), la secuencia de establecimiento es la siguiente:

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Bob puede rechazar una Solicitud de Sesión o Token respondiendo con un mensaje Retry que contenga un bloque de Terminación con un código de razón. Basándose en el código de razón, Alice no debería intentar otra solicitud durante cierto período de tiempo:

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry containing a Termination block

or

TokenRequest --------------------->
<---------------------------  Retry containing a Termination block

Usando la terminología de Noise, la secuencia de establecimiento y datos es la siguiente: (Propiedades de Seguridad del Payload)

XK(s, rs):           Authentication   Confidentiality
    <- s
    ...
    -> e, es                  0                2
    <- e, ee                  2                1
    -> s, se                  2                5
    <-                        2                5

Una vez que se ha establecido una sesión, Alice y Bob pueden intercambiar mensajes de datos.

Packet Header

Todos los paquetes comienzan con un encabezado ofuscado (cifrado). Hay dos tipos de encabezado, largo y corto. Ten en cuenta que los primeros 13 bytes (Destination Connection ID, número de paquete y tipo) son los mismos para todos los encabezados.

Contramedidas Genéricas contra Falsificación de Solicitudes

El encabezado largo es de 32 bytes. Se utiliza antes de que se cree una sesión, para Token Request, SessionRequest, SessionCreated y Retry. También se usa para mensajes de Peer Test y Hole Punch fuera de sesión.

Antes del cifrado del encabezado:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 0, 1, 7, 9, 10, or 11

  ver :: The protocol version, equal to 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: 8 bytes, unsigned big endian integer

  Token :: 8 bytes, unsigned big endian integer

Ataques Slowloris

El header corto tiene 16 bytes. Se utiliza para mensajes Session Created y para mensajes Data. Los mensajes no autenticados como Session Request, Retry y Peer Test siempre utilizarán el header largo.

Se requieren 16 bytes, porque el receptor debe descifrar los primeros 16 bytes para obtener el tipo de mensaje, y luego debe descifrar 16 bytes adicionales si es realmente un encabezado largo, como se indica por el tipo de mensaje.

Para Session Confirmed, antes del cifrado del encabezado:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, all zeros

  type :: The message type = 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

Consulte la sección Fragmentación de Sesión Confirmada a continuación para obtener más información sobre el campo frag.

Para mensajes de datos, antes del cifrado del encabezado:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|flag|moreflags|
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 6

  flag :: 1 byte flags:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-1: unused, set to 0 for future compatibility
         bits 0: when set to 1, immediate ack requested

  moreflags :: 2 bytes, unused, set to 0 for future compatibility

Ataques de Fragmentación y Reensamblaje de Stream

Los IDs de conexión deben generarse de forma aleatoria. Los IDs de origen y destino NO deben ser idénticos, para que un atacante en la ruta no pueda capturar y enviar un paquete de vuelta al originador que parezca válido. NO uses un contador para generar IDs de conexión, para que un atacante en la ruta no pueda generar un paquete que parezca válido.

A diferencia de QUIC, no cambiamos los ID de conexión durante o después del handshake, incluso después de un mensaje Retry. Los ID permanecen constantes desde el primer mensaje (Token Request o Session Request) hasta el último mensaje (Data with Termination). Además, los ID de conexión no cambian durante o después del path challenge o la migración de conexión.

También a diferencia de QUIC es que los IDs de conexión en las cabeceras están siempre cifrados en la cabecera. Ver más abajo.

Ataque de Compromiso de Flujo

Si no se envía ningún bloque de Número de Primer Paquete en el handshake, los paquetes se numeran dentro de una sola sesión, para cada dirección, comenzando desde 0, hasta un máximo de (2**32 -1). Una sesión debe terminarse, y crearse una nueva sesión, mucho antes de que se envíe el número máximo de paquetes.

Si se envía un bloque de Número de Primer Paquete en el handshake, los paquetes se numeran dentro de una sola sesión, para esa dirección, comenzando desde ese número de paquete. El número de paquete puede dar la vuelta durante la sesión. Cuando se ha enviado un máximo de 2**32 paquetes, regresando el número de paquete al número del primer paquete, esa sesión ya no es válida. Una sesión debe terminarse, y debe crearse una nueva sesión, mucho antes de que se envíe el número máximo de paquetes.

TODO rotación de claves, ¿reducir número máximo de paquetes?

Los paquetes de handshake que se determina que están perdidos se retransmiten completos, con el encabezado idéntico incluyendo el número de paquete. Los mensajes de handshake Session Request, Session Created y Session Confirmed DEBEN retransmitirse con el mismo número de paquete y contenido cifrado idéntico, para que se use el mismo hash encadenado para cifrar la respuesta. El mensaje Retry nunca se transmite.

Los paquetes de la fase de datos que se determinan perdidos nunca se retransmiten completos (excepto en la terminación, ver más abajo). Lo mismo aplica para los bloques contenidos dentro de los paquetes perdidos. En su lugar, la información que podría estar contenida en los bloques se envía nuevamente en paquetes nuevos según sea necesario. Los paquetes de datos nunca se retransmiten con el mismo número de paquete. Cualquier retransmisión del contenido del paquete (independientemente de si el contenido permanece igual o no) debe usar el siguiente número de paquete no utilizado.

Retransmitir un paquete completo sin cambios tal como está, con el mismo número de paquete, no está permitido por varias razones. Para información de contexto consulte QUIC RFC 9000 sección 12.3.

  • Es ineficiente almacenar paquetes para retransmisión
  • Un nuevo paquete de datos se ve diferente para un observador en la ruta, no puede saber que es retransmitido
  • Un nuevo paquete obtiene un bloque ack actualizado enviado con él, no el bloque ack anterior
  • Solo retransmites lo que es necesario. algunos fragmentos podrían haber sido ya retransmitidos una vez y confirmados
  • Puedes encajar tanto como necesites en cada paquete retransmitido si hay más pendiente
  • Los endpoints que rastrean todos los paquetes individuales con el propósito de detectar duplicados están en riesgo de acumular estado excesivo. Los datos requeridos para detectar duplicados pueden limitarse manteniendo un número de paquete mínimo por debajo del cual todos los paquetes son inmediatamente descartados.
  • Este esquema es mucho más flexible

Los nuevos paquetes se utilizan para transportar información que se determina que se ha perdido. En general, la información se envía nuevamente cuando se determina que un paquete que contiene esa información se ha perdido, y el envío cesa cuando un paquete que contiene esa información es (permanecen iguales) reconocido.

Excepción: Un paquete de fase de datos que contenga un bloque de Terminación puede, pero no es requerido que sea, retransmitido completo, tal como está. Ver la sección de Terminación de Sesión a continuación.

Los siguientes paquetes contienen un número de paquete aleatorio que es ignorado:

  • Solicitud de Sesión
  • Sesión Creada
  • Solicitud de Token
  • Reintentar
  • Prueba de Par
  • Perforación de Hoyo

Para Alice, la numeración de paquetes salientes comienza en 0 con Session Confirmed. Para Bob, la numeración de paquetes salientes comienza en 0 con el primer paquete Data, que debería ser un ACK del Session Confirmed. Los números de paquete en un ejemplo de handshake estándar serán:

Alice                           Bob

SessionRequest (r)    ------------>
<-------------   SessionCreated (r)
SessionConfirmed (0)  ------------>
<-------------             Data (0) (Ack-only)
Data (1)              ------------> (May be sent before Ack is received)
<-------------             Data (1)
Data (2)              ------------>
Data (3)              ------------>
Data (4)              ------------>
<-------------             Data (2)

r = random packet number (ignored)
Token Request, Retry, and Peer Test
also have random packet numbers.

Cualquier retransmisión de mensajes de handshake (SessionRequest, SessionCreated o SessionConfirmed) debe ser reenviada sin cambios, con el mismo número de paquete. No uses claves efímeras diferentes ni cambies la carga útil al retransmitir estos mensajes.

Denegación de Servicio entre Pares

El header (antes de la ofuscación y protección) siempre se incluye en los datos asociados para la función AEAD, para vincular criptográficamente el header con los datos.

Ataques de Notificación Explícita de Congestión

El cifrado de cabeceras tiene varios objetivos. Consulte la sección “Discusión Adicional de DPI” arriba para obtener antecedentes y suposiciones.

  • Prevenir que el DPI en línea identifique el protocolo
  • Prevenir patrones en una serie de mensajes en la misma conexión, excepto para retransmisiones de handshake
  • Prevenir patrones en mensajes del mismo tipo en diferentes conexiones
  • Prevenir descifrado de encabezados de handshake sin conocimiento de la clave de introducción encontrada en la netdb
  • Prevenir identificación de claves efímeras X25519 sin conocimiento de la clave de introducción encontrada en la netdb
  • Prevenir descifrado del número y tipo de paquete de la fase de datos por cualquier atacante en línea o fuera de línea
  • Prevenir inyección de paquetes de handshake válidos por un observador en el camino o fuera del camino sin conocimiento de la clave de introducción encontrada en la netdb
  • Prevenir inyección de paquetes de datos válidos por un observador en el camino o fuera del camino
  • Permitir clasificación rápida y eficiente de paquetes entrantes
  • Proporcionar resistencia al “probing” de modo que no haya respuesta a una Session Request incorrecta, o si hay una respuesta Retry, la respuesta no sea identificable como I2P sin conocimiento de la clave de introducción encontrada en la netdb
  • El Destination Connection ID no es información crítica, y está bien si puede ser descifrado por un observador con conocimiento de la clave de introducción encontrada en la netdb
  • El número de paquete de un paquete de fase de datos es un nonce AEAD y es información crítica. No debe ser descifrable por un observador incluso con conocimiento de la clave de introducción encontrada en la netdb. Ver Nonces.

Los encabezados se cifran con claves conocidas publicadas en la base de datos de red o calculadas posteriormente. En la fase de handshake, esto es solo para resistencia DPI, ya que la clave es pública y la clave y los nonces se reutilizan, por lo que efectivamente es solo ofuscación. Tenga en cuenta que el cifrado de encabezados también se utiliza para ofuscar las claves efímeras X (en Session Request) e Y (en Session Created).

Consulte la sección Manejo de Paquetes Entrantes a continuación para obtener orientación adicional.

Los bytes 0-15 de todos los headers están cifrados usando un esquema de protección de header mediante XOR con datos calculados a partir de claves conocidas, utilizando ChaCha20, similar a QUIC RFC 9001 y Nonces. Esto asegura que el header corto cifrado y la primera parte del header largo aparezcan como aleatorios.

Para Session Request y Session Created, los bytes 16-31 del encabezado largo y la clave efímera Noise de 32 bytes se cifran usando ChaCha20. Los datos sin cifrar son aleatorios, por lo que los datos cifrados parecerán ser aleatorios.

Para Retry, los bytes 16-31 del encabezado largo se cifran usando ChaCha20. Los datos sin cifrar son aleatorios, por lo que los datos cifrados parecerán ser aleatorios.

A diferencia del esquema de protección de encabezados QUIC RFC 9001, TODAS las partes de todos los encabezados, incluyendo los IDs de conexión de destino y origen, están cifradas. QUIC RFC 9001 y Nonces se enfocan principalmente en cifrar la parte “crítica” del encabezado, es decir, el número de paquete (nonce ChaCha20). Aunque cifrar el ID de sesión hace que la clasificación de paquetes entrantes sea un poco más compleja, hace que algunos ataques sean más difíciles. QUIC define diferentes IDs de conexión para diferentes fases, y para el desafío de ruta y migración de conexión. Aquí usamos los mismos IDs de conexión durante todo el proceso, ya que están cifrados.

Hay siete fases de claves de protección de encabezado:

  • Solicitud de Sesión y Solicitud de Token
  • Sesión Creada
  • Reintentar
  • Sesión Confirmada
  • Fase de Datos
  • Prueba de Par
  • Perforación de Agujero
MessageKey k_header_1Key k_header_2
Token RequestBob Intro KeyBob Intro Key
Session RequestBob Intro KeyBob Intro Key
Session CreatedBob Intro KeySee Session Request K
Session ConfirmedBob Intro KeySee Session Created K
RetryBob Intro KeyBob Intro Key
DataAlice/Bob Intro KeySee data phase KDF
Peer Test 5,7Alice Intro KeyAlice Intro Key
Peer Test 6Charlie Intro KeyCharlie Intro Key
Hole PunchAlice Intro KeyAlice Intro Key
El cifrado de header está diseñado para permitir la clasificación rápida de paquetes entrantes, sin heurísticas complejas o mecanismos de respaldo. Esto se logra utilizando la misma clave k_header_1 para casi todos los mensajes entrantes. Incluso cuando la IP de origen o el puerto de una conexión cambia debido a un cambio real de IP o comportamiento NAT, el paquete puede ser rápidamente mapeado a una sesión con una sola búsqueda del ID de conexión.

Tenga en cuenta que Session Created y Retry son los ÚNICOS mensajes que requieren procesamiento de respaldo para k_header_1 para descifrar el Connection ID, porque utilizan la clave intro del remitente (Bob). TODOS los demás mensajes utilizan la clave intro del receptor para k_header_1. El procesamiento de respaldo solo necesita buscar conexiones salientes pendientes por IP/puerto de origen.

Si el procesamiento de respaldo por IP/puerto de origen no logra encontrar una conexión saliente pendiente, podría haber varias causas:

  • No es un mensaje SSU2
  • Un mensaje SSU2 corrupto
  • La respuesta está falsificada o modificada por un atacante
  • Bob tiene un NAT simétrico
  • Bob cambió la IP o puerto durante el procesamiento del mensaje
  • Bob envió la respuesta a través de una interfaz diferente

Aunque es posible un procesamiento de respaldo adicional para intentar encontrar la conexión saliente pendiente y descifrar el ID de conexión usando el k_header_1 para esa conexión, probablemente no sea necesario. Si Bob tiene problemas con su NAT o enrutamiento de paquetes, probablemente sea mejor dejar que la conexión falle. Este diseño depende de que los endpoints mantengan una dirección estable durante la duración del handshake.

Consulta la sección de Manejo de Paquetes Entrantes a continuación para obtener pautas adicionales.

Consulta las secciones individuales de KDF a continuación para la derivación de las claves de cifrado de encabezado para esa fase.

Oráculo de Reinicio sin Estado

// incoming encrypted packet
  packet = incoming encrypted packet
  len = packet.length

  // take the next-to-last 12 bytes of the packet
  iv = packet[len-24:len-13]
  k_header_1 = header encryption key 1
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_1, iv, data)

  // encrypt the first part of the header by XORing with the mask
  packet[0:7] ^= mask[0:7]

  // take the last 12 bytes of the packet
  iv = packet[len-12:len-1]
  k_header_2 = header encryption key 2
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_2, iv, data)

  // encrypt the second part of the header by XORing with the mask
  packet[8:15] ^= mask[0:7]


  // For Session Request and Session Created only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header and the ephemeral key
  packet[16:63] = ChaCha20.encrypt(k_header_2, iv, packet[16:63])


  // For Retry, Token Request, Peer Test, and Hole Punch only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header
  packet[16:31] = ChaCha20.encrypt(k_header_2, iv, packet[16:31])

Esta KDF utiliza los últimos 24 bytes del paquete como el IV para las dos operaciones ChaCha20. Como todos los paquetes terminan con un MAC de 16 bytes, esto requiere que todas las cargas útiles de paquetes tengan un mínimo de 8 bytes. Este requisito se documenta adicionalmente en las secciones de mensaje a continuación.

Degradación de Versión

Después de descifrar los primeros 8 bytes del encabezado, el receptor conocerá el Destination Connection ID. A partir de ahí, el receptor sabe qué clave de cifrado de encabezado usar para el resto del encabezado, basándose en la fase de clave de la sesión.

Al descifrar los siguientes 8 bytes del encabezado se revelará el tipo de mensaje y se podrá determinar si es un encabezado corto o largo. Si es un encabezado largo, el receptor debe validar los campos de versión y netid. Si la versión es != 2, o el netid es != el valor esperado (generalmente 2, excepto en redes de prueba), el receptor debe descartar el mensaje.

Packet Integrity

Todos los mensajes contienen tres o cuatro partes:

  • El encabezado del mensaje
  • Solo para Session Request y Session Created, una clave efímera
  • Una carga útil cifrada con ChaCha20
  • Un MAC Poly1305

En todos los casos, el header (y si está presente, la clave efímera) está vinculado al MAC de autenticación para asegurar que todo el mensaje esté íntegro.

  • Para los mensajes de handshake Session Request, Session Created y Session Confirmed, el encabezado del mensaje se procesa con mixHash() antes de la fase de procesamiento Noise
  • La clave efímera, si está presente, está cubierta por un misHash() estándar de Noise
  • Para mensajes fuera del handshake Noise, el encabezado se utiliza como Datos Asociados para el cifrado ChaCha20/Poly1305.

Los manejadores de paquetes entrantes siempre deben descifrar la carga útil ChaCha20 y validar el MAC antes de procesar el mensaje, con una excepción: Para mitigar ataques DoS de paquetes con direcciones falsificadas que contienen mensajes Session Request aparentes con un token inválido, un manejador NO necesita intentar descifrar y validar el mensaje completo (requiriendo una operación DH costosa además del descifrado ChaCha20/Poly1305). El manejador puede responder con un mensaje Retry usando los valores encontrados en el encabezado del mensaje Session Request.

Authenticated Encryption

Hay tres instancias separadas de cifrado autenticado (CipherStates). Una durante la fase de handshake, y dos (transmisión y recepción) para la fase de datos. Cada una tiene su propia clave de una KDF.

Los datos cifrados/autenticados se representarán como

+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   Encrypted and authenticated data    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Ataques Dirigidos por Enrutamiento

Formato de datos cifrado y autenticado.

Entradas a las funciones de cifrado/descifrado:


k :: 32 byte cipher key, as generated from KDF

  nonce :: Counter-based nonce, 12 bytes.
           Starts at 0 and incremented for each message.
           First four bytes are always zero.
           Last eight bytes are the counter, little-endian encoded.
           Maximum value is 2**64 - 2.
           Connection must be dropped and restarted after
           it reaches that value.
           The value 2**64 - 1 must never be sent.

  ad :: In handshake phase:
        Associated data, 32 bytes.
        The SHA256 hash of all preceding data.
        In data phase:
        The packet header, 16 bytes.

  data :: Plaintext data, 0 or more bytes

Salida de la función de cifrado, entrada de la función de descifrado:


+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |       ChaCha20 encrypted data         |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Poly1305 Message Authentication Code |
  +              (MAC)                    +
  |             16 bytes                  |
  +----+----+----+----+----+----+----+----+

  encrypted data :: Same size as plaintext data, 0 - 65519 bytes

  MAC :: Poly1305 message authentication code, 16 bytes

Para ChaCha20, lo que se describe aquí corresponde a RFC 7539, que también se utiliza de manera similar en TLS RFC 7905.

Análisis de Tráfico

  • Dado que ChaCha20 es un cifrado de flujo, los textos en claro no necesitan ser rellenados. Los bytes adicionales del flujo de claves se descartan.

  • La clave para el cifrado (256 bits) se acuerda mediante el SHA256 KDF. Los detalles del KDF para cada mensaje están en secciones separadas a continuación.

AEAD Error Handling

  • En todos los mensajes, el tamaño del mensaje AEAD se conoce de antemano. En caso de fallo de autenticación AEAD, el destinatario debe detener el procesamiento adicional del mensaje y descartar el mensaje.

  • Bob debería mantener una lista negra de IPs con fallos repetidos.

KDF for Session Request

La Función de Derivación de Claves (KDF) genera una clave de cifrado de fase de handshake k a partir del resultado DH, utilizando HMAC-SHA256(key, data) como se define en RFC 2104. Estas son las funciones InitializeSymmetric(), MixHash(), y MixKey(), exactamente como se definen en la especificación Noise.

KDF for Initial ChainKey


// Define protocol_name.
  Set protocol_name = "Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256"
   (52 bytes, US-ASCII encoded, no NULL termination).

  // Define Hash h = 32 bytes
  h = SHA256(protocol_name);

  Define ck = 32 byte chaining key. Copy the h data to ck.
  Set ck = h

  // MixHash(null prologue)
  h = SHA256(h);

  // up until here, can all be precalculated by Alice for all outgoing connections

  // Bob's X25519 static keys
  // bpk is published in routerinfo
  bsk = GENERATE_PRIVATE()
  bpk = DERIVE_PUBLIC(bsk)

  // Bob static key
  // MixHash(bpk)
  // || below means append
  h = SHA256(h || bpk);

  // Bob introduction key
  // bik is published in routerinfo
  bik = RANDOM(32)

  // up until here, can all be precalculated by Bob for all incoming connections

KDF for Session Request


// MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Alice's X25519 ephemeral keys
  aesk = GENERATE_PRIVATE()
  aepk = DERIVE_PUBLIC(aesk)

  // Alice ephemeral key X
  // MixHash(aepk)
  h = SHA256(h || aepk);

  // h is used as the associated data for the AEAD in Session Request
  // Retain the Hash h for the Session Created KDF


  End of "e" message pattern.

  This is the "es" message pattern:

  // DH(e, rs) == DH(s, re)
  sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  // ChaChaPoly parameters to encrypt/decrypt
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chainKey for Session Created KDF


  End of "es" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2 = bik

  // Header encryption keys for next message (Session Created)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessCreateHeader", 32)

  // Header encryption keys for next message (Retry)
  k_header_1 = bik
  k_header_2 = bik

SessionRequest (Type 0)

Alice envía a Bob, ya sea como el primer mensaje en el handshake, o en respuesta a un mensaje Retry. Bob responde con un mensaje Session Created. Tamaño: 80 + tamaño del payload. Tamaño mínimo: 88

Si Alice no tiene un token válido, Alice debería enviar un mensaje Token Request en lugar de un Session Request, para evitar la sobrecarga de cifrado asimétrico al generar un Session Request.

Encabezado largo. Contenido Noise: Clave efímera de Alice X Carga útil Noise: DateTime y otros bloques Tamaño máximo de carga útil: MTU - 108 (IPv4) o MTU - 128 (IPv6). Para MTU 1280: La carga útil máxima es 1172 (IPv4) o 1152 (IPv6). Para MTU 1500: La carga útil máxima es 1392 (IPv4) o 1372 (IPv6).

Propiedades de Seguridad del Payload:

XK(s, rs):           Authentication   Confidentiality
    -> e, es                  0                2

    Authentication: None (0).
    This payload may have been sent by any party, including an active attacker.

    Confidentiality: 2.
    Encryption to a known recipient, forward secrecy for sender compromise
    only, vulnerable to replay.  This payload is encrypted based only on DHs
    involving the recipient's static key pair.  If the recipient's static
    private key is compromised, even at a later date, this payload can be
    decrypted.  This message can also be replayed, since there's no ephemeral
    contribution from the recipient.

    "e": Alice generates a new ephemeral key pair and stores it in the e
         variable, writes the ephemeral public key as cleartext into the
         message buffer, and hashes the public key along with the old h to
         derive a new h.

    "es": A DH is performed between the Alice's ephemeral key pair and the
          Bob's static key pair.  The result is hashed along with the old ck to
          derive a new ck and k, and n is set to zero.

El valor X se cifra para garantizar la indistinguibilidad y unicidad de la carga útil, las cuales son contramedidas DPI necesarias. Utilizamos cifrado ChaCha20 para lograr esto, en lugar de alternativas más complejas y lentas como elligator2. El cifrado asimétrico con la clave pública del router de Bob sería demasiado lento. El cifrado ChaCha20 utiliza la clave de introducción de Bob tal como se publica en la base de datos de red.

El cifrado ChaCha20 es solo para resistencia DPI. Cualquier parte que conozca la clave de introducción de Bob, que se publica en la base de datos de la red, puede descifrar el encabezado y el valor X en este mensaje.

Contenidos sin procesar:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |    See Header Encryption KDF          |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key n=0     +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       X, ChaCha20 encrypted           +
  |       with Bob intro key n=0          |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |  k defined in KDF for Session Request |
  +  n = 0                                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  X :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted X)

Datos sin cifrar (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                   X                   |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |     see below for allowed blocks      |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Alice, ignored

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: 0 if not previously received from Bob

  X :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Bloque DateTime
  • Bloque Options (opcional)
  • Bloque Relay Tag Request (opcional)
  • Bloque Padding (opcional)

El tamaño mínimo del payload es de 8 bytes. Dado que el bloque DateTime es de solo 7 bytes, debe estar presente al menos otro bloque.

Notes

  • El valor X único en el bloque inicial de ChaCha20 asegura que el texto cifrado sea diferente para cada sesión.

  • Para proporcionar resistencia contra el sondeo, Bob no debería enviar un mensaje Retry en respuesta a un mensaje Session Request a menos que los campos de tipo de mensaje, versión de protocolo e ID de red en el mensaje Session Request sean válidos.

  • Bob debe rechazar conexiones donde el valor de timestamp esté muy alejado del tiempo actual. Llamemos “D” al delta de tiempo máximo. Bob debe mantener una caché local de valores de handshake previamente utilizados y rechazar duplicados, para prevenir ataques de replay. Los valores en la caché deben tener una vida útil de al menos 2*D. Los valores de caché dependen de la implementación, sin embargo se puede usar el valor X de 32 bytes (o su equivalente cifrado). Rechazar enviando un mensaje Retry que contenga un token cero y un bloque de terminación.

  • Las claves efímeras Diffie-Hellman nunca deben reutilizarse, para prevenir ataques criptográficos, y la reutilización será rechazada como un ataque de repetición.

  • Las opciones “KE” y “auth” deben ser compatibles, es decir, el secreto compartido K debe tener el tamaño apropiado. Si se agregan más opciones “auth”, esto podría cambiar implícitamente el significado de la bandera “KE” para usar un KDF diferente o un tamaño de truncamiento diferente.

  • Bob debe validar que la clave efímera de Alice es un punto válido en la curva aquí.

  • El padding debe limitarse a una cantidad razonable. Bob puede rechazar conexiones con padding excesivo. Bob especificará sus opciones de padding en Session Created. Directrices mín/máx por determinar. ¿Tamaño aleatorio de 0 a 31 bytes mínimo? (Distribución por determinar, ver Apéndice A.) TODO A MENOS QUE se aplique un tamaño mínimo de paquete para PMTU.

  • En la mayoría de errores, incluyendo AEAD, DH, replay aparente, o fallo de validación de clave, Bob debería detener el procesamiento adicional de mensajes y descartar el mensaje sin responder.

  • Bob PUEDE enviar un mensaje Retry que contenga un token cero y un bloque Termination con un código de razón de desviación de reloj si la marca de tiempo en el bloque DateTime está demasiado desviada.

  • Mitigación DoS: DH es una operación relativamente costosa. Al igual que con el protocolo NTCP anterior, los routers deben tomar todas las medidas necesarias para prevenir el agotamiento de CPU o conexiones. Establecer límites en conexiones activas máximas y configuraciones de conexión máximas en progreso. Aplicar timeouts de lectura (tanto por lectura como total para “slowloris”). Limitar conexiones repetidas o simultáneas desde la misma fuente. Mantener listas negras para fuentes que fallan repetidamente. No responder al fallo AEAD. Alternativamente, responder con un mensaje Retry antes de la operación DH y validación AEAD.

  • Campo “ver”: El protocolo Noise general, extensiones y protocolo SSU2 incluyendo especificaciones de carga útil, indicando SSU2. Este campo puede usarse para indicar soporte para cambios futuros.

  • El campo network ID se utiliza para identificar rápidamente conexiones entre redes diferentes. Si este campo no coincide con el network ID de Bob, Bob debe desconectar y bloquear conexiones futuras.

  • Bob debe descartar el mensaje si el ID de Conexión de Origen es igual al ID de Conexión de Destino.

KDF for Session Created and Session Confirmed part 1


// take h saved from Session Request KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Request)

  // MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Bob's X25519 ephemeral keys
  besk = GENERATE_PRIVATE()
  bepk = DERIVE_PUBLIC(besk)

  // h is from KDF for Session Request
  // Bob ephemeral key Y
  // MixHash(bepk)
  h = SHA256(h || bepk);

  // h is used as the associated data for the AEAD in Session Created
  // Retain the Hash h for the Session Confirmed KDF

  End of "e" message pattern.

  This is the "ee" message pattern:

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chaining key ck for Session Confirmed KDF

  End of "ee" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Request KDF above

  // Header protection keys for next message (Session Confirmed)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32)

Migración de Conexión

Bob envía a Alice, en respuesta a un mensaje Session Request. Alice responde con un mensaje Session Confirmed. Tamaño: 80 + tamaño del payload. Tamaño Mínimo: 88

Contenido Noise: Clave efímera Y de Bob Carga útil Noise: DateTime, Address, y otros bloques Tamaño máximo de carga útil: MTU - 108 (IPv4) o MTU - 128 (IPv6). Para MTU 1280: Carga útil máxima es 1172 (IPv4) o 1152 (IPv6). Para MTU 1500: Carga útil máxima es 1392 (IPv4) o 1372 (IPv6).

Propiedades de Seguridad del Payload:

XK(s, rs):           Authentication   Confidentiality
    <- e, ee                  2                1

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 1.
    Encryption to an ephemeral recipient.
    This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
    However, the sender has not authenticated the recipient,
    so this payload might be sent to any party, including an active attacker.


    "e": Bob generates a new ephemeral key pair and stores it in the e variable,
    writes the ephemeral public key as cleartext into the message buffer,
    and hashes the public key along with the old h to derive a new h.

    "ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
    The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

El valor Y se cifra para garantizar la indistinguibilidad y unicidad de la carga útil, que son contramedidas DPI necesarias. Utilizamos cifrado ChaCha20 para lograr esto, en lugar de alternativas más complejas y lentas como elligator2. El cifrado asimétrico a la clave pública del router de Alice sería demasiado lento. El cifrado ChaCha20 utiliza la clave de introducción de Bob, tal como se publica en la base de datos de red.

El cifrado ChaCha20 es solo para resistencia DPI. Cualquier parte que conozca la clave de introducción de Bob, que está publicada en la base de datos de red, y haya capturado los primeros 32 bytes de Session Request, puede descifrar el valor Y en este mensaje.

Contenidos sin procesar:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with derived key n=0       +
  |  See Header Encryption KDF            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       Y, ChaCha20 encrypted           +
  |       with derived key n=0            |
  +              (32 bytes)               +
  |       See Header Encryption KDF       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in KDF for Session Created +
  |  n = 0; see KDF for associated data   |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Y :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted Y)

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                  Y                    |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |      see below for allowed blocks     |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: The Source Connection ID
                               received from Alice in Session Request

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Bob, ignored

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Session Request

  Token :: 0 (unused)

  Y :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Bloque DateTime
  • Bloque Address
  • Bloque Relay Tag (opcional)
  • Bloque New Token (opcional)
  • Bloque First Packet Number (opcional)
  • Bloque Options (opcional)
  • Bloque Termination (no recomendado, enviar en un mensaje de reintento en su lugar)
  • Bloque Padding (opcional)

El tamaño mínimo de payload es de 8 bytes. Dado que los bloques DateTime y Address suman más que eso, el requisito se cumple únicamente con esos dos bloques.

Notes

  • Alice debe validar que la clave efímera de Bob es un punto válido en la curva aquí.

  • El padding debe limitarse a una cantidad razonable. Alice puede rechazar conexiones con padding excesivo. Alice especificará sus opciones de padding en Session Confirmed. Pautas mín/máx por determinar. ¿Tamaño aleatorio de 0 a 31 bytes mínimo? (Distribución por determinar, ver Apéndice A.) TODO A MENOS QUE se aplique un tamaño mínimo de paquete para PMTU.

  • En cualquier error, incluyendo AEAD, DH, timestamp, aparente replay, o falla de validación de clave, Alice debe detener el procesamiento adicional de mensajes y cerrar la conexión sin responder.

  • Alice debe rechazar conexiones donde el valor de timestamp esté demasiado alejado del tiempo actual. Llamemos a la delta máxima de tiempo “D”. Alice debe mantener una caché local de valores de handshake previamente utilizados y rechazar duplicados, para prevenir ataques de replay. Los valores en la caché deben tener una vida útil de al menos 2*D. Los valores de caché dependen de la implementación, sin embargo se puede usar el valor Y de 32 bytes (o su equivalente cifrado).

  • Alice debe descartar el mensaje si la IP y puerto de origen no coinciden con la IP y puerto de destino del Session Request.

  • Alice debe descartar el mensaje si los IDs de Conexión de Destino y Origen no coinciden con los IDs de Conexión de Origen y Destino de la Solicitud de Sesión.

  • Bob envía un bloque de etiqueta de retransmisión si lo solicita Alice en la Solicitud de Sesión.

Issues

  • ¿Incluir opciones de relleno mín/máx aquí?

KDF for Session Confirmed part 1, using Session Created KDF


// take h saved from Session Created KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Created)

  // MixHash(header)
  h = SHA256(h || header)
  // h is used as the associated data for the AEAD in Session Confirmed part 1, below

  This is the "s" message pattern:

  // Alice's X25519 static keys
  ask = GENERATE_PRIVATE()
  apk = DERIVE_PUBLIC(ask)

  // AEAD parameters
  // k is from Session Request
  n = 1
  ad = h
  ciphertext = ENCRYPT(k, n++, apk, ad)

  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // h is used as the associated data for the AEAD in Session Confirmed part 2

  End of "s" message pattern.

  // Header encryption keys for this message
  See Session Confirmed part 2 below

KDF for Session Confirmed part 2


This is the "se" message pattern:

  // DH(ask, bepk) == DH(besk, apk)
  sharedSecret = DH(ask, bepk) = DH(besk, apk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // h from Session Confirmed part 1 is used as the associated data for the AEAD in Session Confirmed part 2
  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // retain the chaining key ck for the data phase KDF
  // retain the hash h for the data phase KDF

  End of "se" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Created KDF above

  // Header protection keys for data phase
  See data phase KDF below

SessionConfirmed (Type 2)

Alice envía a Bob, en respuesta a un mensaje Session Created. Bob responde inmediatamente con un mensaje Data que contiene un bloque ACK. Tamaño: 80 + tamaño del payload. Tamaño Mínimo: Aproximadamente 500 (el tamaño mínimo del bloque router info es de aproximadamente 420 bytes)

Contenido Noise: clave estática de Alice Parte 1 de payload Noise: Ninguna Parte 2 de payload Noise: RouterInfo de Alice, y otros bloques Tamaño máximo de payload: MTU - 108 (IPv4) o MTU - 128 (IPv6). Para MTU 1280: El payload máximo es 1172 (IPv4) o 1152 (IPv6). Para MTU 1500: El payload máximo es 1392 (IPv4) o 1372 (IPv6).

Propiedades de Seguridad del Payload:

XK(s, rs):           Authentication   Confidentiality
    -> s, se                  2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).  The
    sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key
    pair.  Assuming the corresponding private keys are secure, this
    authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.  This payload is
    encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
    DH with the recipient's static key pair.  Assuming the ephemeral private
    keys are secure, and the recipient is not being actively impersonated by an
    attacker that has stolen its static private key, this payload cannot be
    decrypted.

    "s": Alice writes her static public key from the s variable into the
    message buffer, encrypting it, and hashes the output along with the old h
    to derive a new h.

    "se": A DH is performed between the Alice's static key pair and the Bob's
    ephemeral key pair.  The result is hashed along with the old ck to derive a
    new ck and k, and n is set to zero.

Esto contiene dos frames ChaChaPoly. El primero es la clave pública estática cifrada de Alice. El segundo es el payload Noise: el RouterInfo cifrado de Alice, opciones opcionales y padding opcional. Utilizan claves diferentes, porque la función MixKey() es llamada entre ellos.

Contenidos sin procesar:

+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 frame (32 bytes)           |
  +   Encrypted and authenticated data    +
  +   Alice static key S                  +
  | k defined in KDF for Session Created  |
  +     n = 1                             +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  + Length varies (remainder of packet)   +
  |                                       |
  +   ChaChaPoly frame                    +
  |   Encrypted and authenticated         |
  +   see below for allowed blocks        +
  |                                       |
  +     k defined in KDF for              +
  |     Session Confirmed part 2          |
  +     n = 0                             +
  |     see KDF for associated data       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
       inside 48 byte ChaChaPoly frame

Datos no cifrados (etiquetas de autenticación Poly1305 no mostradas):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |              S                        |
  +       Alice static key                +
  |          (32 bytes)                   |
  +                                       +
  |                                       |
  +                                       +
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |        Noise Payload                  |
  +        (length varies)                +
  |        see below for allowed blocks   |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As sent in Session Request,
                               or one received in Session Confirmed?

  Packet Number :: 0 always, for all fragments, even if retransmitted

  type :: 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

  S :: 32 bytes, Alice's X25519 static key, little endian

Payload

  • Bloque RouterInfo (debe ser el primer bloque)
  • Bloque Options (opcional)
  • Bloque New Token (opcional)
  • Bloque Relay Request (opcional)
  • Bloque Peer Test (opcional)
  • Bloque First Packet Number (opcional)
  • Bloques I2NP, First Fragment, o Follow-on Fragment (opcionales, pero probablemente sin espacio)
  • Bloque Padding (opcional)

El tamaño mínimo de carga útil es de 8 bytes. Dado que el bloque RouterInfo será considerablemente mayor que eso, el requisito se cumple solo con ese bloque.

Notes

  • Bob debe realizar la validación habitual de Router Info. Asegurar que el tipo de firma sea compatible, verificar la firma, verificar que la marca de tiempo esté dentro de los límites, y cualquier otra verificación necesaria. Ver más abajo las notas sobre el manejo de Router Infos fragmentados.

  • Bob debe verificar que la clave estática de Alice recibida en el primer frame coincida con la clave estática en el Router Info. Bob debe primero buscar en el Router Info una Dirección de Router NTCP o SSU2 con una opción de versión (v) coincidente. Ver las secciones de Router Info Publicado y Router Info No Publicado a continuación. Ver a continuación las notas sobre el manejo de Router Infos fragmentados.

  • Si Bob tiene una versión anterior del RouterInfo de Alice en su netdb, verificar que la clave estática en la información del router sea la misma en ambos, si está presente, y si la versión anterior tiene menos de XXX de antigüedad (ver tiempo de rotación de clave abajo)

  • Bob debe validar que la clave estática de Alice es un punto válido en la curva aquí.

  • Se deben incluir opciones para especificar parámetros de relleno.

  • En caso de cualquier error, incluyendo fallo de validación AEAD, RI, DH, timestamp, o clave, Bob debe detener el procesamiento adicional de mensajes y cerrar la conexión sin responder.

  • Contenido del frame de la parte 2 del mensaje 3: El formato de este frame es el mismo que el formato de los frames de la fase de datos, excepto que la longitud del frame es enviada por Alice en la Session Request. Ver más abajo para el formato del frame de la fase de datos. El frame debe contener de 1 a 4 bloques en el siguiente orden:

    1. Bloque de Router Info de Alice (requerido)
    2. Bloque de opciones (opcional)
    3. Bloques I2NP (opcional)
    4. Bloque de padding (opcional) Este frame nunca debe contener ningún otro tipo de bloque. TODO: ¿qué pasa con relay y peer test?
  • Se recomienda el bloque de relleno de la parte 2 del mensaje 3.

  • Puede que no haya espacio, o solo una pequeña cantidad de espacio, disponible para bloques I2NP, dependiendo del MTU y el tamaño del Router Info. NO incluyas bloques I2NP si el Router Info está fragmentado. La implementación más simple puede ser nunca incluir bloques I2NP en el mensaje Session Confirmed, y enviar todos los bloques I2NP en mensajes Data posteriores. Consulta la sección de bloques Router Info a continuación para el tamaño máximo de bloque.

Session Confirmed Fragmentation

El mensaje Session Confirmed debe contener la Router Info completa firmada de Alice para que Bob pueda realizar varias verificaciones requeridas:

  • La clave estática “s” en el RI coincide with la clave estática en el handshake
  • La clave de introducción “i” en el RI debe ser extraída y válida, para ser utilizada en la fase de datos
  • La firma del RI es válida

Desafortunadamente, la Router Info, incluso cuando está comprimida con gzip en el bloque RI, puede exceder el MTU. Por lo tanto, el Session Confirmed puede ser fragmentado a través de dos o más paquetes. Este es el ÚNICO caso en el protocolo SSU2 donde una carga útil protegida por AEAD es fragmentada a través de dos o más paquetes.

Los encabezados para cada paquete se construyen de la siguiente manera:

  • TODOS los headers son headers cortos con el mismo número de paquete 0
  • TODOS los headers contienen un campo “frag”, con el número de fragmento y el número total de fragmentos
  • El header no cifrado del fragmento 0 es el dato asociado (AD) para el mensaje “jumbo”
  • Cada header se cifra usando los últimos 24 bytes de datos en ESE paquete

Construye la serie de paquetes de la siguiente manera:

  • Crear un solo bloque RI (fragmento 0 de 1 en el campo frag del bloque RI). No utilizamos fragmentación de bloques RI, eso era para un método alternativo de resolver el mismo problema.
  • Crear un payload “jumbo” con el bloque RI y cualquier otro bloque a incluir
  • Calcular el tamaño total de datos (sin incluir el encabezado), que es el tamaño del payload + 64 bytes para la clave estática y dos MACs
  • Calcular el espacio disponible en cada paquete, que es la MTU menos el encabezado IP (20 o 40), menos el encabezado UDP (8), menos el encabezado corto SSU2 (16). El overhead total por paquete es 44 (IPv4) o 64 (IPv6).
  • Calcular el número de paquetes.
  • Calcular el tamaño de los datos en el último paquete. Debe ser mayor que o igual a 24 bytes, para que funcione el cifrado del encabezado. Si es demasiado pequeño, agregar un bloque de padding, O incrementar el tamaño del bloque de padding si ya está presente, O reducir el tamaño de uno de los otros paquetes para que el último paquete sea lo suficientemente grande.
  • Crear el encabezado no cifrado para el primer paquete, con el número total de fragmentos en el campo frag, y cifrar el payload “jumbo” con Noise, usando el encabezado como AD, como es habitual.
  • Dividir el paquete jumbo cifrado en fragmentos
  • Agregar un encabezado no cifrado para cada fragmento 1-n
  • Cifrar el encabezado para cada fragmento 0-n. Cada encabezado usa las MISMAS k_header_1 y k_header_2 como se define arriba en la KDF de Session Confirmed.
  • Transmitir todos los fragmentos

Proceso de reensamblaje:

Cuando Bob recibe cualquier mensaje Session Confirmed, descifra el encabezado, inspecciona el campo frag, y determina que el Session Confirmed está fragmentado. No descifra (y no puede descifrar) el mensaje hasta que todos los fragmentos sean recibidos y reensamblados.

  • Preservar el header del fragmento 0, ya que se utiliza como Noise AD
  • Descartar los headers de otros fragmentos antes del reensamblaje
  • Reensamblar el payload “jumbo”, con el header del fragmento 0 como AD, y descifrar con Noise
  • Validar el bloque RI como de costumbre
  • Proceder a la fase de datos y enviar ACK 0, como de costumbre

No existe un mecanismo para que Bob confirme fragmentos individuales. Cuando Bob recibe todos los fragmentos, los reensambla, descifra y valida el contenido, Bob realiza un split() como es habitual, entra en la fase de datos y envía un ACK del paquete número 0.

Si Alice no recibe un ACK del paquete número 0, debe retransmitir todos los paquetes de sesión confirmada tal como están.

Ejemplos:

Para MTU de 1500 sobre IPv6, la carga útil máxima es 1372, la sobrecarga del bloque RI es 5, el tamaño máximo de datos RI (comprimidos con gzip) es 1367 (asumiendo que no hay otros bloques). Con dos paquetes, la sobrecarga del segundo paquete es 64, por lo que puede contener otros 1436 bytes de carga útil. Así que dos paquetes son suficientes para un RI comprimido de hasta 2803 bytes.

El RI comprimido más grande visto en la red actual es de aproximadamente 1400 bytes; por lo tanto, en la práctica, dos fragmentos deberían ser suficientes, incluso con una MTU mínima de 1280. El protocolo permite un máximo de 15 fragmentos.

Análisis de seguridad:

La integridad y seguridad de una Session Confirmed fragmentada es la misma que la de una no fragmentada. Cualquier alteración de cualquier fragmento causará que el AEAD de Noise falle después del reensamblaje. Los encabezados de los fragmentos después del fragmento 0 solo se usan para identificar el fragmento. Incluso si un atacante en la ruta tuviera la clave k_header_2 usada para cifrar el encabezado (improbable, derivada del handshake), esto no le permitiría al atacante sustituir un fragmento válido.

KDF for data phase

La fase de datos utiliza el encabezado para los datos asociados.

La KDF genera dos claves de cifrado k_ab y k_ba a partir de la clave de encadenamiento ck, utilizando HMAC-SHA256(key, data) tal como se define en RFC 2104. Esta es la función split(), exactamente como se define en la especificación Noise.

// split()
  // chainKey = from handshake phase
  keydata = HKDF(chainKey, ZEROLEN, "", 64)
  k_ab = keydata[0:31]
  k_ba = keydata[32:63]

  // key is k_ab for Alice to Bob
  // key is k_ba for Bob to Alice

  keydata = HKDF(key, ZEROLEN, "HKDFSSU2DataKeys", 64)
  k_data = keydata[0:31]
  k_header_2 = keydata[32:63]


  // AEAD parameters
  k = k_data
  n = 4 byte packet number from header
  ad = 16 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for data phase
  // aik = Alice's intro key
  // bik = Bob's intro key
  k_header_1 = Receiver's intro key (aik or bik)
  k_header_2: from above

Data Message (Type 6)

Payload de ruido: Se permiten todos los tipos de bloques. Tamaño máximo de payload: MTU - 60 (IPv4) o MTU - 80 (IPv6). Para MTU de 1500: El payload máximo es 1440 (IPv4) o 1420 (IPv6).

Comenzando con la segunda parte de Session Confirmed, todos los mensajes están dentro de una carga útil ChaChaPoly autenticada y cifrada. Todo el relleno está dentro del mensaje. Dentro de la carga útil hay un formato estándar con cero o más “bloques”. Cada bloque tiene un tipo de un byte y una longitud de dos bytes. Los tipos incluyen fecha/hora, mensaje I2NP, opciones, terminación y relleno.

Nota: Bob puede, pero no está obligado, enviar su RouterInfo a Alice como su primer mensaje a Alice en la fase de datos.

Propiedades de Seguridad del Payload:

XK(s, rs):           Authentication   Confidentiality
    <-                        2                5
    ->                        2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.
    This payload is encrypted based on an ephemeral-ephemeral DH as well as
    an ephemeral-static DH with the recipient's static key pair.
    Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
    by an attacker that has stolen its static private key, this payload cannot be decrypted.

Notes

  • El router debe descartar un mensaje con un error AEAD.
+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with intro key and         +
  |  derived key, see Data Phase KDF      |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in Data Phase KDF          +
  |  n = packet number from header        |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|    flags     |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As specified in session setup

  Packet Number :: 4 byte big endian integer

  type :: 6

  flags :: 3 bytes, unused, set to 0 for future compatibility

Notes

  • El tamaño mínimo de payload es de 8 bytes. Este requisito será cumplido por cualquier bloque ACK, I2NP, First Fragment, o Follow-on Fragment. Si no se cumple el requisito, debe incluirse un bloque Padding.

  • Cada número de paquete solo puede usarse una vez. Al retransmitir mensajes I2NP o fragmentos, debe usarse un nuevo número de paquete.

KDF for Peer Test


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Peer Test (Type 7)

Charlie envía a Alice, y Alice envía a Charlie, solo para las fases 5-7 del Peer Test. Las fases 1-4 del Peer Test deben enviarse en sesión usando un bloque Peer Test en un mensaje Data. Consulte las secciones Bloque Peer Test y Proceso Peer Test a continuación para obtener más información.

Tamaño: 48 + tamaño de carga útil.

Payload de Noise: Ver más abajo.

Contenido sin procesar:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  type :: 7

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random number generated by Alice or Charlie

  Source Connection ID :: See below

  Token :: Randomly generated by Alice or Charlie, ignored

Encabezado Largo

  • Bloque DateTime
  • Bloque Address (requerido para los mensajes 6 y 7, ver nota a continuación)
  • Bloque Peer Test
  • Bloque Padding (opcional)

El tamaño mínimo de carga útil es de 8 bytes. Dado que el bloque Peer Test totaliza más que eso, el requisito se cumple solo con este bloque.

En los mensajes 5 y 7, el bloque Peer Test puede ser idéntico al bloque de los mensajes en sesión 3 y 4, conteniendo el acuerdo firmado por Charlie, o puede ser regenerado. La firma es opcional.

En el mensaje 6, el bloque Peer Test puede ser idéntico al bloque de los mensajes 1 y 2 de la sesión, conteniendo la solicitud firmada por Alice, o puede ser regenerado. La firma es opcional.

IDs de Conexión: Los dos IDs de conexión se derivan del nonce de prueba. Para los mensajes 5 y 7 enviados desde Charlie a Alice, el ID de Conexión de Destino son dos copias del nonce de prueba de 4 bytes big-endian, es decir, ((nonce « 32) | nonce). El ID de Conexión de Origen es el inverso del ID de Conexión de Destino, es decir, ~((nonce « 32) | nonce). Para el mensaje 6 enviado desde Alice a Charlie, intercambia los dos IDs de conexión.

Contenido del bloque de direcciones:

  • En el mensaje 5: No requerido.
  • En el mensaje 6: La IP y puerto de Charlie según se seleccionó del RI de Charlie.
  • En el mensaje 7: La IP y puerto reales de Alice desde los cuales se recibió el mensaje 6.

KDF for Retry

El requisito para el mensaje Retry es que Bob no está obligado a descifrar el mensaje Session Request para generar un mensaje Retry como respuesta. Además, este mensaje debe ser rápido de generar, utilizando únicamente cifrado simétrico.


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Retry (Type 9)

Bob envía a Alice, en respuesta a un mensaje Session Request o Token Request. Alice responde con un nuevo Session Request. Tamaño: 48 + tamaño del payload.

También sirve como mensaje de Terminación (es decir, “No Reintentar”) si se incluye un bloque de Terminación.

Carga útil de Noise: Ver más abajo.

Contenidos sin procesar:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: The Source Connection ID
                               received from Alice in Token Request
                               or Session Request

  Packet Number :: Random number generated by Bob

  type :: 9

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Token Request
                          or Session Request

  Token :: 8 byte unsigned integer, randomly generated by Bob, nonzero,
           or zero if session is rejected and a termination block is included

Encabezado Corto

  • Bloque DateTime
  • Bloque Address
  • Bloque Options (opcional)
  • Bloque Termination (opcional, si la sesión es rechazada)
  • Bloque Padding (opcional)

El tamaño mínimo de payload es 8 bytes. Dado que los bloques DateTime y Address suman más que eso, el requisito se cumple únicamente con esos dos bloques.

Numeración de ID de Conexión

  • Para proporcionar resistencia al sondeo, un router no debería enviar un mensaje Retry en respuesta a un mensaje Session Request o Token Request a menos que los campos de tipo de mensaje, versión de protocolo e ID de red en el mensaje Request sean válidos.

  • Para limitar la magnitud de cualquier ataque de amplificación que pueda montarse usando direcciones de origen falsificadas, el mensaje Retry no debe contener grandes cantidades de relleno. Se recomienda que el mensaje Retry no sea más grande que tres veces el tamaño del mensaje al que está respondiendo. Alternativamente, use un método simple como agregar una cantidad aleatoria de relleno en el rango de 1-64 bytes.

KDF for Token Request

Este mensaje debe ser rápido de generar, usando únicamente cifrado simétrico.


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Token Request (Type 10)

Alice envía a Bob. Bob responde con un mensaje Retry. Tamaño: 48 + tamaño del payload.

Si Alice no tiene un token válido, Alice debería enviar este mensaje en lugar de una Session Request, para evitar la sobrecarga de cifrado asimétrico al generar una Session Request.

Payload de Noise: Ver más abajo.

Contenidos en bruto:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Datos sin cifrar (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  Packet Number :: Random number generated by Alice

  type :: 10

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: zero

Numeración de Paquetes

  • Bloque DateTime
  • Bloque de relleno

El tamaño mínimo de payload es de 8 bytes.

Vinculación de Encabezado

  • Para proporcionar resistencia al sondeo, un router no debería enviar un mensaje Retry en respuesta a un mensaje Token Request a menos que los campos de tipo de mensaje, versión de protocolo e ID de red en el mensaje Token Request sean válidos.

  • Esto NO es un mensaje Noise estándar y no forma parte del handshake. No está vinculado al mensaje Session Request más que por los IDs de conexión.

  • En la mayoría de errores, incluyendo AEAD, o aparente replay Bob debería detener el procesamiento adicional de mensajes y descartar el mensaje sin responder.

  • Bob debe rechazar conexiones donde el valor del timestamp esté demasiado alejado del tiempo actual. Llama al delta máximo de tiempo “D”. Bob debe mantener una caché local de valores de handshake utilizados previamente y rechazar duplicados, para prevenir ataques de replay. Los valores en la caché deben tener un tiempo de vida de al menos 2*D. Los valores de caché dependen de la implementación, sin embargo el valor X de 32 bytes (o su equivalente encriptado) puede ser utilizado.

  • Bob PUEDE enviar un mensaje Retry que contenga un token cero y un bloque Termination con un código de razón de sesgo de reloj si la marca de tiempo en el bloque DateTime está demasiado sesgada.

  • Tamaño mínimo: TBD, ¿mismas reglas que para Session Created?

KDF for Hole Punch

Este mensaje debe ser rápido de generar, usando únicamente cifrado simétrico.


// AEAD parameters
  // aik = Alice's intro key
  k = aik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = aik
  k_header_2 = aik

Hole Punch (Type 11)

Charlie envía a Alice, en respuesta a un Relay Intro recibido de Bob. Alice responde con una nueva Session Request. Tamaño: 48 + tamaño del payload.

Carga útil de Noise: Ver más abajo.

Contenido sin procesar:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Datos no cifrados (etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  Packet Number :: Random number generated by Charlie

  type :: 11

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: See below

  Token :: 8 byte unsigned integer, randomly generated by Charlie, nonzero.

Cifrado de Cabeceras

  • Bloque DateTime
  • Bloque Address
  • Bloque Relay Response
  • Bloque Padding (opcional)

El tamaño mínimo de la carga útil es de 8 bytes. Dado que los bloques DateTime y Address suman más que eso, el requisito se cumple únicamente con esos dos bloques.

IDs de Conexión: Los dos IDs de conexión se derivan del nonce de relay. El ID de Conexión de Destino son dos copias del nonce de relay de 4 bytes en big-endian, es decir, ((nonce « 32) | nonce). El ID de Conexión de Origen es el inverso del ID de Conexión de Destino, es decir, ~((nonce « 32) | nonce).

Alice debería ignorar el token en la cabecera. El token que se debe usar en la Session Request está en el bloque Relay Response.

Noise Payload

Cada carga útil de Noise contiene cero o más “bloques”.

Esto utiliza el mismo formato de bloque definido en las especificaciones de NTCP2 y ECIES. Los tipos de bloque individuales se definen de manera diferente. El término equivalente en QUIC RFC 9000 es “frames”.

Existen preocupaciones de que alentar a los implementadores a compartir código puede llevar a problemas de análisis. Los implementadores deben considerar cuidadosamente los beneficios y riesgos de compartir código, y asegurar que las reglas de ordenamiento y bloques válidos sean diferentes para los dos contextos.

Consideraciones de Seguridad

Hay uno o más bloques en la carga útil cifrada. Un bloque es un formato simple Tag-Length-Value (TLV). Cada bloque contiene un identificador de un byte, una longitud de dos bytes, y cero o más bytes de datos. Este formato es idéntico al de NTCP2 y ECIES, sin embargo las definiciones de bloques son diferentes.

Para extensibilidad, los receptores deben ignorar los bloques con identificadores desconocidos y tratarlos como relleno.

(Etiqueta de autenticación Poly1305 no mostrada):

+----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  ~               .   .   .               ~

  blk :: 1 byte, see below
  size :: 2 bytes, big endian, size of data to follow, 0 - TBD
  data :: the data

El cifrado del encabezado utiliza los últimos 24 bytes del paquete como IV para las dos operaciones ChaCha20. Como todos los paquetes terminan con un MAC de 16 bytes, esto requiere que todas las cargas útiles de los paquetes tengan un mínimo de 8 bytes. Si una carga útil no cumpliera con este requisito, se debe incluir un bloque de relleno.

El payload máximo de ChaChaPoly varía según el tipo de mensaje, MTU y el tipo de dirección IPv4 o IPv6. El payload máximo es MTU - 60 para IPv4 y MTU - 80 para IPv6. Los datos de payload máximos son MTU - 63 para IPv4 y MTU - 83 para IPv6. El límite superior es aproximadamente 1440 bytes para IPv4, MTU 1500, mensaje Data. El tamaño máximo total del bloque es el tamaño máximo del payload. El tamaño máximo de bloque individual es el tamaño máximo total del bloque. El tipo de bloque es 1 byte. La longitud del bloque es 2 bytes. El tamaño máximo de datos de bloque individual es el tamaño máximo de bloque individual menos 3.

Notas:

  • Los implementadores deben asegurar que al leer un bloque, los datos malformados o maliciosos no causen que las lecturas se desborden hacia el siguiente bloque o más allá del límite del payload.

  • Las implementaciones deben ignorar los tipos de bloques desconocidos para compatibilidad hacia adelante.

Tipos de bloque:

Payload Block TypeType NumberBlock Length
DateTime07
Options115+
Router Info2varies
I2NP Message3varies
First Fragment4varies
Follow-on Fragment5varies
Termination69 typ.
Relay Request7varies
Relay Response8varies
Relay Intro9varies
Peer Test10varies
Next Nonce11TBD
ACK12varies
Address139 or 21
reserved14
Relay Tag Request153
Relay Tag167
New Token1715
Path Challenge18varies
Path Response19varies
First Packet Number207
Congestion214
reserved for experimental features224-253
Padding254varies
reserved for future extension255

Block Ordering Rules

En la Sesión Confirmada, la Información del Router debe ser el primer bloque.

En todos los demás mensajes, el orden no está especificado, excepto por los siguientes requisitos: El relleno (Padding), si está presente, debe ser el último bloque. La terminación (Termination), si está presente, debe ser el último bloque excepto por el relleno (Padding). No se permiten múltiples bloques de relleno (Padding) en una sola carga útil.

Block Specifications

KDF de Cifrado de Cabecera

Para sincronización de tiempo:

+----+----+----+----+----+----+----+
  | 0  |    4    |     timestamp     |
  +----+----+----+----+----+----+----+

  blk :: 0
  size :: 2 bytes, big endian, value = 4
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106

Notas:

  • A diferencia de SSU 1, no hay marca de tiempo en el encabezado del paquete para la fase de datos en SSU 2.
  • Las implementaciones deben enviar periódicamente bloques DateTime en la fase de datos.
  • Las implementaciones deben redondear al segundo más cercano para prevenir el sesgo de reloj en la red.

Validación de Encabezados

Pasar opciones actualizadas. Las opciones incluyen: Relleno mínimo y máximo.

El bloque de opciones tendrá longitud variable.

+----+----+----+----+----+----+----+----+
  | 1  |  size   |tmin|tmax|rmin|rmax|tdmy|
  +----+----+----+----+----+----+----+----+
  |tdmy|  rdmy   |  tdelay |  rdelay |    |
  ~----+----+----+----+----+----+----+    ~
  |              more_options             |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 1
  size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum

  tmin, tmax, rmin, rmax :: requested padding limits
      tmin and rmin are for desired resistance to traffic analysis.
      tmax and rmax are for bandwidth limits.
      tmin and tmax are the transmit limits for the router sending this options block.
      rmin and rmax are the receive limits for the router sending this options block.
      Each is a 4.4 fixed-point float representing 0 to 15.9375
      (or think of it as an unsigned 8-bit integer divided by 16.0).
      This is the ratio of padding to data. Examples:
      Value of 0x00 means no padding
      Value of 0x01 means add 6 percent padding
      Value of 0x10 means add 100 percent padding
      Value of 0x80 means add 800 percent (8x) padding
      Alice and Bob will negotiate the minimum and maximum in each direction.
      These are guidelines, there is no enforcement.
      Sender should honor receiver's maximum.
      Sender may or may not honor receiver's minimum, within bandwidth constraints.

  tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
  rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
  tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
  rdelay: Requested intra-message delay, 2 bytes big endian, msec average

  Padding distribution specified as additional parameters?
  Random delay specified as additional parameters?

  more_options :: Format TBD

Problemas de Opciones:

  • La negociación de opciones está por determinar.

RouterInfo

Pasa el RouterInfo de Alice a Bob. Se usa únicamente en la carga útil de la parte 2 de Session Confirmed. No se debe usar en la fase de datos; utiliza un Mensaje I2NP DatabaseStore en su lugar.

Tamaño Mínimo: Aproximadamente 420 bytes, a menos que la identidad del router y la firma en la información del router sean compresibles, lo cual es poco probable.

NOTA: El bloque Router Info nunca se fragmenta. El campo frag es siempre 0/1. Consulte la sección Fragmentación de Session Confirmed arriba para más información.

+----+----+----+----+----+----+----+----+
  | 2  |  size   |flag|frag|              |
  +----+----+----+----+----+              +
  |                                       |
  +       Router Info fragment            +
  | (Alice RI in Session Confirmed)       |
  + (Alice, Bob, or third-party           +
  |  RI in data phase)                    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 2
  size :: 2 bytes, big endian, 2 + fragment size
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 0 for local store, 1 for flood request
         bit 1: 0 for uncompressed, 1 for gzip compressed
         bits 7-2: Unused, set to 0 for future compatibility
  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number, always 0
         bits 3-0: total fragments, always 1, big endian

  routerinfo :: Alice's or Bob's RouterInfo

Notas:

  • El Router Info se comprime opcionalmente con gzip, según se indica con el bit de bandera 1. Esto es diferente de NTCP2, donde nunca se comprime, y de un Mensaje DatabaseStore, donde siempre se comprime. La compresión es opcional porque usualmente proporciona poco beneficio para Router Infos pequeños, donde hay poco contenido compresible, pero es muy beneficiosa para Router Infos grandes con varias Router Addresses compresibles. Se recomienda la compresión si permite que un Router Info quepa en un solo paquete Session Confirmed sin fragmentación.

  • Tamaño máximo del primer fragmento o único fragmento en el mensaje Session Confirmed: MTU - 113 para IPv4 o MTU - 133 para IPv6. Asumiendo una MTU predeterminada de 1500 bytes, y sin otros bloques en el mensaje, 1387 para IPv4 o 1367 para IPv6. El 97% de los router infos actuales son menores que 1367 sin compresión gzip. El 99.9% de los router infos actuales son menores que 1367 cuando se comprimen con gzip. Asumiendo una MTU mínima de 1280 bytes, y sin otros bloques en el mensaje, 1167 para IPv4 o 1147 para IPv6. El 94% de los router infos actuales son menores que 1147 sin compresión gzip. El 97% de los router infos actuales son menores que 1147 cuando se comprimen con gzip.

  • El byte frag ahora no se usa, el bloque Router Info nunca se fragmenta. El byte frag debe establecerse en fragmento 0, total de fragmentos 1. Consulte la sección Fragmentación de Session Confirmed anterior para más información.

  • El flooding no debe ser solicitado a menos que haya RouterAddresses publicadas en el RouterInfo. El router receptor no debe hacer flood del RouterInfo a menos que tenga RouterAddresses publicadas en él.

  • Este protocolo no proporciona una confirmación de que el RouterInfo fue almacenado o distribuido por flood. Si se desea confirmación, y el receptor es floodfill, el emisor debería enviar en su lugar un I2NP DatabaseStoreMessage estándar con un token de respuesta.

I2NP Message

Un mensaje I2NP completo con un encabezado modificado.

Esto utiliza los mismos 9 bytes para el encabezado I2NP que en NTCP2 (tipo, ID del mensaje, expiración corta).

+----+----+----+----+----+----+----+----+
  | 3  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |     message       |
  +----+----+----+----+                   +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 3
  size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
          I2NP message body size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: I2NP message body

Notas:

  • Este es el mismo formato de encabezado I2NP de 9 bytes utilizado en NTCP2.

  • Este es exactamente el mismo formato que el bloque First Fragment, pero el tipo de bloque indica que este es un mensaje completo.

  • El tamaño máximo incluyendo el encabezado I2NP de 9 bytes es MTU - 63 para IPv4 y MTU - 83 para IPv6.

ChaCha20/Poly1305

El primer fragmento (fragmento #0) de un mensaje I2NP con un encabezado modificado.

Esto utiliza los mismos 9 bytes para el encabezado I2NP que en NTCP2 (tipo, ID de mensaje, expiración corta).

El número total de fragmentos no está especificado.

+----+----+----+----+----+----+----+----+
  | 4  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |                   |
  +----+----+----+----+                   +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 4
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: Partial I2NP message body, bytes 0 - (size - 10)

Notas:

  • Este es el mismo formato de cabecera I2NP de 9 bytes utilizado en NTCP2.

  • Este es exactamente el mismo formato que el bloque de Mensaje I2NP, pero el tipo de bloque indica que este es el primer fragmento de un mensaje.

  • La longitud del mensaje parcial debe ser mayor que cero.

  • Como en SSU 1, se recomienda enviar el último fragmento primero, para que el receptor conozca el número total de fragmentos y pueda asignar eficientemente los búferes de recepción.

  • El tamaño máximo incluyendo el encabezado I2NP de 9 bytes es MTU - 63 para IPv4 y MTU - 83 para IPv6.

Notas

Un fragmento adicional (número de fragmento mayor que cero) de un mensaje I2NP.

+----+----+----+----+----+----+----+----+
  | 5  |  size   |frag|    msg id         |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 5
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 5).
  frag :: Fragment info:
          Bit order: 76543210 (bit 7 is MSB)
          bits 7-1: fragment number 1 - 127 (0 not allowed)
          bit 0: isLast (1 = true)
  msg id :: 4 bytes, big endian, I2NP message ID
  message :: Partial I2NP message body

Notas:

  • La longitud del mensaje parcial debe ser mayor que cero.

  • Como en SSU 1, se recomienda enviar el último fragmento primero, para que el receptor conozca el número total de fragmentos y pueda asignar eficientemente los buffers de recepción.

  • Como en SSU 1, el número máximo de fragmento es 127, pero el límite práctico es 63 o menos. Las implementaciones pueden limitar el máximo a lo que es práctico para un tamaño máximo de mensaje I2NP de aproximadamente 64 KB, que son aproximadamente 55 fragmentos con un MTU mínimo de 1280. Consulte la sección Tamaño Máximo de Mensaje I2NP a continuación.

  • El tamaño máximo del mensaje parcial (sin incluir frag y message id) es MTU - 68 para IPv4 y MTU - 88 para IPv6.

Manejo de Errores AEAD

Descartar la conexión. Este debe ser el último bloque sin relleno en la carga útil.

+----+----+----+----+----+----+----+----+
  | 6  |  size   |    valid data packets  |
  +----+----+----+----+----+----+----+----+
      received   | rsn|     addl data     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  +----+----+----+----+----+----+----+----+

  blk :: 6
  size :: 2 bytes, big endian, value = 9 or more
  valid data packets received :: The number of valid packets received
                                (current receive nonce value)
                                0 if error occurs in handshake phase
                                8 bytes, big endian
  rsn :: reason, 1 byte:
         0: normal close or unspecified
         1: termination received
         2: idle timeout
         3: router shutdown
         4: data phase AEAD failure
         5: incompatible options
         6: incompatible signature type
         7: clock skew
         8: padding violation
         9: AEAD framing error
         10: payload format error
         11: Session Request error
         12: Session Created error
         13: Session Confirmed error
         14: Timeout
         15: RI signature verification fail
         16: s parameter missing, invalid, or mismatched in RouterInfo
         17: banned
         18: bad token
         19: connection limits
         20: incompatible version
         21: wrong net ID
         22: replaced by new session
  addl data :: optional, 0 or more bytes, for future expansion, debugging,
               or reason text.
               Format unspecified and may vary based on reason code.

Notas:

  • No todas las razones pueden ser realmente utilizadas, depende de la implementación. La mayoría de fallos generalmente resultarán en que el mensaje sea descartado, no en una terminación. Ver notas en las secciones de mensaje handshake anteriores. Las razones adicionales listadas son por consistencia, logging, debugging, o si cambian las políticas.
  • Se recomienda que un bloque ACK sea incluido con el bloque de Terminación.
  • En la fase de datos, por cualquier razón que no sea “termination received”, el peer debería responder with un bloque de terminación con la razón “termination received”.

RelayRequest

Enviado en un mensaje Data dentro de la sesión, de Alice a Bob. Ver la sección Proceso de Relay más abajo.

+----+----+----+----+----+----+----+----+
  |  7 |  size   |flag|       nonce       |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 7
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility

  The data below here is covered
  by the signature, and Bob forwards it unmodified.

  nonce :: 4 bytes, randomly generated by Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Notas:

  • La dirección IP siempre se incluye (a diferencia de SSU 1) y puede ser diferente a la IP utilizada para la sesión.

Firma:

Alice firma la solicitud y la incluye en este bloque; Bob la reenvía en el bloque Relay Intro a Charlie. Algoritmo de firma: Firmar los siguientes datos con la clave de firma del router de Alice:

  • prologue: 16 bytes “RelayRequestData”, sin terminación nula (no incluido en el mensaje)
  • bhash: hash del router de Bob de 32 bytes (no incluido en el mensaje)
  • chash: hash del router de Charlie de 32 bytes (no incluido en el mensaje)
  • nonce: nonce de 4 bytes
  • relay tag: etiqueta de relay de 4 bytes
  • timestamp: marca de tiempo de 4 bytes (segundos)
  • ver: versión SSU de 1 byte
  • asz: tamaño del endpoint (puerto + IP) de 1 byte (6 o 18)
  • AlicePort: número de puerto de Alice de 2 bytes
  • Alice IP: dirección IP de Alice de (asz - 2) bytes

KDF para ChainKey Inicial

Enviado en un mensaje Data dentro de la sesión, de Charlie a Bob o de Bob a Alice, Y en el mensaje Hole Punch de Charlie a Alice. Ver la sección Proceso de Relay más abajo.

+----+----+----+----+----+----+----+----+
  |  8 |  size   |flag|code|    nonce
  +----+----+----+----+----+----+----+----+
       |     timestamp     | ver| csz|Char
  +----+----+----+----+----+----+----+----+
   Port|   Charlie IP addr |              |
  +----+----+----+----+----+              +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  blk :: 8
  size :: 2 bytes, 6
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, Charlie is banned
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, relay tag not found
         6: rejected by Bob, Alice RI not found
         7-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         71-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD

  The data below is covered by the signature if the code is 0 (accept).
  Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Bob or Alice

  The data below is present only if the code is 0 (accept).

  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  csz :: 1 byte endpoint (port + IP) size (0 or 6 or 18)
         may be 0 for some rejection codes
  CharliePort :: 2 byte Charlie's port number, big endian
                 not present if csz is 0
  Charlie IP :: (csz - 2) byte representation of Charlie's IP address,
                network byte order
                not present if csz is 0
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Charlie.
               Not present if rejected by Bob.
  token :: Token generated by Charlie for Alice to use
           in the Session Request.
           Only present if code is 0 (accept)

Notas:

El token debe ser usado inmediatamente por Alice en la Session Request.

Firma:

Si Charlie acepta (código de respuesta 0) o rechaza (código de respuesta 64 o superior), Charlie firma la respuesta y la incluye en este bloque; Bob la reenvía en el bloque Relay Response a Alice. Algoritmo de firma: Firmar los siguientes datos con la clave de firma del router de Charlie:

  • prólogo: 16 bytes “RelayAgreementOK”, sin terminación nula (no incluido en el mensaje)
  • bhash: hash del router de Bob de 32 bytes (no incluido en el mensaje)
  • nonce: nonce de 4 bytes
  • timestamp: marca de tiempo de 4 bytes (segundos)
  • ver: versión SSU de 1 byte
  • csz: tamaño del endpoint (puerto + IP) de 1 byte (0 o 6 o 18)
  • CharliePort: número de puerto de Charlie de 2 bytes (no presente si csz es 0)
  • Charlie IP: dirección IP de Charlie de (csz - 2) bytes (no presente si csz es 0)

Si Bob rechaza (código de respuesta 1-63), Bob firma la respuesta y la incluye en este bloque. Algoritmo de firma: Firmar los siguientes datos con la clave de firma del router de Bob:

  • prologue: 16 bytes “RelayAgreementOK”, no terminado en null (no incluido en el mensaje)
  • bhash: Hash de 32 bytes del router de Bob (no incluido en el mensaje)
  • nonce: Nonce de 4 bytes
  • timestamp: Timestamp de 4 bytes (segundos)
  • ver: Versión SSU de 1 byte
  • csz: 1 byte = 0

KDF para Solicitud de Sesión

Enviado en un mensaje Data en sesión, de Bob a Charlie. Ver la sección Proceso de Relay abajo.

Debe estar precedido por un bloque RouterInfo, o un bloque de mensaje I2NP DatabaseStore (o fragmento), que contenga la información del Router de Alice, ya sea en la misma carga útil (si hay espacio), o en un mensaje anterior.

+----+----+----+----+----+----+----+----+
  |  9 |  size   |flag|                   |
  +----+----+----+----+                   +
  |                                       |
  +                                       +
  |         Alice Router Hash             |
  +             32 bytes                  +
  |                                       |
  +                   +----+----+----+----+
  |                   |      nonce        |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 9
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's 32-byte router hash,

  The data below here is covered
  by the signature, as received from Alice in the Relay Request,
  and Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Notas:

  • Para IPv4, la dirección IP de Alice siempre es de 4 bytes, porque Alice está intentando conectarse a Charlie vía IPv4. IPv6 es compatible, y la dirección IP de Alice puede ser de 16 bytes.

  • Para IPv4, este mensaje debe enviarse a través de una conexión IPv4 establecida, ya que es la única manera en que Bob conoce la dirección IPv4 de Charlie para devolvérsela a Alice en el RelayResponse_. IPv6 es compatible, y este mensaje puede enviarse a través de una conexión IPv6 establecida.

  • Cualquier dirección SSU publicada con introducers debe contener “4” o “6” en la opción “caps”.

Firma:

Alice firma la solicitud y Bob la reenvía en este bloque a Charlie. Algoritmo de verificación: Verificar los siguientes datos con la clave de firma del router de Alice:

  • prologue: 16 bytes “RelayRequestData”, sin terminación nula (no incluido en el mensaje)
  • bhash: hash del router de Bob de 32 bytes (no incluido en el mensaje)
  • chash: hash del router de Charlie de 32 bytes (no incluido en el mensaje)
  • nonce: nonce de 4 bytes
  • relay tag: etiqueta de relay de 4 bytes
  • timestamp: marca de tiempo de 4 bytes (segundos)
  • ver: versión SSU de 1 byte
  • asz: tamaño del endpoint (puerto + IP) de 1 byte (6 o 18)
  • AlicePort: número de puerto de Alice de 2 bytes
  • Alice IP: dirección IP de Alice de (asz - 2) bytes

PeerTest

Enviado ya sea en un mensaje Data dentro de la sesión, o un mensaje Peer Test fuera de sesión. Ver sección Proceso de Peer Test a continuación.

Para el mensaje 2, debe estar precedido por un bloque RouterInfo, o bloque de mensaje I2NP DatabaseStore (o fragmento), que contenga la Router Info de Alice, ya sea en la misma carga útil (si hay espacio), o en un mensaje anterior.

Para el mensaje 4, si el relay es aceptado (código de razón 0), debe estar precedido por un bloque RouterInfo, o un bloque de mensaje I2NP DatabaseStore (o fragmento), que contenga la Router Info de Charlie, ya sea en la misma carga útil (si hay espacio), o en un mensaje anterior.

+----+----+----+----+----+----+----+----+
  | 10 |  size   | msg|code|flag|         |
  +----+----+----+----+----+----+         +
  | Alice router hash (message 2 only)    |
  +             or                        +
  | Charlie router hash (message 4 only)  |
  + or all zeros if rejected by Bob       +
  | Not present in messages 1,3,5,6,7     |
  +                             +----+----+
  |                             | ver|
  +----+----+----+----+----+----+----+----+
     nonce       |     timestamp     | asz|
  +----+----+----+----+----+----+----+----+
  |AlicePort|  Alice IP address |         |
  +----+----+----+----+----+----+         +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 10
  size :: 2 bytes, big endian, size of data to follow
  msg :: 1 byte message number 1-7
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, no Charlie available
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, address unsupported
         6-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         70-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD
         reject codes only allowed in messages 3 and 4
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's or Charlie's 32-byte router hash,
          only present in messages 2 and 4.
          All zeros (fake hash) in message 4 if rejected by Bob.

  For messages 1-4, the data below here is covered
  by the signature, if present, and Bob forwards it unmodified.

  ver :: 1 byte SSU version:
         1: SSU 1 (not supported)
         2: SSU 2 (required)
  nonce :: 4 byte test nonce, big endian
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice or Charlie.
               Only present for messages 1-4.
               Optional in message 5-7.

Notas:

  • A diferencia de SSU 1, el mensaje 1 debe incluir la dirección IP y el puerto de Alice.

  • Se admite la prueba de direcciones IPv6, y la comunicación Alice-Bob y Alice-Charlie puede ser vía IPv6, si Bob y Charlie indican soporte con una capacidad ‘B’ en su dirección IPv6 publicada. Consulta la Propuesta 126 para más detalles.

Alice envía la solicitud a Bob usando una sesión existente sobre el transporte (IPv4 o IPv6) que desea probar. Cuando Bob recibe una solicitud de Alice vía IPv4, Bob debe seleccionar un Charlie que anuncie una dirección IPv4. Cuando Bob recibe una solicitud de Alice vía IPv6, Bob debe seleccionar un Charlie que anuncie una dirección IPv6. La comunicación real Bob-Charlie puede ser vía IPv4 o IPv6 (es decir, independiente del tipo de dirección de Alice).

  • Los mensajes 1-4 deben estar contenidos en un mensaje Data en una sesión existente.

  • Bob debe enviar el RI de Alice a Charlie antes de enviar el mensaje 2.

  • Bob debe enviar el RI de Charlie a Alice antes de enviar el mensaje 4, si es aceptado (código de razón 0).

  • Los mensajes 5-7 deben estar contenidos en un mensaje Peer Test fuera de sesión.

  • Los mensajes 5 y 7 pueden contener los mismos datos firmados que se enviaron en los mensajes 3 y 4, o pueden ser regenerados con una nueva marca de tiempo. La firma es opcional.

  • El mensaje 6 puede contener los mismos datos firmados que se enviaron en los mensajes 1 y 2, o puede ser regenerado con una nueva marca de tiempo. La firma es opcional.

Firmas:

Alice firma la solicitud y la incluye en el mensaje 1; Bob la reenvía en el mensaje 2 a Charlie. Charlie firma la respuesta y la incluye en el mensaje 3; Bob la reenvía en el mensaje 4 a Alice. Algoritmo de firma: Firmar o verificar los siguientes datos con la clave de firma de Alice o Charlie:

  • prologue: 16 bytes “PeerTestValidate”, sin terminación nula (no incluido en el mensaje)
  • bhash: Hash del router de Bob de 32 bytes (no incluido en el mensaje)
  • ahash: Hash del router de Alice de 32 bytes (Solo utilizado en la firma para los mensajes 3 y 4; no incluido en el mensaje 3 o 4)
  • ver: 1 byte versión SSU
  • nonce: 4 bytes nonce de prueba
  • timestamp: 4 bytes marca de tiempo (segundos)
  • asz: 1 byte tamaño del endpoint (puerto + IP) (6 o 18)
  • AlicePort: 2 bytes número de puerto de Alice
  • Alice IP: (asz - 2) bytes dirección IP de Alice

Carga útil

TODO solo si rotamos claves

+----+----+----+----+----+----+----+----+
  | 11 |  size   |      TBD               |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 11
  size :: 2 bytes, big endian, size of data to follow

Notas

4 bytes de confirmación de recepción, seguidos por un contador de confirmaciones y cero o más rangos de confirmaciones negativas/positivas.

Este diseño está adaptado y simplificado de QUIC. Los objetivos del diseño son los siguientes:

  • Queremos codificar eficientemente un “bitfield”, que es una secuencia de bits que representa paquetes confirmados.
  • El bitfield consiste principalmente en 1’s. Tanto los 1’s como los 0’s generalmente vienen en “grupos” secuenciales.
  • La cantidad de espacio disponible en el paquete para confirmaciones varía.
  • El bit más importante es el de numeración más alta. Los de numeración más baja son menos importantes. Por debajo de cierta distancia del bit más alto, los bits más antiguos serán “olvidados” y nunca se enviarán de nuevo.

La codificación especificada a continuación logra estos objetivos de diseño, enviando el número del bit más alto que está establecido en 1, junto con bits consecutivos adicionales menores que también están establecidos en 1. Después de eso, si hay espacio, uno o más “rangos” que especifican el número de bits consecutivos 0 y bits consecutivos 1 menores que ese. Ver QUIC RFC 9000 sección 13.2.3 para más contexto.

+----+----+----+----+----+----+----+----+
  | 12 |  size   |    Ack Through    |acnt|
  +----+----+----+----+----+----+----+----+
  |  range  |  range  |     .   .   .     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 12
  size :: 2 bytes, big endian, size of data to follow,
          5 minimum
  ack through :: highest packet number acked
  acnt :: number of acks lower than ack through also acked,
          0-255
  range :: If present,
           1 byte nack count followed by 1 byte ack count,
           0-255 each

Ejemplos:

Queremos hacer ACK solo del paquete 10:

  • Ack Through: 10
  • acnt: 0
  • no se incluyen rangos

Queremos hacer ACK solo de los paquetes 8-10:

  • Ack Through: 10
  • acnt: 2
  • no se incluyen rangos

Queremos ACK 10 9 8 6 5 2 1 0, y NACK 7 4 3. La codificación del Bloque ACK es:

  • Ack Through: 10
  • acnt: 2 (ack 9 8)
  • rango: 1 2 (nack 7, ack 6 5)
  • rango: 2 3 (nack 4 3, ack 2 1 0)

Notas:

  • Los rangos pueden no estar presentes. El número máximo de rangos no está especificado, pueden ser tantos como quepan en el paquete.
  • Range nack puede ser cero si se está confirmando más de 255 paquetes consecutivos.
  • Range ack puede ser cero si se está negando más de 255 paquetes consecutivos.
  • Range nack y ack no pueden ser ambos cero.
  • Después del último rango, los paquetes no son ni confirmados ni negados. La longitud del bloque ack y cómo se manejan los acks/nacks antiguos queda a criterio del remitente del bloque ack. Ver las secciones de ack más abajo para discusión.
  • El ack through debería ser el número de paquete más alto recibido, y cualquier paquete superior no ha sido recibido. Sin embargo, en situaciones limitadas, podría ser menor, como confirmar un solo paquete que “llena un hueco”, o una implementación simplificada que no mantiene el estado de todos los paquetes recibidos. Por encima del más alto recibido, los paquetes no son ni confirmados ni negados, pero después de varios bloques ack, puede ser apropiado entrar en modo de retransmisión rápida.
  • Este formato es una versión simplificada del de QUIC. Está diseñado para codificar eficientemente un gran número de ACKs, junto con ráfagas de NACKs.
  • Los bloques ACK se usan para confirmar paquetes de la fase de datos. Solo deben incluirse para paquetes de la fase de datos dentro de la sesión.

Address

2 bytes de puerto y 4 o 16 bytes de dirección IP. La dirección de Alice, enviada a Alice por Bob, o la dirección de Bob, enviada a Bob por Alice.

+----+----+----+----+----+----+----+----+
  | 13 | 6 or 18 |   Port  | IP Address    
  +----+----+----+----+----+----+----+----+
       |
  +----+

  blk :: 13
  size :: 2 bytes, big endian, 6 or 18
  port :: 2 bytes, big endian
  ip :: 4 byte IPv4 or 16 byte IPv6 address,
        big endian (network byte order)

Relay Tag Request

Esto puede ser enviado por Alice en un mensaje Session Request, Session Confirmed o Data. No es compatible en el mensaje Session Created, ya que Bob aún no tiene el RI de Alice y no sabe si Alice soporta relay. Además, si Bob está recibiendo una conexión entrante, probablemente no necesite introducers (excepto quizás para el otro tipo ipv4/ipv6).

Cuando se envía en el Session Request, Bob puede responder con un Relay Tag en el mensaje Session Created, o puede elegir esperar hasta recibir el RouterInfo de Alice en el Session Confirmed para validar la identidad de Alice antes de responder en un mensaje Data. Si Bob no desea hacer relay para Alice, no envía un bloque Relay Tag.

+----+----+----+
  | 15 |    0    |
  +----+----+----+

  blk :: 15
  size :: 2 bytes, big endian, value = 0

Carga útil

Esto puede ser enviado por Bob en un mensaje Session Confirmed o Data, en respuesta a una Relay Tag Request de Alice.

Cuando se envía el Relay Tag Request en el Session Request, Bob puede responder con un Relay Tag en el mensaje Session Created, o puede elegir esperar hasta recibir el RouterInfo de Alice en el Session Confirmed para validar la identidad de Alice antes de responder en un mensaje Data. Si Bob no desea hacer relay para Alice, no envía un bloque Relay Tag.

+----+----+----+----+----+----+----+
  | 16 |    4    |    relay tag      |
  +----+----+----+----+----+----+----+

  blk :: 16
  size :: 2 bytes, big endian, value = 4
  relay tag :: 4 bytes, big endian, nonzero

Notas

Para una conexión posterior. Generalmente incluido en los mensajes Session Created y Session Confirmed. También puede enviarse nuevamente en el mensaje Data de una sesión de larga duración si el token anterior expira.

+----+----+----+----+----+----+----+----+
  | 17 |   12    |     expires       |
  +----+----+----+----+----+----+----+----+
                  token              |
  +----+----+----+----+----+----+----+

  blk :: 17
  size :: 2 bytes, big endian, value = 12
  expires :: Unix timestamp, unsigned seconds.
             Wraps around in 2106
  token :: 8 bytes, big endian

Problemas

Un Ping con datos arbitrarios que se devuelven en una Path Response, utilizado como keep-alive o para validar un cambio de IP/Puerto.

+----+----+----+----+----+----+----+----+
  | 18 |  size   |    Arbitrary Data      |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 18
  size :: 2 bytes, big endian, size of data to follow
  data :: Arbitrary data to be returned in a Path Response
          length as selected by sender

Notas:

Se recomienda un tamaño mínimo de datos de 8 bytes, que contenga datos aleatorios, pero no es obligatorio.

Path Response

Un Pong con los datos recibidos en el Path Challenge, como respuesta al Path Challenge, usado como keep-alive o para validar un cambio de IP/Puerto.

+----+----+----+----+----+----+----+----+
  | 19 |  size   |                        |
  +----+----+----+                        +
  |    Data received in Path Challenge    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 19
  size :: 2 bytes, big endian, size of data to follow
  data :: As received in a Path Challenge

First Packet Number

Opcionalmente incluido en el handshake en cada dirección, para especificar el primer número de paquete que será enviado. Esto proporciona más seguridad para el cifrado de encabezados, similar a TCP.

No completamente especificado, no soportado actualmente.

+----+----+----+----+----+----+----+
  | 20 |  size   |  First pkt number |
  +----+----+----+----+----+----+----+

  blk :: 20
  size :: 4
  pkt num :: The first packet number to be sent in the data phase

Congestion

Este bloque está diseñado para ser un método extensible para intercambiar información de control de congestión. El control de congestión puede ser complejo y puede evolucionar a medida que obtengamos más experiencia con el protocolo en pruebas en vivo, o después del despliegue completo.

Esto mantiene cualquier información de congestión fuera de los bloques I2NP, First Fragment, Followon Fragment y ACK de alto uso, donde no hay espacio asignado para flags. Aunque hay tres bytes de flags no utilizados en el encabezado del paquete Data, eso también proporciona espacio limitado para extensibilidad y protección de cifrado más débil.

Aunque es algo derrochador usar un bloque de 4 bytes para dos bits de información, al poner esto en un bloque separado, podemos extenderlo fácilmente con datos adicionales como tamaños de ventana actuales, RTT medido, u otras flags. La experiencia ha demostrado que solo los bits de flag a menudo es insuficiente e incómodo para la implementación de esquemas avanzados de control de congestión. Intentar agregar soporte para cualquier característica posible de control de congestión en, por ejemplo, el bloque ACK, desperdiciaría espacio y agregaría complejidad al análisis de ese bloque.

Las implementaciones no deben asumir que el otro router soporta algún bit de bandera o característica particular incluida aquí, a menos que la implementación sea requerida por una versión futura de esta especificación.

Este bloque debería ser probablemente el último bloque que no sea de relleno en la carga útil.

+----+----+----+----+
  | 21 |  size   |flag|
  +----+----+----+----+

  blk :: 21
  size :: 1 (or more if extended)
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 1 to request immediate ack
         bit 1: 1 for explicit congestion notification (ECN)
         bits 7-2: Unused, set to 0 for future compatibility

Carga útil

Esto es para el relleno dentro de las cargas útiles AEAD. El relleno para todos los mensajes está dentro de las cargas útiles AEAD.

El padding debe adherirse aproximadamente a los parámetros negociados. Bob envió sus parámetros mín/máx tx/rx solicitados en Session Created. Alice envió sus parámetros mín/máx tx/rx solicitados en Session Confirmed. Las opciones actualizadas pueden enviarse durante la fase de datos. Ver la información del bloque de opciones arriba.

Si está presente, este debe ser el último bloque en la carga útil.

+----+----+----+----+----+----+----+----+
  |254 |  size   |      padding           |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 254
  size :: 2 bytes, big endian, size of padding to follow
  padding :: random data

Notas:

  • Size = 0 está permitido.

  • Estrategias de relleno por determinar.

  • Relleno mínimo por determinar.

  • Se permiten cargas útiles de solo relleno.

  • Valores predeterminados de relleno por determinar.

  • Ver bloque de opciones para negociación de parámetros de relleno

  • Ver bloque de opciones para parámetros de relleno mín/máx

  • No exceder la MTU. Si es necesario más relleno, enviar múltiples mensajes.

  • La respuesta del router ante violación del relleno negociado depende de la implementación.

  • La longitud del padding debe decidirse por mensaje individual y estimaciones de la distribución de longitud, o deben añadirse retrasos aleatorios. Estas contramedidas deben incluirse para resistir DPI, ya que los tamaños de mensaje revelarían que el tráfico I2P está siendo transportado por el protocolo de transporte. El esquema exacto de padding es un área de trabajo futuro, el Apéndice A de NTCP2 proporciona más información sobre el tema.

Replay Prevention

SSU2 está diseñado para minimizar el impacto de los mensajes reproducidos por un atacante.

Los mensajes Token Request, Retry, Session Request, Session Created, Hole Punch y Peer Test fuera de sesión deben contener bloques DateTime.

Tanto Alice como Bob validan que el tiempo de estos mensajes esté dentro de un desfase válido (recomendado +/- 2 minutos). Para la “resistencia al sondeo”, Bob no debería responder a mensajes de Token Request o Session Request si el desfase es inválido, ya que estos mensajes pueden ser un ataque de repetición o sondeo.

Bob puede elegir rechazar mensajes duplicados de Token Request y Retry, incluso si el skew es válido, mediante un filtro Bloom u otro mecanismo. Sin embargo, el tamaño y el costo de CPU de responder a estos mensajes es bajo. En el peor de los casos, un mensaje Token Request replicado puede invalidar un token enviado previamente.

El sistema de tokens minimiza enormemente el impacto de los mensajes Session Request reproducidos. Dado que los tokens solo pueden usarse una vez, un mensaje Session Request reproducido nunca tendrá un token válido. Bob puede elegir rechazar mensajes Session Request duplicados, incluso si el desfase es válido, mediante un filtro Bloom u otro mecanismo. Sin embargo, el tamaño y costo de CPU de responder con un mensaje Retry es bajo. En el peor caso, enviar un mensaje Retry puede invalidar un token enviado previamente.

Los mensajes duplicados de Session Created y Session Confirmed no se validarán porque el estado del handshake de Noise no estará en el estado correcto para descifrarlos. En el peor de los casos, un peer puede retransmitir un Session Confirmed en respuesta a un aparente Session Created duplicado.

Los mensajes de Hole Punch y Peer Test repetidos deberían tener poco o ningún impacto.

Los routers deben usar el número de paquete del mensaje de datos para detectar y descartar mensajes de fase de datos duplicados. Cada número de paquete debe usarse solo una vez. Los mensajes repetidos deben ser ignorados.

Handshake Retransmission

Session Request

Si Alice no recibe ningún Session Created o Retry:

Mantener los mismos IDs de origen y conexión, clave efímera, y número de paquete 0. O simplemente conservar y retransmitir el mismo paquete cifrado. El número de paquete no debe incrementarse, porque eso cambiaría el valor hash encadenado usado para cifrar el mensaje Session Created.

Intervalos de retransmisión recomendados: 1.25, 2.5, y 5 segundos (1.25, 3.75, y 8.75 segundos después del primer envío). Tiempo de espera recomendado: 15 segundos en total

Session Created

Si Bob no recibe ningún Session Confirmed:

Mantén los mismos IDs de origen y conexión, clave efímera, y número de paquete 0. O simplemente conserva el paquete cifrado. El número de paquete no debe incrementarse, porque eso cambiaría el valor hash encadenado usado para cifrar el mensaje Session Confirmed.

Intervalos de retransmisión recomendados: 1, 2 y 4 segundos (1, 3 y 7 segundos después del primer envío). Tiempo de espera recomendado: 12 segundos en total

Session Confirmed

En SSU 1, Alice no cambia a la fase de datos hasta que se recibe el primer paquete de datos de Bob. Esto hace que SSU 1 sea una configuración de dos viajes de ida y vuelta.

Para SSU 2, intervalos de retransmisión de Session Confirmed recomendados: 1.25, 2.5 y 5 segundos (1.25, 3.75 y 8.75 segundos después del primer envío).

Hay varias alternativas. Todas son 1 RTT:

  1. Alice asume que Session Confirmed fue recibido, envía mensajes de datos inmediatamente, nunca retransmite Session Confirmed. Los paquetes de datos recibidos fuera de orden (antes de Session Confirmed) serán indescifrables, pero serán retransmitidos. Si Session Confirmed se pierde, todos los mensajes de datos enviados serán descartados.

  2. Como en 1), enviar mensajes de datos inmediatamente, pero también retransmitir Session Confirmed hasta que se reciba un mensaje de datos.

  3. Podríamos usar IK en lugar de XK, ya que tiene solo dos mensajes en el handshake, pero usa un DH adicional (4 en lugar de 3).

La implementación recomendada es la opción 2). Alice debe conservar la información requerida para retransmitir el mensaje Session Confirmed. Alice también debería retransmitir todos los mensajes Data después de que el mensaje Session Confirmed sea retransmitido.

Al retransmitir Session Confirmed, mantener los mismos IDs de origen y conexión, clave efímera, y número de paquete 1. O simplemente conservar el paquete cifrado. El número de paquete no debe incrementarse, porque eso cambiaría el valor del hash encadenado que es una entrada para la función split().

Bob puede retener (poner en cola) los mensajes de datos recibidos antes del mensaje Session Confirmed. Ni las claves de protección de cabecera ni las claves de descifrado están disponibles antes de que se reciba el mensaje Session Confirmed, por lo que Bob no sabe que son mensajes de datos, pero eso se puede presumir. Después de que se recibe el mensaje Session Confirmed, Bob es capaz de descifrar y procesar los mensajes de datos en cola. Si esto es demasiado complejo, Bob puede simplemente descartar los mensajes de datos no descifrables, ya que Alice los retransmitirá.

Nota: Si se pierden los paquetes de sesión confirmada, Bob retransmitirá session created. El encabezado de session created no será descifrable con la clave intro de Alice, ya que está configurado con la clave intro de Bob (a menos que se realice el descifrado de respaldo con la clave intro de Bob). Bob puede retransmitir inmediatamente los paquetes de session confirmed si no han sido previamente confirmados, y se recibe un paquete no descifrable.

Token Request

Si Alice no recibe ningún Retry:

Mantener los mismos IDs de origen y conexión. Una implementación puede generar un nuevo número de paquete aleatorio y cifrar un nuevo paquete; o puede reutilizar el mismo número de paquete o simplemente retener y retransmitir el mismo paquete cifrado. El número de paquete no debe incrementarse, porque eso cambiaría el valor hash encadenado utilizado para cifrar el mensaje Session Created.

Intervalos de retransmisión recomendados: 3 y 6 segundos (3 y 9 segundos después del primer envío). Tiempo de espera recomendado: 15 segundos en total

Retry

Si Bob no recibe ninguna Session Request:

Un mensaje Retry no se retransmite al agotar el tiempo de espera, para reducir los impactos de las direcciones de origen falsificadas.

Sin embargo, un mensaje Retry puede ser retransmitido en respuesta a un mensaje Session Request repetido que se reciba con el token original (inválido), o en respuesta a un mensaje Token Request repetido. En cualquier caso, esto indica que el mensaje Retry se perdió.

Si se recibe un segundo mensaje Session Request con un token diferente pero aún inválido, descartar la sesión pendiente y no responder.

Si se reenvía el mensaje Retry: Mantener los mismos IDs de origen y conexión y el token. Una implementación puede generar un nuevo número de paquete aleatorio y cifrar un nuevo paquete; O puede reutilizar el mismo número de paquete o simplemente retener y retransmitir el mismo paquete cifrado.

Total Timeout

El timeout total recomendado para el handshake es de 20 segundos.

Duplicates and Error Handling

Los duplicados de los tres mensajes de handshake Noise Session Request, Session Created y Session Confirmed deben ser detectados antes de MixHash() del encabezado. Aunque el procesamiento AEAD de Noise presumiblemente fallará después de eso, el hash del handshake ya estaría corrupto.

Si cualquiera de los tres mensajes se corrompe y falla en AEAD, el handshake no puede recuperarse posteriormente ni siquiera con retransmisión, porque MixHash() ya fue llamado en el mensaje corrupto.

Tokens

El Token en el header de Session Request se utiliza para mitigación de DoS, para prevenir la suplantación de direcciones de origen, y como resistencia a ataques de replay.

Si Bob no acepta el token en el mensaje Session Request, Bob NO descifra el mensaje, ya que requiere una operación DH costosa. Bob simplemente envía un mensaje Retry con un nuevo token.

Si posteriormente se recibe un mensaje Session Request con ese token, Bob procede a descifrar ese mensaje y continuar con el handshake.

El token debe ser un valor de 8 bytes generado aleatoriamente, si el generador del token almacena los valores y la IP y puerto asociados (en memoria o de forma persistente). El generador no puede generar un valor opaco, por ejemplo, usando SipHash (con una semilla secreta K0, K1) de la IP, puerto y hora o día actual, para crear tokens que no necesiten ser guardados en memoria, porque este método hace difícil rechazar tokens reutilizados y ataques de repetición.

Los tokens solo pueden usarse una vez. Un token enviado de Bob a Alice en un mensaje Retry debe usarse inmediatamente y expira en unos pocos segundos. Un token enviado en un bloque New Token en una sesión establecida puede usarse en una conexión posterior, y expira en el momento especificado en ese bloque. La expiración es especificada por el remitente; los valores recomendados son de una hora como mínimo y varias horas como máximo.

Si la IP o puerto de un router cambia, debe eliminar todos los tokens guardados (tanto entrantes como salientes) para la IP o puerto anterior, ya que ya no son válidos. Los tokens pueden opcionalmente persistir a través de reinicios del router, dependiendo de la implementación. La aceptación de un token no expirado no está garantizada; si Bob ha olvidado o eliminado sus tokens guardados, enviará un Retry a Alice. Un router puede elegir limitar el almacenamiento de tokens, y remover los tokens almacenados más antiguos incluso si no han expirado.

Los bloques de Nuevo Token pueden enviarse de Alice a Bob o de Bob a Alice. Típicamente se enviarían una vez, durante o poco después del establecimiento de la sesión. El token puede reenviarse antes o después de la expiración con un nuevo tiempo de expiración, o puede enviarse un nuevo token. Los routers deben asumir que solo el último token recibido es válido; no hay requisito de almacenar múltiples tokens entrantes o salientes para la misma IP/puerto.

Un token está vinculado a la combinación de IP/puerto de origen e IP/puerto de destino. Un token recibido en IPv4 no puede ser usado para IPv6 o viceversa.

Si cualquiera de los peers migra a una nueva IP o puerto durante la sesión (consulte la sección de Migración de Conexión), cualquier token intercambiado previamente se invalida y se deben intercambiar nuevos tokens.

Las implementaciones pueden, pero no están obligadas a, guardar tokens en disco y recargarlos al reiniciar. Si se persisten, la implementación debe asegurarse de que la IP y el puerto no hayan cambiado desde el apagado antes de recargarlos.

I2NP Message Fragmentation

Diferencias con SSU 1

Nota: Como en SSU 1, el fragmento inicial no contiene información sobre el número total de fragmentos o la longitud total. Los fragmentos posteriores no contienen información sobre su desplazamiento. Esto proporciona al remitente la flexibilidad de fragmentar “sobre la marcha” basándose en el espacio disponible en el paquete. (Java I2P no hace esto; “pre-fragmenta” antes de que se envíe el primer fragmento) Sin embargo, esto sí impone una carga al receptor de almacenar fragmentos recibidos fuera de orden y retrasar el reensamblaje hasta que se reciban todos los fragmentos.

Como en SSU 1, cualquier retransmisión de fragmentos debe preservar la longitud (y el desplazamiento implícito) de la transmisión previa del fragmento.

SSU 2 sí separa los tres casos (mensaje completo, fragmento inicial y fragmento de continuación) en tres tipos de bloque diferentes, para mejorar la eficiencia de procesamiento.

I2NP Message Duplication

Este protocolo NO previene completamente la entrega duplicada de mensajes I2NP. Los duplicados a nivel de IP o los ataques de repetición serán detectados en la capa SSU2, porque cada número de paquete solo puede ser usado una vez.

Cuando los mensajes I2NP o fragmentos son retransmitidos en nuevos paquetes, sin embargo, esto no es detectable en la capa SSU2. El router debe hacer cumplir la expiración I2NP (tanto demasiado antiguo como demasiado lejos en el futuro) y usar un filtro Bloom u otro mecanismo basado en el ID del mensaje I2NP.

El router, o en la implementación de SSU2, pueden utilizar mecanismos adicionales para detectar duplicados. Por ejemplo, SSU2 podría mantener una caché de IDs de mensajes recibidos recientemente. Esto depende de la implementación.

Congestion Control

Esta propuesta especifica el protocolo para la numeración de paquetes y bloques ACK. Esto proporciona información suficiente en tiempo real para que un transmisor implemente un algoritmo de control de congestión eficiente y responsivo, mientras permite flexibilidad e innovación en esa implementación. Esta sección discute objetivos de implementación y proporciona sugerencias. Se puede encontrar orientación general en RFC 9002. Véase también RFC 6298 para orientación sobre temporizadores de retransmisión.

Los paquetes de datos que solo contienen ACK no deberían contar para los bytes o paquetes en tránsito y no están controlados por congestión. A diferencia de TCP, SSU2 puede detectar la pérdida de estos paquetes y esa información puede usarse para ajustar el estado de congestión. Sin embargo, este documento no especifica un mecanismo para hacerlo.

Los paquetes que contengan algunos otros bloques que no sean de datos también pueden ser excluidos del control de congestión si se desea, dependiendo de la implementación. Por ejemplo:

  • Prueba de par
  • Solicitud/introducción/respuesta de retransmisión
  • Desafío/respuesta de ruta

Se recomienda que el control de congestión se base en el conteo de bytes, no en el conteo de paquetes, siguiendo las directrices de los RFC de TCP y QUIC RFC 9002. Un límite adicional de conteo de paquetes también puede ser útil para prevenir el desbordamiento del buffer en el kernel o en middleboxes, dependiendo de la implementación, aunque esto puede añadir una complejidad significativa. Si la salida de paquetes por sesión y/o total está limitada por ancho de banda y/o regulada, esto puede mitigar la necesidad de limitar el conteo de paquetes.

Packet Numbers

En SSU 1, los ACKs y NACKs contenían números de mensaje I2NP y máscaras de bits de fragmentos. Los transmisores rastreaban el estado de ACK de los mensajes salientes (y sus fragmentos) y retransmitían fragmentos según fuera necesario.

En SSU 2, los ACK y NACK contienen números de paquete. Los transmisores deben mantener una estructura de datos con una asignación de números de paquete a sus contenidos. Cuando un paquete recibe ACK o NACK, el transmisor debe determinar qué mensajes I2NP y fragmentos estaban en ese paquete, para decidir qué retransmitir.

Session Confirmed ACK

Bob envía un ACK del paquete 0, que confirma el mensaje Session Confirmed y permite a Alice proceder a la fase de datos, y descartar el mensaje Session Confirmed grande que se estaba guardando para una posible retransmisión. Esto reemplaza el DeliveryStatusMessage enviado por Bob en SSU 1.

Bob debería enviar un ACK tan pronto como sea posible después de recibir el mensaje Session Confirmed. Un pequeño retraso (no más de 50 ms) es aceptable, ya que al menos un mensaje Data debería llegar casi inmediatamente después del mensaje Session Confirmed, de modo que el ACK pueda confirmar tanto el Session Confirmed como el mensaje Data. Esto evitará que Bob tenga que retransmitir el mensaje Session Confirmed.

Generating ACKs

Definición: Paquetes que requieren confirmación: Los paquetes que contienen bloques que requieren confirmación provocan un ACK del receptor dentro del retraso máximo de confirmación y se denominan paquetes que requieren confirmación.

Los routers confirman todos los paquetes que reciben y procesan. Sin embargo, solo los paquetes que requieren confirmación causan que se envíe un bloque ACK dentro del retraso máximo de confirmación. Los paquetes que no requieren confirmación solo se confirman cuando se envía un bloque ACK por otras razones.

Al enviar un paquete por cualquier motivo, un endpoint debería intentar incluir un bloque ACK si no se ha enviado uno recientemente. Hacerlo ayuda con la detección oportuna de pérdidas en el peer.

En general, la retroalimentación frecuente de un receptor mejora la respuesta a pérdidas y congestión, pero esto debe equilibrarse contra la carga excesiva generada por un receptor que envía un bloque ACK en respuesta a cada paquete que solicita confirmación. La orientación ofrecida a continuación busca lograr este equilibrio.

Los paquetes de datos en sesión que contengan cualquier bloque EXCEPTO los siguientes provocan confirmación (ack-eliciting):

  • Bloque ACK
  • Bloque de dirección
  • Bloque DateTime
  • Bloque de relleno
  • Bloque de terminación
  • Cualquier bloque en el mismo paquete que un bloque de terminación
  • ¿Otros?

Los paquetes que contienen un bloque de Terminación con una razón distinta a “termination received” son confirmados con un paquete que contiene un bloque de Terminación con “termination received”.

Los paquetes fuera de sesión, incluyendo mensajes de handshake y mensajes de peer test 5-7, tienen sus propios mecanismos de confirmación. Ver más abajo.

Handshake ACKs

Estos son casos especiales:

  • Token Request es confirmado implícitamente por Retry
  • Session Request es confirmado implícitamente por Session Created o Retry
  • Retry es confirmado implícitamente por Session Request
  • Session Created es confirmado implícitamente por Session Confirmed
  • Session Confirmed debe ser confirmado inmediatamente

Sending ACK Blocks

Los bloques ACK se utilizan para reconocer los paquetes de la fase de datos. Solo deben incluirse para paquetes de la fase de datos dentro de la sesión.

Cada paquete debe ser reconocido al menos una vez, y los paquetes que requieren confirmación deben ser reconocidos al menos una vez dentro de un retraso máximo.

Un endpoint debe confirmar inmediatamente todos los paquetes de handshake que requieren confirmación dentro de su retraso máximo, con la siguiente excepción. Antes de la confirmación del handshake, un endpoint podría no tener las claves de cifrado del encabezado del paquete para descifrar los paquetes cuando se reciben. Por lo tanto, podría almacenarlos en buffer y confirmarlos cuando las claves necesarias estén disponibles.

Dado que los paquetes que contienen solo bloques ACK no están controlados por congestión, un endpoint no debe enviar más de un paquete de este tipo en respuesta a recibir un paquete que solicita acuse de recibo.

Un endpoint no debe enviar un paquete que no requiera acknowledgment en respuesta a un paquete que no requiera acknowledgment, incluso si hay gaps de paquetes que preceden al paquete recibido. Esto evita un bucle infinito de acknowledgments, que podría impedir que la conexión llegue a estar inactiva. Los paquetes que no requieren acknowledgment son eventualmente confirmados cuando el endpoint envía un bloque ACK en respuesta a otros eventos.

Un endpoint que solo está enviando bloques ACK no recibirá confirmaciones de su par a menos que esas confirmaciones estén incluidas en paquetes con bloques que requieren confirmación. Un endpoint debería enviar un bloque ACK con otros bloques cuando hay nuevos paquetes que requieren confirmación por reconocer. Cuando solo es necesario confirmar paquetes que no requieren confirmación, un endpoint PUEDE elegir no enviar un bloque ACK con bloques salientes hasta que se haya recibido un paquete que requiere confirmación.

Un endpoint que solo está enviando paquetes que no requieren confirmación podría optar por añadir ocasionalmente un bloque que requiera confirmación a esos paquetes para asegurar que reciba una confirmación. En ese caso, un endpoint NO DEBE enviar un bloque que requiera confirmación en todos los paquetes que de otro modo no requerirían confirmación, para evitar un bucle infinito de confirmaciones.

Para ayudar a la detección de pérdidas en el emisor, un endpoint debe generar y enviar un bloque ACK sin demora cuando recibe un paquete que provoca ack en cualquiera de estos casos:

  • Cuando el paquete recibido tiene un número de paquete menor que otro paquete que provoca confirmación que ha sido recibido

  • Cuando el paquete tiene un número de paquete mayor que el paquete que provoca ack con el número más alto que se ha recibido y hay paquetes faltantes entre ese paquete y este paquete.

  • Cuando la bandera ack-immediate en el encabezado del paquete está establecida

Se espera que los algoritmos sean resistentes a receptores que no sigan las recomendaciones ofrecidas anteriormente. Sin embargo, una implementación solo debería desviarse de estos requisitos después de una consideración cuidadosa de las implicaciones de rendimiento de un cambio, tanto para las conexiones realizadas por el endpoint como para otros usuarios de la red.

ACK Frequency

Un receptor determina con qué frecuencia enviar confirmaciones de recibo en respuesta a paquetes que solicitan confirmación. Esta determinación implica un compromiso.

Los endpoints dependen de confirmaciones oportunas para detectar pérdidas. Los controladores de congestión basados en ventana dependen de las confirmaciones para gestionar su ventana de congestión. En ambos casos, retrasar las confirmaciones puede afectar negativamente el rendimiento.

Por otro lado, reducir la frecuencia de paquetes que transportan únicamente acknowledgments reduce el costo de transmisión y procesamiento de paquetes en ambos extremos. Puede mejorar el throughput de la conexión en enlaces severamente asimétricos y reducir el volumen de tráfico de acknowledgment utilizando la capacidad de la ruta de retorno; ver Sección 3 de RFC 3449.

Un receptor debería enviar un bloque ACK después de recibir al menos dos paquetes que requieren confirmación. Esta recomendación es de naturaleza general y es consistente con las recomendaciones para el comportamiento de endpoints TCP RFC 5681. El conocimiento de las condiciones de red, el conocimiento del controlador de congestión del peer, o investigación y experimentación adicional podrían sugerir estrategias de confirmación alternativas con mejores características de rendimiento.

Un receptor puede procesar múltiples paquetes disponibles antes de determinar si enviar un bloque ACK en respuesta. En general, el receptor no debería retrasar un ACK por más de RTT / 6, o 150 ms como máximo.

La bandera ack-immediate en el encabezado del paquete de datos es una solicitud para que el receptor envíe un ack poco después de la recepción, probablemente dentro de unos pocos ms. En general, el receptor no debería retrasar un ACK inmediato por más de RTT / 16, o 5 ms como máximo.

Immediate ACK Flag

El receptor no conoce el tamaño de la ventana de envío del emisor, por lo que no sabe cuánto tiempo debe esperar antes de enviar un ACK. La bandera de ACK inmediato en el encabezado del paquete de datos es una forma importante de mantener el rendimiento máximo al minimizar el RTT efectivo. La bandera de ACK inmediato está en el byte 13 del encabezado, bit 0, es decir, (header[13] & 0x01). Cuando está activada, se solicita un ACK inmediato. Consulte la sección del encabezado corto anterior para más detalles.

Hay varias estrategias posibles que un emisor puede usar para determinar cuándo establecer la bandera immediate-ack:

  • Se establece una vez cada N paquetes, para algún N pequeño
  • Se establece en el último de una ráfaga de paquetes
  • Se establece cuando la ventana de envío está casi llena, por ejemplo más de 2/3 llena
  • Se establece en todos los paquetes con fragmentos retransmitidos

Las banderas de ACK inmediato solo deberían ser necesarias en paquetes de datos que contengan mensajes I2NP o fragmentos de mensajes.

ACK Block Size

Cuando se envía un bloque ACK, se incluyen uno o más rangos de paquetes confirmados. Incluir confirmaciones para paquetes más antiguos reduce la posibilidad de retransmisiones espurias causadas por la pérdida de bloques ACK enviados previamente, a costa de bloques ACK más grandes.

Los bloques ACK siempre deben confirmar los paquetes recibidos más recientemente, y cuanto más desordenados estén los paquetes, más importante es enviar un bloque ACK actualizado rápidamente, para evitar que el par declare un paquete como perdido y retransmita erróneamente los bloques que contiene. Un bloque ACK debe caber dentro de un solo paquete. Si no es así, entonces se omiten los rangos más antiguos (aquellos con los números de paquete más pequeños).

Un receptor limita el número de rangos ACK que recuerda y envía en bloques ACK, tanto para limitar el tamaño de los bloques ACK como para evitar el agotamiento de recursos. Después de recibir confirmaciones para un bloque ACK, el receptor debería dejar de rastrear esos rangos ACK confirmados. Los emisores pueden esperar confirmaciones para la mayoría de los paquetes, pero este protocolo no garantiza la recepción de una confirmación para cada paquete que el receptor procesa.

Es posible que retener muchos rangos ACK pueda causar que un bloque ACK se vuelva demasiado grande. Un receptor puede descartar rangos ACK no reconocidos para limitar el tamaño del bloque ACK, a costa de incrementar las retransmisiones del emisor. Esto es necesario si un bloque ACK sería demasiado grande para caber en un paquete. Los receptores también pueden limitar más el tamaño del bloque ACK para preservar espacio para otros bloques o para limitar el ancho de banda que consumen los reconocimientos.

Un receptor debe mantener un rango de ACK a menos que pueda garantizar que no aceptará posteriormente paquetes con números en ese rango. Mantener un número mínimo de paquete que aumente a medida que se descartan rangos es una forma de lograr esto con un estado mínimo.

Los receptores pueden descartar todos los rangos ACK, pero deben conservar el número de paquete más grande que ha sido procesado exitosamente, ya que se utiliza para recuperar números de paquete de paquetes posteriores.

La siguiente sección describe un enfoque ejemplar para determinar qué paquetes reconocer en cada bloque ACK. Aunque el objetivo de este algoritmo es generar un reconocimiento para cada paquete que se procesa, aún es posible que los reconocimientos se pierdan.

Limiting Ranges by Tracking ACK Blocks

Cuando se envía un paquete que contiene un bloque ACK, el campo Ack Through en ese bloque puede ser guardado. Cuando se confirma un paquete que contiene un bloque ACK, el receptor puede dejar de confirmar paquetes menores o iguales al campo Ack Through en el bloque ACK enviado.

Un receptor que envía solo paquetes que no requieren confirmación, como bloques ACK, podría no recibir una confirmación durante un largo período de tiempo. Esto podría causar que el receptor mantenga estado para un gran número de bloques ACK durante un largo período de tiempo, y los bloques ACK que envía podrían ser innecesariamente grandes. En tal caso, un receptor podría enviar un PING u otro pequeño bloque que requiera confirmación ocasionalmente, como una vez por viaje de ida y vuelta, para obtener un ACK del par.

En casos sin pérdida de bloque ACK, este algoritmo permite un mínimo de 1 RTT de reordenamiento. En casos con pérdida de bloque ACK y reordenamiento, este enfoque no garantiza que cada acknowledgment sea visto por el emisor antes de que ya no esté incluido en el bloque ACK. Los paquetes podrían recibirse fuera de orden, y todos los bloques ACK posteriores que los contengan podrían perderse. En este caso, el algoritmo de recuperación de pérdidas podría causar retransmisiones espurias, pero el emisor continuará progresando.

Congestion

Los transportes I2P no garantizan la entrega en orden de los mensajes I2NP. Por lo tanto, la pérdida de un mensaje de Datos que contenga uno o más mensajes I2NP o fragmentos NO impide que se entreguen otros mensajes I2NP; no hay bloqueo de cabecera de línea. Las implementaciones deberían continuar enviando nuevos mensajes durante la fase de recuperación de pérdidas si la ventana de envío lo permite.

Retransmission

Un emisor no debe retener el contenido completo de un mensaje para ser retransmitido de forma idéntica (excepto para mensajes de handshake, ver arriba). Un emisor debe ensamblar mensajes que contengan información actualizada (ACKs, NACKs y datos no confirmados) cada vez que envíe un mensaje. Un emisor debe evitar retransmitir información de mensajes una vez que han sido confirmados. Esto incluye mensajes que son confirmados después de haber sido declarados perdidos, lo cual puede ocurrir en presencia de reordenamiento de red.

Window

Por definir. Se puede encontrar orientación general en RFC 9002.

Connection Migration

La IP o puerto de un peer puede cambiar durante la duración de una sesión. Un cambio de IP puede ser causado por la rotación de direcciones temporales IPv6, cambio de IP periódico impulsado por el ISP, un cliente móvil que transiciona entre IPs de WiFi y celular, u otros cambios de red local. Un cambio de puerto puede ser causado por un re-enlace NAT después de que el enlace anterior haya expirado.

La IP o puerto de un peer puede parecer cambiar debido a varios ataques dentro y fuera de la ruta, incluyendo la modificación o inyección de paquetes.

La migración de conexiones es el proceso mediante el cual se valida un nuevo endpoint de origen (IP+puerto), mientras se previenen cambios que no están validados. Este proceso es una versión simplificada de la definida en QUIC RFC 9000. Este proceso se define únicamente para la fase de datos de una sesión. La migración no está permitida durante el handshake. Todos los paquetes de handshake deben ser verificados para confirmar que provienen de la misma IP y puerto que los paquetes enviados y recibidos anteriormente. En otras palabras, la IP y puerto de un peer deben ser constantes durante el handshake.

Threat Model

(Adaptado de QUIC RFC 9000)

Notas

Un peer puede falsificar su dirección de origen para hacer que un endpoint envíe cantidades excesivas de datos a un host que no los desea. Si el endpoint envía significativamente más datos que el peer que está falsificando, la migración de conexión podría usarse para amplificar el volumen de datos que un atacante puede generar hacia una víctima.

Fragmentación de Sesión Confirmada

Un atacante en el camino podría causar una migración de conexión espuria copiando y reenviando un paquete con una dirección falsificada de tal manera que llegue antes que el paquete original. El paquete con la dirección falsificada será visto como proveniente de una conexión en migración, y el paquete original será visto como duplicado y descartado. Después de una migración espuria, la validación de la dirección de origen fallará porque la entidad en la dirección de origen no tiene las claves criptográficas necesarias para leer o responder al Path Challenge que se le envía, incluso si quisiera hacerlo.

Off-Path Packet Forwarding

Un atacante fuera de ruta que pueda observar paquetes podría reenviar copias de paquetes genuinos a los endpoints. Si el paquete copiado llega antes que el paquete genuino, esto aparecerá como una re-vinculación NAT. Cualquier paquete genuino será descartado como duplicado. Si el atacante es capaz de continuar reenviando paquetes, podría ser capaz de causar migración a una ruta a través del atacante. Esto coloca al atacante en la ruta, otorgándole la capacidad de observar o descartar todos los paquetes subsecuentes.

Privacy Implications

QUIC RFC 9000 especifica cambiar los IDs de conexión al cambiar las rutas de red. Usar un ID de conexión estable en múltiples rutas de red permitiría a un observador pasivo correlacionar la actividad entre esas rutas. Un endpoint que se mueve entre redes podría no desear que su actividad sea correlacionada por alguna entidad distinta a su peer. Sin embargo, QUIC no cifra los IDs de conexión en el header. SSU2 sí lo hace, por lo que la fuga de privacidad requeriría que el observador pasivo también tenga acceso a la base de datos de red para obtener la clave de introducción necesaria para descifrar el ID de conexión. Incluso con la clave de introducción, este no es un ataque fuerte, y no cambiamos los IDs de conexión después de la migración en SSU2, ya que esto sería una complicación significativa.

Initiating Path Validation

Durante la fase de datos, los peers deben verificar que la IP de origen y el puerto de cada paquete de datos recibido. Si la IP o el puerto es diferente al recibido anteriormente, Y el paquete no es un número de paquete duplicado, Y el paquete se descifra exitosamente, la sesión entra en la fase de validación de ruta.

Además, un peer debe verificar que la nueva IP y puerto sean válidos según las reglas de validación locales (no bloqueados, no puertos ilegales, etc.). Los peers NO están obligados a soportar migración entre IPv4 e IPv6, y pueden tratar una nueva IP en la otra familia de direcciones como inválida, ya que este no es un comportamiento esperado y puede agregar complejidad significativa de implementación. Al recibir un paquete de una IP/puerto inválidos, una implementación puede simplemente descartarlo, o puede iniciar una validación de ruta con la IP/puerto anterior.

Al entrar en la fase de validación de ruta, sigue los siguientes pasos:

  • Iniciar un temporizador de tiempo de espera de validación de ruta de varios segundos, o varias veces el RTO actual (por determinar)
  • Reducir la ventana de congestión al mínimo
  • Reducir el PMTU al mínimo (1280)
  • Enviar un paquete de datos que contenga un bloque Path Challenge, un bloque Address (que contenga la nueva IP/puerto), y, típicamente, un bloque ACK, a la nueva IP y puerto. Este paquete utiliza el mismo ID de conexión y claves de cifrado que la sesión actual. Los datos del bloque Path Challenge deben contener entropía suficiente (al menos 8 bytes) para que no puedan ser falsificados.
  • Opcionalmente, también enviar un Path Challenge a la IP/puerto antigua, con datos de bloque diferentes. Ver más abajo.
  • Iniciar un temporizador de tiempo de espera de Path Response basado en el RTO actual (típicamente RTT + un múltiplo de RTTdev)

Durante la fase de validación de ruta, la sesión puede continuar procesando paquetes entrantes. Ya sea desde la IP/puerto anterior o nueva. La sesión también puede continuar enviando y confirmando paquetes de datos. Sin embargo, la ventana de congestión y el PMTU deben permanecer en los valores mínimos durante la fase de validación de ruta, para evitar ser utilizados en ataques de denegación de servicio enviando grandes cantidades de tráfico a una dirección falsificada.

Una implementación puede, pero no está obligada, a intentar validar múltiples rutas simultáneamente. Esto probablemente no vale la pena por la complejidad. Puede, pero no está obligada, a recordar una IP/puerto anterior como ya validada, y omitir la validación de ruta si un peer regresa a su IP/puerto anterior.

Si se recibe una Respuesta de Ruta (Path Response), que contiene los datos idénticos enviados en el Desafío de Ruta (Path Challenge), la Validación de Ruta ha tenido éxito. No se requiere que la IP/puerto de origen del mensaje de Respuesta de Ruta sea el mismo al que se envió el Desafío de Ruta.

Si no se recibe una Respuesta de Ruta antes de que expire el temporizador de Respuesta de Ruta, envía otro Desafío de Ruta y duplica el temporizador de Respuesta de Ruta.

Si no se recibe una Path Response antes de que expire el temporizador de Path Validation, la Path Validation ha fallado.

Message Contents

Los mensajes Data deben contener los siguientes bloques. El orden no está especificado excepto que Padding debe ir al final:

  • Bloque de Validación de Ruta o Respuesta de Ruta. La Validación de Ruta contiene datos opacos, se recomienda un mínimo de 8 bytes. La Respuesta de Ruta contiene los datos de la Validación de Ruta.
  • Bloque de Dirección que contiene la IP aparente del destinatario
  • Bloque DateTime
  • Bloque ACK
  • Bloque de Relleno

No se recomienda incluir ningún otro bloque (por ejemplo, I2NP) en el mensaje.

Se permite incluir un bloque de Path Validation en el mensaje que contiene el Path Response, para iniciar una validación en la otra dirección.

Los bloques Path Challenge y Path Response requieren ACK. El Path Challenge será confirmado con ACK por un mensaje Data que contenga los bloques Path Response y ACK. El Path Response debería ser confirmado con ACK por un mensaje Data que contenga un bloque ACK.

Routing during Path Validation

La especificación QUIC no es clara sobre dónde enviar paquetes de datos durante la validación de ruta - ¿a la IP/puerto antigua o nueva? Hay un equilibrio que debe encontrarse entre responder rápidamente a cambios de IP/puerto, y no enviar tráfico a direcciones falsificadas. Además, los paquetes falsificados no deben poder impactar sustancialmente una sesión existente. Los cambios solo de puerto probablemente sean causados por reenlace NAT después de un período de inactividad; los cambios de IP podrían ocurrir durante fases de alto tráfico en una o ambas direcciones.

Las estrategias están sujetas a investigación y refinamiento. Las posibilidades incluyen:

  • No enviar paquetes de datos a la nueva IP/puerto hasta que sea validada
  • Continuar enviando paquetes de datos a la IP/puerto anterior hasta que la nueva IP/puerto sea validada
  • Revalidar simultáneamente la IP/puerto anterior
  • No enviar ningún dato hasta que la IP/puerto anterior o nueva sea validada
  • Diferentes estrategias para cambio solo de puerto que para cambio de IP
  • Diferentes estrategias para un cambio IPv6 en el mismo /32, probablemente causado por rotación de dirección temporal

Responding to Path Challenge

Al recibir un Path Challenge, el peer debe responder con un paquete de datos que contenga un Path Response, con los datos del Path Challenge. TODO ¿¿¿Quizás???: El Path Response debe enviarse a la IP/puerto desde el cual se recibió el Path Challenge. Esto NO ES NECESARIAMENTE la IP/puerto que se estableció previamente para el peer. Esto asegura que la validación de ruta por un peer solo tenga éxito si la ruta es funcional en ambas direcciones. Consulte la sección Validación después del Cambio Local a continuación.

A menos que la IP/puerto sea diferente de la IP/puerto previamente conocida para el peer, trata un Path Challenge como un simple ping, y simplemente responde incondicionalmente con un Path Response. El receptor no mantiene ni cambia ningún estado basado en un Path Challenge recibido. Si la IP/puerto es diferente, un peer debe verificar que la nueva IP y puerto son válidos según las reglas de validación locales (no bloqueados, no puertos ilegales, etc.). Los peers NO están obligados a soportar respuestas entre familias de direcciones cruzadas entre IPv4 e IPv6, y pueden tratar una nueva IP en la otra familia de direcciones como inválida, ya que esto no es un comportamiento esperado.

A menos que esté limitada por el control de congestión, la Path Response debería enviarse inmediatamente. Las implementaciones deberían tomar medidas para limitar la velocidad de las Path Responses o el ancho de banda utilizado si es necesario.

Un bloque Path Challenge generalmente va acompañado de un bloque Address en el mismo mensaje. Si el bloque de dirección contiene una nueva IP/puerto, un peer puede validar esa IP/puerto e iniciar peer testing de esa nueva IP/puerto, con el peer de sesión o cualquier otro peer. Si el peer piensa que está tras firewall, y solo cambió el puerto, este cambio probablemente se debe a NAT rebinding, y probablemente no se requiera peer testing adicional.

Successful Path Validation

En una validación exitosa de la ruta, la conexión se migra completamente a la nueva IP/puerto. En caso de éxito:

  • Salir de la fase de validación de ruta
  • Todos los paquetes se envían a la nueva IP y puerto.
  • Se eliminan las restricciones en la ventana de congestión y PMTU, y se les permite aumentar. No simplemente restaurarlas a los valores anteriores, ya que la nueva ruta puede tener características diferentes.
  • Si la IP cambió, establecer el RTT calculado y RTO a valores iniciales. Debido a que los cambios solo de puerto son comúnmente el resultado de revinculación NAT u otra actividad de middlebox, el peer puede en su lugar retener su estado de control de congestión y estimación de tiempo de ida y vuelta en esos casos en lugar de revertir a valores iniciales.
  • Eliminar (invalidar) cualquier token enviado o recibido para la IP/puerto anterior (opcional)
  • Enviar un nuevo bloque de token para la nueva IP/puerto (opcional)

Cancelling Path Validation

Durante la fase de validación de ruta, cualquier paquete válido y no duplicado que se reciba desde la IP/puerto antigua y sea descifrado exitosamente causará que la Validación de Ruta sea cancelada. Es importante que una validación de ruta cancelada, causada por un paquete falsificado, no provoque que una sesión válida sea terminada o significativamente interrumpida.

En validación de ruta cancelada:

  • Salir de la fase de validación de ruta
  • Todos los paquetes se envían a la IP y puerto antiguos.
  • Se eliminan las restricciones en la ventana de congestión y PMTU, y se les permite aumentar, o, opcionalmente, restaurar los valores anteriores
  • Retransmitir cualquier paquete de datos que fue enviado previamente a la nueva IP/puerto a la IP/puerto antigua.

Failed Path Validation

Es importante que una validación de ruta fallida, causada por un paquete falsificado, no provoque que una sesión válida sea terminada o significativamente interrumpida.

En validación de ruta fallida:

  • Salir de la fase de validación de ruta
  • Todos los paquetes se envían a la IP y puerto antiguos.
  • Se eliminan las restricciones en la ventana de congestión y PMTU, y se permite que aumenten.
  • Opcionalmente, iniciar una validación de ruta en la IP y puerto antiguos. Si falla, terminar la sesión.
  • De lo contrario, seguir las reglas estándar de tiempo de espera y terminación de sesión.
  • Retransmitir cualquier paquete de datos que haya sido enviado previamente a la nueva IP/puerto a la IP/puerto antiguos.

Validation After Local Change

El proceso anterior está definido para peers que reciben un paquete desde una IP/puerto modificado. Sin embargo, también puede iniciarse en la otra dirección, por un peer que detecta que su IP o puerto han cambiado. Un peer puede ser capaz de detectar que su IP local cambió; sin embargo, es mucho menos probable que detecte que su puerto cambió debido a un reenlazado de NAT. Por lo tanto, esto es opcional.

Al recibir un desafío de ruta de un peer cuya IP o puerto ha cambiado, el otro peer debe iniciar un desafío de ruta en la dirección opuesta.

Seguridad del Relay

Los bloques Path Validation y Path Response pueden utilizarse en cualquier momento como paquetes Ping/Pong. La recepción de un bloque Path Validation no cambia ningún estado en el receptor, a menos que se reciba desde una IP/puerto diferente.

Multiple Sessions

Los peers no deberían establecer múltiples sesiones con el mismo peer, ya sea SSU 1 o 2, o con las mismas o diferentes direcciones IP. Sin embargo, esto podría ocurrir, ya sea debido a errores, o porque se perdió un mensaje de terminación de sesión anterior, o en una carrera donde el mensaje de terminación aún no ha llegado.

Si Bob tiene una sesión existente con Alice, cuando Bob recibe el Session Confirmed de Alice, completando el handshake y estableciendo una nueva sesión, Bob debería:

  • Migrar cualquier mensaje I2NP saliente no enviado o no confirmado desde la sesión antigua a la nueva
  • Enviar una terminación con código de motivo 22 en la sesión antigua
  • Eliminar la sesión antigua y reemplazarla con la nueva

Session Termination

Seguridad de Prueba de Pares

Las sesiones en la fase de handshake generalmente se terminan simplemente por timeout, o al no responder más. Opcionalmente, pueden terminarse incluyendo un bloque de Terminación en la respuesta, pero la mayoría de los errores no es posible responder a ellos debido a la falta de claves criptográficas. Incluso si las claves están disponibles para una respuesta que incluya un bloque de terminación, generalmente no vale la pena el CPU para realizar el DH para la respuesta. Una excepción PUEDE ser un bloque de Terminación en un mensaje de reintento, que es poco costoso de generar.

Objetivos de Diseño de Relay y Peer Test

Las sesiones en la fase de datos se terminan enviando un mensaje de datos que incluye un bloque de Terminación. Este mensaje también debe incluir un bloque ACK. Puede, si la sesión ha estado activa el tiempo suficiente para que un token enviado previamente haya expirado o esté a punto de expirar, incluir un bloque New Token. Este mensaje no solicita acknowledgment. Al recibir un bloque de Terminación con cualquier razón excepto “Termination Received”, el peer responde con un mensaje de datos que contiene un bloque de Terminación con la razón “Termination Received”.

Después de enviar o recibir un bloque de Terminación, la sesión debe entrar en la fase de cierre durante un período máximo de tiempo por determinar. El estado de cierre es necesario para protegerse contra la pérdida del paquete que contiene el bloque de Terminación, y contra paquetes en tránsito en la otra dirección. Mientras está en la fase de cierre, no hay requisito de procesar ningún paquete recibido adicional. Una sesión en estado de cierre envía un paquete que contiene un bloque de Terminación en respuesta a cualquier paquete entrante que atribuya a la sesión. Una sesión debe limitar la velocidad a la que genera paquetes en el estado de cierre. Por ejemplo, una sesión podría esperar un número progresivamente creciente de paquetes recibidos o cantidad de tiempo antes de responder a los paquetes recibidos.

Para minimizar el estado que un router mantiene para una sesión que se está cerrando, las sesiones pueden, pero no están obligadas a, enviar exactamente el mismo paquete con el mismo número de paquete tal como está en respuesta a cualquier paquete recibido. Nota: Permitir la retransmisión de un paquete de terminación es una excepción al requisito de que se use un nuevo número de paquete para cada paquete. Enviar nuevos números de paquete es principalmente ventajoso para la recuperación de pérdidas y el control de congestión, los cuales no se espera que sean relevantes para una conexión cerrada. Retransmitir el paquete final requiere menos estado.

Después de recibir un bloque de Terminación con la razón “Termination Received”, la sesión puede salir de la fase de cierre.

Cleanup

Al finalizar de manera normal o anormal, los routers deben poner en cero todos los datos efímeros en memoria, incluyendo claves efímeras de handshake, claves criptográficas simétricas, e información relacionada.

MTU

Los requisitos varían, dependiendo de si la dirección publicada se comparte con SSU 1. El mínimo actual de SSU 1 IPv4 es 620, lo cual definitivamente es demasiado pequeño.

El MTU mínimo de SSU2 es 1280 tanto para IPv4 como para IPv6, que es igual al especificado en RFC 9000. Ver más abajo. Al incrementar el MTU mínimo, los mensajes de túnel de 1 KB y los mensajes cortos de construcción de túnel cabrán en un datagrama, reduciendo enormemente la cantidad típica de fragmentación. Esto también permite un incremento en el tamaño máximo de mensaje I2NP. Los mensajes de streaming de 1820 bytes deberían caber en dos datagramas.

Un router no debe habilitar SSU2 o publicar una dirección SSU2 a menos que el MTU para esa dirección sea al menos 1280.

Los routers deben publicar un MTU no predeterminado en cada dirección de router SSU o SSU2.

Resumen

Dirección compartida with SSU 1, debe seguir las reglas de SSU 1. IPv4: Por defecto y máximo es 1484. Mínimo es 1292. (IPv4 MTU + 4) debe ser un múltiplo de 16. IPv6: Debe ser publicado, el mínimo es 1280 y el máximo es 1488. IPv6 MTU debe ser un múltiplo de 16.

Garantías de Entrega

IPv4: Por defecto y máximo es 1500. Mínimo es 1280. IPv6: Por defecto y máximo es 1500. Mínimo es 1280. Sin reglas de múltiplos de 16, pero probablemente debería ser múltiplo de 2 al menos.

Marco de Protocolo Noise

Para SSU 1, el Java I2P actual realiza el descubrimiento PMTU comenzando con paquetes pequeños y aumentando gradualmente el tamaño, o incrementando basándose en el tamaño del paquete recibido. Esto es rudimentario y reduce considerablemente la eficiencia. Continuar con esta característica en SSU 2 está por determinar.

Estudios recientes PMTU sugieren que un mínimo para IPv4 de 1200 o más funcionaría para más del 99% de las conexiones. QUIC RFC 9000 requiere un tamaño mínimo de paquete IP de 1280 bytes.

cita RFC 9000:

El tamaño máximo del datagrama se define como el tamaño más grande de carga útil UDP que se puede enviar a través de una ruta de red utilizando un solo datagrama UDP. QUIC NO DEBE utilizarse si la ruta de red no puede soportar un tamaño máximo de datagrama de al menos 1200 bytes.

QUIC asume un tamaño mínimo de paquete IP de al menos 1280 bytes. Este es el tamaño mínimo de IPv6 [IPv6] y también es compatible con la mayoría de las redes IPv4 modernas. Asumiendo el tamaño mínimo de cabecera IP de 40 bytes para IPv6 y 20 bytes para IPv4 y un tamaño de cabecera UDP de 8 bytes, esto resulta en un tamaño máximo de datagrama de 1232 bytes para IPv6 y 1252 bytes para IPv4. Por lo tanto, se espera que las redes IPv4 modernas y todas las rutas de red IPv6 puedan soportar QUIC.

Nota: Este requisito de soportar una carga útil UDP de 1200 bytes limita el espacio disponible para las cabeceras de extensión IPv6 a 32 bytes o las opciones IPv4 a 52 bytes si la ruta solo soporta la MTU mínima de IPv6 de 1280 bytes. Esto afecta a los paquetes Initial y la validación de rutas.

fin de cita

Adiciones al Framework

QUIC requiere que los datagramas Initial en ambas direcciones sean de al menos 1200 bytes, para prevenir ataques de amplificación y asegurar que la PMTU lo soporte en ambas direcciones.

Podríamos requerir esto para Session Request y Session Created, con un costo sustancial en ancho de banda. Quizás podríamos hacer esto solo si no tenemos un token, o después de recibir un mensaje Retry. Por determinar

QUIC requiere que Bob no envíe más de tres veces la cantidad de datos recibidos hasta que la dirección del cliente sea validada. SSU2 cumple este requisito de manera inherente, porque el mensaje Retry tiene aproximadamente el mismo tamaño que el mensaje Token Request, y es más pequeño que el mensaje Session Request. Además, el mensaje Retry solo se envía una vez.

Estimación de sobrecarga de procesamiento

QUIC requiere que los mensajes que contengan bloques PATH_CHALLENGE o PATH_RESPONSE tengan al menos 1200 bytes, para prevenir ataques de amplificación y asegurar que el PMTU lo soporte en ambas direcciones.

También podríamos requerir esto, a un costo sustancial en ancho de banda. Sin embargo, estos casos deberían ser raros. Por determinar

Max I2NP Message Size

IPv4: No se asume fragmentación IP. El encabezado IP + datagrama es de 28 bytes. Esto asume que no hay opciones IPv4. El tamaño máximo del mensaje es MTU - 28. El encabezado de la fase de datos es de 16 bytes y el MAC es de 16 bytes, totalizando 32 bytes. El tamaño de la carga útil es MTU - 60. La carga útil máxima de la fase de datos es 1440 para una MTU máxima de 1500. La carga útil máxima de la fase de datos es 1220 para una MTU mínima de 1280.

IPv6: No se permite la fragmentación IP. El encabezado IP + datagrama es de 48 bytes. Esto asume que no hay encabezados de extensión IPv6. El tamaño máximo del mensaje es MTU - 48. El encabezado de la fase de datos es de 16 bytes y el MAC es de 16 bytes, totalizando 32 bytes. El tamaño de la carga útil es MTU - 80. La carga útil máxima de la fase de datos es 1420 para un MTU máximo de 1500. La carga útil máxima de la fase de datos es 1200 para un MTU mínimo de 1280.

En SSU 1, las directrices eran un máximo estricto de aproximadamente 32 KB para un mensaje I2NP basado en 64 fragmentos máximos y un MTU mínimo de 620. Debido a la sobrecarga de los LeaseSets agrupados y las claves de sesión, el límite práctico a nivel de aplicación era aproximadamente 6KB menor, o alrededor de 26KB. El protocolo SSU 1 permite 128 fragmentos, pero las implementaciones actuales lo limitan a 64 fragmentos.

Al elevar la MTU mínima a 1280, con una carga útil de fase de datos de aproximadamente 1200, un mensaje SSU 2 de alrededor de 76 KB es posible en 64 fragmentos y 152 KB en 128 fragmentos. Esto permite fácilmente un máximo de 64 KB.

Debido a la fragmentación en túneles y la fragmentación en SSU 2, la probabilidad de pérdida de mensajes aumenta exponencialmente con el tamaño del mensaje. Continuamos recomendando un límite práctico de aproximadamente 10 KB en la capa de aplicación para datagramas I2NP.

Peer Test Process

Consulta Seguridad de Peer Test arriba para un análisis de SSU1 Peer Test y los objetivos para SSU2 Peer Test.

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest
          <---------------- Charlie RI
4.      <------------------ PeerTest

5.      <----------------------------------------- PeerTest
6. PeerTest ----------------------------------------->
7.      <----------------------------------------- PeerTest

Cuando es rechazado por Bob:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
4.      <------------------ PeerTest (reject)

Cuando es rechazado por Charlie:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest (reject)
                        (optional: Bob could try another Charlie here)
4.      <------------------ PeerTest (reject)

NOTA: Los RI pueden enviarse ya sea como mensajes I2NP Database Store en bloques I2NP, o como bloques RI (si son lo suficientemente pequeños). Estos pueden estar contenidos en los mismos paquetes que los bloques de prueba de peer, si son lo suficientemente pequeños.

Los mensajes 1-4 están en sesión usando bloques Peer Test en un mensaje Data. Los mensajes 5-7 están fuera de sesión usando bloques Peer Test en un mensaje Peer Test.

NOTA: Como en SSU 1, los mensajes 4 y 5 pueden llegar en cualquier orden. El mensaje 5 y/o 7 pueden no recibirse en absoluto si Alice está detrás de un firewall. Cuando el mensaje 5 llega antes que el mensaje 4, Alice no puede enviar inmediatamente el mensaje 6, porque aún no tiene la clave de introducción de Charlie para cifrar la cabecera. Cuando el mensaje 4 llega antes que el mensaje 5, Alice no debería enviar inmediatamente el mensaje 6, porque debería esperar a ver si el mensaje 5 llega sin abrir el firewall con el mensaje 6.

MessagePathIntro Key
1A->B sessionin-session
2B->C sessionin-session
3C->B sessionin-session
4B->A sessionin-session
5C->AAlice
6A->CCharlie
7C->AAlice

Versions

Las pruebas entre pares de diferentes versiones no son compatibles. La única combinación de versiones permitida es donde todos los pares son versión 2.

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121no, Bob must s
122no, Bob must s
211no, Bob must s
212no, Bob must s
221no, use 2/2/2
222yes

Establecimiento de Sesión

Los mensajes 1-4 están en sesión y están cubiertos por los procesos de ACK de fase de datos y retransmisión. Los bloques de Peer Test requieren confirmación de recepción.

Los mensajes 5-7 pueden ser retransmitidos, sin cambios.

Encabezado de Paquete

Al igual que en SSU 1, se admite la prueba de direcciones IPv6, y la comunicación Alice-Bob y Alice-Charlie puede ser a través de IPv6, si Bob y Charlie indican soporte con una capacidad ‘B’ en su dirección IPv6 publicada. Consulte la Propuesta 126 para obtener detalles.

Como en SSU 1 antes de 0.9.50, Alice envía la solicitud a Bob usando una sesión existente sobre el transporte (IPv4 o IPv6) que desea probar. Cuando Bob recibe una solicitud de Alice vía IPv4, Bob debe seleccionar un Charlie que anuncie una dirección IPv4. Cuando Bob recibe una solicitud de Alice vía IPv6, Bob debe seleccionar un Charlie que anuncie una dirección IPv6. La comunicación real Bob-Charlie puede ser vía IPv4 o IPv6 (es decir, independiente del tipo de dirección de Alice). Este NO es el comportamiento de SSU 1 a partir de 0.9.50, donde se permiten solicitudes mixtas IPv4/v6.

Processing by Bob

A diferencia de SSU 1, Alice especifica la IP y puerto de prueba solicitados en el mensaje 1. Bob debe validar esta IP y puerto, y rechazar con código 5 si son inválidos. La validación de IP recomendada es que, para IPv4, coincida con la IP de Alice, y para IPv6, al menos los primeros 8 bytes de la IP coincidan. La validación de puerto debe rechazar puertos privilegiados y puertos para protocolos conocidos.

Relay Process

Consulta Seguridad de Relay arriba para un análisis de SSU1 Relay y los objetivos para SSU2 Relay.

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

5.      <-------------------------------------------- HolePunch
6. SessionRequest -------------------------------------------->
7.      <-------------------------------------------- SessionCreated
8. SessionConfirmed ------------------------------------------>

Cuando es rechazado por Bob:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
4.      <-------------- RelayResponse

Cuando es rechazado por Charlie:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

NOTA: Los RI pueden enviarse como mensajes I2NP Database Store en bloques I2NP, o como bloques RI (si son suficientemente pequeños). Estos pueden estar contenidos en los mismos paquetes que los bloques relay, si son suficientemente pequeños.

En SSU 1, la información del router de Charlie contiene la IP, puerto, clave de introducción, etiqueta de relay y expiración de cada introducer.

En SSU 2, la información del router de Charlie contiene el hash del router, la etiqueta de relay y la expiración de cada introducer.

Alice debería reducir el número de viajes de ida y vuelta requeridos primero seleccionando un introducer (Bob) al que ya tenga una conexión. Segundo, si no tiene ninguno, seleccionar un introducer del cual ya tenga la información del router.

El relaying entre versiones cruzadas también debería ser compatible si es posible. Esto facilitará una transición gradual de SSU 1 a SSU 2. Las combinaciones de versiones permitidas son (TODO):

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121yes?
122no, use 1/2/1
211yes?
212yes?
221no, use 2/2/2
222yes

Retransmissions

Relay Request, Relay Intro y Relay Response están todos dentro de la sesión y están cubiertos por los procesos de ACK de la fase de datos y retransmisión. Los bloques Relay Request, Relay Intro y Relay Response provocan acknowledgment.

El hole punch puede ser retransmitido, como en SSU 1.

IPv4/v6

Todas las funciones del relay SSU 1 son compatibles, incluyendo aquellas documentadas en la Propuesta 158 y soportadas desde la versión 0.9.50. Las introducciones IPv4 e IPv6 son compatibles. Una Solicitud de Relay puede enviarse a través de una sesión IPv4 para una introducción IPv6, y una Solicitud de Relay puede enviarse a través de una sesión IPv6 para una introducción IPv4.

Processing by Alice

A continuación se presentan las diferencias con respecto a SSU 1 y las recomendaciones para la implementación de SSU 2.

Notas

En SSU 1, la introducción es relativamente económica, y Alice generalmente envía Relay Requests a todos los introducers. En SSU 2, la introducción es más costosa, ya que primero se debe establecer una conexión con un introducer. Para minimizar la latencia y la sobrecarga de la introducción, los pasos de procesamiento recomendados son los siguientes:

  • Ignorar cualquier introducer que haya expirado basándose en el valor iexp de la dirección
  • Si ya se ha establecido una conexión SSU2 con uno o más introducers, elegir uno y enviar el Relay Request únicamente a ese introducer.
  • De lo contrario, si se conoce localmente un Router Info para uno o más introducers, elegir uno y conectarse únicamente a ese introducer.
  • De lo contrario, buscar los Router Infos para todos los introducers, conectarse al introducer cuyo Router Info se reciba primero.

Notas

En tanto SSU 1 como SSU 2, la Respuesta de Relay y el Hole Punch pueden recibirse en cualquier orden, o pueden no recibirse en absoluto.

En SSU 1, Alice generalmente recibe el Relay Response (1 RTT) antes del Hole Punch (1 1/2 RTT). Puede que no esté bien documentado en esas especificaciones, pero Alice debe recibir el Relay Response de Bob antes de continuar, para recibir la IP de Charlie. Si el Hole Punch se recibe primero, Alice no lo reconocerá, porque no contiene datos y la IP de origen no es reconocida. Después de recibir el Relay Response, Alice debería esperar CUALQUIERA de estas opciones: recibir el Hole Punch de Charlie, O un breve retraso (recomendado 500 ms) antes de iniciar el handshake con Charlie.

En SSU 2, Alice generalmente recibirá el Hole Punch (1 1/2 RTT) antes de la Relay Response (2 RTT). El SSU 2 Hole Punch es más fácil de procesar que en SSU 1, porque es un mensaje completo con IDs de conexión definidos (derivados del relay nonce) y contenido que incluye la IP de Charlie. La Relay Response (mensaje Data) y el mensaje Hole Punch contienen el bloque Relay Response firmado idéntico. Por lo tanto, Alice puede iniciar el handshake con Charlie después de CUALQUIERA de estas opciones: recibir el Hole Punch de Charlie, O recibir la Relay Response de Bob.

La verificación de firma del Hole Punch incluye el hash del router del introducer (Bob). Si se han enviado Relay Requests a más de un introducer, hay varias opciones para validar la firma:

  • Prueba cada hash al cual se envió una solicitud
  • Usa diferentes nonces para cada introducer, y úsalo para determinar a qué introducer estaba respondiendo este Hole Punch
  • No vuelvas a validar la firma si el contenido es idéntico al del Relay Response, si ya fue recibido
  • No valides la firma en absoluto

Si Charlie está detrás de un NAT simétrico, su puerto reportado en la Relay Response y el Hole Punch puede no ser preciso. Por lo tanto, Alice debería verificar el puerto de origen UDP del mensaje Hole Punch, y usar ese si es diferente al puerto reportado.

Tag Requests by Bob

En SSU 1, solo Alice podía solicitar un tag, en el Session Request. Bob nunca podía solicitar un tag, y Alice no podía hacer relay para Bob.

En SSU2, Alice generalmente solicita una etiqueta en la Solicitud de Sesión, pero tanto Alice como Bob también pueden solicitar una etiqueta en la fase de datos. Bob generalmente no está detrás de firewall después de recibir una solicitud entrante, pero podría estarlo después de un relay, o el estado de Bob puede cambiar, o puede solicitar un introductor para el otro tipo de dirección (IPv4/v6). Por lo tanto, en SSU2, es posible que tanto Alice como Bob sean simultáneamente relays para la otra parte.

Published Router Info

Address Properties

Las siguientes propiedades de dirección pueden publicarse, sin cambios respecto a SSU 1, incluyendo los cambios en la Propuesta 158 soportados a partir de la API 0.9.50:

  • caps: capacidades [B,C,4,6]

  • host: IP (IPv4 o IPv6). Se permite dirección IPv6 abreviada (con “::”). Puede estar presente o no si hay firewall. No se permiten nombres de host.

  • iexp[0-2]: Expiración de este introductor. Dígitos ASCII, en segundos desde el epoch. Solo presente si está tras firewall y se requieren introductores. Opcional (incluso si otras propiedades para este introductor están presentes).

  • ihost[0-2]: IP del introducer (IPv4 o IPv6). Se permite dirección IPv6 acortada (con “::”). Solo presente si está detrás de firewall y se requieren introducers. No se permiten nombres de host. Solo dirección SSU.

  • ikey[0-2]: Clave de introducción Base 64 del introductor. Solo presente si está detrás de firewall y se requieren introductores. Solo dirección SSU.

  • iport[0-2]: Puerto del introductor 1024 - 65535. Solo presente si está detrás de firewall y se requieren introductores. Solo dirección SSU.

  • itag[0-2]: Etiqueta del introductor 1 - (2**32 - 1) Dígitos ASCII. Solo presente si está detrás de firewall y se requieren introductores.

  • key: Clave de introducción Base 64.

  • mtu: Opcional. Ver la sección MTU anterior.

  • port: 1024 - 65535 Puede estar presente o no si está detrás de un firewall.

Published Addresses

La RouterAddress publicada (parte del RouterInfo) tendrá un identificador de protocolo de “SSU” o “SSU2”.

La RouterAddress debe contener tres opciones para indicar soporte SSU2:

  • s=(Base64 key) La clave pública estática Noise actual (s) para esta RouterAddress. Codificada en Base 64 usando el alfabeto Base 64 estándar de I2P. 32 bytes en binario, 44 bytes codificados en Base 64, clave pública X25519 little-endian.

  • i=(Clave Base64) La clave de introducción actual para cifrar las cabeceras de esta RouterAddress. Codificada en Base 64 usando el alfabeto estándar de I2P Base 64. 32 bytes en binario, 44 bytes codificada en Base 64, clave ChaCha20 big-endian.

  • v=2 La versión actual (2). Cuando se publica como “SSU”, se implica soporte adicional para la versión 1. El soporte para versiones futuras será con valores separados por comas, p. ej. v=2,3 La implementación debe verificar la compatibilidad, incluyendo múltiples versiones si hay una coma presente. Las versiones separadas por comas deben estar en orden numérico.

Alice debe verificar que las tres opciones estén presentes y sean válidas antes de conectarse usando el protocolo SSU2.

Cuando se publica como “SSU” con las opciones “s”, “i” y “v”, y con las opciones “host” y “port”, el router debe aceptar conexiones entrantes en ese host y puerto para los protocolos SSU y SSU2, y detectar automáticamente la versión del protocolo.

Cuando se publica como “SSU2” con las opciones “s”, “i” y “v”, y con las opciones “host” y “port”, el router acepta conexiones entrantes en ese host y puerto únicamente para el protocolo SSU2.

Si un router admite tanto conexiones SSU1 como SSU2 pero no implementa detección automática de versión para conexiones entrantes, debe anunciar tanto direcciones “SSU” como “SSU2”, e incluir las opciones SSU2 únicamente en la dirección “SSU2”. El router debería establecer un valor de coste más bajo (mayor prioridad) en la dirección “SSU2” que en la dirección “SSU”, para que SSU2 sea preferido.

Si se publican múltiples RouterAddresses SSU2 (ya sea como “SSU” o “SSU2”) en el mismo RouterInfo (para direcciones IP o puertos adicionales), todas las direcciones que especifiquen el mismo puerto deben contener las opciones y valores SSU2 idénticos. En particular, todas deben contener la misma clave estática “s” y clave de introducción “i”.

Introducers

Cuando se publica como SSU o SSU2 con introducers, están presentes las siguientes opciones:

  • ih[0-2]=(Base64 hash) Un hash de router para un introducer. Codificado en Base 64 usando el alfabeto Base 64 estándar de I2P. 32 bytes en binario, 44 bytes codificado en Base 64

  • iexp[0-2]: Vencimiento de este introducer. Sin cambios desde SSU 1.

  • itag[0-2]: Etiqueta del introductor 1 - (2**32 - 1) Sin cambios respecto a SSU 1.

Las siguientes opciones son solo para SSU y no se usan para SSU2. En SSU2, Alice obtiene esta información del RI de Charlie en su lugar.

  • ihost[0-2]
  • ikey[0-2]
  • itag[0-2]

Un router no debe publicar host o puerto en la dirección cuando publique introducers. Un router debe publicar caps 4 y/o 6 en la dirección cuando publique introducers para indicar soporte para IPv4 y/o IPv6. Esto es lo mismo que la práctica actual para las direcciones SSU 1 recientes.

Nota: Si se publica como SSU, y hay una mezcla de introducers SSU 1 y SSU2, los introducers SSU 1 deben estar en los índices más bajos y los introducers SSU2 deben estar en los índices más altos, para compatibilidad con routers más antiguos.

Unpublished SSU2 Address

Si Alice no publica su dirección SSU2 (como “SSU” o “SSU2”) para conexiones entrantes, debe publicar una dirección de router “SSU2” que contenga únicamente su clave estática y la versión SSU2, para que Bob pueda validar la clave después de recibir el RouterInfo de Alice en la parte 2 de Session Confirmed.

  • s=(Clave Base64) Como se define arriba para las direcciones publicadas.

  • i=(Clave Base64) Como se define arriba para las direcciones publicadas.

  • v=2 Como se define arriba para direcciones publicadas.

Esta dirección del router no contendrá opciones “host” o “port”, ya que estas no son necesarias para conexiones SSU2 salientes. El costo publicado para esta dirección no importa estrictamente, ya que es solo de entrada; sin embargo, puede ser útil para otros routers si el costo se establece más alto (menor prioridad) que otras direcciones. El valor sugerido es 14.

Alice también puede simplemente agregar las opciones “i”, “s” y “v” a una dirección “SSU” publicada existente.

Integridad de Paquetes

Usar las mismas claves estáticas para NTCP2 y SSU2 está permitido, pero no se recomienda.

Debido al almacenamiento en caché de los RouterInfos, los routers no deben rotar la clave pública estática o el IV mientras el router esté funcionando, ya sea en una dirección publicada o no. Los routers deben almacenar de forma persistente esta clave e IV para reutilizarlos después de un reinicio inmediato, para que las conexiones entrantes continúen funcionando y los tiempos de reinicio no queden expuestos. Los routers deben almacenar de forma persistente, o de otra manera determinar, el tiempo del último apagado, para que el tiempo de inactividad anterior pueda calcularse al iniciarse.

Sujeto a preocupaciones sobre exponer los tiempos de reinicio, los routers pueden rotar esta clave o IV al arrancar si el router estuvo previamente inactivo durante algún tiempo (varios días como mínimo).

Si el router tiene alguna RouterAddress SSU2 publicada (como SSU o SSU2), el tiempo mínimo de inactividad antes de la rotación debería ser mucho más largo, por ejemplo un mes, a menos que la dirección IP local haya cambiado o el router “rekeys”.

Si el router tiene RouterAddresses SSU publicadas, pero no SSU2 (como SSU o SSU2) el tiempo mínimo de inactividad antes de la rotación debería ser más largo, por ejemplo un día, a menos que la dirección IP local haya cambiado o el router haga “rekeys”. Esto aplica incluso si la dirección SSU publicada tiene introducers.

Si el router no tiene ningún RouterAddress publicado (SSU, SSU2, o SSU), el tiempo mínimo de inactividad antes de la rotación puede ser tan corto como dos horas, incluso si la dirección IP cambia, a menos que el router haga “rekeys”.

Si el router “rekeys” a un Router Hash diferente, también debería generar una nueva clave de ruido y clave de introducción.

Las implementaciones deben estar conscientes de que cambiar la clave pública estática o el IV prohibirá las conexiones SSU2 entrantes de routers que hayan almacenado en caché un RouterInfo más antiguo. La publicación de RouterInfo, la selección de peers de túnel (incluyendo tanto OBGW como el salto más cercano IB), la selección de túneles de cero saltos, la selección de transporte y otras estrategias de implementación deben tener esto en cuenta.

La rotación de claves de introducción está sujeta a las mismas reglas que la rotación de claves.

Nota: El tiempo mínimo de inactividad antes de regenerar las claves puede modificarse para garantizar la salud de la red y prevenir el reseeding por parte de un router inactivo durante un período moderado de tiempo.

Identity Hiding

La negabilidad no es un objetivo. Ver descripción general arriba.

A cada patrón se le asignan propiedades que describen la confidencialidad proporcionada a la clave pública estática del iniciador, y a la clave pública estática del respondedor. Las suposiciones subyacentes son que las claves privadas efímeras son seguras, y que las partes abortan el handshake si reciben una clave pública estática de la otra parte en la que no confían.

Esta sección solo considera la filtración de identidad a través de campos de clave pública estática en los handshakes. Por supuesto, las identidades de los participantes de Noise podrían estar expuestas a través de otros medios, incluyendo campos de payload, análisis de tráfico, o metadatos como direcciones IP.

Alice: (8) Cifrado con forward secrecy hacia una parte autenticada.

Bob: (3) No se transmite, pero un atacante pasivo puede verificar candidatos para la clave privada del respondedor y determinar si el candidato es correcto.

Bob publica su clave pública estática en la netDb. Alice puede no hacerlo, pero debe incluirla en el RI enviado a Bob.

Packet Guidelines

Cifrado Autenticado

Mensajes de handshake (Session Request/Created/Confirmed, Retry) pasos básicos, en orden:

  • Crear cabecera de 16 o 32 bytes
  • Crear payload
  • mixHash() la cabecera (excepto para Retry)
  • Cifrar el payload usando Noise (excepto para Retry, usar ChaChaPoly con la cabecera como AD)
  • Cifrar la cabecera, y para Session Request/Created, la clave efímera

Pasos básicos de los mensajes de la fase de datos, en orden:

  • Crear encabezado de 16 bytes
  • Crear carga útil
  • Cifrar la carga útil usando ChaChaPoly usando el encabezado como AD
  • Cifrar el encabezado

Inbound Packet Handling

Carga útil

Procesamiento inicial de todos los mensajes entrantes:

  • Descifrar los primeros 8 bytes del encabezado (el ID de Conexión de Destino) con la clave de introducción
  • Buscar la conexión por el ID de Conexión de Destino
  • Si la conexión se encuentra y está en la fase de datos, ir a la sección de fase de datos
  • Si la conexión no se encuentra, ir a la sección de handshake
  • Nota: Los mensajes de Peer Test y Hole Punch también pueden ser buscados por el ID de Conexión de Destino creado a partir del nonce de prueba o retransmisión.

Procesamiento de mensajes de handshake (Session Request/Created/Confirmed, Retry, Token Request) y otros mensajes fuera de sesión (Peer Test, Hole Punch):

  • Descifrar los bytes 8-15 del encabezado (el tipo de paquete, versión y net ID) con la intro key. Si es una Session Request, Token Request, Peer Test o Hole Punch válida, continuar
  • Si no es un mensaje válido, buscar una conexión saliente pendiente por la IP/puerto origen del paquete, tratar el paquete como Session Created o Retry. Re-descifrar los primeros 8 bytes del encabezado con la clave correcta, y los bytes 8-15 del encabezado (el tipo de paquete, versión y net ID). Si es una Session Created o Retry válida, continuar
  • Si no es un mensaje válido, fallar, o poner en cola como posible paquete de fase de datos fuera de orden
  • Para Session Request/Created, Retry, Token Request, Peer Test y Hole Punch, descifrar los bytes 16-31 del encabezado
  • Para Session Request/Created, descifrar la clave efímera
  • Validar todos los campos del encabezado, detenerse si no son válidos
  • mixHash() el encabezado
  • Para Session Request/Created/Confirmed, descifrar la carga útil usando Noise
  • Para Retry y fase de datos, descifrar la carga útil usando ChaChaPoly
  • Procesar el encabezado y la carga útil

Procesamiento de mensajes de fase de datos:

  • Descifrar los bytes 8-15 del encabezado (el tipo de paquete, versión e ID de red) con la clave correcta
  • Descifrar la carga útil usando ChaChaPoly usando el encabezado como AD
  • Procesar el encabezado y la carga útil

Details

En SSU 1, la clasificación de paquetes entrantes es difícil, porque no hay un encabezado que indique el número de sesión. Los routers deben primero hacer coincidir la IP de origen y el puerto con un estado de peer existente, y si no se encuentra, intentar múltiples descifrajes con diferentes claves para encontrar el estado de peer apropiado o iniciar uno nuevo. En el caso de que la IP de origen o el puerto para una sesión existente cambien, posiblemente debido al comportamiento NAT, el router puede usar heurísticas costosas para intentar hacer coincidir el paquete con una sesión existente y recuperar el contenido.

SSU 2 está diseñado para minimizar el esfuerzo de clasificación de paquetes entrantes mientras mantiene la resistencia DPI y otras amenazas en la ruta. El número de Connection ID se incluye en el encabezado para todos los tipos de mensaje, y se cifra (ofusca) usando ChaCha20 con una clave y nonce conocidos. Además, el tipo de mensaje también se incluye en el encabezado (cifrado con protección de encabezado a una clave conocida y luego ofuscado con ChaCha20) y puede usarse para clasificación adicional. En ningún caso es necesaria una operación criptográfica asimétrica de prueba DH u otra para clasificar un paquete.

Para casi todos los mensajes de todos los peers, la clave ChaCha20 para el cifrado del Connection ID es la clave de introducción del router de destino tal como se publica en la netDb.

Las únicas excepciones son los primeros mensajes enviados de Bob a Alice (Session Created o Retry) donde la clave de introducción de Alice aún no es conocida por Bob. En estos casos, se utiliza la clave de introducción de Bob como la clave.

El protocolo está diseñado para minimizar el procesamiento de clasificación de paquetes que podría requerir operaciones criptográficas adicionales en múltiples pasos de respaldo o heurísticas complejas. Además, la gran mayoría de los paquetes recibidos no requerirán una búsqueda de respaldo (posiblemente costosa) por IP/puerto de origen y un segundo descifrado de encabezado. Solo Session Created y Retry (y posiblemente otros por determinar) requerirán el procesamiento de respaldo. Si un endpoint cambia de IP o puerto después de la creación de la sesión, el ID de conexión aún se usa para buscar la sesión. Nunca es necesario usar heurísticas para encontrar la sesión, por ejemplo buscando una sesión diferente con la misma IP pero un puerto diferente.

Por lo tanto, los pasos de procesamiento recomendados en la lógica del bucle del receptor son:

  1. Descifrar los primeros 8 bytes con ChaCha20 usando la clave de introducción local, para recuperar el ID de Conexión de Destino. Si el ID de Conexión coincide con una sesión entrante actual o pendiente:

a) Usando la clave apropiada, descifrar los bytes 8-15 del encabezado

  to recover the version, net ID, and message type.

b) Si el tipo de mensaje es Session Confirmed, es un encabezado largo.

  Verify the net ID and protocol version are valid.
  Decrypt the bytes 15-31 of the header with ChaCha20
  using the local intro key. Then MixHash() the
  decrypted 32 byte header and decrypt the message with Noise.

c) Si el tipo de mensaje es válido pero no es Session Confirmed,

  it is a short header.
  Verify the net ID and protocol version are valid.
  decrypt the rest of the message with ChaCha20/Poly1305
  using the session key, using the decrypted 16-byte header
  as the AD.

d) (opcional) Si el ID de conexión es una sesión entrante pendiente

  awaiting a Session Confirmed message,
  but the net ID, protocol, or message type is not valid,
  it could be a Data message received out-of-order before the
  Session Confirmed, so the data phase header protection keys are not yet known,
  and the header bytes 8-15 were incorrectly decrypted.
  Queue the message, and attempt to decrypt it once the
  Session Confirmed message is received.

e) Si b) o c) falla, descartar el mensaje.

  1. Si el ID de conexión no coincide con una sesión actual: Verificar que la cabecera de texto plano en los bytes 8-15 sea válida (sin realizar ninguna operación de protección de cabecera). Verificar que el ID de red y la versión del protocolo sean válidos, y que el tipo de mensaje sea Session Request, u otro tipo de mensaje permitido fuera de sesión (por determinar).

a) Si todo es válido y el tipo de mensaje es Session Request,

  decrypt bytes 16-31 of the header and the 32-byte X value
  with ChaCha20 using the local intro key.
  • Si el token en los bytes 24-31 del header es aceptado, entonces MixHash() el header de 32 bytes descifrado y descifra el mensaje con Noise. Envía un Session Created como respuesta.
    • Si el token no es aceptado, envía un mensaje Retry a la IP/puerto de origen con un token. No intentes descifrar el mensaje con Noise para evitar ataques DDoS.

b) Si el tipo de mensaje es algún otro mensaje que es válido

  out-of-session, presumably with a short header,
  decrypt the rest of the message with ChaCha20/Poly1305
  using the intro key, and using the decrypted 16-byte header
  as the AD. Process the message.

c) Si a) o b) falla, ir al paso 3)

  1. Buscar una sesión saliente pendiente por la IP/puerto de origen del paquete.

a) Si se encuentra, re-descifrar los primeros 8 bytes con ChaCha20 usando la clave de introducción de Bob

  to recover the Destination Connection ID.

b) Si el ID de conexión coincide con la sesión pendiente:

  Using the correct key, decrypt bytes 8-15 of the header
  to recover the version, net ID, and message type.
  Verify the net ID and protocol version are valid, and
  the message type is Session Created or Retry, or other message type
  allowed out-of-session (TBD).
  • Si todo es válido y el tipo de mensaje es Session Created, descifrar los siguientes 16 bytes del encabezado y el valor Y de 32 bytes con ChaCha20 usando la clave de introducción de Bob. Luego MixHash() el encabezado de 32 bytes descifrado y descifrar el mensaje con Noise. Enviar un Session Confirmed como respuesta.

    • Si todo es válido y el tipo de mensaje es Retry, descifrar los bytes 16-31 del encabezado con ChaCha20 usando la clave de introducción de Bob. Descifrar y validar el mensaje usando ChaCha20/Poly1305 usando TBD como la clave y TBD como el nonce y el encabezado de 32 bytes descifrado como el AD. Reenviar un Session Request con el token recibido como respuesta.
    • Si el tipo de mensaje es algún otro mensaje que sea válido fuera de sesión, presumiblemente con un encabezado corto, descifrar el resto del mensaje con ChaCha20/Poly1305 usando la clave de introducción, y usando el encabezado de 16 bytes descifrado como el AD. Procesar el mensaje.

    c) If a pending outbound session is not found, or the connection ID does not match the pending session, drop the message, unless the port is shared with SSU 1.

  1. Si se ejecuta SSU 1 en el mismo puerto, intentar procesar el mensaje como un paquete SSU 1.

Error Handling

En general, una sesión (en la fase de handshake o de datos) nunca debe ser destruida después de recibir un paquete con un tipo de mensaje inesperado. Esto previene ataques de inyección de paquetes. Estos paquetes también se recibirán comúnmente después de la retransmisión de un paquete de handshake, cuando las claves de descifrado del encabezado ya no son válidas.

En la mayoría de los casos, simplemente descartar el paquete. Una implementación puede, pero no está obligada a, retransmitir el paquete enviado previamente (mensaje de handshake o ACK 0) como respuesta.

Después de enviar Session Created como Bob, los paquetes inesperados suelen ser paquetes de datos que no se pueden descifrar porque los paquetes Session Confirmed se perdieron o llegaron fuera de orden. Poner en cola los paquetes e intentar descifrarlos después de recibir los paquetes Session Confirmed.

Después de recibir Session Confirmed como Bob, los paquetes inesperados son comúnmente paquetes Session Confirmed retransmitidos, porque se perdió el ACK 0 del Session Confirmed. Los paquetes inesperados pueden ser descartados. Una implementación puede, pero no está obligada a, enviar un paquete Data que contenga un bloque ACK en respuesta.

Notes

Para Session Created y Session Confirmed, las implementaciones deben validar cuidadosamente todos los campos de encabezado descifrados (Connection IDs, número de paquete, tipo de paquete, versión, id, frag, y flags) ANTES de llamar mixHash() en el encabezado e intentar descifrar la carga útil con Noise AEAD. Si el descifrado Noise AEAD falla, no se puede realizar ningún procesamiento adicional, porque mixHash() habrá corrompido el estado del handshake, a menos que una implementación almacene y “revierta” el estado del hash.

Version Detection

Es posible que no sea posible detectar de manera eficiente si los paquetes entrantes son de la versión 1 o 2 en el mismo puerto de entrada. Los pasos anteriores pueden tener sentido realizarlos antes del procesamiento de SSU 1, para evitar intentar operaciones DH de prueba utilizando ambas versiones del protocolo.

Por determinar si es necesario.

  • Tiempo de espera de retransmisión de handshake saliente: 1,25 segundos, con backoff exponencial (retransmisiones a los 1,25, 3,75 y 8,75 segundos)
  • Tiempo de espera total de handshake saliente: 15 segundos
  • Tiempo de espera de retransmisión de handshake entrante: 1 segundo, con backoff exponencial (retransmisiones a 1, 3 y 7 segundos)
  • Tiempo de espera total de handshake entrante: 12 segundos
  • Tiempo de espera después de enviar reintento: 9 segundos
  • Retraso de ACK: max(10, min(rtt/6, 150)) ms
  • Retraso de ACK inmediato: min(rtt/16, 5) ms
  • Rangos máximos de ACK: ¿256?
  • Profundidad máxima de ACK: ¿512?
  • Distribución de padding: 0-15 bytes, o mayor

Variants, Fallbacks, and General Issues

Por determinar

Packet Overhead Analysis

Asume IPv4, sin incluir el relleno adicional, sin incluir los tamaños de las cabeceras IP y UDP. El relleno es un relleno mod-16 solo para SSU 1.

SSU 1

MessageHeader+MACKeysDataPaddingTotalNotes
Session Request4025653304Incl.
Session Created37256791336Incl.
Session Confirmed3746213512Incl.
Data (RI)3710141051Incl.
Data (1 full msg)371451Incl.
Total2254
SSU 2
MessageHeader+MACsKeysDataPaddingTotalNotes
Session Request4832787DateTi
Session Created48321696DateTi
Session Confirmed4832100510851000 b
Data (1 full msg)321446
Total1314
TODO A MENOS QUE se aplique el tamaño mínimo de paquete en Session Request y Created para PMTU.