SSU2

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

Status

Plano de implementação:

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
A Sessão Básica inclui a fase de handshake e de dados. O protocolo estendido inclui relay e teste de peers.

Visão Geral

Esta proposta descreve um protocolo de acordo de chaves autenticado para melhorar a resistência do SSU a várias formas de identificação automatizada e ataques.

A proposta está organizada da seguinte forma: os objetivos de segurança são apresentados, seguidos por uma discussão do protocolo básico. Em seguida, uma especificação completa de todas as mensagens do protocolo é fornecida. Por fim, endereços de router e identificação de versão são discutidos.

Assim como outros transportes do I2P, o SSU2 é definido para transporte ponto a ponto (router para router) de mensagens I2NP. Não é um canal de dados de propósito geral. Como o SSU, também fornece dois serviços adicionais: Retransmissão para travessia de NAT e Teste de Peers para determinação de acessibilidade de entrada. Também fornece um terceiro serviço, não presente no SSU, para migração de conexão quando um peer muda de IP ou porta.

Motivação

SSU é a única camada de protocolo restante que requer ElGamal, que é muito lento. O controle de fluxo para SSU é complexo e não funciona bem. Partes do SSU são vulneráveis a ataques de falsificação de endereço. O handshake não usa Noise.

Objetivos de Design

  • Reduzir o uso de CPU eliminando ElGamal. Usar X25519 para o DH.

  • Manter as funções Peer Test e Relay, e aumentar a segurança para elas.

  • Facilitar a implementação ao permitir algoritmos padrão de controle de fluxo.

  • Reduzir a latência de configuração. O tempo médio de configuração é atualmente cerca de 135 ms para NTCP2 e 187 ms para SSU, mesmo que NTCP2 tenha uma viagem de ida e volta adicional; substituir ElGamal no SSU2 deveria reduzi-lo, mas outras mudanças também podem ajudar.

  • Manter ou aumentar o throughput máximo comparado ao SSU 1, conforme medido em uma faixa de latências simuladas e percentuais de perda de pacotes em uma testnet.

  • Prevenir ataques de amplificação de tráfego e roteamento incorreto de endereços de origem falsificados através de “validação de endereço”.

  • Tornar a identificação de pacotes mais fácil, para reduzir a dependência de fallbacks e heurísticas que tornam o código excessivamente complexo.

  • Formalizar e melhorar a migração de conexões quando o IP ou porta do peer muda. Não migre conexões até que a validação de endereço esteja completa, para prevenir ataques. Algumas implementações SSU 1 usam heurísticas custosas para lidar com mudanças de porta devido ao rebinding de NAT. Nenhuma implementação SSU 1 conhecida consegue lidar com mudanças de IP.

  • Suporte SSU 1 e 2 em uma única porta, detecção automática, e publicado como um único “transport” (ou seja, RouterAddress) no NetDB.

  • Publicar suporte para versão 1 apenas, 2 apenas, ou 1+2 no NetDB em um campo separado, e usar versão 1 apenas como padrão (não vincular o suporte de versão a uma versão específica do router)

  • Garantir que todas as implementações (Java/i2pd/Go) possam adicionar suporte à versão 2 (ou não) em seus próprios cronogramas

  • Adicionar preenchimento aleatório a todas as mensagens, incluindo mensagens de handshake e dados. Todo o preenchimento deve ser coberto pelo MAC, ao contrário do preenchimento de fim de pacote no SSU 1. Fornecer mecanismo de opções para ambos os lados solicitarem preenchimento mínimo e máximo e/ou distribuição de preenchimento. Os detalhes específicos da distribuição de preenchimento são dependentes da implementação e podem ou não ser especificados no próprio protocolo.

  • Ofuscar os cabeçalhos e conteúdos de mensagens que não estão totalmente criptografadas suficientemente para que equipamentos de DPI e assinaturas de antivírus não possam classificá-las facilmente. Também garantir que as mensagens enviadas para um único peer ou conjunto de peers não tenham um padrão similar de bits.

  • Corrigir perda de bits no DH devido ao formato Java Ticket1112, e acelerar o DH mudando para X25519.

  • Mudar para uma função real de derivação de chave (KDF) em vez de usar o resultado DH como está

  • Adicionar “resistência a sondagem” (como o Tor chama); isso inclui resistência a replay.

  • Manter troca de chaves autenticada bidirecional (2W-AKE). 1W-AKE não é suficiente para nossa aplicação.

  • Confiar na chave pública estática publicada no RouterInfo como outra parte da autenticação.

  • Adicionar opções/versão no handshake para extensibilidade futura.

  • Não adicionar significativamente à CPU necessária para configuração de conexão; se possível, reduzi-la significativamente.

  • Remover o requisito de preenchimento para um múltiplo de 16 bytes imposto pela criptografia AES no SSU 1.

  • Use ChaCha/Poly1305 padrão para criptografia e MAC, substituindo a criptografia AES e o MAC HMAC-MD5-128 não padrão usado no SSU 1.

  • Use chaves de encriptação separadas para envio e recebimento, em vez das chaves comuns para ambas as direções usadas no SSU 1.

  • Use um handshake de 3 mensagens e uma viagem de ida e volta, como no NTCP2. Remove o atraso esperando por mensagens de dados que torna o SSU efetivamente um handshake de duas viagens de ida e volta.

  • Melhorar drasticamente a eficiência de ACKs e NACKs, que é horrível no SSU 1. Reduzir a largura de banda necessária para ACKs e NACKs, e aumentar o tamanho de pacote disponível para dados. Codificar eficientemente NACKs para uma rajada de mensagens perdidas, que é comum em WiFi.

  • Reduzir a complexidade necessária para implementar a fragmentação de mensagens I2NP. Contornar os mecanismos de fragmentação e codificação para mensagens I2NP completas.

  • Minimize a sobrecarga do protocolo antes do preenchimento, especialmente para ACKs. Embora o preenchimento seja adicionado, a sobrecarga antes do preenchimento ainda é sobrecarga. Nós de baixa largura de banda devem ser capazes de usar SSU2.

  • Manter timestamps para detecção de replay e skew.

  • Evitar quaisquer problemas do ano 2038 em timestamps, deve funcionar até pelo menos 2106.

  • Aumentar o MTU mínimo de 620 para 1280 para eficiência, facilidade de implementação, e aumento do tamanho máximo de mensagem I2NP. Fragmentação e remontagem são bastante custosas. Ao fornecer espaço para mensagens de túnel de 1028 bytes, uma grande maioria das mensagens I2NP não exigirá fragmentação.

  • Aumentar o MTU máximo de 1488 (1484 para IPv6) para 1500 para eficiência. Remover o requisito de que o MTU seja um múltiplo de 16.

  • Aumentar o tamanho máximo de mensagem I2NP de aproximadamente 32K no SSU 1 para aproximadamente 64 KB como no NTCP2.

  • Remover a assinatura dos campos IP e porta do handshake, para que routers que não conhecem seu IP externo e porta possam se conectar.

  • Manter o mecanismo de descoberta de IP/porta do SSU 1 no handshake, para que os routers possam descobrir seu IP e porta externos.

  • Incluir representantes dos desenvolvedores de roteadores Java, C++ e Go no design.

Non-Goals

  • Resistência à DPI à prova de balas… isso seriam transportes plugáveis, Proposta 109.

  • Um transporte baseado em TLS (ou semelhante ao HTTPS)… que seria a Proposta 104.

  • Resistência a DPI baseada em tempo (o tempo/atrasos entre mensagens podem ser dependentes da implementação; atrasos intra-mensagem podem ser introduzidos a qualquer momento, incluindo antes do envio do padding aleatório, por exemplo). Atrasos artificiais (o que o obfs4 chama de IAT ou inter-arrival time) são independentes do protocolo em si.

  • Negabilidade de participar numa sessão (há assinaturas presentes).

Não-objetivos que podem ser parcialmente reconsiderados ou discutidos:

  • O grau de proteção contra Deep Packet Inspection (DPI)

  • Segurança Pós-Quântica (PQ)

  • Negação plausível

Security Goals

Consideramos três partes:

  • Alice, que deseja estabelecer uma nova sessão.
  • Bob, com quem Alice deseja estabelecer uma sessão.
  • Mallory, o “homem no meio” entre Alice e Bob.

No máximo dois participantes podem se envolver em ataques ativos.

Alice e Bob estão ambos na posse de um par de chaves estático, que está contido em sua RouterIdentity.

O protocolo proposto tenta permitir que Alice e Bob concordem com uma chave secreta compartilhada (K) sob os seguintes requisitos:

  1. Segurança da chave privada: nem Bob nem Mallory aprendem qualquer coisa sobre a chave privada estática de Alice. Simetricamente, Alice não aprende qualquer coisa sobre a chave privada estática de Bob.

  2. A chave de sessão K é conhecida apenas por Alice e Bob.

  3. Sigilo perfeito para frente: a chave de sessão acordada permanece secreta no futuro, mesmo quando as chaves privadas estáticas de Alice e/ou Bob são reveladas após a chave ter sido acordada.

  4. Autenticação bidirecional: Alice tem certeza de que estabeleceu uma sessão com Bob, e vice-versa.

  5. Proteção contra DPI online: Garantir que não seja trivial detectar que Alice e Bob estão envolvidos no protocolo usando apenas técnicas diretas de inspeção profunda de pacotes (DPI). Veja abaixo.

  6. Negação plausível limitada: nem Alice nem Bob podem negar a participação no protocolo, mas se qualquer um vazar a chave compartilhada, a outra parte pode negar a autenticidade do conteúdo dos dados transmitidos.

A presente proposta tenta fornecer todos os cinco requisitos baseados no protocolo Station-To-Station (STS). Note que este protocolo também é a base para o protocolo SSU.

Additional DPI Discussion

Assumimos dois componentes DPI:

Online DPI

DPI online inspecionando todos os fluxos em tempo real. As conexões podem ser bloqueadas ou alteradas de outra forma. Os dados de conexão ou metadados podem ser identificados e armazenados para análise offline. O DPI online não tem acesso à base de dados da rede I2P. O DPI online tem apenas capacidade computacional limitada em tempo real, incluindo cálculo de comprimento, inspeção de campos e cálculos simples como XOR. O DPI online tem a capacidade de funções criptográficas rápidas em tempo real como ChaCha20, AEAD e hashing, mas estas seriam demasiado dispendiosas para aplicar à maioria ou a todos os fluxos. Qualquer aplicação destas operações criptográficas aplicar-se-ia apenas a fluxos em combinações IP/Porta previamente identificadas por análise offline. O DPI online não tem a capacidade de funções criptográficas de alta sobrecarga como DH ou elligator2. O DPI online não foi projetado especificamente para detetar I2P, embora possa ter regras de classificação limitadas para esse propósito.

É um objetivo prevenir a identificação do protocolo por um DPI online.

A noção de DPI online ou “direto” é aqui considerada para incluir as seguintes capacidades do adversário:

  1. A capacidade de inspecionar todos os dados enviados ou recebidos pelo alvo.

  2. A capacidade de realizar operações nos dados observados, como aplicar cifras de bloco ou funções hash.

  3. A capacidade de armazenar e comparar com mensagens enviadas anteriormente.

  4. A capacidade de modificar, atrasar ou fragmentar pacotes.

No entanto, assume-se que o DPI online tem as seguintes restrições:

  1. A incapacidade de mapear endereços IP para hashes de router. Embora isso seja trivial com acesso em tempo real à base de dados da rede, exigiria um sistema DPI especificamente projetado para ter como alvo o I2P.

  2. A incapacidade de usar informações de tempo para detectar o protocolo.

  3. De forma geral, a caixa de ferramentas DPI online não contém ferramentas integradas que sejam especificamente projetadas para detecção de I2P. Isso inclui a criação de “honeypots”, que por exemplo incluiriam padding não aleatório em suas mensagens. Note que isso não exclui sistemas de machine learning ou ferramentas DPI altamente configuráveis, desde que atendam aos outros requisitos.

Para combater a análise de payload, é garantido que todas as mensagens sejam indistinguíveis de dados aleatórios. Isso também exige que seu comprimento seja aleatório, o que é mais complicado do que apenas adicionar padding aleatório. De fato, no Apêndice A, os autores argumentam que um esquema de padding ingênuo (ou seja, uniforme) não resolve o problema. O Apêndice A, portanto, propõe incluir atrasos aleatórios ou desenvolver um esquema de padding alternativo que possa fornecer proteção razoável para o ataque proposto.

Para proteger contra a sexta entrada acima, as implementações devem incluir atrasos aleatórios no protocolo. Tais técnicas não são cobertas por esta proposta, mas elas também poderiam resolver os problemas de comprimento de padding. Em resumo, a proposta fornece boa proteção contra análise de payload (quando as considerações no Apêndice A são levadas em conta), mas apenas proteção limitada contra análise de fluxo.

Offline DPI

DPI offline inspecionando dados armazenados pelo DPI online para análise posterior. O DPI offline pode ser projetado especificamente para detectar I2P. O DPI offline não tem acesso em tempo real ao banco de dados da rede I2P. O DPI offline tem acesso a esta e outras especificações I2P. O DPI offline possui capacidade computacional ilimitada, incluindo todas as funções criptográficas definidas nesta especificação.

O DPI offline não tem a capacidade de bloquear conexões existentes. O DPI offline tem a capacidade de fazer envio quase em tempo real (dentro de minutos da configuração) para host/porta das partes por injeção de pacotes. O DPI offline tem a capacidade de fazer replay quase em tempo real (dentro de minutos da configuração) de mensagens anteriores (modificadas ou não) para “sondagem” ou outras razões.

Não é um objetivo prevenir a identificação do protocolo por um DPI offline. Toda decodificação de dados ofuscados nas duas primeiras mensagens, que é implementada pelos routers I2P, também pode ser implementada pelo DPI offline.

É um objetivo rejeitar tentativas de conexão que usem repetição de mensagens anteriores.

Address Validation

O seguinte é copiado do QUIC RFC 9000. Para cada seção, revise e edite.

A validação de endereço garante que um endpoint não possa ser usado para um ataque de amplificação de tráfego. Em tal ataque, um pacote é enviado para um servidor com informações de endereço de origem falsificadas que identificam uma vítima. Se um servidor gerar pacotes maiores ou em maior quantidade em resposta a esse pacote, o atacante pode usar o servidor para enviar mais dados em direção à vítima do que seria capaz de enviar por conta própria.

A principal defesa contra ataques de amplificação é verificar se um peer é capaz de receber pacotes no endereço de transporte que ele reivindica. Portanto, após receber pacotes de um endereço que ainda não foi validado, um endpoint DEVE limitar a quantidade de dados que envia para o endereço não validado a três vezes a quantidade de dados recebidos desse endereço. Esse limite no tamanho das respostas é conhecido como limite anti-amplificação.

A validação de endereços é realizada tanto durante o estabelecimento de conexão (ver Seção 8.1) quanto durante a migração de conexão (ver Seção 8.2).

Address Validation during Connection Establishment

O estabelecimento de conexão fornece implicitamente validação de endereço para ambos os pontos finais. Em particular, o recebimento de um pacote protegido com chaves de Handshake confirma que o peer processou com sucesso um pacote Initial. Uma vez que um ponto final tenha processado com sucesso um pacote de Handshake do peer, ele pode considerar que o endereço do peer foi validado.

Além disso, um endpoint PODE considerar o endereço do peer validado se o peer usar um ID de conexão escolhido pelo endpoint e o ID de conexão contiver pelo menos 64 bits de entropia.

Para o cliente, o valor do campo Destination Connection ID em seu primeiro pacote Initial permite que ele valide o endereço do servidor como parte do processamento bem-sucedido de qualquer pacote. Pacotes Initial do servidor são protegidos com chaves que são derivadas deste valor (veja Seção 5.2 de QUIC-TLS). Alternativamente, o valor é ecoado pelo servidor em pacotes Version Negotiation (Seção 6) ou incluído no Integrity Tag em pacotes Retry (Seção 5.8 de QUIC-TLS).

Antes de validar o endereço do cliente, os servidores NÃO DEVEM enviar mais de três vezes a quantidade de bytes do que o número de bytes que receberam. Isso limita a magnitude de qualquer ataque de amplificação que possa ser executado usando endereços de origem falsificados. Para fins de evitar amplificação antes da validação de endereço, os servidores DEVEM contar todos os bytes de payload recebidos em datagramas que são unicamente atribuídos a uma única conexão. Isso inclui datagramas que contêm pacotes que são processados com sucesso e datagramas que contêm pacotes que são todos descartados.

Os clientes DEVEM garantir que os datagramas UDP contendo pacotes Initial tenham payloads UDP de pelo menos 1200 bytes, adicionando frames PADDING conforme necessário. Um cliente que envia datagramas com padding permite que o servidor envie mais dados antes de completar a validação de endereço.

A perda de um pacote Initial ou Handshake do servidor pode causar um deadlock se o cliente não enviar pacotes Initial ou Handshake adicionais. Um deadlock pode ocorrer quando o servidor atinge seu limite anti-amplificação e o cliente recebeu acknowledgments para todos os dados que enviou. Neste caso, quando o cliente não tem motivo para enviar pacotes adicionais, o servidor será incapaz de enviar mais dados porque não validou o endereço do cliente. Para prevenir este deadlock, os clientes DEVEM enviar um pacote em um Probe Timeout (PTO); veja Seção 6.2 de QUIC-RECOVERY. Especificamente, o cliente DEVE enviar um pacote Initial em um datagrama UDP que contenha pelo menos 1200 bytes se não tiver chaves Handshake, e caso contrário enviar um pacote Handshake.

Um servidor pode desejar validar o endereço do cliente antes de iniciar o handshake criptográfico. QUIC usa um token no pacote Initial para fornecer validação de endereço antes de completar o handshake. Este token é entregue ao cliente durante o estabelecimento da conexão com um pacote Retry (veja Seção 8.1.2) ou em uma conexão anterior usando o frame NEW_TOKEN (veja Seção 8.1.3).

Além dos limites de envio impostos antes da validação de endereço, os servidores também são restringidos no que podem enviar pelos limites definidos pelo controlador de congestionamento. Os clientes são restringidos apenas pelo controlador de congestionamento.

Token Construction

Um token enviado em um frame NEW_TOKEN ou um pacote Retry DEVE ser construído de forma que permita ao servidor identificar como foi fornecido a um cliente. Esses tokens são transportados no mesmo campo, mas requerem tratamento diferente dos servidores.

Address Validation Using Retry Packets

Ao receber o pacote Initial do cliente, o servidor pode solicitar validação de endereço enviando um pacote Retry (Seção 17.2.5) contendo um token. Este token DEVE ser repetido pelo cliente em todos os pacotes Initial que ele enviar para essa conexão após receber o pacote Retry.

Em resposta ao processamento de um pacote Initial contendo um token que foi fornecido em um pacote Retry, um servidor não pode enviar outro pacote Retry; ele só pode recusar a conexão ou permitir que ela prossiga.

Desde que não seja possível para um atacante gerar um token válido para seu próprio endereço (veja Seção 8.1.4) e o cliente seja capaz de retornar esse token, isso prova ao servidor que ele recebeu o token.

Um servidor também pode usar um pacote Retry para adiar os custos de estado e processamento do estabelecimento de conexão. Exigir que o servidor forneça um ID de conexão diferente, junto com o parâmetro de transporte original_destination_connection_id definido na Seção 18.2, força o servidor a demonstrar que ele, ou uma entidade com a qual coopera, recebeu o pacote Initial original do cliente. Fornecer um ID de conexão diferente também concede ao servidor algum controle sobre como os pacotes subsequentes são roteados. Isso pode ser usado para direcionar conexões para uma instância de servidor diferente.

Se um servidor recebe um Initial de cliente que contém um token Retry inválido mas é válido de outra forma, ele sabe que o cliente não aceitará outro token Retry. O servidor pode descartar esse pacote e permitir que o cliente expire para detectar falha no handshake, mas isso poderia impor uma penalidade de latência significativa no cliente. Em vez disso, o servidor DEVERIA fechar imediatamente (Seção 10.2) a conexão com um erro INVALID_TOKEN. Note que um servidor não estabeleceu nenhum estado para a conexão neste ponto e, portanto, não entra no período de fechamento.

Um fluxo mostrando o uso de um pacote Retry é mostrado na 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

Um servidor PODE fornecer aos clientes um token de validação de endereço durante uma conexão que pode ser usado em uma conexão subsequente. A validação de endereço é especialmente importante com 0-RTT porque um servidor potencialmente envia uma quantidade significativa de dados para um cliente em resposta aos dados 0-RTT.

O servidor usa o frame NEW_TOKEN (Seção 19.7) para fornecer ao cliente um token de validação de endereço que pode ser usado para validar conexões futuras. Em uma conexão futura, o cliente inclui este token em pacotes Initial para fornecer validação de endereço. O cliente DEVE incluir o token em todos os pacotes Initial que enviar, a menos que um Retry substitua o token por um mais recente. O cliente NÃO DEVE usar o token fornecido em um Retry para conexões futuras. Os servidores PODEM descartar qualquer pacote Initial que não carregue o token esperado.

Diferentemente do token que é criado para um pacote Retry, que é usado imediatamente, o token enviado no frame NEW_TOKEN pode ser usado após algum período de tempo ter passado. Assim, um token DEVE ter um tempo de expiração, que pode ser tanto um tempo de expiração explícito ou um timestamp de emissão que pode ser usado para calcular dinamicamente o tempo de expiração. Um servidor pode armazenar o tempo de expiração ou incluí-lo de forma criptografada no token.

Um token emitido com NEW_TOKEN NÃO DEVE incluir informações que permitiriam que valores fossem vinculados por um observador à conexão na qual foi emitido. Por exemplo, não pode incluir o ID de conexão anterior ou informações de endereçamento, a menos que os valores estejam criptografados. Um servidor DEVE garantir que cada frame NEW_TOKEN que envia seja único entre todos os clientes, com exceção daqueles enviados para reparar perdas de frames NEW_TOKEN enviados anteriormente. Informações que permitem ao servidor distinguir entre tokens de Retry e NEW_TOKEN PODEM estar acessíveis a entidades que não sejam o servidor.

É improvável que o número da porta do cliente seja o mesmo em duas conexões diferentes; portanto, é improvável que a validação da porta seja bem-sucedida.

Um token recebido em um frame NEW_TOKEN é aplicável a qualquer servidor para o qual a conexão é considerada autoritativa (por exemplo, nomes de servidor incluídos no certificado). Ao conectar-se a um servidor para o qual o cliente mantém um token aplicável e não utilizado, ele DEVE incluir esse token no campo Token de seu pacote Initial. Incluir um token pode permitir que o servidor valide o endereço do cliente sem uma viagem de ida e volta adicional. Um cliente NÃO DEVE incluir um token que não é aplicável ao servidor ao qual está se conectando, a menos que o cliente tenha conhecimento de que o servidor que emitiu o token e o servidor ao qual o cliente está se conectando estejam gerenciando conjuntamente os tokens. Um cliente PODE usar um token de qualquer conexão anterior para esse servidor.

Um token permite que um servidor correlacione atividade entre a conexão onde o token foi emitido e qualquer conexão onde ele é usado. Clientes que desejam quebrar a continuidade de identidade com um servidor podem descartar tokens fornecidos usando o frame NEW_TOKEN. Em comparação, um token obtido em um pacote Retry DEVE ser usado imediatamente durante a tentativa de conexão e não pode ser usado em tentativas de conexão subsequentes.

Um cliente NÃO DEVERIA reutilizar um token de um frame NEW_TOKEN para diferentes tentativas de conexão. Reutilizar um token permite que conexões sejam vinculadas por entidades no caminho da rede; veja Seção 9.5.

Os clientes podem receber múltiplos tokens numa única conexão. Além de prevenir a vinculação, qualquer token pode ser usado em qualquer tentativa de conexão. Os servidores podem enviar tokens adicionais para habilitar a validação de endereço para múltiplas tentativas de conexão ou substituir tokens mais antigos que podem se tornar inválidos. Para um cliente, essa ambiguidade significa que enviar o token não utilizado mais recente tem maior probabilidade de ser efetivo. Embora salvar e usar tokens mais antigos não tenha consequências negativas, os clientes podem considerar tokens mais antigos como tendo menor probabilidade de serem úteis ao servidor para validação de endereço.

Quando um servidor recebe um pacote Initial com um token de validação de endereço, ele DEVE tentar validar o token, a menos que já tenha concluído a validação de endereço. Se o token for inválido, então o servidor DEVERIA proceder como se o cliente não tivesse um endereço validado, incluindo potencialmente enviar um pacote Retry. Tokens fornecidos com frames NEW_TOKEN e pacotes Retry podem ser distinguidos pelos servidores (veja Seção 8.1.1), e os últimos podem ser validados de forma mais rigorosa. Se a validação for bem-sucedida, o servidor DEVERIA então permitir que o handshake prossiga.

Nota: A justificativa para tratar o cliente como não validado em vez de descartar o pacote é que o cliente pode ter recebido o token em uma conexão anterior usando o frame NEW_TOKEN, e se o servidor perdeu o estado, pode ser incapaz de validar o token completamente, levando à falha da conexão se o pacote for descartado.

Em um design sem estado, um servidor pode usar tokens criptografados e autenticados para passar informações para clientes que o servidor pode posteriormente recuperar e usar para validar um endereço de cliente. Tokens não são integrados ao handshake criptográfico e, portanto, não são autenticados. Por exemplo, um cliente pode conseguir reutilizar um token. Para evitar ataques que exploram essa propriedade, um servidor pode limitar o uso de tokens apenas às informações necessárias para validar endereços de clientes.

Os clientes PODEM usar tokens obtidos em uma conexão para qualquer tentativa de conexão usando a mesma versão. Ao selecionar um token para usar, os clientes não precisam considerar outras propriedades da conexão que está sendo tentada, incluindo a escolha de possíveis protocolos de aplicação, tickets de sessão ou outras propriedades de conexão.

Address Validation Token Integrity

Um token de validação de endereço DEVE ser difícil de adivinhar. Incluir um valor aleatório com pelo menos 128 bits de entropia no token seria suficiente, mas isso depende do servidor lembrar o valor que envia aos clientes.

Um esquema baseado em tokens permite ao servidor transferir qualquer estado associado à validação para o cliente. Para que este design funcione, o token DEVE ser coberto por proteção de integridade contra modificação ou falsificação por clientes. Sem proteção de integridade, clientes maliciosos poderiam gerar ou adivinhar valores para tokens que seriam aceitos pelo servidor. Apenas o servidor requer acesso à chave de proteção de integridade para tokens.

Não há necessidade de um formato único bem definido para o token porque o servidor que gera o token também o consome. Os tokens enviados em pacotes Retry DEVEM incluir informações que permitam ao servidor verificar que o endereço IP de origem e a porta nos pacotes do cliente permanecem constantes.

Os tokens enviados em frames NEW_TOKEN DEVEM incluir informações que permitam ao servidor verificar que o endereço IP do cliente não mudou desde quando o token foi emitido. Os servidores podem usar tokens de frames NEW_TOKEN para decidir não enviar um pacote Retry, mesmo que o endereço do cliente tenha mudado. Se o endereço IP do cliente tiver mudado, o servidor DEVE aderir ao limite anti-amplificação; veja a Seção 8. Note que na presença de NAT, este requisito pode ser insuficiente para proteger outros hosts que compartilham o NAT de ataques de amplificação.

Atacantes poderiam reutilizar tokens para usar servidores como amplificadores em ataques DDoS. Para proteger contra tais ataques, servidores DEVEM garantir que a reutilização de tokens seja prevenida ou limitada. Servidores DEVERIAM garantir que tokens enviados em pacotes Retry sejam aceitos apenas por um curto período, pois são retornados imediatamente pelos clientes. Tokens que são fornecidos em frames NEW_TOKEN (Seção 19.7) precisam ser válidos por mais tempo, mas NÃO DEVERIAM ser aceitos múltiplas vezes. Servidores são encorajados a permitir que tokens sejam usados apenas uma vez, se possível; tokens PODEM incluir informações adicionais sobre clientes para estreitar ainda mais a aplicabilidade ou reutilização.

DPI Online

A validação de caminho é usada por ambos os peers durante a migração de conexão (veja Seção 9) para verificar a acessibilidade após uma mudança de endereço. Na validação de caminho, os endpoints testam a acessibilidade entre um endereço local específico e um endereço de peer específico, onde um endereço é a tupla de 2 elementos do endereço IP e porta.

A validação de caminho testa se os pacotes enviados em um caminho para um peer são recebidos por esse peer. A validação de caminho é usada para garantir que os pacotes recebidos de um peer em migração não carreguem um endereço de origem falsificado.

A validação de caminho não valida que um peer pode enviar na direção de retorno. Confirmações não podem ser usadas para validação de caminho de retorno porque contêm entropia insuficiente e podem ser falsificadas. Os endpoints determinam independentemente a acessibilidade em cada direção de um caminho e, portanto, a acessibilidade de retorno só pode ser estabelecida pelo peer.

A validação de caminho pode ser usada a qualquer momento por qualquer endpoint. Por exemplo, um endpoint pode verificar se um peer ainda possui seu endereço após um período de inatividade.

A validação de caminho não é projetada como um mecanismo de travessia de NAT. Embora o mecanismo descrito aqui possa ser eficaz para a criação de vinculações de NAT que suportam travessia de NAT, a expectativa é que um endpoint seja capaz de receber pacotes sem primeiro ter enviado um pacote nesse caminho. A travessia eficaz de NAT precisa de mecanismos de sincronização adicionais que não são fornecidos aqui.

Um endpoint PODE incluir outros frames com os frames PATH_CHALLENGE e PATH_RESPONSE usados para validação de caminho. Em particular, um endpoint pode incluir frames PADDING com um frame PATH_CHALLENGE para Path Maximum Transmission Unit Discovery (PMTUD); veja Seção 14.2.1. Um endpoint também pode incluir seu próprio frame PATH_CHALLENGE ao enviar um frame PATH_RESPONSE.

Um endpoint usa um novo ID de conexão para sondas enviadas de um novo endereço local; veja Seção 9.5. Ao sondar um novo caminho, um endpoint pode garantir que seu par tenha um ID de conexão não utilizado disponível para respostas. Enviar frames NEW_CONNECTION_ID e PATH_CHALLENGE no mesmo pacote, se o active_connection_id_limit do par permitir, garante que um ID de conexão não utilizado estará disponível para o par ao enviar uma resposta.

Um endpoint pode escolher sondar simultaneamente múltiplos caminhos. O número de caminhos simultâneos usados para sondas é limitado pelo número de IDs de conexão extras que seu peer forneceu anteriormente, já que cada novo endereço local usado para uma sonda requer um ID de conexão previamente não utilizado.

DPI Offline

Para iniciar a validação de caminho, um endpoint envia um frame PATH_CHALLENGE contendo uma carga útil imprevisível no caminho a ser validado.

Um endpoint PODE enviar múltiplos frames PATH_CHALLENGE para se proteger contra perda de pacotes. No entanto, um endpoint NÃO DEVE enviar múltiplos frames PATH_CHALLENGE em um único pacote.

Um endpoint NÃO DEVE sondar um novo caminho com pacotes contendo um quadro PATH_CHALLENGE com mais frequência do que enviaria um pacote Initial. Isso garante que a migração de conexão não seja mais carga em um novo caminho do que estabelecer uma nova conexão.

O endpoint DEVE usar dados imprevisíveis em cada frame PATH_CHALLENGE para que possa associar a resposta do peer com o PATH_CHALLENGE correspondente.

Um endpoint DEVE expandir datagramas que contenham um frame PATH_CHALLENGE para pelo menos o menor tamanho máximo de datagrama permitido de 1200 bytes, a menos que o limite anti-amplificação para o caminho não permita o envio de um datagrama deste tamanho. O envio de datagramas UDP deste tamanho garante que o caminho de rede do endpoint para o peer possa ser usado para QUIC; veja a Seção 14.

Quando um endpoint não consegue expandir o tamanho do datagrama para 1200 bytes devido ao limite anti-amplificação, o MTU do caminho não será validado. Para garantir que o MTU do caminho seja suficientemente grande, o endpoint DEVE realizar uma segunda validação de caminho enviando um frame PATH_CHALLENGE em um datagrama de pelo menos 1200 bytes. Esta validação adicional pode ser realizada após um PATH_RESPONSE ser recebido com sucesso ou quando bytes suficientes tiverem sido recebidos no caminho para que o envio do datagrama maior não resulte em exceder o limite anti-amplificação.

Ao contrário de outros casos onde os datagramas são expandidos, os endpoints NÃO DEVEM descartar datagramas que pareçam ser muito pequenos quando contêm PATH_CHALLENGE ou PATH_RESPONSE.

Path Validation Responses

Ao receber um quadro PATH_CHALLENGE, um endpoint DEVE responder ecoando os dados contidos no quadro PATH_CHALLENGE em um quadro PATH_RESPONSE. Um endpoint NÃO DEVE atrasar a transmissão de um pacote contendo um quadro PATH_RESPONSE, a menos que seja limitado pelo controle de congestionamento.

Um quadro PATH_RESPONSE DEVE ser enviado no caminho de rede onde o quadro PATH_CHALLENGE foi recebido. Isso garante que a validação de caminho por um peer só seja bem-sucedida se o caminho for funcional em ambas as direções. Este requisito NÃO DEVE ser aplicado pelo endpoint que inicia a validação de caminho, pois isso permitiria um ataque na migração; veja a Seção 9.3.3.

Um endpoint DEVE expandir datagramas que contêm um frame PATH_RESPONSE para pelo menos o menor tamanho máximo permitido de datagrama de 1200 bytes. Isso verifica que o caminho é capaz de transportar datagramas deste tamanho em ambas as direções. No entanto, um endpoint NÃO DEVE expandir o datagrama contendo o PATH_RESPONSE se os dados resultantes excederem o limite anti-amplificação. Espera-se que isso ocorra apenas se o PATH_CHALLENGE recebido não foi enviado em um datagrama expandido.

Um endpoint NÃO DEVE enviar mais de um frame PATH_RESPONSE em resposta a um frame PATH_CHALLENGE; veja Seção 13.3. Espera-se que o peer envie mais frames PATH_CHALLENGE conforme necessário para provocar frames PATH_RESPONSE adicionais.

Validação de Endereço durante o Estabelecimento de Conexão

A validação de caminho é bem-sucedida quando um frame PATH_RESPONSE é recebido contendo os dados que foram enviados em um frame PATH_CHALLENGE anterior. Um frame PATH_RESPONSE recebido em qualquer caminho de rede valida o caminho no qual o PATH_CHALLENGE foi enviado.

Se um endpoint enviar um frame PATH_CHALLENGE em um datagrama que não foi expandido para pelo menos 1200 bytes e se a resposta validar o endereço do peer, o caminho é validado mas não o MTU do caminho. Como resultado, o endpoint agora pode enviar mais de três vezes a quantidade de dados que foi recebida. No entanto, o endpoint DEVE iniciar outra validação de caminho com um datagrama expandido para verificar se o caminho suporta o MTU necessário.

O recebimento de uma confirmação para um pacote contendo um frame PATH_CHALLENGE não é uma validação adequada, uma vez que a confirmação pode ser falsificada por um peer malicioso.

Construção de Token

A validação de caminho só falha quando o endpoint que tenta validar o caminho abandona sua tentativa de validar o caminho.

Os endpoints DEVEM abandonar a validação de caminho baseada em um temporizador. Ao definir este temporizador, as implementações são alertadas de que o novo caminho pode ter um tempo de ida e volta mais longo que o original. É RECOMENDADO um valor de três vezes o maior entre o PTO atual ou o PTO para o novo caminho (usando kInitialRtt, conforme definido em QUIC-RECOVERY).

Este timeout permite que múltiplos PTOs expirem antes de falhar a validação de caminho, de modo que a perda de um único frame PATH_CHALLENGE ou PATH_RESPONSE não cause falha na validação de caminho.

Note que o endpoint pode receber pacotes contendo outros frames no novo caminho, mas um frame PATH_RESPONSE com dados apropriados é necessário para que a validação do caminho seja bem-sucedida.

Quando um endpoint abandona a validação de caminho, ele determina que o caminho não é utilizável. Isso não implica necessariamente uma falha da conexão – endpoints podem continuar enviando pacotes por outros caminhos conforme apropriado. Se nenhum caminho estiver disponível, um endpoint pode aguardar que um novo caminho se torne disponível ou fechar a conexão. Um endpoint que não tem um caminho de rede válido para seu par PODE sinalizar isso usando o erro de conexão NO_VIABLE_PATH, observando que isso só é possível se o caminho de rede existe mas não suporta o MTU necessário (Seção 14).

Uma validação de caminho pode ser abandonada por outras razões além de falha. Principalmente, isso acontece se uma migração de conexão para um novo caminho é iniciada enquanto uma validação de caminho no caminho antigo está em andamento.

Connection Migration

O seguinte é copiado do QUIC RFC 9000. Para cada seção, revise e edite.

O uso de um ID de conexão permite que as conexões sobrevivam a mudanças nos endereços dos endpoints (endereço IP e porta), como aquelas causadas por um endpoint migrando para uma nova rede. Esta seção descreve o processo pelo qual um endpoint migra para um novo endereço.

O design do QUIC depende de que os endpoints mantenham um endereço estável durante a duração do handshake. Um endpoint NÃO DEVE iniciar migração de conexão antes que o handshake seja confirmado, conforme definido na Seção 4.1.2 de QUIC-TLS.

Se o peer enviou o parâmetro de transporte disable_active_migration, um endpoint também NÃO DEVE enviar pacotes (incluindo pacotes de sondagem; veja Seção 9.1) de um endereço local diferente para o endereço que o peer usou durante o handshake, a menos que o endpoint tenha agido em um parâmetro de transporte preferred_address do peer. Se o peer violar este requisito, o endpoint DEVE ou descartar os pacotes recebidos nesse caminho sem gerar um Stateless Reset ou prosseguir com a validação do caminho e permitir que o peer migre. Gerar um Stateless Reset ou fechar a conexão permitiria que terceiros na rede causassem o fechamento de conexões através de spoofing ou manipulação do tráfego observado.

Nem todas as mudanças de endereço de peer são migrações intencionais ou ativas. O peer pode experimentar rebinding de NAT: uma mudança de endereço devido a um middlebox, geralmente um NAT, alocando uma nova porta de saída ou até mesmo um novo endereço IP de saída para um fluxo. Um endpoint DEVE realizar validação de caminho (Seção 8.2) se detectar qualquer mudança no endereço de um peer, a menos que tenha validado previamente esse endereço.

Quando um endpoint não tem um caminho validado no qual enviar pacotes, ele PODE descartar o estado da conexão. Um endpoint capaz de migração de conexão PODE aguardar que um novo caminho se torne disponível antes de descartar o estado da conexão.

Este documento limita a migração de conexões para novos endereços de cliente, exceto conforme descrito na Seção 9.6. Os clientes são responsáveis por iniciar todas as migrações. Os servidores não enviam pacotes não-exploratórios (ver Seção 9.1) para um endereço de cliente até que vejam um pacote não-exploratório desse endereço. Se um cliente receber pacotes de um endereço de servidor desconhecido, o cliente DEVE descartar esses pacotes.

Validação de Endereço Usando Pacotes de Retry

Um endpoint PODE sondar a acessibilidade de peer a partir de um novo endereço local usando validação de caminho (Seção 8.2) antes de migrar a conexão para o novo endereço local. A falha da validação de caminho simplesmente significa que o novo caminho não é utilizável para esta conexão. A falha ao validar um caminho não causa o encerramento da conexão, a menos que não haja caminhos alternativos válidos disponíveis.

Os frames PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID e PADDING são “frames de sondagem”, e todos os outros frames são “frames de não-sondagem”. Um pacote contendo apenas frames de sondagem é um “pacote de sondagem”, e um pacote contendo qualquer outro frame é um “pacote de não-sondagem”.

Validação de Endereço para Conexões Futuras

Um endpoint pode migrar uma conexão para um novo endereço local enviando pacotes contendo frames não-exploratórios desse endereço.

Cada endpoint valida o endereço de seu peer durante o estabelecimento da conexão. Portanto, um endpoint em migração pode enviar para seu peer sabendo que o peer está disposto a receber no endereço atual do peer. Assim, um endpoint pode migrar para um novo endereço local sem primeiro validar o endereço do peer.

Para estabelecer a alcançabilidade no novo caminho, um endpoint inicia a validação de caminho (Seção 8.2) no novo caminho. Um endpoint PODE adiar a validação de caminho até que um par envie o próximo frame não-exploratório para seu novo endereço.

Ao migrar, o novo caminho pode não suportar a taxa de envio atual do endpoint. Portanto, o endpoint reinicia seu controlador de congestionamento e estimativa de RTT, conforme descrito na Seção 9.4.

O novo caminho pode não ter a mesma capacidade ECN. Portanto, o endpoint valida a capacidade ECN conforme descrito na Seção 13.4.

Integridade do Token de Validação de Endereço

Receber um pacote de um novo endereço de peer contendo um frame não-probing indica que o peer migrou para esse endereço.

Se o destinatário permitir a migração, DEVE enviar pacotes subsequentes para o novo endereço do peer e DEVE iniciar a validação de caminho (Seção 8.2) para verificar a propriedade do endereço pelo peer se a validação ainda não estiver em andamento. Se o destinatário não tiver IDs de conexão não utilizados do peer, não será capaz de enviar nada no novo caminho até que o peer forneça um; veja a Seção 9.5.

Um endpoint só muda o endereço para o qual envia pacotes em resposta ao pacote não-probing com o número mais alto. Isto garante que um endpoint não envie pacotes para um endereço de peer antigo no caso de receber pacotes fora de ordem.

Um endpoint PODE enviar dados para um endereço de peer não validado, mas DEVE se proteger contra ataques potenciais conforme descrito nas Seções 9.3.1 e 9.3.2. Um endpoint PODE pular a validação de um endereço de peer se esse endereço foi visto recentemente. Em particular, se um endpoint retornar para um caminho previamente validado após detectar alguma forma de migração espúria, pular a validação de endereço e restaurar a detecção de perda e estado de congestionamento pode reduzir o impacto de desempenho do ataque.

Após alterar o endereço para o qual envia pacotes não-exploratórios, um endpoint pode abandonar qualquer validação de caminho para outros endereços.

Receber um pacote de um novo endereço de peer pode ser o resultado de um NAT rebinding no peer.

Após verificar um novo endereço de cliente, o servidor DEVE enviar novos tokens de validação de endereço (Seção 8) para o cliente.

Validação de Caminho

É possível que um peer esteja falsificando seu endereço de origem para fazer com que um endpoint envie quantidades excessivas de dados para um host não disposto. Se o endpoint enviar significativamente mais dados do que o peer que está falsificando, a migração de conexão pode ser usada para amplificar o volume de dados que um atacante pode gerar em direção a uma vítima.

Como descrito na Seção 9.3, um endpoint é obrigatório para validar o novo endereço de um peer para confirmar a posse do peer do novo endereço. Até que o endereço de um peer seja considerado válido, um endpoint limita a quantidade de dados que envia para esse endereço; veja a Seção 8. Na ausência desse limite, um endpoint corre o risco de ser usado para um ataque de negação de serviço contra uma vítima desavisada.

Se um endpoint pula a validação de um endereço de peer como descrito acima, ele não precisa limitar sua taxa de envio.

Iniciando a Validação de Caminho

Um atacante no caminho poderia causar uma migração de conexão espúria copiando e encaminhando um pacote com um endereço falsificado de tal forma que chegue antes do pacote original. O pacote com o endereço falsificado será visto como vindo de uma conexão em migração, e o pacote original será visto como duplicado e descartado. Após uma migração espúria, a validação do endereço de origem falhará porque a entidade no endereço de origem não possui as chaves criptográficas necessárias para ler ou responder ao frame PATH_CHALLENGE que é enviado para ela, mesmo que quisesse.

Para proteger a conexão de falhar devido a essa migração espúria, um endpoint DEVE reverter para usar o último endereço de peer validado quando a validação de um novo endereço de peer falhar. Adicionalmente, o recebimento de pacotes com números de pacote maiores do endereço de peer legítimo irá desencadear outra migração de conexão. Isso fará com que a validação do endereço da migração espúria seja abandonada, assim contendo migrações iniciadas pelo atacante injetando um único pacote.

Se um endpoint não tiver estado sobre o último endereço de peer validado, DEVE fechar a conexão silenciosamente descartando todo o estado da conexão. Isso resulta em novos pacotes na conexão sendo tratados genericamente. Por exemplo, um endpoint PODE enviar um Stateless Reset em resposta a quaisquer pacotes de entrada adicionais.

Respostas de Validação de Caminho

Um atacante fora do caminho que pode observar pacotes pode encaminhar cópias de pacotes genuínos para os endpoints. Se o pacote copiado chegar antes do pacote genuíno, isso aparecerá como uma reassociação NAT. Qualquer pacote genuíno será descartado como duplicata. Se o atacante conseguir continuar encaminhando pacotes, poderá causar migração para um caminho via o atacante. Isso coloca o atacante no caminho, dando-lhe a capacidade de observar ou descartar todos os pacotes subsequentes.

Este estilo de ataque depende do atacante usar um caminho que tenha aproximadamente as mesmas características que o caminho direto entre os pontos finais. O ataque é mais confiável se relativamente poucos pacotes forem enviados ou se a perda de pacotes coincidir com a tentativa de ataque.

Um pacote não-sondante recebido no caminho original que aumenta o número máximo de pacote recebido fará com que o endpoint retorne para esse caminho. Provocar pacotes neste caminho aumenta a probabilidade de que o ataque seja malsucedido. Portanto, a mitigação deste ataque depende de provocar a troca de pacotes.

Em resposta a uma migração aparente, os endpoints DEVEM validar o caminho anteriormente ativo usando um frame PATH_CHALLENGE. Isso induz o envio de novos pacotes nesse caminho. Se o caminho não for mais viável, a tentativa de validação expirará e falhará; se o caminho for viável mas não for mais desejado, a validação será bem-sucedida mas resultará apenas no envio de pacotes de sondagem no caminho.

Um endpoint que recebe um PATH_CHALLENGE em um caminho ativo DEVE enviar um pacote não-probing em resposta. Se o pacote não-probing chegar antes de qualquer cópia feita por um atacante, isso resulta na conexão sendo migrada de volta para o caminho original. Qualquer migração subsequente para outro caminho reinicia todo esse processo.

Esta defesa é imperfeita, mas isso não é considerado um problema sério. Se o caminho via o ataque é confiavelmente mais rápido que o caminho original, apesar de múltiplas tentativas de usar esse caminho original, não é possível distinguir entre um ataque e uma melhoria no roteamento.

Um endpoint também poderia usar heurísticas para melhorar a detecção deste estilo de ataque. Por exemplo, o rebinding de NAT é improvável se pacotes foram recebidos recentemente no caminho antigo; similarmente, rebinding é raro em caminhos IPv6. Os endpoints também podem procurar por pacotes duplicados. Por outro lado, uma mudança no ID de conexão é mais provável de indicar uma migração intencional em vez de um ataque.

Validação de Caminho Bem-Sucedida

A capacidade disponível no novo caminho pode não ser a mesma do caminho antigo. Os pacotes enviados no caminho antigo NÃO DEVEM contribuir para o controle de congestionamento ou estimativa de RTT para o novo caminho.

Ao confirmar a propriedade de um peer sobre seu novo endereço, um endpoint DEVE imediatamente reinicializar o controlador de congestionamento e o estimador de tempo de ida e volta para o novo caminho com valores iniciais (veja Apêndices A.3 e B.3 de QUIC-RECOVERY) a menos que a única mudança no endereço do peer seja seu número de porta. Como mudanças apenas de porta são comumente resultado de revinculação de NAT ou outra atividade de middlebox, o endpoint PODE em vez disso reter seu estado de controle de congestionamento e estimativa de tempo de ida e volta nesses casos em vez de reverter para valores iniciais. Em casos onde o estado de controle de congestionamento retido de um caminho antigo é usado em um novo caminho com características substancialmente diferentes, um remetente poderia transmitir de forma muito agressiva até que o controlador de congestionamento e o estimador de RTT tenham se adaptado. Geralmente, implementações são aconselhadas a ser cautelosas ao usar valores anteriores em um novo caminho.

Pode haver reordenação aparente no receptor quando um endpoint envia dados e sondas de/para múltiplos endereços durante o período de migração, já que os dois caminhos resultantes podem ter tempos de ida e volta diferentes. Um receptor de pacotes em múltiplos caminhos ainda enviará frames ACK cobrindo todos os pacotes recebidos.

Embora múltiplos caminhos possam ser usados durante a migração de conexão, um único contexto de controle de congestionamento e um único contexto de recuperação de perda (conforme descrito em QUIC-RECOVERY) podem ser adequados. Por exemplo, um endpoint pode atrasar a mudança para um novo contexto de controle de congestionamento até que seja confirmado que um caminho antigo não é mais necessário (como no caso descrito na Seção 9.3.3).

Um remetente pode fazer exceções para pacotes de sonda de forma que sua detecção de perda seja independente e não cause indevidamente que o controlador de congestionamento reduza sua taxa de envio. Um endpoint pode definir um temporizador separado quando um PATH_CHALLENGE é enviado, que é cancelado se o PATH_RESPONSE correspondente for recebido. Se o temporizador disparar antes do PATH_RESPONSE ser recebido, o endpoint pode enviar um novo PATH_CHALLENGE e reiniciar o temporizador por um período de tempo mais longo. Este temporizador DEVE ser definido conforme descrito na Seção 6.2.1 de QUIC-RECOVERY e NÃO DEVE ser mais agressivo.

Validação de Caminho Falhada

Usar um ID de conexão estável em múltiplos caminhos de rede permitiria que um observador passivo correlacionasse atividades entre esses caminhos. Um endpoint que se move entre redes pode não desejar que sua atividade seja correlacionada por qualquer entidade além de seu par, então IDs de conexão diferentes são usados ao enviar de endereços locais diferentes, conforme discutido na Seção 5.1. Para que isso seja efetivo, os endpoints precisam garantir que os IDs de conexão que fornecem não possam ser vinculados por qualquer outra entidade.

A qualquer momento, os endpoints PODEM alterar o Destination Connection ID que transmitem para um valor que não tenha sido usado em outro caminho.

Um endpoint NÃO DEVE reutilizar um connection ID ao enviar de mais de um endereço local – por exemplo, ao iniciar migração de conexão conforme descrito na Seção 9.2 ou ao sondar um novo caminho de rede conforme descrito na Seção 9.1.

Da mesma forma, um endpoint NÃO DEVE reutilizar um connection ID ao enviar para mais de um endereço de destino. Devido a mudanças na rede fora do controle de seu peer, um endpoint pode receber pacotes de um novo endereço de origem com o mesmo valor do campo Destination Connection ID, caso em que ELE PODE continuar a usar o connection ID atual com o novo endereço remoto enquanto ainda envia do mesmo endereço local.

Estes requisitos sobre reutilização de ID de conexão aplicam-se apenas ao envio de pacotes, pois mudanças não intencionais no caminho sem uma mudança no ID de conexão são possíveis. Por exemplo, após um período de inatividade da rede, a religação NAT pode fazer com que os pacotes sejam enviados em um novo caminho quando o cliente retoma o envio. Um endpoint responde a tal evento conforme descrito na Seção 9.3.

Usar IDs de conexão diferentes para pacotes enviados em ambas as direções em cada novo caminho de rede elimina o uso do ID de conexão para vincular pacotes da mesma conexão em diferentes caminhos de rede. A proteção de cabeçalho garante que números de pacotes não possam ser usados para correlacionar atividades. Isso não impede que outras propriedades dos pacotes, como tempo e tamanho, sejam usadas para correlacionar atividades.

Um endpoint NÃO DEVE iniciar migração com um peer que tenha solicitado um connection ID de comprimento zero, porque o tráfego sobre o novo caminho pode ser trivialmente vinculável ao tráfego sobre o antigo. Se o servidor conseguir associar pacotes com um connection ID de comprimento zero à conexão correta, isso significa que o servidor está usando outras informações para demultiplexar pacotes. Por exemplo, um servidor pode fornecer um endereço único para cada cliente – por exemplo, usando serviços alternativos HTTP ALTSVC. Informações que possam permitir o roteamento correto de pacotes através de múltiplos caminhos de rede também permitirão que a atividade nesses caminhos seja vinculada por entidades que não sejam o peer.

Um cliente pode desejar reduzir a vinculabilidade trocando para um novo ID de conexão, porta UDP de origem ou endereço IP (veja RFC8981) ao enviar tráfego após um período de inatividade. Alterar o endereço do qual envia pacotes ao mesmo tempo pode fazer com que o servidor detecte uma migração de conexão. Isso garante que os mecanismos que suportam migração sejam exercitados mesmo para clientes que não experimentam rebindings de NAT ou migrações genuínas. Alterar o endereço pode fazer com que um peer reinicie seu estado de controle de congestionamento (veja Seção 9.4), então endereços DEVEM ser alterados apenas raramente.

Um endpoint que esgota os IDs de conexão disponíveis não pode sondar novos caminhos ou iniciar migração, nem pode responder a sondagens ou tentativas de seu peer de migrar. Para garantir que a migração seja possível e que pacotes enviados em diferentes caminhos não possam ser correlacionados, endpoints DEVEM fornecer novos IDs de conexão antes que peers migrem; veja Seção 5.1.1. Se um peer pode ter esgotado os IDs de conexão disponíveis, um endpoint em migração poderia incluir um frame NEW_CONNECTION_ID em todos os pacotes enviados em um novo caminho de rede.

Server’s Preferred Address

QUIC permite que servidores aceitem conexões em um endereço IP e tentem transferir essas conexões para um endereço mais preferido logo após o handshake. Isso é particularmente útil quando clientes inicialmente se conectam a um endereço compartilhado por múltiplos servidores, mas prefeririam usar um endereço unicast para garantir estabilidade da conexão. Esta seção descreve o protocolo para migrar uma conexão para um endereço de servidor preferido.

A migração de uma conexão para um novo endereço de servidor durante a conexão não é suportada pela versão do QUIC especificada neste documento. Se um cliente receber pacotes de um novo endereço de servidor quando o cliente não iniciou uma migração para esse endereço, o cliente DEVE descartar esses pacotes.

Sondando um Novo Caminho

Um servidor transmite um endereço preferido incluindo o parâmetro de transporte preferred_address no handshake TLS.

Os servidores PODEM comunicar um endereço preferido de cada família de endereços (IPv4 e IPv6) para permitir que os clientes escolham aquele mais adequado à sua conexão de rede.

Uma vez confirmado o handshake, o cliente DEVE selecionar um dos dois endereços fornecidos pelo servidor e iniciar a validação de caminho (ver Seção 8.2). Um cliente constrói pacotes usando qualquer ID de conexão ativo não utilizado anteriormente, obtido do parâmetro de transporte preferred_address ou de um frame NEW_CONNECTION_ID.

Assim que a validação do caminho for bem-sucedida, o cliente DEVE começar a enviar todos os pacotes futuros para o novo endereço do servidor usando o novo ID de conexão e descontinuar o uso do endereço antigo do servidor. Se a validação do caminho falhar, o cliente DEVE continuar enviando todos os pacotes futuros para o endereço IP original do servidor.

Iniciando Migração de Conexão

Um cliente que migra para um endereço preferido DEVE validar o endereço que escolhe antes de migrar; veja a Seção 21.5.3.

Um servidor pode receber um pacote endereçado ao seu endereço IP preferido a qualquer momento após aceitar uma conexão. Se este pacote contém um frame PATH_CHALLENGE, o servidor envia um pacote contendo um frame PATH_RESPONSE conforme a Seção 8.2. O servidor DEVE enviar pacotes não-exploratórios a partir de seu endereço original até receber um pacote não-exploratório do cliente em seu endereço preferido e até que o servidor tenha validado o novo caminho.

O servidor DEVE sondar no caminho em direção ao cliente a partir de seu endereço preferido. Isso ajuda a proteger contra migração espúria iniciada por um atacante.

Uma vez que o servidor tenha completado sua validação de caminho e tenha recebido um pacote não-sondagem com um novo número de pacote mais alto em seu endereço preferido, o servidor começa a enviar pacotes não-sondagem para o cliente exclusivamente a partir de seu endereço IP preferido. O servidor DEVERIA descartar pacotes mais novos para esta conexão que são recebidos no endereço IP antigo. O servidor PODE continuar a processar pacotes atrasados que são recebidos no endereço IP antigo.

Os endereços que um servidor fornece no parâmetro de transporte preferred_address são válidos apenas para a conexão em que são fornecidos. Um cliente NÃO DEVE usar estes endereços para outras conexões, incluindo conexões que são retomadas a partir da conexão atual.

Respondendo à Migração de Conexão

Um cliente pode precisar executar uma migração de conexão antes de ter migrado para o endereço preferido do servidor. Neste caso, o cliente DEVE executar validação de caminho tanto para o endereço original quanto para o endereço preferido do servidor a partir do novo endereço do cliente de forma simultânea.

Se a validação de caminho do endereço preferido do servidor for bem-sucedida, o cliente DEVE abandonar a validação do endereço original e migrar para usar o endereço preferido do servidor. Se a validação de caminho do endereço preferido do servidor falhar mas a validação do endereço original do servidor for bem-sucedida, o cliente PODE migrar para seu novo endereço e continuar enviando para o endereço original do servidor.

Se os pacotes recebidos no endereço preferido do servidor tiverem um endereço de origem diferente do observado do cliente durante o handshake, o servidor DEVE proteger-se contra ataques potenciais conforme descrito nas Seções 9.3.1 e 9.3.2. Além da migração simultânea intencional, isso também pode ocorrer porque a rede de acesso do cliente usou um binding NAT diferente para o endereço preferido do servidor.

Os servidores DEVEM iniciar a validação de caminho para o novo endereço do cliente ao receber um pacote de sonda de um endereço diferente; veja a Seção 8.

Um cliente que migra para um novo endereço DEVERIA usar um endereço preferencial da mesma família de endereços para o servidor.

O ID de conexão fornecido no parâmetro de transporte preferred_address não é específico para os endereços que são fornecidos. Este ID de conexão é fornecido para garantir que o cliente tenha um ID de conexão disponível para migração, mas o cliente PODE usar este ID de conexão em qualquer caminho.

Falsificação de Endereço de Peer

QUIC recomenda que endpoints que enviam dados usando IPv6 DEVEM aplicar um rótulo de fluxo IPv6 em conformidade com RFC 6437, a menos que a API local não permita definir rótulos de fluxo IPv6.

Infelizmente, a API Java não permite definir rótulos de fluxo IPv6.

Não-Objetivos

O seguinte é copiado do QUIC RFC 9000. Para cada seção, revise e edite.

O objetivo do QUIC é fornecer uma conexão de transporte segura. A Seção 21.1 fornece uma visão geral dessas propriedades; as seções subsequentes discutem restrições e ressalvas sobre essas propriedades, incluindo descrições de ataques conhecidos e contramedidas.

Falsificação de Endereço no Caminho

Uma análise de segurança completa do QUIC está fora do escopo deste documento. Esta seção fornece uma descrição informal das propriedades de segurança desejadas como auxílio aos implementadores e para ajudar a orientar a análise do protocolo.

QUIC assume o modelo de ameaças descrito em SEC-CONS e fornece proteções contra muitos dos ataques que surgem desse modelo.

Para esse propósito, os ataques são divididos em ataques passivos e ativos. Atacantes passivos têm a capacidade de ler pacotes da rede, enquanto atacantes ativos também têm a capacidade de escrever pacotes na rede. No entanto, um ataque passivo pode envolver um atacante com a capacidade de causar uma mudança de roteamento ou outra modificação no caminho percorrido pelos pacotes que compõem uma conexão.

Os atacantes são adicionalmente categorizados como atacantes no caminho (on-path) ou atacantes fora do caminho (off-path). Um atacante no caminho pode ler, modificar ou remover qualquer pacote que observa de tal forma que o pacote não chegue mais ao seu destino, enquanto um atacante fora do caminho observa os pacotes mas não pode impedir que o pacote original chegue ao seu destino pretendido. Ambos os tipos de atacantes também podem transmitir pacotes arbitrários. Esta definição difere daquela da Seção 3.5 de SEC-CONS no sentido de que um atacante fora do caminho é capaz de observar pacotes.

As propriedades do handshake, pacotes protegidos e migração de conexão são consideradas separadamente.

Encaminhamento de Pacotes Fora do Caminho

O handshake QUIC incorpora o handshake TLS 1.3 e herda as propriedades criptográficas descritas no Apêndice E.1 de TLS13. Muitas das propriedades de segurança do QUIC dependem do handshake TLS fornecer essas propriedades. Qualquer ataque ao handshake TLS poderia afetar o QUIC.

Qualquer ataque ao handshake TLS que comprometa o sigilo ou a singularidade das chaves de sessão, ou a autenticação dos pares participantes, afeta outras garantias de segurança fornecidas pelo QUIC que dependem dessas chaves. Por exemplo, a migração (Seção 9) depende da eficácia das proteções de confidencialidade, tanto para a negociação de chaves usando o handshake TLS quanto para a proteção de pacotes QUIC, para evitar a vinculabilidade entre caminhos de rede.

Um ataque à integridade do handshake TLS pode permitir que um atacante afete a seleção do protocolo de aplicação ou versão QUIC.

Além das propriedades fornecidas pelo TLS, o handshake QUIC oferece alguma defesa contra ataques DoS no handshake.

Detecção de Perda e Controle de Congestionamento

A validação de endereço (Seção 8) é usada para verificar que uma entidade que reivindica um determinado endereço é capaz de receber pacotes nesse endereço. A validação de endereço limita os alvos de ataques de amplificação a endereços para os quais um atacante pode observar pacotes.

Antes da validação de endereço, os endpoints têm limitações no que podem enviar. Os endpoints não podem enviar dados para um endereço não validado em quantidade superior a três vezes os dados recebidos desse endereço.

Nota: O limite anti-amplificação aplica-se apenas quando um endpoint responde a pacotes recebidos de um endereço não validado. O limite anti-amplificação não se aplica a clientes ao estabelecer uma nova conexão ou ao iniciar migração de conexão.

Implicações de Privacidade da Migração de Conexão

Calcular o primeiro voo do servidor para um handshake completo é potencialmente caro, exigindo tanto uma assinatura quanto um cálculo de troca de chaves. Para prevenir ataques de DoS computacionais, o pacote Retry fornece um mecanismo barato de troca de tokens que permite aos servidores validar o endereço IP de um cliente antes de fazer quaisquer cálculos caros ao custo de uma única viagem de ida e volta. Após um handshake bem-sucedido, os servidores podem emitir novos tokens para um cliente, o que permitirá o estabelecimento de novas conexões sem incorrer neste custo.

Endereço Preferido do Servidor

Um atacante on-path ou off-path pode forçar o falha do handshake substituindo ou correndo contra os pacotes Initial. Uma vez que pacotes Initial válidos tenham sido trocados, os pacotes Handshake subsequentes são protegidos com as chaves Handshake, e um atacante on-path não pode forçar falha do handshake exceto descartando pacotes para fazer com que os endpoints abandonem a tentativa.

Um atacante no caminho da rede também pode substituir os endereços dos pacotes em ambos os lados e, portanto, fazer com que o cliente ou servidor tenha uma visão incorreta dos endereços remotos. Tal ataque é indistinguível das funções executadas por um NAT.

Comunicando um Endereço Preferido

Todo o handshake é criptograficamente protegido, com os pacotes Initial sendo criptografados com chaves por versão e os pacotes Handshake e posteriores sendo criptografados com chaves derivadas da troca de chaves TLS. Além disso, a negociação de parâmetros é incorporada ao transcript TLS e, portanto, fornece as mesmas garantias de integridade que a negociação TLS comum. Um atacante pode observar os parâmetros de transporte do cliente (desde que conheça o salt específico da versão), mas não pode observar os parâmetros de transporte do servidor e não pode influenciar a negociação de parâmetros.

Os IDs de conexão não são criptografados, mas têm proteção de integridade em todos os pacotes.

Esta versão do QUIC não incorpora um mecanismo de negociação de versão; implementações de versões incompatíveis simplesmente falharão ao estabelecer uma conexão.

Migração para um Endereço Preferido

A proteção de pacotes (Seção 12.1) aplica criptografia autenticada a todos os pacotes, exceto pacotes de Negociação de Versão, embora pacotes Initial e Retry tenham proteção limitada devido ao uso de material de chaveamento específico da versão; consulte QUIC-TLS para mais detalhes. Esta seção considera ataques passivos e ativos contra pacotes protegidos.

Tanto atacantes no caminho quanto fora do caminho podem montar um ataque passivo no qual salvam pacotes observados para um ataque offline contra a proteção de pacotes em um momento futuro; isso é verdade para qualquer observador de qualquer pacote em qualquer rede.

Um atacante que injeta pacotes sem conseguir observar pacotes válidos para uma conexão é improvável que seja bem-sucedido, uma vez que a proteção de pacotes garante que pacotes válidos são gerados apenas por endpoints que possuem o material de chave estabelecido durante o handshake; veja as Seções 7 e 21.1.1. Da mesma forma, qualquer atacante ativo que observe pacotes e tente inserir novos dados ou modificar dados existentes nesses pacotes não deve conseguir gerar pacotes considerados válidos pelo endpoint receptor, exceto pacotes Initial.

Um ataque de spoofing, no qual um atacante ativo reescreve partes desprotegidas de um pacote que ele encaminha ou injeta, como o endereço de origem ou destino, só é eficaz se o atacante puder encaminhar pacotes para o endpoint original. A proteção de pacotes garante que as cargas úteis dos pacotes só possam ser processadas pelos endpoints que completaram o handshake, e pacotes inválidos são ignorados por esses endpoints.

Um atacante também pode modificar os limites entre pacotes e datagramas UDP, fazendo com que múltiplos pacotes sejam agrupados em um único datagrama ou dividindo pacotes agrupados em múltiplos datagramas. Além dos datagramas contendo pacotes Initial, que requerem preenchimento, a modificação de como os pacotes são organizados em datagramas não tem efeito funcional em uma conexão, embora possa alterar algumas características de desempenho.

Interação da Migração de Cliente e Endereço Preferido

A migração de conexão (Seção 9) fornece aos endpoints a capacidade de transicionar entre endereços IP e portas em múltiplos caminhos, usando um caminho por vez para transmissão e recebimento de frames não-exploratórios. A validação de caminho (Seção 8.2) estabelece que um peer está tanto disposto quanto capaz de receber pacotes enviados em um caminho específico. Isso ajuda a reduzir os efeitos do spoofing de endereços ao limitar o número de pacotes enviados para um endereço falsificado.

Esta seção descreve as propriedades de segurança pretendidas da migração de conexão sob vários tipos de ataques DoS.

Uso do Flow Label IPv6 e Migração

Um atacante que pode fazer com que um pacote que observa não alcance mais seu destino pretendido é considerado um atacante no caminho (on-path attacker). Quando um atacante está presente entre um cliente e servidor, os pontos finais são obrigados a enviar pacotes através do atacante para estabelecer conectividade em um determinado caminho.

Um atacante on-path pode:

  • Inspecionar pacotes

  • Modificar cabeçalhos de pacotes IP e UDP

  • Injetar novos pacotes

  • Atrasar pacotes

  • Reordenar pacotes

  • Descartar pacotes

  • Dividir e mesclar datagramas ao longo dos limites de pacotes

Um atacante no caminho não pode:

  • Modificar uma porção autenticada de um pacote e fazer com que o destinatário aceite esse pacote

Um atacante on-path tem a oportunidade de modificar os pacotes que observa; no entanto, qualquer modificação a uma porção autenticada de um pacote fará com que ele seja descartado pelo endpoint receptor como inválido, já que as cargas úteis dos pacotes são tanto autenticadas quanto criptografadas.

QUIC tem como objetivo restringir as capacidades de um atacante no caminho da seguinte forma:

  1. Um atacante no caminho pode impedir o uso de um caminho para uma conexão, causando falha na conexão se ela não puder usar um caminho diferente que não contenha o atacante. Isso pode ser alcançado descartando todos os pacotes, modificando-os para que falhem na descriptografia, ou outros métodos.

  2. Um atacante no caminho pode impedir a migração para um novo caminho para o qual o atacante também está no caminho, causando falha na validação do caminho no novo caminho.

  3. Um atacante on-path não pode impedir que um cliente migre para um caminho no qual o atacante não está on-path.

  4. Um atacante no caminho pode reduzir o throughput de uma conexão atrasando pacotes ou descartando-os.

  5. Um atacante no caminho não pode fazer com que um endpoint aceite um pacote para o qual ele tenha modificado uma parte autenticada desse pacote.

Off-Path Active Attacks

Um atacante fora do caminho não está diretamente no caminho entre um cliente e servidor, mas poderia ser capaz de obter cópias de alguns ou todos os pacotes enviados entre o cliente e o servidor. Ele também é capaz de enviar cópias desses pacotes para qualquer um dos endpoints.

Um atacante off-path pode:

  • Inspecionar pacotes

  • Injetar novos pacotes

  • Reordenar pacotes injetados

Um atacante fora do caminho não pode:

  • Modificar pacotes enviados por endpoints

  • Atrasar pacotes

  • Descartar pacotes

  • Reordenar pacotes originais

Um atacante fora do caminho pode criar cópias modificadas de pacotes que observou e injetar essas cópias na rede, potencialmente com endereços de origem e destino falsificados.

Para os propósitos desta discussão, assume-se que um atacante fora do caminho tem a capacidade de injetar uma cópia modificada de um pacote na rede que chegará ao endpoint de destino antes da chegada do pacote original observado pelo atacante. Em outras palavras, um atacante tem a capacidade de consistentemente “vencer” uma corrida com os pacotes legítimos entre os endpoints, potencialmente fazendo com que o pacote original seja ignorado pelo destinatário.

Também se assume que um atacante possui os recursos necessários para afetar o estado do NAT. Em particular, um atacante pode fazer com que um endpoint perca sua vinculação NAT e então obter a mesma porta para uso com seu próprio tráfego.

QUIC visa restringir as capacidades de um atacante fora do caminho da seguinte forma:

  1. Um atacante fora do caminho pode competir com pacotes e tentar se tornar um atacante “limitado” no caminho.

  2. Um atacante fora do caminho pode fazer com que a validação de caminho seja bem-sucedida para pacotes encaminhados com o endereço de origem listado como o atacante fora do caminho, desde que ele possa fornecer conectividade melhorada entre o cliente e o servidor.

  3. Um atacante fora do caminho não pode fazer com que uma conexão seja fechada depois que o handshake foi concluído.

  4. Um atacante fora do caminho não pode causar falha na migração para um novo caminho se não conseguir observar o novo caminho.

  5. Um atacante fora do caminho pode se tornar um atacante limitado no caminho durante a migração para um novo caminho para o qual também é um atacante fora do caminho.

  6. Um atacante off-path pode se tornar um atacante on-path limitado ao afetar o estado NAT compartilhado de forma que envie pacotes para o servidor a partir do mesmo endereço IP e porta que o cliente originalmente utilizou.

Visão Geral das Propriedades de Segurança

Um atacante limitado on-path é um atacante off-path que ofereceu roteamento melhorado de pacotes ao duplicar e encaminhar pacotes originais entre o servidor e o cliente, fazendo com que esses pacotes cheguem antes das cópias originais de modo que os pacotes originais sejam descartados pelo endpoint de destino.

Um atacante limitado no caminho difere de um atacante no caminho pelo fato de não estar no caminho original entre os endpoints, e portanto os pacotes originais enviados por um endpoint ainda estão chegando ao seu destino. Isso significa que uma futura falha em rotear pacotes copiados para o destino mais rapidamente que o seu caminho original não impedirá que os pacotes originais cheguem ao destino.

Um atacante limitado no caminho pode:

  • Inspecionar pacotes

  • Injetar novos pacotes

  • Modificar cabeçalhos de pacotes não criptografados

  • Reordenar pacotes

Um atacante limitado no caminho não pode:

  • Atrasar pacotes para que cheguem mais tarde do que os pacotes enviados no caminho original

  • Descartar pacotes

  • Modificar a porção autenticada e criptografada de um pacote e fazer com que o destinatário aceite esse pacote

Um atacante on-path limitado pode apenas atrasar pacotes até o ponto em que os pacotes originais chegem antes dos pacotes duplicados, significando que não pode oferecer roteamento com latência pior que o caminho original. Se um atacante on-path limitado descartar pacotes, a cópia original ainda chegará ao endpoint de destino.

QUIC visa restringir as capacidades de um atacante off-path limitado da seguinte forma:

  1. Um atacante limitado on-path não pode causar o fechamento de uma conexão uma vez que o handshake tenha sido completado.

  2. Um atacante limitado no caminho não pode causar o fechamento de uma conexão inativa se o cliente for o primeiro a retomar a atividade.

  3. Um atacante limitado no caminho pode fazer com que uma conexão inativa seja considerada perdida se o servidor for o primeiro a retomar a atividade.

Note que essas garantias são as mesmas garantias fornecidas para qualquer NAT, pelas mesmas razões.

Handshake

Como um transporte criptografado e autenticado, QUIC oferece uma gama de proteções contra negação de serviço. Uma vez que o handshake criptográfico esteja completo, os endpoints QUIC descartam a maioria dos pacotes que não são autenticados, limitando significativamente a capacidade de um atacante interferir com conexões existentes.

Uma vez estabelecida uma conexão, os endpoints QUIC podem aceitar alguns pacotes ICMP não autenticados (ver Seção 14.2.1), mas o uso desses pacotes é extremamente limitado. O único outro tipo de pacote que um endpoint pode aceitar é um reset sem estado (Seção 10.3), que depende do token ser mantido em segredo até ser usado.

Durante a criação de uma conexão, o QUIC apenas fornece proteção contra ataques de fora do caminho da rede. Todos os pacotes QUIC contêm prova de que o destinatário viu um pacote precedente de seu par.

Os endereços não podem mudar durante o handshake, então os endpoints podem descartar pacotes que são recebidos em um caminho de rede diferente.

Os campos Source and Destination Connection ID são o principal meio de proteção contra um ataque off-path durante o handshake; veja a Seção 8.1. É necessário que estes correspondam aos definidos por um peer. Exceto para Initial e Stateless Resets, um endpoint apenas aceita pacotes que incluam um campo Destination Connection ID que corresponda a um valor que o endpoint escolheu anteriormente. Esta é a única proteção oferecida para pacotes Version Negotiation.

O campo Destination Connection ID em um pacote Initial é selecionado por um cliente para ser imprevisível, o que serve a um propósito adicional. Os pacotes que transportam o handshake criptográfico são protegidos com uma chave derivada deste connection ID e um salt específico para a versão QUIC. Isso permite que os endpoints usem o mesmo processo para autenticar pacotes que recebem como usam após a conclusão do handshake criptográfico. Pacotes que não podem ser autenticados são descartados. Proteger pacotes desta forma fornece uma forte garantia de que o remetente do pacote viu o pacote Initial e o compreendeu.

Essas proteções não são destinadas a serem eficazes contra um atacante que seja capaz de receber pacotes QUIC antes da conexão ser estabelecida. Tal atacante pode potencialmente enviar pacotes que serão aceitos pelos endpoints QUIC. Esta versão do QUIC tenta detectar esse tipo de ataque, mas espera que os endpoints falhem ao estabelecer uma conexão ao invés de se recuperarem. Em sua maior parte, o protocolo de handshake criptográfico QUIC-TLS é responsável por detectar adulteração durante o handshake.

Os endpoints têm permissão para usar outros métodos para detectar e tentar recuperar-se de interferência com o handshake. Pacotes inválidos podem ser identificados e descartados usando outros métodos, mas nenhum método específico é exigido neste documento.

Anti-Amplificação

Um atacante pode ser capaz de receber um token de validação de endereço (Seção 8) de um servidor e então liberar o endereço IP que usou para adquirir esse token. Em um momento posterior, o atacante pode iniciar uma conexão 0-RTT com um servidor falsificando esse mesmo endereço, que agora pode endereçar um endpoint diferente (vítima). O atacante pode assim potencialmente fazer com que o servidor envie uma quantidade de dados equivalente à janela de congestionamento inicial em direção à vítima.

Os servidores DEVEM fornecer mitigações para este ataque limitando o uso e o tempo de vida dos tokens de validação de endereço; veja a Seção 8.1.3.

DoS do Lado do Servidor

Um endpoint que confirma pacotes que não recebeu pode fazer com que um controlador de congestionamento permita o envio em taxas além do que a rede suporta. Um endpoint PODE pular números de pacotes ao enviar pacotes para detectar esse comportamento. Um endpoint pode então imediatamente fechar a conexão com um erro de conexão do tipo PROTOCOL_VIOLATION; veja a Seção 10.2.

Terminação de Handshake On-Path

Um ataque de falsificação de requisição ocorre quando um endpoint faz com que seu par emita uma requisição direcionada a uma vítima, com a requisição controlada pelo endpoint. Ataques de falsificação de requisição visam fornecer a um atacante acesso às capacidades de seu par que poderiam estar indisponíveis para o atacante de outra forma. Para um protocolo de rede, um ataque de falsificação de requisição é frequentemente usado para explorar qualquer autorização implícita conferida ao par pela vítima devido à localização do par na rede.

Para que a falsificação de solicitação seja eficaz, um atacante precisa ser capaz de influenciar quais pacotes o peer envia e para onde esses pacotes são enviados. Se um atacante puder direcionar um serviço vulnerável com uma carga útil controlada, esse serviço pode realizar ações que são atribuídas ao peer do atacante, mas são decididas pelo atacante.

Por exemplo, explorações de falsificação de solicitação entre sites CSRF na Web fazem com que um cliente emita solicitações que incluem cookies de autorização COOKIE, permitindo que um site acesse informações e ações que devem ser restritas a um site diferente.

Como o QUIC funciona sobre UDP, a modalidade de ataque principal de preocupação é aquela onde um atacante pode selecionar o endereço para o qual seu par envia datagramas UDP e pode controlar parte do conteúdo desprotegido desses pacotes. Como muito dos dados enviados pelos endpoints QUIC são protegidos, isso inclui controle sobre texto cifrado. Um ataque é bem-sucedido se um atacante conseguir fazer com que um par envie um datagrama UDP para um host que realizará alguma ação baseada no conteúdo do datagrama.

Esta seção discute maneiras pelas quais QUIC pode ser usado para ataques de falsificação de solicitações.

Esta seção também descreve contramedidas limitadas que podem ser implementadas por endpoints QUIC. Essas mitigações podem ser empregadas unilateralmente por uma implementação ou implantação QUIC, sem que os alvos potenciais para ataques de falsificação de solicitações precisem tomar ação. No entanto, essas contramedidas podem ser insuficientes se os serviços baseados em UDP não autorizarem adequadamente as solicitações.

Porque o ataque de migração descrito na Seção 21.5.4 é bastante poderoso e não possui contramedidas adequadas, as implementações de servidor QUIC devem assumir que atacantes podem fazer com que elas gerem payloads UDP arbitrários para destinos arbitrários. Servidores QUIC NÃO DEVEM ser implantados em redes que não implementem filtragem de entrada BCP38 e também tenham endpoints UDP inadequadamente protegidos.

Embora geralmente não seja possível garantir que os clientes não estejam colocalizados com endpoints vulneráveis, esta versão do QUIC não permite que servidores migrem, impedindo assim ataques de migração falsificada contra clientes. Qualquer extensão futura que permita migração de servidor DEVE também definir contramedidas para ataques de falsificação.

Negociação de Parâmetros

QUIC oferece algumas oportunidades para um atacante influenciar ou controlar onde seu peer envia datagramas UDP:

  • estabelecimento de conexão inicial (Seção 7), onde um servidor é capaz de escolher onde um cliente envia datagramas – por exemplo, ao popular registros DNS;

  • endereços preferenciais (Seção 9.6), onde um servidor é capaz de escolher onde um cliente envia datagramas;

  • migrações de conexão falsificadas (Seção 9.3.1), onde um cliente é capaz de usar spoofing de endereço de origem para selecionar onde um servidor envia datagramas subsequentes; e

  • pacotes falsificados que fazem com que um servidor envie um pacote de Negociação de Versão (Seção 21.5.5).

Em todos os casos, o atacante pode fazer com que seu par envie datagramas para uma vítima que pode não entender QUIC. Ou seja, esses pacotes são enviados pelo par antes da validação do endereço; veja a Seção 8.

Fora da porção criptografada dos pacotes, o QUIC oferece a um endpoint várias opções para controlar o conteúdo dos datagramas UDP que seu peer envia. O campo Destination Connection ID oferece controle direto sobre bytes que aparecem no início dos pacotes enviados pelo peer; veja a Seção 5.1. O campo Token nos pacotes Initial oferece ao servidor controle sobre outros bytes dos pacotes Initial; veja a Seção 17.2.2.

Não há medidas nesta versão do QUIC para prevenir controle indireto sobre as porções criptografadas dos pacotes. É necessário assumir que os endpoints são capazes de controlar o conteúdo dos frames que um peer envia, especialmente aqueles frames que transportam dados de aplicação, como frames STREAM. Embora isso dependa em algum grau dos detalhes do protocolo da aplicação, algum controle é possível em muitos contextos de uso de protocolo. Como o atacante tem acesso às chaves de proteção de pacotes, é provável que seja capaz de prever como um peer irá criptografar pacotes futuros. Controle bem-sucedido sobre o conteúdo do datagrama então requer apenas que o atacante seja capaz de prever o número do pacote e a colocação de frames em pacotes com alguma quantidade de confiabilidade.

Esta seção assume que limitar o controle sobre o conteúdo do datagrama não é viável. O foco das mitigações nas seções subsequentes está em limitar as maneiras pelas quais os datagramas enviados antes da validação de endereço podem ser usados para falsificação de solicitação.

Pacotes Protegidos

Um atacante atuando como servidor pode escolher o endereço IP e a porta na qual anuncia sua disponibilidade, então pacotes Initial de clientes são considerados disponíveis para uso neste tipo de ataque. A validação de endereço implícita no handshake garante que – para uma nova conexão – um cliente não enviará outros tipos de pacotes para um destino que não entende QUIC ou não está disposto a aceitar uma conexão QUIC.

A proteção inicial de pacotes (Seção 5.2 de QUIC-TLS) torna difícil para os servidores controlar o conteúdo dos pacotes Initial enviados pelos clientes. Um cliente que escolhe um Destination Connection ID imprevisível garante que os servidores sejam incapazes de controlar qualquer parte da porção criptografada dos pacotes Initial dos clientes.

No entanto, o campo Token está aberto ao controle do servidor e permite que um servidor use clientes para montar ataques de falsificação de solicitação. O uso de tokens fornecidos com o frame NEW_TOKEN (Seção 8.1.3) oferece a única opção para falsificação de solicitação durante o estabelecimento da conexão.

Os clientes, no entanto, não são obrigados a usar o frame NEW_TOKEN. Ataques de falsificação de requisição que dependem do campo Token podem ser evitados se os clientes enviarem um campo Token vazio quando o endereço do servidor tiver mudado desde quando o frame NEW_TOKEN foi recebido.

Os clientes poderiam evitar usar NEW_TOKEN se o endereço do servidor mudar. No entanto, não incluir um campo Token poderia afetar adversamente o desempenho. Os servidores poderiam depender do NEW_TOKEN para permitir o envio de dados que excedam o limite de três vezes no envio de dados; consulte a Seção 8.1. Em particular, isso afeta casos onde os clientes usam 0-RTT para solicitar dados dos servidores.

Enviar um pacote Retry (Seção 17.2.5) oferece ao servidor a opção de alterar o campo Token. Após enviar um Retry, o servidor também pode controlar o campo Destination Connection ID de pacotes Initial subsequentes do cliente. Isso também pode permitir controle indireto sobre o conteúdo criptografado de pacotes Initial. No entanto, a troca de um pacote Retry valida o endereço do servidor, impedindo assim o uso de pacotes Initial subsequentes para falsificação de solicitações.

Migração de Conexão

Os servidores podem especificar um endereço preferencial, para o qual os clientes migram após confirmar o handshake; veja a Seção 9.6. O campo Destination Connection ID dos pacotes que o cliente envia para um endereço preferencial pode ser usado para falsificação de requisições.

Um cliente NÃO DEVE enviar frames não-probing para um endereço preferido antes de validar esse endereço; veja Seção 8. Isso reduz drasticamente as opções que um servidor tem para controlar a porção criptografada dos datagramas.

Este documento não oferece nenhuma contramedida adicional que seja específica ao uso de endereços preferenciais e possa ser implementada por endpoints. As medidas genéricas descritas na Seção 21.5.6 podem ser usadas como mitigação adicional.

Ataques Ativos no Caminho

Os clientes podem apresentar um endereço de origem falsificado como parte de uma migração de conexão aparente para fazer com que um servidor envie datagramas para esse endereço.

O campo Destination Connection ID em quaisquer pacotes que um servidor subsequentemente envie para este endereço falsificado pode ser usado para falsificação de solicitação. Um cliente também pode ser capaz de influenciar o texto cifrado.

Um servidor que apenas envia pacotes de sondagem (Seção 9.1) para um endereço antes da validação do endereço fornece a um atacante apenas controle limitado sobre a porção criptografada dos datagramas. No entanto, particularmente para NAT rebinding, isso pode afetar adversamente o desempenho. Se o servidor envia quadros carregando dados de aplicação, um atacante pode ser capaz de controlar a maior parte do conteúdo dos datagramas.

Este documento não oferece contramedidas específicas que possam ser implementadas por endpoints, além das medidas genéricas descritas na Seção 21.5.6. No entanto, contramedidas para spoofing de endereços ao nível da rede – em particular, filtragem de ingresso BCP38 – são especialmente eficazes contra ataques que usam spoofing e se originam de uma rede externa.

Ataques Ativos Fora do Caminho

Clientes que conseguem apresentar um endereço de origem falsificado num pacote podem fazer com que um servidor envie um pacote de Negociação de Versão (Seção 17.2.1) para esse endereço.

A ausência de restrições de tamanho nos campos de ID de conexão para pacotes de uma versão desconhecida aumenta a quantidade de dados que o cliente controla do datagrama resultante. O primeiro byte deste pacote não está sob controle do cliente e os próximos quatro bytes são zero, mas o cliente consegue controlar até 512 bytes a partir do quinto byte.

Nenhuma contramedida específica é fornecida para este ataque, embora proteções genéricas (Seção 21.5.6) possam se aplicar. Neste caso, a filtragem de entrada BCP38 também é eficaz.

Ataques Ativos Limitados no Caminho

A defesa mais eficaz contra ataques de falsificação de solicitação é modificar serviços vulneráveis para usar autenticação forte. No entanto, isso nem sempre está sob o controle de uma implantação QUIC. Esta seção descreve algumas outras medidas que os endpoints QUIC poderiam tomar unilateralmente. Essas medidas adicionais são todas discricionárias porque, dependendo das circunstâncias, elas poderiam interferir ou impedir usos legítimos.

Serviços oferecidos sobre interfaces loopback frequentemente carecem de autenticação adequada. Endpoints PODEM prevenir tentativas de conexão ou migração para um endereço loopback. Endpoints NÃO DEVEM permitir conexões ou migração para um endereço loopback se o mesmo serviço estava previamente disponível em uma interface diferente ou se o endereço foi fornecido por um serviço em um endereço não-loopback. Endpoints que dependem dessas capacidades poderiam oferecer uma opção para desabilitar essas proteções.

Da mesma forma, os endpoints poderiam considerar uma mudança de endereço para um endereço link-local RFC4291 ou um endereço em uma faixa de uso privado RFC1918 a partir de um endereço global, unique-local RFC4193, ou não-privado como uma possível tentativa de falsificação de requisição. Os endpoints poderiam se recusar a usar esses endereços inteiramente, mas isso carrega um risco significativo de interferir com usos legítimos. Os endpoints NÃO DEVEM se recusar a usar um endereço a menos que tenham conhecimento específico sobre a rede indicando que enviar datagramas para endereços não validados em uma determinada faixa não é seguro.

Os endpoints PODEM escolher reduzir o risco de falsificação de solicitação não incluindo valores de frames NEW_TOKEN em pacotes Initial ou enviando apenas frames de sondagem em pacotes antes de completar a validação de endereço. Note que isso não impede que um atacante use o campo Destination Connection ID para um ataque.

Os endpoints não devem ter informações específicas sobre a localização de servidores que possam ser alvos vulneráveis de um ataque de falsificação de solicitação. No entanto, pode ser possível ao longo do tempo identificar portas UDP específicas que são alvos comuns de ataques ou padrões específicos em datagramas que são usados para ataques. Os endpoints PODEM escolher evitar o envio de datagramas para essas portas ou não enviar datagramas que correspondam a esses padrões antes de validar o endereço de destino. Os endpoints PODEM descartar IDs de conexão contendo padrões conhecidos como problemáticos sem usá-los.

Nota: Modificar endpoints para aplicar essas proteções é mais eficiente do que implementar proteções baseadas em rede, pois os endpoints não precisam realizar processamento adicional ao enviar para um endereço que foi validado.

Negação de Serviço por Handshake

Os ataques comumente conhecidos como Slowloris SLOWLORIS tentam manter muitas conexões abertas para o endpoint de destino e mantê-las abertas pelo maior tempo possível. Esses ataques podem ser executados contra um endpoint QUIC gerando a quantidade mínima de atividade necessária para evitar ser fechado por inatividade. Isso pode envolver o envio de pequenas quantidades de dados, abertura gradual de janelas de controle de fluxo para controlar a taxa do remetente, ou fabricação de quadros ACK que simulam uma alta taxa de perda.

Implementações QUIC DEVEM fornecer mitigações para ataques Slowloris, como aumentar o número máximo de clientes que o servidor permitirá, limitar o número de conexões que um único endereço IP pode fazer, impor restrições na velocidade mínima de transferência que uma conexão pode ter, e restringir o tempo que um endpoint pode permanecer conectado.

Ataque de Amplificação

Um remetente adversário pode intencionalmente não enviar partes dos dados do stream, fazendo com que o receptor comprometa recursos para os dados não enviados. Isso pode causar um comprometimento desproporcional de memória do buffer de recepção e/ou a criação de uma estrutura de dados grande e ineficiente no receptor.

Um receptor adversarial pode intencionalmente não reconhecer pacotes contendo dados de stream numa tentativa de forçar o remetente a armazenar os dados de stream não reconhecidos para retransmissão.

O ataque aos receptores é mitigado se as janelas de controle de fluxo correspondem à memória disponível. No entanto, alguns receptores irão comprometer excessivamente a memória e anunciar offsets de controle de fluxo no agregado que excedem a memória real disponível. A estratégia de overcommitment pode levar a melhor performance quando os endpoints se comportam adequadamente, mas torna os endpoints vulneráveis ao ataque de fragmentação de stream.

As implementações QUIC DEVEM fornecer mitigações para ataques de fragmentação de fluxo. As mitigações podem consistir em evitar o comprometimento excessivo de memória, limitar o tamanho das estruturas de dados de rastreamento, atrasar a remontagem de frames STREAM, implementar heurísticas baseadas na idade e duração dos buracos de remontagem, ou alguma combinação dessas.

Ataque de ACK Otimista

Um endpoint adversário pode abrir um grande número de streams, esgotando o estado em um endpoint. O endpoint adversário pode repetir o processo em um grande número de conexões, de maneira similar aos ataques de SYN flooding no TCP.

Normalmente, os clientes abrirão streams sequencialmente, conforme explicado na Seção 2.1. No entanto, quando vários streams são iniciados em intervalos curtos, perda ou reordenação pode fazer com que frames STREAM que abrem streams sejam recebidos fora de sequência. Ao receber um ID de stream de número mais alto, um receptor é obrigatório a abrir todos os streams intermediários do mesmo tipo; veja Seção 3.2. Assim, em uma nova conexão, abrir o stream 4000000 abre 1 milhão e 1 streams bidirecionais iniciados pelo cliente.

O número de streams ativos é limitado pelos parâmetros de transporte initial_max_streams_bidi e initial_max_streams_uni conforme atualizados por quaisquer frames MAX_STREAMS recebidos, como explicado na Seção 4.6. Se escolhidos criteriosamente, esses limites mitigam o efeito do ataque de comprometimento de stream. No entanto, definir o limite muito baixo pode afetar o desempenho quando as aplicações esperam abrir um grande número de streams.

Ataques de Falsificação de Solicitação

QUIC e TLS contêm frames ou mensagens que têm usos legítimos em alguns contextos, mas esses frames ou mensagens podem ser abusados para fazer com que um peer gaste recursos de processamento sem ter qualquer impacto observável no estado da conexão.

As mensagens também podem ser usadas para alterar e reverter o estado de maneiras pequenas ou irrelevantes, como enviando pequenos incrementos para limites de controle de fluxo.

Se os custos de processamento forem desproporcionalmente grandes em comparação ao consumo de largura de banda ou efeito no estado, então isso poderia permitir que um peer malicioso esgote a capacidade de processamento.

Embora existam usos legítimos para todas as mensagens, as implementações DEVEM rastrear o custo de processamento relativo ao progresso e tratar quantidades excessivas de quaisquer pacotes não produtivos como indicativo de um ataque. Os endpoints PODEM responder a essa condição com um erro de conexão ou descartando pacotes.

Opções de Controle para Endpoints

Um atacante no caminho da rede poderia manipular o valor dos campos ECN no cabeçalho IP para influenciar a taxa do remetente. RFC3168 discute manipulações e seus efeitos com mais detalhes.

Um atacante limitado no caminho pode duplicar e enviar pacotes com campos ECN modificados para afetar a taxa do remetente. Se pacotes duplicados forem descartados por um receptor, um atacante precisará competir com o pacote duplicado contra o original para ter sucesso neste ataque. Portanto, endpoints QUIC ignoram o campo ECN em um pacote IP, a menos que pelo menos um pacote QUIC nesse pacote IP seja processado com sucesso; veja Seção 13.4.

Falsificação de Solicitação com Pacotes Iniciais do Cliente

Resets sem estado criam um possível ataque de negação de serviço análogo a uma injeção de reset TCP. Este ataque é possível se um atacante conseguir fazer com que um token de reset sem estado seja gerado para uma conexão com um ID de conexão selecionado. Um atacante que conseguir fazer com que este token seja gerado pode resetar uma conexão ativa com o mesmo ID de conexão.

Se um pacote puder ser roteado para diferentes instâncias que compartilham uma chave estática – por exemplo, alterando um endereço IP ou porta – então um atacante pode fazer com que o servidor envie um reset sem estado. Para se defender contra esse tipo de negação de serviço, endpoints que compartilham uma chave estática para resets sem estado (veja Seção 10.3.2) DEVEM ser organizados de forma que pacotes com um determinado ID de conexão sempre cheguem a uma instância que possui estado de conexão, a menos que essa conexão não esteja mais ativa.

Mais genericamente, servidores NÃO DEVEM gerar um reset sem estado se uma conexão com o ID de conexão correspondente puder estar ativa em qualquer endpoint usando a mesma chave estática.

No caso de um cluster que usa balanceamento de carga dinâmico, é possível que uma mudança na configuração do balanceador de carga possa ocorrer enquanto uma instância ativa mantém o estado da conexão. Mesmo que uma instância mantenha o estado da conexão, a mudança no roteamento e o reset sem estado resultante farão com que a conexão seja terminada. Se não há chance do pacote ser roteado para a instância correta, é melhor enviar um reset sem estado do que aguardar o timeout da conexão. No entanto, isso é aceitável apenas se o roteamento não puder ser influenciado por um atacante.

Falsificação de Solicitação com Endereços Preferenciais

Este documento define pacotes de Negociação de Versão QUIC (Seção 6), que podem ser usados para negociar a versão QUIC utilizada entre dois endpoints. No entanto, este documento não especifica como essa negociação será realizada entre esta versão e versões futuras subsequentes. Em particular, pacotes de Negociação de Versão não contêm nenhum mecanismo para prevenir ataques de downgrade de versão. Versões futuras do QUIC que usem pacotes de Negociação de Versão DEVEM definir um mecanismo que seja robusto contra ataques de downgrade de versão.

Falsificação de Solicitação com Migração Falsificada

As implantações devem limitar a capacidade de um atacante de direcionar uma nova conexão para uma instância de servidor específica. Idealmente, as decisões de roteamento são tomadas independentemente dos valores selecionados pelo cliente, incluindo endereços. Uma vez que uma instância é selecionada, um ID de conexão pode ser selecionado para que pacotes posteriores sejam roteados para a mesma instância.

Falsificação de Requisição com Negociação de Versão

O comprimento dos pacotes QUIC pode revelar informações sobre o comprimento do conteúdo desses pacotes. O frame PADDING é fornecido para que os endpoints tenham alguma capacidade de obscurecer o comprimento do conteúdo do pacote; veja a Seção 19.1.

Derrotar a análise de tráfego é desafiador e objeto de pesquisa ativa. O comprimento não é a única maneira pela qual informações podem vazar. Os endpoints também podem revelar informações sensíveis através de outros canais laterais, como o tempo dos pacotes.

Relay Security

A seguir está uma análise de Relay Request, Relay Response, Relay Intro, e Hole Punch no SSU1.

Restrições: É importante que os Relays sejam rápidos. Os round trips devem ser minimizados. Largura de banda e CPU não são tão importantes.

SSU 1: Alice primeiro conecta ao introducer Bob, que retransmite a solicitação para Charlie (que está atrás de firewall). Após o hole punch, a sessão é estabelecida entre Alice e Charlie como em um estabelecimento direto.

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

Autenticação: Relay Request e Relay Response não são autenticados de forma segura, pois Alice e Bob geralmente não possuem uma sessão existente; essas mensagens usam chaves de introdução publicadas. Relay Request/Response em sessão é permitido e preferido se uma sessão existir.

O Relay Intro de Bob para Charlie é obrigatório estar numa sessão existente, portanto presume-se que seja seguro.

Bob pode falsificar Relay Intros ou alterar IP/porta do Relay Request. Não há mecanismos para vincular criptograficamente solicitações a intros ou para prevenir ou detectar Bobs maliciosos.

O hash do router do Bob não está atualmente publicado no Router Info do Charlie, então isso deve ser adicionado se quisermos que as mensagens Alice-Bob sejam autenticadas. Adicionalmente, outros parâmetros SSU2 teriam que ser publicados no Router Info do Charlie, ou Alice teria que procurar o Router Info do Bob no netDb, adicionando atraso adicional. A autenticação adicionaria uma ida e volta entre Alice e Bob.

Ao encaminhar o hash do router da Alice para o Charlie, Charlie poderia determinar mais facilmente se deseja receber uma conexão da Alice, verificando uma lista de banimentos local. Não há mecanismo para o Charlie rejeitar o relay enviando uma rejeição através do Bob para a Alice. Não há mecanismo para o Charlie aceitar o relay enviando uma aceitação através do Bob para a Alice. A Alice deve aguardar o HolePunch, ou simplesmente enviar o SessionRequest às cegas. O HolePunch pode vir de uma porta diferente da que a Alice esperava, devido ao NAT, o que pode tornar mais difícil reconhecer de qual router o HolePunch veio.

Alice poderia enviar sua Router Info completa na Relay Request para Bob, e encaminhada para Charlie na Relay Intro.

A Relay Request não contém um timestamp, portanto não possui prevenção contra replay. O IP de origem pode ser falsificado, fazendo com que Charlie envie um Hole Punch para qualquer IP/porta. A Relay Request não é assinada, e mesmo se fosse assinada e tivesse timestamp, Charlie não possui a Router Identity completa para conseguir verificar a assinatura.

O protocolo define um campo de desafio de comprimento variável de 0-255 bytes. O desafio no Relay Request é passado para Charlie no Relay Intro. No entanto, o protocolo não especifica como criar, usar ou verificar o desafio, e não está implementado. Se o HolePunch contivesse o desafio, Alice seria capaz de correlacionar facilmente o HolePunch com Charlie.

O nonce de quatro bytes pode precisar ser substituído ou complementado por um ID de conexão de 8 bytes.

A mensagem vazia de Hole Punch é única e pode ser usada por observadores no caminho para identificar o protocolo, isso deve ser alterado.

Discussão Adicional sobre DPI

Segue uma análise do Peer Test no SSU1.

Restrições: Não é particularmente importante que os Testes de Pares sejam rápidos, ou de baixa largura de banda, ou de baixo consumo de CPU, exceto talvez na inicialização do router, onde preferimos que o router descubra sua acessibilidade de forma relativamente rápida.

SSU 1:

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

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

Como a especificação do SSU1 é difícil de seguir, documentamos o conteúdo das mensagens abaixo.

MessagePathAlice IP incl?Intro Key
1A->B sessionnoAlice
2B->C sessionyesAlice
3C->B sessionyesCharlie
4B->A sessionyesCharlie
5C->AyesCharlie
6A->CnoAlice
7C->AyesCharlie
Autenticação: Alice sempre escolherá um Bob com uma sessão existente. Bob rejeitará PeerTests de peers sem uma sessão estabelecida. A mensagem 1 é enviada dentro da sessão. Portanto, a mensagem 1 é segura e autenticada.

Bob seleciona um Charlie com quem ele tem uma sessão existente. As mensagens 2 e 3 são enviadas dentro da sessão. Portanto, as mensagens 2 e 3 são seguras e autenticadas.

A Mensagem 4 deve ser enviada in-session; no entanto, a especificação SSU 1 anteriormente dizia que ela é enviada com a chave de introdução publicada da Alice, o que significa não in-session. Antes da versão 0.9.52, o Java I2P enviava com a chave de introdução. A partir da versão 0.9.52, a especificação estabelece que a chave de sessão deve ser usada, e o Java I2P envia a mensagem in-session a partir da versão 0.9.52.

Alice não deve ter uma sessão existente com Charlie para que o teste prossiga; Alice aborta o teste se Bob escolher um Charlie que tenha uma sessão com Alice. Portanto, as mensagens 5-7 não são seguras e autenticadas.

Todas as mensagens de Peer Test contêm um nonce de 4 bytes que é escolhido pela Alice. Este nonce não é usado criptograficamente.

Ataques possíveis nas mensagens 5-7: a ser pesquisado.

O hash do router da Alice não é conhecido pelo Charlie. O hash do router do Charlie não é conhecido pela Alice. Esses devem ser adicionados ao protocolo se quisermos que as mensagens Alice-Charlie sejam autenticadas. Além disso, outros parâmetros SSU2 teriam que ser fornecidos nas mensagens do Peer Test, ou Charlie teria que buscar as Router Info da Alice na base de dados da rede, adicionando atraso adicional. A autenticação adicionaria uma ida e volta entre Charlie e Alice.

Ao encaminhar o hash do router da Alice para Charlie, Charlie poderia determinar mais facilmente se deseja participar de um Peer Test com Alice, verificando uma lista de banimentos local.

O nonce de quatro bytes pode precisar ser substituído ou complementado por um ID de conexão de 8 bytes.

Relay and Peer Test Design Goals

O Relay e o Peer Test têm construções similares. Em ambos os casos, Alice solicita que Bob encaminhe uma requisição de serviço para Charlie, e Charlie então atua sobre essa requisição.

Problemas atuais do Teste de Peer SSU1:

  • O Peer Test não tem proteções contra um Bob malicioso
  • O Peer Test não tem maneira de Bob ou Charlie rejeitarem uma solicitação
  • O Peer Test não tem maneira de Alice conhecer a identidade de Charlie ou de Alice rejeitar um Charlie
  • O Peer Test não tem maneira de Charlie conhecer a identidade de Alice ou de Charlie rejeitar uma Alice
  • O Peer Test tem seu próprio esquema de retransmissão ad-hoc
  • O Peer Test requer uma máquina de estados complexa para saber qual mensagem é para qual estado
  • Sem saber que Charlie a rejeitou, Alice tratará o teste como uma falha.

Problemas atuais do SSU1 Relay:

A maioria dos problemas de Peer Test listados acima também se aplicam ao Peer Test.

Temos os seguintes objetivos para melhorar a segurança do Relay e Peer Test:

  • Charlie deve publicar informações suficientes sobre seus introdutores (Bobs) no netDb para que Alice possa validar as informações se necessário. Por exemplo, publicar um hash de roteador para cada introdutor permitiria que Alice, tempo permitindo, buscasse as informações do roteador no netDb.

  • Proteger contra falsificação de endereços ou ameaças no caminho que podem falsificar, alterar, forjar ou repetir solicitações de Alice para Bob. Bob deve garantir que Alice é um router I2P real e que o endereço de solicitação e teste apresentado são válidos.

  • Proteger contra Bobs maliciosos que possam falsificar, alterar, forjar, ou reproduzir solicitações encaminhadas para Charlie. Charlie deve garantir que tanto Alice quanto Bob são routers I2P reais e que a solicitação e endereço de teste apresentados são válidos.

  • Bob deve receber informações suficientes de Alice para poder validar a solicitação e então aceitá-la ou recusá-la. Bob deve ter um mecanismo para enviar a aceitação ou rejeição de volta para Alice. Bob nunca deve ser obrigado a executar a ação solicitada.

  • Charlie deve receber informações suficientes de Bob para poder validar a solicitação e então aceitá-la ou recusá-la. Charlie deve ter um mecanismo para enviar a aceitação ou rejeição de volta para Bob, para ser encaminhada para Alice. Charlie nunca deve ser obrigado a realizar a ação solicitada.

  • Alice deve ser capaz de validar que a resposta encaminhada via Bob realmente se originou de Charlie.

  • Alice e Charlie devem ser capazes de validar que suas mensagens diretas subsequentes (não retransmitidas via Bob) são da fonte esperada e são routers I2P reais.

Os seguintes mecanismos podem auxiliar no alcance desses objetivos:

  • Timestamps

  • Assinaturas usando a chave de assinatura do router

  • Usando dados de desafio incluídos na solicitação

  • Criptografia usando a chave de criptografia do router

  • Enviando hashes de router, Router Identities, ou Router Infos, não apenas IPs e portas.

  • Validação de informações do router consultando a base de dados da rede

  • Verificando informações do router, IPs e portas contra listas de bloqueio

  • Limitação de taxa

  • Exigindo estabelecimento de sessão

Esses possíveis mecanismos podem aumentar o tempo de processamento e latência das funções Relay ou Peer Test. Todos os efeitos devem ser avaliados.

O relaying entre versões e teste de peers também devem ser suportados se possível. Isso facilitará uma transição gradual do SSU 1 para o SSU 2. As combinações de versão possíveis são:

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 Segurança

Summary

Contamos com vários protocolos existentes, tanto dentro do I2P quanto de padrões externos, para inspiração, orientação e reutilização de código:

  • Modelos de ameaça: Do NTCP2 NTCP2, com ameaças adicionais significativas relevantes ao transporte UDP conforme analisado pelo QUIC RFC 9000 RFC 9001.

  • Escolhas criptográficas: De NTCP2.

  • Handshake: Noise XK do NTCP2 e NOISE. Simplificações significativas para o NTCP2 são possíveis devido ao encapsulamento (limites de mensagem inerentes) fornecido pelo UDP.

  • Ofuscação de chave efêmera do handshake: Adaptado do NTCP2 mas usando ChaCha20 do ECIES em vez de AES.

  • Cabeçalhos de pacote: Adaptado do WireGuard WireGuard e QUIC RFC 9000 RFC 9001.

  • Ofuscação do cabeçalho de pacote: Adaptado do NTCP2 mas usando ChaCha20 do ECIES em vez de AES.

  • Proteção de cabeçalho de pacote: Adaptado do QUIC RFC 9001 e Nonces

  • Cabeçalhos usados como dados associados AEAD como em ECIES.

  • Numeração de pacotes: Adaptada do WireGuard WireGuard e QUIC RFC 9000 RFC 9001.

  • Mensagens: Adaptado de SSU

  • Fragmentação I2NP: Adaptado de SSU

  • Relay e Peer Testing: Adaptado de SSU

  • Assinaturas de dados de Relay e Peer Test: Da especificação de estruturas comuns Common

  • Formato de bloco: De NTCP2 e ECIES.

  • Padding e opções: De NTCP2 e ECIES.

  • Acks, nacks: Adaptado do QUIC RFC 9000.

  • Controle de fluxo: TBD

Não há primitivas criptográficas novas que não tenham sido usadas no I2P antes.

Validação de Endereço

Assim como outros transportes I2P NTCP, NTCP2 e SSU 1, este transporte não é uma facilidade de propósito geral para entrega de um fluxo ordenado de bytes. Ele foi projetado para o transporte de mensagens I2NP. Não há abstração de “fluxo” fornecida.

Além disso, assim como o SSU, contém recursos adicionais para travessia de NAT facilitada por peers e teste de acessibilidade (conexões de entrada).

Quanto ao SSU 1, ele NÃO fornece entrega ordenada de mensagens I2NP. Nem fornece entrega garantida de mensagens I2NP. Por eficiência, ou devido à entrega fora de ordem de datagramas UDP ou perda desses datagramas, mensagens I2NP podem ser entregues no destino final fora de ordem, ou podem não ser entregues de forma alguma. Uma mensagem I2NP pode ser retransmitida várias vezes se necessário, mas a entrega pode eventualmente falhar sem causar a desconexão completa da conexão. Além disso, novas mensagens I2NP podem continuar sendo enviadas mesmo enquanto a retransmissão (recuperação de perda) está ocorrendo para outras mensagens I2NP.

Este protocolo NÃO previne completamente a entrega duplicada de mensagens I2NP. O router deve aplicar a expiração I2NP e usar um filtro Bloom ou outro mecanismo baseado no ID da mensagem I2NP. Veja a seção Duplicação de Mensagem I2NP abaixo.

Noise Protocol Framework

Esta proposta fornece os requisitos baseados no Noise Protocol Framework NOISE (Revisão 33, 2017-10-04). O Noise tem propriedades similares ao protocolo Station-To-Station (STS), que é a base para o protocolo SSU. Na terminologia do Noise, Alice é o iniciador, e Bob é o respondedor.

SSU2 é baseado no protocolo Noise Noise_XK_25519_ChaChaPoly_SHA256. (O identificador real para a função de derivação de chave inicial é “Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256” para indicar extensões I2P - veja a seção KDF 1 abaixo)

NOTA: Este identificador é diferente daquele usado para NTCP2, porque todas as três mensagens de handshake usam o cabeçalho como dados associados.

Este protocolo Noise utiliza as seguintes primitivas:

  • Padrão de Handshake: XK Alice transmite sua chave para Bob (X) Alice já conhece a chave estática de Bob (K)

  • Função DH: X25519 X25519 DH com um comprimento de chave de 32 bytes conforme especificado na RFC 7748.

  • Função de Cifra: ChaChaPoly AEAD_CHACHA20_POLY1305 conforme especificado na RFC 7539 seção 2.8. Nonce de 12 bytes, com os primeiros 4 bytes definidos como zero.

  • Hash Function: SHA256 Hash padrão de 32 bytes, já amplamente utilizado no I2P.

Additions to the Framework

Esta proposta define as seguintes melhorias para Noise_XK_25519_ChaChaPoly_SHA256. Estas geralmente seguem as diretrizes na seção 13 do NOISE.

  1. Mensagens de handshake (Session Request, Created, Confirmed) incluem um cabeçalho de 16 ou 32 bytes.

  2. Os cabeçalhos para as mensagens de handshake (Session Request, Created, Confirmed) são usados como entrada para mixHash() antes da criptografia/descriptografia para vincular os cabeçalhos à mensagem.

  3. Os cabeçalhos são criptografados e protegidos.

  4. Chaves efêmeras em texto claro são ofuscadas com criptografia ChaCha20 usando uma chave e IV conhecidos. Isso é mais rápido que elligator2.

  5. O formato do payload é definido para mensagens 1, 2, e a fase de dados. Claro, isso não está definido no Noise.

A fase de dados usa criptografia similar, mas não compatível com, a fase de dados Noise.

Processing overhead estimate

A definir

Definitions

Definimos as seguintes funções correspondentes aos blocos de construção 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 contém exatamente uma mensagem. O comprimento do datagrama (após os cabeçalhos IP e UDP) é o comprimento da mensagem. Preenchimento, se houver, está contido em um bloco de preenchimento dentro da mensagem. Neste documento, usamos os termos “datagrama” e “pacote” de forma quase intercambiável. Cada datagrama (ou pacote) contém uma única mensagem (diferentemente do QUIC, onde um datagrama pode conter múltiplos pacotes QUIC). O “cabeçalho do pacote” é a parte após o cabeçalho IP/UDP.

Exceção: A mensagem Session Confirmed é única no sentido de que pode ser fragmentada em múltiplos pacotes. Consulte a seção Session Confirmed Fragmentation abaixo para mais informações.

Todas as mensagens SSU2 têm pelo menos 40 bytes de comprimento. Qualquer mensagem com comprimento de 1-39 bytes é inválida. Todas as mensagens SSU2 têm menos ou igual a 1472 (IPv4) ou 1452 (IPv6) bytes de comprimento. O formato da mensagem é baseado em mensagens Noise, com modificações para enquadramento e indistinguibilidade. Implementações que usam bibliotecas Noise padrão devem pré-processar as mensagens recebidas para o formato de mensagem Noise padrão. Todos os campos criptografados são textos cifrados AEAD.

As seguintes mensagens são definidas:

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

Session Establishment

A sequência de estabelecimento padrão, quando Alice possui um token válido previamente recebido de Bob, é a seguinte:

Alice                           Bob

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

Quando Alice não tem um token válido, a sequência de estabelecimento é a seguinte:

Alice                           Bob

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

Quando Alice acredita que tem um token válido, mas Bob o rejeita (talvez porque Bob reiniciou), a sequência de estabelecimento é a seguinte:

Alice                           Bob

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

Bob pode rejeitar uma Session ou Token Request respondendo com uma mensagem Retry contendo um bloco Termination com um código de motivo. Com base no código de motivo, Alice não deve tentar outra solicitação por algum período de tempo:

Alice                           Bob

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

or

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

Usando a terminologia Noise, a sequência de estabelecimento e dados é a seguinte: (Propriedades de Segurança do Payload)

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

Uma vez que uma sessão tenha sido estabelecida, Alice e Bob podem trocar mensagens Data.

Packet Header

Todos os pacotes começam com um cabeçalho ofuscado (criptografado). Existem dois tipos de cabeçalho, longo e curto. Note que os primeiros 13 bytes (ID da Conexão de Destino, número do pacote e tipo) são os mesmos para todos os cabeçalhos.

Contramedidas Genéricas Contra Falsificação de Solicitações

O cabeçalho longo tem 32 bytes. É usado antes de uma sessão ser criada, para Token Request, SessionRequest, SessionCreated e Retry. Também é usado para mensagens Peer Test e Hole Punch fora de sessão.

Antes da criptografia do cabeçalho:


+----+----+----+----+----+----+----+----+
  |      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

O cabeçalho curto tem 16 bytes. É usado para mensagens Session Created e para mensagens de dados. Mensagens não autenticadas como Session Request, Retry e Peer Test sempre usarão o cabeçalho longo.

16 bytes são necessários, porque o receptor deve descriptografar os primeiros 16 bytes para obter o tipo de mensagem, e então deve descriptografar 16 bytes adicionais se for realmente um cabeçalho longo, conforme indicado pelo tipo de mensagem.

Para Session Confirmed, antes da criptografia do cabeçalho:


+----+----+----+----+----+----+----+----+
  |      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 a seção Fragmentação de Sessão Confirmada abaixo para mais informações sobre o campo frag.

Para mensagens de dados, antes da criptografia do cabeçalho:


+----+----+----+----+----+----+----+----+
  |      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 Fragmentação e Remontagem de Stream

Os IDs de conexão devem ser gerados aleatoriamente. Os IDs de origem e destino NÃO devem ser idênticos, para que um atacante no caminho não possa capturar e enviar um pacote de volta ao originador que pareça válido. NÃO use um contador para gerar IDs de conexão, para que um atacante no caminho não possa gerar um pacote que pareça válido.

Ao contrário do QUIC, não alteramos os IDs de conexão durante ou após o handshake, mesmo após uma mensagem de Retry. Os IDs permanecem constantes desde a primeira mensagem (Token Request ou Session Request) até a última mensagem (Data with Termination). Além disso, os IDs de conexão não mudam durante ou após path challenge ou migração de conexão.

Também diferente do QUIC é que os IDs de conexão nos cabeçalhos são sempre criptografados no cabeçalho. Veja abaixo.

Ataque de Comprometimento de Stream

Se nenhum bloco First Packet Number for enviado no handshake, os pacotes são numerados dentro de uma única sessão, para cada direção, começando do 0, até um máximo de (2**32 -1). Uma sessão deve ser encerrada, e uma nova sessão criada, bem antes do número máximo de pacotes ser enviado.

Se um bloco First Packet Number for enviado no handshake, os pacotes são numerados dentro de uma única sessão, para essa direção, começando a partir desse número de pacote. O número do pacote pode dar a volta durante a sessão. Quando um máximo de 2**32 pacotes tiverem sido enviados, fazendo o número do pacote voltar ao primeiro número de pacote, essa sessão não é mais válida. Uma sessão deve ser terminada, e uma nova sessão criada, bem antes do número máximo de pacotes ser enviado.

TODO rotação de chaves, reduzir número máximo de pacotes?

Os pacotes de handshake que são determinados como perdidos são retransmitidos integralmente, com o cabeçalho idêntico incluindo o número do pacote. As mensagens de handshake Session Request, Session Created e Session Confirmed DEVEM ser retransmitidas com o mesmo número de pacote e conteúdo criptografado idêntico, para que o mesmo hash encadeado seja usado para criptografar a resposta. A mensagem Retry nunca é transmitida.

Pacotes da fase de dados que são determinados como perdidos nunca são retransmitidos integralmente (exceto terminação, veja abaixo). O mesmo se aplica aos blocos que estão contidos dentro de pacotes perdidos. Em vez disso, a informação que pode estar contida em blocos é enviada novamente em novos pacotes conforme necessário. Pacotes de Dados nunca são retransmitidos com o mesmo número de pacote. Qualquer retransmissão de conteúdo de pacote (independentemente de o conteúdo permanecer o mesmo ou não) deve usar o próximo número de pacote não utilizado.

Retransmitir um pacote inteiro inalterado como está, com o mesmo número de pacote, não é permitido por várias razões. Para contexto, consulte QUIC RFC 9000 seção 12.3.

  • É ineficiente armazenar pacotes para retransmissão
  • Um novo pacote de dados parece diferente para um observador no caminho, não é possível saber que é retransmitido
  • Um novo pacote recebe um bloco ack atualizado enviado com ele, não o bloco ack antigo
  • Você só retransmite o que é necessário. alguns fragmentos podem já ter sido retransmitidos uma vez e confirmados
  • Você pode ajustar o quanto precisar em cada pacote retransmitido se mais estiver pendente
  • Endpoints que rastreiam todos os pacotes individuais com o propósito de detectar duplicatas estão em risco de acumular estado excessivo. Os dados necessários para detectar duplicatas podem ser limitados mantendo um número mínimo de pacote abaixo do qual todos os pacotes são imediatamente descartados.
  • Este esquema é muito mais flexível

Novos pacotes são usados para transportar informações que foram determinadas como perdidas. Em geral, informações são enviadas novamente quando um pacote contendo essas informações é determinado como perdido, e o envio cessa quando um pacote contendo essas informações é (permanecem iguais) reconhecido.

Exceção: Um pacote de fase de dados contendo um bloco de Terminação pode, mas não é obrigatório, ser retransmitido inteiro, como está. Consulte a seção Terminação de Sessão abaixo.

Os seguintes pacotes contêm um número de pacote aleatório que é ignorado:

  • Solicitação de Sessão
  • Sessão Criada
  • Solicitação de Token
  • Tentar Novamente
  • Teste de Peer
  • Hole Punch

Para Alice, a numeração de pacotes de saída começa em 0 com Session Confirmed. Para Bob, a numeração de pacotes de saída começa em 0 com o primeiro pacote Data, que deve ser um ACK do Session Confirmed. Os números de pacotes em um exemplo de handshake padrão serão:

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.

Qualquer retransmissão de mensagens de handshake (SessionRequest, SessionCreated, ou SessionConfirmed) deve ser reenviada inalterada, com o mesmo número de pacote. Não use chaves efêmeras diferentes ou altere o payload ao retransmitir essas mensagens.

Negação de Serviço entre Pares

O cabeçalho (antes da ofuscação e proteção) é sempre incluído nos dados associados para a função AEAD, para vincular criptograficamente o cabeçalho aos dados.

Ataques de Notificação Explícita de Congestionamento

A criptografia do cabeçalho tem vários objetivos. Consulte a seção “Additional DPI Discussion” acima para contexto e pressupostos.

  • Impedir que o DPI online identifique o protocolo
  • Impedir padrões numa série de mensagens na mesma conexão, exceto para retransmissões de handshake
  • Impedir padrões em mensagens do mesmo tipo em diferentes conexões
  • Impedir descriptografia de cabeçalhos de handshake sem conhecimento da chave de introdução encontrada no netDb
  • Impedir identificação de chaves efêmeras X25519 sem conhecimento da chave de introdução encontrada no netDb
  • Impedir descriptografia do número e tipo de pacote da fase de dados por qualquer atacante online ou offline
  • Impedir injeção de pacotes de handshake válidos por um observador no caminho ou fora do caminho sem conhecimento da chave de introdução encontrada no netDb
  • Impedir injeção de pacotes de dados válidos por um observador no caminho ou fora do caminho
  • Permitir classificação rápida e eficiente de pacotes recebidos
  • Fornecer resistência a “probing” para que não haja resposta a uma Session Request inválida, ou se houver uma resposta Retry, a resposta não seja identificável como I2P sem conhecimento da chave de introdução encontrada no netDb
  • O Destination Connection ID não é dado crítico, e é aceitável que possa ser descriptografado por um observador com conhecimento da chave de introdução encontrada no netDb
  • O número de pacote de um pacote da fase de dados é um nonce AEAD e é dado crítico. Não deve ser descriptografável por um observador mesmo com conhecimento da chave de introdução encontrada no netDb. Veja Nonces.

Os cabeçalhos são criptografados com chaves conhecidas publicadas na network database ou calculadas posteriormente. Na fase de handshake, isso é apenas para resistência a DPI, pois a chave é pública e a chave e nonces são reutilizados, então é efetivamente apenas ofuscação. Note que a criptografia do cabeçalho também é usada para ofuscar as chaves efêmeras X (no Session Request) e Y (no Session Created).

Consulte a seção Tratamento de Pacotes de Entrada abaixo para orientações adicionais.

Os bytes 0-15 de todos os cabeçalhos são criptografados usando um esquema de proteção de cabeçalho através de XOR com dados calculados a partir de chaves conhecidas, utilizando ChaCha20, similar ao QUIC RFC 9001 e Nonces. Isso garante que o cabeçalho curto criptografado e a primeira parte do cabeçalho longo aparentem ser aleatórios.

Para Session Request e Session Created, os bytes 16-31 do cabeçalho longo e a chave efêmera Noise de 32 bytes são criptografados usando ChaCha20. Os dados não criptografados são aleatórios, então os dados criptografados parecerão ser aleatórios.

Para Retry, os bytes 16-31 do cabeçalho longo são criptografados usando ChaCha20. Os dados não criptografados são aleatórios, então os dados criptografados parecerão ser aleatórios.

Ao contrário do esquema de proteção de cabeçalho QUIC RFC 9001, TODAS as partes de todos os cabeçalhos, incluindo IDs de conexão de destino e origem, são criptografadas. QUIC RFC 9001 e Nonces estão principalmente focados em criptografar a parte “crítica” do cabeçalho, ou seja, o número do pacote (nonce ChaCha20). Embora criptografar o ID de sessão torne a classificação de pacotes recebidos um pouco mais complexa, isso torna alguns ataques mais difíceis. QUIC define diferentes IDs de conexão para diferentes fases, e para desafio de caminho e migração de conexão. Aqui usamos os mesmos IDs de conexão por toda parte, já que eles são criptografados.

Existem sete fases de chave de proteção de cabeçalho:

  • Solicitação de Sessão e Solicitação de Token
  • Sessão Criada
  • Repetir
  • Sessão Confirmada
  • Fase de Dados
  • Teste de Peer
  • Hole Punch
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
A criptografia de cabeçalho é projetada para permitir a classificação rápida de pacotes de entrada, sem heurísticas complexas ou alternativas. Isso é alcançado usando a mesma chave k_header_1 para quase todas as mensagens de entrada. Mesmo quando o IP de origem ou porta de uma conexão muda devido a uma mudança real de IP ou comportamento NAT, o pacote pode ser rapidamente mapeado para uma sessão com uma única consulta do ID de conexão.

Note que Session Created e Retry são as ÚNICAS mensagens que requerem processamento de fallback para k_header_1 para descriptografar o Connection ID, porque elas usam a chave intro do remetente (Bob). TODAS as outras mensagens usam a chave intro do receptor para k_header_1. O processamento de fallback precisa apenas procurar conexões de saída pendentes por IP/porta de origem.

Se o processamento de fallback por IP/porta de origem falhar ao encontrar uma conexão de saída pendente, pode haver várias causas:

  • Não é uma mensagem SSU2
  • Uma mensagem SSU2 corrompida
  • A resposta é falsificada ou modificada por um atacante
  • Bob tem um NAT simétrico
  • Bob mudou o IP ou porta durante o processamento da mensagem
  • Bob enviou a resposta por uma interface diferente

Embora seja possível realizar processamento adicional de fallback para tentar encontrar a conexão de saída pendente e descriptografar o ID da conexão usando o k_header_1 para essa conexão, provavelmente não é necessário. Se Bob tiver problemas com seu NAT ou roteamento de pacotes, provavelmente é melhor deixar a conexão falhar. Este design depende dos endpoints manterem um endereço estável durante a duração do handshake.

Veja a seção Inbound Packet Handling abaixo para diretrizes adicionais.

Consulte as seções individuais do KDF abaixo para a derivação das chaves de criptografia do cabeçalho para essa fase.

Oráculo de Reset sem 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 usa os últimos 24 bytes do pacote como o IV para as duas operações ChaCha20. Como todos os pacotes terminam com um MAC de 16 bytes, isso exige que todas as cargas úteis dos pacotes tenham um mínimo de 8 bytes. Este requisito está adicionalmente documentado nas seções de mensagens abaixo.

Downgrade de Versão

Após descriptografar os primeiros 8 bytes do cabeçalho, o receptor saberá o Destination Connection ID. A partir daí, o receptor sabe qual chave de criptografia de cabeçalho usar para o restante do cabeçalho, com base na fase da chave da sessão.

Descriptografar os próximos 8 bytes do cabeçalho revelará então o tipo de mensagem e permitirá determinar se é um cabeçalho curto ou longo. Se for um cabeçalho longo, o receptor deve validar os campos version e netid. Se a version for != 2, ou o netid for != o valor esperado (geralmente 2, exceto em redes de teste), o receptor deve descartar a mensagem.

Packet Integrity

Todas as mensagens contêm três ou quatro partes:

  • O cabeçalho da mensagem
  • Apenas para Session Request e Session Created, uma chave efêmera
  • Um payload criptografado com ChaCha20
  • Um MAC Poly1305

Em todos os casos, o cabeçalho (e se presente, a chave efêmera) está vinculado ao MAC de autenticação para garantir que toda a mensagem esteja íntegra.

  • Para mensagens de handshake Session Request, Session Created e Session Confirmed, o cabeçalho da mensagem é mixHash()eado antes da fase de processamento Noise
  • A chave efêmera, se presente, é coberta por um misHash() Noise padrão
  • Para mensagens fora do handshake Noise, o cabeçalho é usado como Dados Associados para a encriptação ChaCha20/Poly1305.

Os manipuladores de pacotes de entrada devem sempre descriptografar a carga útil ChaCha20 e validar o MAC antes de processar a mensagem, com uma exceção: Para mitigar ataques DoS de pacotes com endereços falsificados contendo mensagens aparentes de Session Request com um token inválido, um manipulador NÃO precisa tentar descriptografar e validar a mensagem completa (exigindo uma operação DH custosa além da descriptografia ChaCha20/Poly1305). O manipulador pode responder com uma mensagem Retry usando os valores encontrados no cabeçalho da mensagem Session Request.

Authenticated Encryption

Existem três instâncias separadas de criptografia autenticada (CipherStates). Uma durante a fase de handshake, e duas (transmissão e recepção) para a fase de dados. Cada uma tem sua própria chave de uma KDF.

Os dados criptografados/autenticados serão representados como

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

Ataques Direcionados por Roteamento

Formato de dados criptografado e autenticado.

Entradas para as funções de criptografia/descriptografia:


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

Saída da função de criptografia, entrada da função de descriptografia:


+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |       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, o que é descrito aqui corresponde à RFC 7539, que também é usada de forma similar no TLS RFC 7905.

Análise de Tráfego

  • Como o ChaCha20 é uma cifra de fluxo, os textos simples não precisam ser preenchidos. Bytes adicionais de keystream são descartados.

  • A chave para a cifra (256 bits) é acordada por meio do SHA256 KDF. Os detalhes do KDF para cada mensagem estão em seções separadas abaixo.

AEAD Error Handling

  • Em todas as mensagens, o tamanho da mensagem AEAD é conhecido antecipadamente. Em caso de falha na autenticação AEAD, o destinatário deve interromper o processamento adicional da mensagem e descartar a mensagem.

  • O Bob deve manter uma lista negra de IPs com falhas repetidas.

KDF for Session Request

A Key Derivation Function (KDF) gera uma chave de cifra da fase de handshake k a partir do resultado DH, usando HMAC-SHA256(key, data) conforme definido na RFC 2104. Estas são as funções InitializeSymmetric(), MixHash(), e MixKey(), exatamente como definidas na especificação 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 envia para Bob, seja como a primeira mensagem no handshake, ou em resposta a uma mensagem Retry. Bob responde com uma mensagem Session Created. Tamanho: 80 + tamanho do payload. Tamanho Mínimo: 88

Se Alice não possui um token válido, Alice deve enviar uma mensagem Token Request em vez de Session Request, para evitar a sobrecarga de criptografia assimétrica na geração de um Session Request.

Cabeçalho longo. Conteúdo Noise: chave efêmera X de Alice Payload Noise: DateTime e outros blocos Tamanho máximo do payload: MTU - 108 (IPv4) ou MTU - 128 (IPv6). Para MTU 1280: Payload máximo é 1172 (IPv4) ou 1152 (IPv6). Para MTU 1500: Payload máximo é 1392 (IPv4) ou 1372 (IPv6).

Propriedades de Segurança da Carga Útil:

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.

O valor X é criptografado para garantir a indistinguibilidade e unicidade da carga útil, que são contramedidas DPI necessárias. Usamos criptografia ChaCha20 para alcançar isso, em vez de alternativas mais complexas e lentas como elligator2. Criptografia assimétrica para a chave pública do router de Bob seria muito lenta. A criptografia ChaCha20 usa a chave de introdução de Bob conforme publicada na base de dados da rede.

A criptografia ChaCha20 é apenas para resistência a DPI. Qualquer parte que conhecer a chave de introdução do Bob, que é publicada no netDb, pode descriptografar o cabeçalho e o valor X nesta mensagem.

Conteúdo bruto:

+----+----+----+----+----+----+----+----+
  |  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)

Dados não criptografados (tag de autenticação Poly1305 não 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

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

O tamanho mínimo do payload é 8 bytes. Como o bloco DateTime tem apenas 7 bytes, pelo menos um outro bloco deve estar presente.

Notes

  • O valor X único no bloco inicial do ChaCha20 garante que o texto cifrado é diferente para cada sessão.

  • Para fornecer resistência a sondagem, Bob não deve enviar uma mensagem Retry em resposta a uma mensagem Session Request a menos que os campos message type, protocol version e network ID na mensagem Session Request sejam válidos.

  • Bob deve rejeitar conexões onde o valor do timestamp está muito distante do tempo atual. Chame o tempo delta máximo de “D”. Bob deve manter um cache local de valores de handshake usados anteriormente e rejeitar duplicatas, para prevenir ataques de replay. Valores no cache devem ter um tempo de vida de pelo menos 2*D. Os valores do cache são dependentes da implementação, porém o valor X de 32 bytes (ou seu equivalente criptografado) pode ser usado. Rejeite enviando uma mensagem Retry contendo um token zero e um bloco de terminação.

  • As chaves efêmeras Diffie-Hellman nunca podem ser reutilizadas, para prevenir ataques criptográficos, e a reutilização será rejeitada como um ataque de replay.

  • As opções “KE” e “auth” devem ser compatíveis, ou seja, o segredo compartilhado K deve ter o tamanho apropriado. Se mais opções “auth” forem adicionadas, isso pode alterar implicitamente o significado da flag “KE” para usar um KDF diferente ou um tamanho de truncamento diferente.

  • Bob deve validar que a chave efêmera de Alice é um ponto válido na curva aqui.

  • O padding deve ser limitado a uma quantidade razoável. Bob pode rejeitar conexões com padding excessivo. Bob especificará suas opções de padding em Session Created. Diretrizes de mín/máx a definir. Tamanho aleatório de 0 a 31 bytes mínimo? (Distribuição a ser determinada, veja Apêndice A.) TODO A MENOS QUE o tamanho mínimo de pacote seja imposto para PMTU.

  • Na maioria dos erros, incluindo AEAD, DH, replay aparente, ou falha de validação de chave, Bob deve interromper o processamento adicional da mensagem e descartar a mensagem sem responder.

  • Bob PODE enviar uma mensagem Retry contendo um token zero e um bloco Termination com um código de razão de clock skew se o timestamp no bloco DateTime estiver muito desalinhado.

  • Mitigação de DoS: DH é uma operação relativamente custosa. Como com o protocolo NTCP anterior, os routers devem tomar todas as medidas necessárias para prevenir esgotamento de CPU ou conexões. Estabeleça limites no máximo de conexões ativas e máximo de configurações de conexão em progresso. Aplique timeouts de leitura (tanto por leitura quanto total para “slowloris”). Limite conexões repetidas ou simultâneas da mesma origem. Mantenha listas negras para origens que falhem repetidamente. Não responda a falha de AEAD. Alternativamente, responda com uma mensagem Retry antes da operação DH e validação AEAD.

  • Campo “ver”: O protocolo Noise geral, extensões e protocolo SSU2 incluindo especificações de payload, indicando SSU2. Este campo pode ser usado para indicar suporte para mudanças futuras.

  • O campo network ID é usado para identificar rapidamente conexões entre redes. Se este campo não corresponder ao network ID do Bob, Bob deve desconectar e bloquear conexões futuras.

  • Bob deve descartar a mensagem se o Source Connection ID for igual ao Destination Connection ID.

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)

Migração de Conexão

Bob envia para Alice, em resposta a uma mensagem Session Request. Alice responde com uma mensagem Session Confirmed. Tamanho: 80 + tamanho do payload. Tamanho Mínimo: 88

Conteúdo Noise: Chave efêmera Y do Bob Payload Noise: DateTime, Address e outros blocos Tamanho máximo do payload: MTU - 108 (IPv4) ou MTU - 128 (IPv6). Para MTU 1280: Payload máximo é 1172 (IPv4) ou 1152 (IPv6). Para MTU 1500: Payload máximo é 1392 (IPv4) ou 1372 (IPv6).

Propriedades de Segurança do 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.

O valor Y é criptografado para garantir a indistinguibilidade e unicidade do payload, que são contramedidas DPI necessárias. Utilizamos criptografia ChaCha20 para alcançar isso, em vez de alternativas mais complexas e lentas como elligator2. Criptografia assimétrica para a chave pública do router de Alice seria muito lenta. A criptografia ChaCha20 usa a chave de introdução de Bob, conforme publicada na netDb.

A criptografia ChaCha20 é apenas para resistência a DPI. Qualquer parte que conheça a chave de introdução do Bob, que é publicada na base de dados da rede, e capture os primeiros 32 bytes da Solicitação de Sessão, pode descriptografar o valor Y nesta mensagem.

Conteúdo bruto:

+----+----+----+----+----+----+----+----+
  |  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)

Dados não criptografados (tag de autenticação Poly1305 não 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

  • Bloco DateTime
  • Bloco Address
  • Bloco Relay Tag (opcional)
  • Bloco New Token (opcional)
  • Bloco First Packet Number (opcional)
  • Bloco Options (opcional)
  • Bloco Termination (não recomendado, envie em uma mensagem de retry em vez disso)
  • Bloco Padding (opcional)

O tamanho mínimo do payload é 8 bytes. Como os blocos DateTime e Address totalizam mais do que isso, o requisito é atendido apenas com esses dois blocos.

Notes

  • Alice deve validar que a chave efêmera de Bob é um ponto válido na curva aqui.

  • O padding deve ser limitado a uma quantidade razoável. Alice pode rejeitar conexões com padding excessivo. Alice especificará suas opções de padding em Session Confirmed. Diretrizes de mín/máx a serem determinadas. Tamanho aleatório de 0 a 31 bytes mínimo? (Distribuição a ser determinada, ver Apêndice A.) TODO A MENOS QUE o tamanho mínimo de pacote seja aplicado para PMTU.

  • Em qualquer erro, incluindo AEAD, DH, timestamp, replay aparente, ou falha de validação de chave, Alice deve parar o processamento de mensagens adicionais e fechar a conexão sem responder.

  • Alice deve rejeitar conexões onde o valor do timestamp está muito distante do tempo atual. Chame o delta de tempo máximo de “D”. Alice deve manter um cache local de valores de handshake previamente usados e rejeitar duplicatas, para prevenir ataques de replay. Valores no cache devem ter um tempo de vida de pelo menos 2*D. Os valores do cache são dependentes da implementação, porém o valor Y de 32 bytes (ou seu equivalente criptografado) pode ser usado.

  • Alice deve descartar a mensagem se o IP de origem e a porta não coincidirem com o IP de destino e a porta da Session Request.

  • Alice deve descartar a mensagem se os IDs de Conexão de Destino e Origem não coincidirem com os IDs de Conexão de Origem e Destino do Session Request.

  • Bob envia um bloco de relay tag se solicitado por Alice no Session Request.

Issues

  • Incluir opções de preenchimento mín/máx aqui?

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 envia para Bob, em resposta a uma mensagem Session Created. Bob responde imediatamente com uma mensagem Data contendo um bloco ACK. Tamanho: 80 + tamanho do payload. Tamanho Mínimo: Cerca de 500 (o tamanho mínimo do bloco router info é cerca de 420 bytes)

Conteúdo Noise: Chave estática da Alice Parte 1 do payload Noise: Nenhuma Parte 2 do payload Noise: RouterInfo da Alice, e outros blocos Tamanho máximo do payload: MTU - 108 (IPv4) ou MTU - 128 (IPv6). Para MTU 1280: Payload máximo é 1172 (IPv4) ou 1152 (IPv6). Para MTU 1500: Payload máximo é 1392 (IPv4) ou 1372 (IPv6).

Propriedades de Segurança do 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.

Isto contém dois quadros ChaChaPoly. O primeiro é a chave pública estática criptografada de Alice. O segundo é a carga útil do Noise: o RouterInfo criptografado de Alice, opções opcionais e preenchimento opcional. Eles usam chaves diferentes, porque a função MixKey() é chamada entre eles.

Conteúdo bruto:

+----+----+----+----+----+----+----+----+
  |  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

Dados não criptografados (tags de autenticação Poly1305 não 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

  • Bloco RouterInfo (deve ser o primeiro bloco)
  • Bloco Options (opcional)
  • Bloco New Token (opcional)
  • Bloco Relay Request (opcional)
  • Bloco Peer Test (opcional)
  • Bloco First Packet Number (opcional)
  • Blocos I2NP, First Fragment, ou Follow-on Fragment (opcionais, mas provavelmente sem espaço)
  • Bloco Padding (opcional)

O tamanho mínimo do payload é de 8 bytes. Como o bloco RouterInfo será bem maior que isso, o requisito é atendido apenas com esse bloco.

Notes

  • Bob deve realizar a validação usual do Router Info. Certifique-se de que o tipo de assinatura é suportado, verifique a assinatura, verifique se o timestamp está dentro dos limites, e quaisquer outras verificações necessárias. Veja abaixo as notas sobre o manuseio de Router Infos fragmentados.

  • O Bob deve verificar se a chave estática da Alice recebida no primeiro quadro corresponde à chave estática no Router Info. O Bob deve primeiro pesquisar no Router Info por um Router Address NTCP ou SSU2 com uma opção de versão (v) correspondente. Veja as seções Published Router Info e Unpublished Router Info abaixo. Veja abaixo as notas sobre como lidar com Router Infos fragmentados.

  • Se Bob tiver uma versão mais antiga do RouterInfo da Alice em sua netDb, verifique se a chave estática nas informações do router é a mesma em ambas, se presente, e se a versão mais antiga for menos que XXX antiga (veja o tempo de rotação de chave abaixo)

  • Bob deve validar que a chave estática de Alice é um ponto válido na curva aqui.

  • As opções devem ser incluídas, para especificar parâmetros de padding.

  • Em caso de qualquer erro, incluindo falha de validação AEAD, RI, DH, timestamp, ou chave, Bob deve interromper o processamento de mensagens e fechar a conexão sem responder.

  • Conteúdo do quadro da parte 2 da Mensagem 3: O formato deste quadro é o mesmo que o formato dos quadros da fase de dados, exceto que o comprimento do quadro é enviado pela Alice na Solicitação de Sessão. Veja abaixo o formato do quadro da fase de dados. O quadro deve conter de 1 a 4 blocos na seguinte ordem:

    1. Bloco Router Info da Alice (obrigatório)
    2. Bloco de opções (opcional)
    3. Blocos I2NP (opcional)
    4. Bloco de preenchimento (opcional) Este quadro nunca deve conter nenhum outro tipo de bloco. TODO: e quanto ao relay e peer test?
  • O bloco de preenchimento da parte 2 da Mensagem 3 é recomendado.

  • Pode não haver espaço disponível, ou apenas uma pequena quantidade de espaço, para blocos I2NP, dependendo do MTU e do tamanho do Router Info. NÃO inclua blocos I2NP se o Router Info estiver fragmentado. A implementação mais simples pode ser nunca incluir blocos I2NP na mensagem Session Confirmed, e enviar todos os blocos I2NP em mensagens Data subsequentes. Veja a seção de bloco Router Info abaixo para o tamanho máximo do bloco.

Session Confirmed Fragmentation

A mensagem Session Confirmed deve conter as informações completas do Router Info assinado da Alice para que Bob possa realizar várias verificações obrigatórias:

  • A chave estática “s” no RI corresponde à chave estática no handshake
  • A chave de introdução “i” no RI deve ser extraída e válida, para ser usada na fase de dados
  • A assinatura do RI é válida

Infelizmente, o Router Info, mesmo quando comprimido com gzip no bloco RI, pode exceder o MTU. Portanto, o Session Confirmed pode ser fragmentado em dois ou mais pacotes. Este é o ÚNICO caso no protocolo SSU2 onde um payload protegido por AEAD é fragmentado em dois ou mais pacotes.

Os cabeçalhos para cada pacote são construídos da seguinte forma:

  • TODOS os cabeçalhos são cabeçalhos curtos com o mesmo número de pacote 0
  • TODOS os cabeçalhos contêm um campo “frag”, com o número do fragmento e número total de fragmentos
  • O cabeçalho não criptografado do fragmento 0 é o dado associado (AD) para a mensagem “jumbo”
  • Cada cabeçalho é criptografado usando os últimos 24 bytes de dados NAQUELE pacote

Construa a série de pacotes da seguinte forma:

  • Criar um único bloco RI (fragmento 0 de 1 no campo frag do bloco RI). Não usamos fragmentação de bloco RI, isso era para um método alternativo de resolver o mesmo problema.
  • Criar um payload “jumbo” com o bloco RI e quaisquer outros blocos a serem incluídos
  • Calcular o tamanho total dos dados (não incluindo o cabeçalho), que é o tamanho do payload + 64 bytes para a chave estática e dois MACs
  • Calcular o espaço disponível em cada pacote, que é o MTU menos o cabeçalho IP (20 ou 40), menos o cabeçalho UDP (8), menos o cabeçalho curto SSU2 (16). O overhead total por pacote é 44 (IPv4) ou 64 (IPv6).
  • Calcular o número de pacotes.
  • Calcular o tamanho dos dados no último pacote. Deve ser maior ou igual a 24 bytes, para que a criptografia do cabeçalho funcione. Se for muito pequeno, adicionar um bloco de preenchimento, OU aumentar o tamanho do bloco de preenchimento se já estiver presente, OU reduzir o tamanho de um dos outros pacotes para que o último pacote seja grande o suficiente.
  • Criar o cabeçalho não criptografado para o primeiro pacote, com o número total de fragmentos no campo frag, e criptografar o payload “jumbo” com Noise, usando o cabeçalho como AD, como de costume.
  • Dividir o pacote jumbo criptografado em fragmentos
  • Adicionar um cabeçalho não criptografado para cada fragmento 1-n
  • Criptografar o cabeçalho para cada fragmento 0-n. Cada cabeçalho usa os MESMOS k_header_1 e k_header_2 conforme definidos acima no KDF Session Confirmed.
  • Transmitir todos os fragmentos

Processo de remontagem:

Quando Bob recebe qualquer mensagem Session Confirmed, ele descriptografa o cabeçalho, inspeciona o campo frag e determina que o Session Confirmed está fragmentado. Ele não (e não pode) descriptografar a mensagem até que todos os fragmentos sejam recebidos e remontados.

  • Preserve o cabeçalho para o fragmento 0, pois ele é usado como o Noise AD
  • Descarte os cabeçalhos para outros fragmentos antes da remontagem
  • Remonte o payload “jumbo”, com o cabeçalho para o fragmento 0 como AD, e descriptografe com Noise
  • Valide o bloco RI como de costume
  • Prossiga para a fase de dados e envie ACK 0, como de costume

Não existe mecanismo para Bob confirmar fragmentos individuais. Quando Bob recebe todos os fragmentos, remonta, descriptografa e valida o conteúdo, Bob executa um split() como de costume, entra na fase de dados e envia um ACK do pacote número 0.

Se Alice não receber um ACK do pacote número 0, ela deve retransmitir todos os pacotes confirmados da sessão como estão.

Exemplos:

Para MTU de 1500 sobre IPv6, a carga útil máxima é 1372, a sobrecarga do bloco RI é 5, o tamanho máximo de dados RI (comprimidos com gzip) é 1367 (assumindo nenhum outro bloco). Com dois pacotes, a sobrecarga do 2º pacote é 64, então pode conter outros 1436 bytes de carga útil. Portanto, dois pacotes são suficientes para um RI comprimido de até 2803 bytes.

O maior RI comprimido observado na rede atual tem cerca de 1400 bytes; portanto, na prática, dois fragmentos devem ser suficientes, mesmo com um MTU mínimo de 1280. O protocolo permite no máximo 15 fragmentos.

Análise de segurança:

A integridade e segurança de um Session Confirmed fragmentado é a mesma de um não fragmentado. Qualquer alteração de qualquer fragmento causará falha do Noise AEAD após a remontagem. Os cabeçalhos dos fragmentos após o fragmento 0 são usados apenas para identificar o fragmento. Mesmo que um atacante no caminho tivesse a chave k_header_2 usada para criptografar o cabeçalho (improvável, derivada do handshake), isso não permitiria ao atacante substituir um fragmento válido.

KDF for data phase

A fase de dados usa o cabeçalho para dados associados.

O KDF gera duas chaves de cifra k_ab e k_ba a partir da chave de encadeamento ck, usando HMAC-SHA256(key, data) conforme definido na RFC 2104. Esta é a função split(), exatamente como definida na especificação 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 Noise: Todos os tipos de bloco são permitidos Tamanho máximo do payload: MTU - 60 (IPv4) ou MTU - 80 (IPv6). Para MTU 1500: Payload máximo é 1440 (IPv4) ou 1420 (IPv6).

Começando com a 2ª parte do Session Confirmed, todas as mensagens estão dentro de um payload ChaChaPoly autenticado e criptografado. Todo o padding está dentro da mensagem. Dentro do payload há um formato padrão com zero ou mais “blocos”. Cada bloco tem um tipo de um byte e um comprimento de dois bytes. Os tipos incluem data/hora, mensagem I2NP, opções, terminação e padding.

Nota: Bob pode, mas não é obrigatório, enviar seu RouterInfo para Alice como sua primeira mensagem para Alice na fase de dados.

Propriedades de Segurança da Carga Útil:

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

  • O router deve descartar uma mensagem com um erro 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)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dados não criptografados (tag de autenticação Poly1305 não 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

  • O tamanho mínimo do payload é 8 bytes. Este requisito será atendido por qualquer bloco ACK, I2NP, First Fragment ou Follow-on Fragment. Se o requisito não for atendido, um bloco Padding deve ser incluído.

  • Cada número de pacote pode ser usado apenas uma vez. Ao retransmitir mensagens I2NP ou fragmentos, um novo número de pacote deve ser usado.

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 envia para Alice, e Alice envia para Charlie, apenas para as fases 5-7 do Peer Test. As fases 1-4 do Peer Test devem ser enviadas in-session usando um bloco Peer Test em uma mensagem Data. Consulte as seções Peer Test Block e Peer Test Process abaixo para mais informações.

Tamanho: 48 + tamanho do payload.

Payload de ruído: Veja abaixo.

Conteúdo bruto:

+----+----+----+----+----+----+----+----+
  |  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)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dados não criptografados (tag de autenticação Poly1305 não 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

Cabeçalho Longo

  • Bloco DateTime
  • Bloco Address (obrigatório para mensagens 6 e 7, veja a nota abaixo)
  • Bloco Peer Test
  • Bloco Padding (opcional)

O tamanho mínimo do payload é 8 bytes. Como o bloco Peer Test totaliza mais que isso, o requisito é atendido apenas com este bloco.

Nas mensagens 5 e 7, o bloco Peer Test pode ser idêntico ao bloco das mensagens 3 e 4 da sessão, contendo o acordo assinado por Charlie, ou pode ser regenerado. A assinatura é opcional.

Na mensagem 6, o bloco Peer Test pode ser idêntico ao bloco das mensagens 1 e 2 da sessão, contendo a solicitação assinada por Alice, ou pode ser regenerado. A assinatura é opcional.

IDs de Conexão: Os dois IDs de conexão são derivados do nonce de teste. Para as mensagens 5 e 7 enviadas de Charlie para Alice, o ID de Conexão de Destino são duas cópias do nonce de teste de 4 bytes em big-endian, ou seja, ((nonce « 32) | nonce). O ID de Conexão de Origem é o inverso do ID de Conexão de Destino, ou seja, ~((nonce « 32) | nonce). Para a mensagem 6 enviada de Alice para Charlie, inverta os dois IDs de conexão.

Conteúdo do bloco de endereço:

  • Na mensagem 5: Não necessário.
  • Na mensagem 6: IP e porta do Charlie conforme selecionados do RI do Charlie.
  • Na mensagem 7: IP e porta reais da Alice de onde a mensagem 6 foi recebida.

KDF for Retry

O requisito para a mensagem Retry é que Bob não é obrigatório a descriptografar a mensagem Session Request para gerar uma mensagem Retry em resposta. Além disso, esta mensagem deve ser rápida de gerar, usando apenas criptografia simétrica.


// 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 envia para Alice, em resposta a uma mensagem Session Request ou Token Request. Alice responde com um novo Session Request. Tamanho: 48 + tamanho do payload.

Também serve como uma mensagem de Terminação (ou seja, “Não Tentar Novamente”) se um bloco de Terminação estiver incluído.

Payload do Noise: Veja abaixo.

Conteúdo 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)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dados não criptografados (tag de autenticação Poly1305 não 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

Cabeçalho Curto

  • Bloco DateTime
  • Bloco Address
  • Bloco Options (opcional)
  • Bloco Termination (opcional, se a sessão for rejeitada)
  • Bloco Padding (opcional)

O tamanho mínimo do payload é de 8 bytes. Como os blocos DateTime e Address totalizam mais que isso, o requisito é atendido apenas com esses dois blocos.

Numeração do ID de Conexão

  • Para fornecer resistência a sondagem, um router não deve enviar uma mensagem Retry em resposta a uma mensagem Session Request ou Token Request, a menos que os campos de tipo de mensagem, versão do protocolo e ID da rede na mensagem Request sejam válidos.

  • Para limitar a magnitude de qualquer ataque de amplificação que possa ser montado usando endereços de origem falsificados, a mensagem Retry não deve conter grandes quantidades de padding. É recomendado que a mensagem Retry não seja maior que três vezes o tamanho da mensagem à qual está respondendo. Alternativamente, use um método simples como adicionar uma quantidade aleatória de padding no intervalo de 1-64 bytes.

KDF for Token Request

Esta mensagem deve ser rápida de gerar, usando apenas criptografia simétrica.


// 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 envia para Bob. Bob responde com uma mensagem Retry. Tamanho: 48 + tamanho do payload.

Se Alice não possui um token válido, Alice deve enviar esta mensagem em vez de uma Session Request, para evitar a sobrecarga de criptografia assimétrica na geração de uma Session Request.

Payload do Noise: Veja abaixo.

Conteúdo 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)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dados não criptografados (tag de autenticação Poly1305 não 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

Numeração de Pacotes

  • Bloco DateTime
  • Bloco Padding

O tamanho mínimo do payload é de 8 bytes.

Vinculação de Cabeçalho

  • Para fornecer resistência a sondagem, um router não deve enviar uma mensagem Retry em resposta a uma mensagem Token Request a menos que os campos de tipo de mensagem, versão do protocolo e ID da rede na mensagem Token Request sejam válidos.

  • Esta NÃO é uma mensagem Noise padrão e não faz parte do handshake. Não está vinculada à mensagem Session Request exceto pelos IDs de conexão.

  • Na maioria dos erros, incluindo AEAD, ou aparente replay Bob deve interromper o processamento adicional de mensagens e descartar a mensagem sem responder.

  • O Bob deve rejeitar conexões onde o valor do timestamp está muito distante do tempo atual. Chame o tempo delta máximo de “D”. O Bob deve manter um cache local de valores de handshake usados anteriormente e rejeitar duplicatas, para prevenir ataques de replay. Valores no cache devem ter um tempo de vida de pelo menos 2*D. Os valores do cache são dependentes da implementação, porém o valor X de 32 bytes (ou seu equivalente criptografado) pode ser usado.

  • Bob PODE enviar uma mensagem Retry contendo um token zero e um bloco Termination com um código de razão de desvio de relógio se o timestamp no bloco DateTime estiver muito desviado.

  • Tamanho mínimo: A definir, mesmas regras do Session Created?

KDF for Hole Punch

Esta mensagem deve ser rápida de gerar, usando apenas criptografia simétrica.


// 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 envia para Alice, em resposta a um Relay Intro recebido de Bob. Alice responde com um novo Session Request. Tamanho: 48 + tamanho do payload.

Payload do Noise: Veja abaixo.

Conteúdo bruto:

+----+----+----+----+----+----+----+----+
  |  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)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dados não criptografados (tag de autenticação Poly1305 não 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.

Criptografia do Cabeçalho

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

O tamanho mínimo do payload é 8 bytes. Como os blocos DateTime e Address totalizam mais que isso, o requisito é atendido apenas com esses dois blocos.

IDs de Conexão: Os dois IDs de conexão são derivados do relay nonce. O ID de Conexão de Destino são duas cópias do relay nonce de 4 bytes em big-endian, ou seja, ((nonce « 32) | nonce). O ID de Conexão de Origem é o inverso do ID de Conexão de Destino, ou seja, ~((nonce « 32) | nonce).

Alice deve ignorar o token no cabeçalho. O token a ser usado na Solicitação de Sessão está no bloco de Resposta do Relay.

Noise Payload

Cada payload de Noise contém zero ou mais “blocos”.

Isso usa o mesmo formato de bloco conforme definido nas especificações NTCP2 e ECIES. Os tipos de blocos individuais são definidos de forma diferente. O termo equivalente no QUIC RFC 9000 é “frames”.

Há preocupações de que encorajar implementadores a compartilhar código pode levar a problemas de análise. Os implementadores devem considerar cuidadosamente os benefícios e riscos de compartilhar código, e garantir que as regras de ordenação e blocos válidos sejam diferentes para os dois contextos.

Considerações de Segurança

Existem um ou mais blocos no payload criptografado. Um bloco é um formato simples Tag-Length-Value (TLV). Cada bloco contém um identificador de um byte, um comprimento de dois bytes e zero ou mais bytes de dados. Este formato é idêntico ao do NTCP2 e ECIES, no entanto as definições dos blocos são diferentes.

Para extensibilidade, os receptores devem ignorar blocos com identificadores desconhecidos e tratá-los como preenchimento.

(Tag de autenticação Poly1305 não 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

A criptografia do cabeçalho utiliza os últimos 24 bytes do pacote como o IV para as duas operações ChaCha20. Como todos os pacotes terminam com um MAC de 16 bytes, isso exige que todas as cargas úteis dos pacotes tenham um mínimo de 8 bytes. Se uma carga útil não atender a esse requisito, um bloco de Padding deve ser incluído.

O payload máximo do ChaChaPoly varia com base no tipo de mensagem, MTU e tipo de endereço IPv4 ou IPv6. O payload máximo é MTU - 60 para IPv4 e MTU - 80 para IPv6. Os dados de payload máximos são MTU - 63 para IPv4 e MTU - 83 para IPv6. O limite superior é cerca de 1440 bytes para IPv4, MTU 1500, mensagem de dados. O tamanho máximo total do bloco é o tamanho máximo do payload. O tamanho máximo de bloco único é o tamanho máximo total do bloco. O tipo de bloco é 1 byte. O comprimento do bloco é 2 bytes. O tamanho máximo de dados de bloco único é o tamanho máximo de bloco único menos 3.

Notas:

  • Os implementadores devem garantir que, ao ler um bloco, dados malformados ou maliciosos não causem leituras que ultrapassem o próximo bloco ou além do limite do payload.

  • As implementações devem ignorar tipos de blocos desconhecidos para compatibilidade futura.

Tipos de bloco:

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

Na Sessão Confirmada, as Informações do Router devem ser o primeiro bloco.

Em todas as outras mensagens, a ordem não é especificada, exceto pelos seguintes requisitos: Padding, se presente, deve ser o último bloco. Termination, se presente, deve ser o último bloco exceto por Padding. Múltiplos blocos Padding não são permitidos em uma única carga útil.

Block Specifications

KDF de Criptografia do Cabeçalho

Para sincronização de tempo:

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

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

Notas:

  • Ao contrário do SSU 1, não há timestamp no cabeçalho do pacote para a fase de dados no SSU 2.
  • As implementações devem enviar periodicamente blocos DateTime na fase de dados.
  • As implementações devem arredondar para o segundo mais próximo para evitar desvio de relógio na rede.

Validação de Cabeçalho

Passar opções atualizadas. As opções incluem: Padding mínimo e máximo.

O bloco de opções terá comprimento variável.

+----+----+----+----+----+----+----+----+
  | 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 com Opções:

  • A negociação de opções está TBD.

RouterInfo

Passar o RouterInfo da Alice para o Bob. Usado apenas na carga útil da parte 2 do Session Confirmed. Não deve ser usado na fase de dados; use uma Mensagem I2NP DatabaseStore em vez disso.

Tamanho Mínimo: Cerca de 420 bytes, a menos que a identidade do router e a assinatura no router info sejam compressíveis, o que é improvável.

NOTA: O bloco Router Info nunca é fragmentado. O campo frag é sempre 0/1. Consulte a seção Fragmentação da Sessão Confirmada acima para mais informações.

+----+----+----+----+----+----+----+----+
  | 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:

  • O Router Info é opcionalmente comprimido com gzip, conforme indicado pelo bit 1 da flag. Isso é diferente do NTCP2, onde nunca é comprimido, e de uma Mensagem DatabaseStore, onde sempre é comprimido. A compressão é opcional porque geralmente oferece pouco benefício para Router Infos pequenos, onde há pouco conteúdo comprimível, mas é muito benéfica para Router Infos grandes com vários Router Addresses comprimíveis. A compressão é recomendada se permitir que um Router Info caiba em um único pacote Session Confirmed sem fragmentação.

  • Tamanho máximo do primeiro ou único fragmento na mensagem Session Confirmed: MTU - 113 para IPv4 ou MTU - 133 para IPv6. Assumindo MTU padrão de 1500 bytes, e nenhum outro bloco na mensagem, 1387 para IPv4 ou 1367 para IPv6. 97% dos router infos atuais são menores que 1367 sem gzipping. 99,9% dos router infos atuais são menores que 1367 quando comprimidos com gzip. Assumindo MTU mínimo de 1280 bytes, e nenhum outro bloco na mensagem, 1167 para IPv4 ou 1147 para IPv6. 94% dos router infos atuais são menores que 1147 sem gzipping. 97% dos router infos atuais são menores que 1147 quando comprimidos com gzip.

  • O byte frag agora não é usado, o bloco Router Info nunca é fragmentado. O byte frag deve ser definido como fragmento 0, total de fragmentos 1. Veja a seção Session Confirmed Fragmentation acima para mais informações.

  • O flooding não deve ser solicitado a menos que existam RouterAddresses publicados no RouterInfo. O router receptor não deve fazer flood do RouterInfo a menos que existam RouterAddresses publicados nele.

  • Este protocolo não fornece uma confirmação de que o RouterInfo foi armazenado ou propagado por floodfill. Se a confirmação for desejada, e o receptor for floodfill, o remetente deve enviar uma DatabaseStoreMessage I2NP padrão com um token de resposta.

I2NP Message

Uma mensagem I2NP completa com um cabeçalho modificado.

Isto usa os mesmos 9 bytes para o cabeçalho I2NP como em NTCP2 (tipo, ID da mensagem, expiração curta).

+----+----+----+----+----+----+----+----+
  | 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 é o mesmo formato de cabeçalho I2NP de 9 bytes usado no NTCP2.

  • Este é exatamente o mesmo formato do bloco First Fragment, mas o tipo de bloco indica que esta é uma mensagem completa.

  • Tamanho máximo incluindo cabeçalho I2NP de 9 bytes é MTU - 63 para IPv4 e MTU - 83 para IPv6.

ChaCha20/Poly1305

O primeiro fragmento (fragmento #0) de uma mensagem I2NP com um cabeçalho modificado.

Isso usa os mesmos 9 bytes para o cabeçalho I2NP como no NTCP2 (tipo, ID da mensagem, expiração curta).

O número total de fragmentos não é 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 é o mesmo formato de cabeçalho I2NP de 9 bytes usado no NTCP2.

  • Este é exatamente o mesmo formato que o bloco de Mensagem I2NP, mas o tipo de bloco indica que este é o primeiro fragmento de uma mensagem.

  • O comprimento da mensagem parcial deve ser maior que zero.

  • Como no SSU 1, recomenda-se enviar o último fragmento primeiro, para que o receptor saiba o número total de fragmentos e possa alocar eficientemente os buffers de recepção.

  • O tamanho máximo incluindo o cabeçalho I2NP de 9 bytes é MTU - 63 para IPv4 e MTU - 83 para IPv6.

Notas

Um fragmento adicional (número do fragmento maior que zero) de uma mensagem 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:

  • O comprimento da mensagem parcial deve ser maior que zero.

  • Como no SSU 1, é recomendado enviar o último fragmento primeiro, para que o receptor saiba o número total de fragmentos e possa alocar eficientemente os buffers de recepção.

  • Como no SSU 1, o número máximo de fragmentos é 127, mas o limite prático é 63 ou menos. As implementações podem limitar o máximo ao que é prático para um tamanho máximo de mensagem I2NP de cerca de 64 KB, o que equivale a aproximadamente 55 fragmentos com um MTU mínimo de 1280. Veja a seção Tamanho Máximo de Mensagem I2NP abaixo.

  • O tamanho máximo de mensagem parcial (não incluindo frag e message id) é MTU - 68 para IPv4 e MTU - 88 para IPv6.

Tratamento de Erros AEAD

Descartar a conexão. Este deve ser o último bloco sem padding no payload.

+----+----+----+----+----+----+----+----+
  | 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:

  • Nem todas as razões podem ser realmente utilizadas, depende da implementação. A maioria das falhas geralmente resultará na mensagem sendo descartada, não em uma terminação. Veja as notas nas seções de mensagens de handshake acima. Razões adicionais listadas são para consistência, logging, debugging, ou se a política mudar.
  • É recomendado que um bloco ACK seja incluído com o bloco de Terminação.
  • Na fase de dados, por qualquer razão diferente de “termination received”, o peer deve responder com um bloco de terminação com a razão “termination received”.

RelayRequest

Enviado numa mensagem de Dados em sessão, de Alice para Bob. Consulte a seção Processo de Relay abaixo.

+----+----+----+----+----+----+----+----+
  |  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:

  • O endereço IP é sempre incluído (ao contrário do SSU 1) e pode ser diferente do IP usado para a sessão.

Assinatura:

Alice assina a solicitação e a inclui neste bloco; Bob a encaminha no bloco Relay Intro para Charlie. Algoritmo de assinatura: Assine os seguintes dados com a chave de assinatura do router da Alice:

  • prologue: 16 bytes “RelayRequestData”, não terminado em null (não incluído na mensagem)
  • bhash: Hash do router de 32 bytes do Bob (não incluído na mensagem)
  • chash: Hash do router de 32 bytes do Charlie (não incluído na mensagem)
  • nonce: nonce de 4 bytes
  • relay tag: tag de relay de 4 bytes
  • timestamp: timestamp de 4 bytes (segundos)
  • ver: versão SSU de 1 byte
  • asz: tamanho do endpoint (porta + IP) de 1 byte (6 ou 18)
  • AlicePort: número da porta da Alice de 2 bytes
  • Alice IP: endereço IP da Alice de (asz - 2) bytes

KDF para ChainKey Inicial

Enviado em uma mensagem Data na sessão, de Charlie para Bob ou de Bob para Alice, E na mensagem Hole Punch de Charlie para Alice. Veja a seção Processo de Relay abaixo.

+----+----+----+----+----+----+----+----+
  |  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:

O token deve ser usado imediatamente pela Alice na Solicitação de Sessão.

Assinatura:

Se Charlie concordar (código de resposta 0) ou rejeitar (código de resposta 64 ou superior), Charlie assina a resposta e a inclui neste bloco; Bob a encaminha no bloco Relay Response para Alice. Algoritmo de assinatura: Assinar os seguintes dados com a chave de assinatura do router do Charlie:

  • prologue: 16 bytes “RelayAgreementOK”, não terminado em null (não incluído na mensagem)
  • bhash: Hash de 32 bytes do router do Bob (não incluído na mensagem)
  • nonce: nonce de 4 bytes
  • timestamp: timestamp de 4 bytes (segundos)
  • ver: versão SSU de 1 byte
  • csz: tamanho do endpoint (porta + IP) de 1 byte (0 ou 6 ou 18)
  • CharliePort: número da porta do Charlie de 2 bytes (não presente se csz for 0)
  • Charlie IP: endereço IP do Charlie de (csz - 2) bytes (não presente se csz for 0)

Se Bob rejeitar (código de resposta 1-63), Bob assina a resposta e a inclui neste bloco. Algoritmo de assinatura: Assinar os seguintes dados com a chave de assinatura do router do Bob:

  • prologue: 16 bytes “RelayAgreementOK”, não terminado em null (não incluído na mensagem)
  • bhash: Hash do router de Bob de 32 bytes (não incluído na mensagem)
  • nonce: Nonce de 4 bytes
  • timestamp: Timestamp de 4 bytes (segundos)
  • ver: Versão SSU de 1 byte
  • csz: 1 byte = 0

KDF para Solicitação de Sessão

Enviado em uma mensagem Data dentro da sessão, de Bob para Charlie. Veja a seção Processo de Relay abaixo.

Deve ser precedido por um bloco RouterInfo, ou bloco de mensagem I2NP DatabaseStore (ou fragmento), contendo as Informações do Router da Alice, seja na mesma carga útil (se houver espaço), ou em uma mensagem 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, o endereço IP da Alice é sempre 4 bytes, porque a Alice está tentando conectar ao Charlie via IPv4. IPv6 é suportado, e o endereço IP da Alice pode ser 16 bytes.

  • Para IPv4, esta mensagem deve ser enviada através de uma conexão IPv4 estabelecida, pois essa é a única forma de Bob conhecer o endereço IPv4 de Charlie para retornar para Alice no RelayResponse_. IPv6 é suportado, e esta mensagem pode ser enviada através de uma conexão IPv6 estabelecida.

  • Qualquer endereço SSU publicado com introducers deve conter “4” ou “6” na opção “caps”.

Assinatura:

Alice assina a solicitação e Bob a encaminha neste bloco para Charlie. Algoritmo de verificação: Verificar os seguintes dados com a chave de assinatura do router da Alice:

  • prologue: 16 bytes “RelayRequestData”, não terminado em null (não incluído na mensagem)
  • bhash: hash do router de 32 bytes do Bob (não incluído na mensagem)
  • chash: hash do router de 32 bytes do Charlie (não incluído na mensagem)
  • nonce: nonce de 4 bytes
  • relay tag: tag de relay de 4 bytes
  • timestamp: timestamp de 4 bytes (segundos)
  • ver: versão SSU de 1 byte
  • asz: tamanho do endpoint (porta + IP) de 1 byte (6 ou 18)
  • AlicePort: número da porta da Alice de 2 bytes
  • Alice IP: endereço IP da Alice de (asz - 2) bytes

PeerTest

Enviado em uma mensagem Data durante a sessão, ou em uma mensagem Peer Test fora da sessão. Veja a seção Processo de Peer Test abaixo.

Para a mensagem 2, deve ser precedida por um bloco RouterInfo, ou bloco de mensagem I2NP DatabaseStore (ou fragmento), contendo as Informações do Router da Alice, seja no mesmo payload (se houver espaço), ou em uma mensagem anterior.

Para a mensagem 4, se o relay for aceito (código de razão 0), deve ser precedido por um bloco RouterInfo, ou bloco de mensagem I2NP DatabaseStore (ou fragmento), contendo as Router Info do Charlie, seja no mesmo payload (se houver espaço), ou em uma mensagem 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:

  • Ao contrário do SSU 1, a mensagem 1 deve incluir o endereço IP e porta da Alice.

  • O teste de endereços IPv6 é suportado, e a comunicação Alice-Bob e Alice-Charlie pode ser via IPv6, se Bob e Charlie indicarem suporte com uma capacidade ‘B’ em seu endereço IPv6 publicado. Consulte a Proposta 126 para detalhes.

Alice envia a solicitação para Bob usando uma sessão existente sobre o transporte (IPv4 ou IPv6) que ela deseja testar. Quando Bob recebe uma solicitação de Alice via IPv4, Bob deve selecionar um Charlie que anuncie um endereço IPv4. Quando Bob recebe uma solicitação de Alice via IPv6, Bob deve selecionar um Charlie que anuncie um endereço IPv6. A comunicação real Bob-Charlie pode ser via IPv4 ou IPv6 (ou seja, independente do tipo de endereço de Alice).

  • As mensagens 1-4 devem estar contidas numa mensagem Data numa sessão existente.

  • Bob deve enviar o RI de Alice para Charlie antes de enviar a mensagem 2.

  • Bob deve enviar o RI de Charlie para Alice antes de enviar a mensagem 4, se aceito (código de razão 0).

  • As mensagens 5-7 devem estar contidas numa mensagem Peer Test fora de sessão.

  • As mensagens 5 e 7 podem conter os mesmos dados assinados enviados nas mensagens 3 e 4, ou podem ser regenerados com um novo timestamp. A assinatura é opcional.

  • A mensagem 6 pode conter os mesmos dados assinados enviados nas mensagens 1 e 2, ou pode ser regenerada com um novo timestamp. A assinatura é opcional.

Assinaturas:

Alice assina a requisição e a inclui na mensagem 1; Bob a encaminha na mensagem 2 para Charlie. Charlie assina a resposta e a inclui na mensagem 3; Bob a encaminha na mensagem 4 para Alice. Algoritmo de assinatura: Assinar ou verificar os seguintes dados com a chave de assinatura da Alice ou do Charlie:

  • prologue: 16 bytes “PeerTestValidate”, não terminado em null (não incluído na mensagem)
  • bhash: Hash do roteador de Bob de 32 bytes (não incluído na mensagem)
  • ahash: Hash do roteador de Alice de 32 bytes (Usado apenas na assinatura para mensagens 3 e 4; não incluído na mensagem 3 ou 4)
  • ver: 1 byte versão SSU
  • nonce: 4 bytes nonce de teste
  • timestamp: 4 bytes timestamp (segundos)
  • asz: 1 byte tamanho do endpoint (porta + IP) (6 ou 18)
  • AlicePort: 2 bytes número da porta de Alice
  • Alice IP: (asz - 2) bytes endereço IP de Alice

Payload

TODO apenas se rotacionarmos chaves

+----+----+----+----+----+----+----+----+
  | 11 |  size   |      TBD               |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 11
  size :: 2 bytes, big endian, size of data to follow

Notas

4 bytes de confirmação (ack through), seguidos por uma contagem de confirmação e zero ou mais intervalos de confirmação negativa/confirmação (nack/ack).

Este design é adaptado e simplificado do QUIC. Os objetivos do design são os seguintes:

  • Queremos codificar eficientemente um “bitfield”, que é uma sequência de bits representando pacotes confirmados.
  • O bitfield é principalmente composto por 1’s. Tanto os 1’s quanto os 0’s geralmente vêm em “grupos” sequenciais.
  • A quantidade de espaço no pacote disponível para confirmações varia.
  • O bit mais importante é o de numeração mais alta. Os de numeração mais baixa são menos importantes. Abaixo de uma certa distância do bit mais alto, os bits mais antigos serão “esquecidos” e nunca mais enviados novamente.

A codificação especificada abaixo atinge esses objetivos de design, enviando o número do bit mais alto que está definido como 1, juntamente com bits consecutivos adicionais menores que esse que também estão definidos como 1. Após isso, se houver espaço, uma ou mais “faixas” especificando o número de bits 0 consecutivos e bits 1 consecutivos menores que esse. Veja QUIC RFC 9000 seção 13.2.3 para mais 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

Exemplos:

Queremos fazer ACK apenas do pacote 10:

  • Ack Through: 10
  • acnt: 0
  • nenhum intervalo está incluído

Queremos fazer ACK apenas dos pacotes 8-10:

  • Ack Through: 10
  • acnt: 2
  • nenhum intervalo está incluído

Queremos fazer ACK de 10 9 8 6 5 2 1 0, e NACK de 7 4 3. A codificação do Bloco ACK é:

  • Ack Through: 10
  • acnt: 2 (ack 9 8)
  • range: 1 2 (nack 7, ack 6 5)
  • range: 2 3 (nack 4 3, ack 2 1 0)

Notas:

  • Os intervalos podem não estar presentes. O número máximo de intervalos não é especificado, pode ser tantos quantos couberem no pacote.
  • O range nack pode ser zero se confirmando mais de 255 pacotes consecutivos.
  • O range ack pode ser zero se rejeitando mais de 255 pacotes consecutivos.
  • Range nack e ack não podem ser ambos zero.
  • Após o último intervalo, os pacotes não são nem confirmados nem rejeitados. O comprimento do bloco ack e como acks/nacks antigos são tratados fica a critério do remetente do bloco ack. Veja as seções de ack abaixo para discussão.
  • O ack through deve ser o número mais alto de pacote recebido, e quaisquer pacotes mais altos não foram recebidos. No entanto, em situações limitadas, pode ser menor, como confirmando um único pacote que “preenche uma lacuna”, ou uma implementação simplificada que não mantém o estado de todos os pacotes recebidos. Acima do mais alto recebido, os pacotes não são nem confirmados nem rejeitados, mas após vários blocos ack, pode ser apropriado entrar no modo de retransmissão rápida.
  • Este formato é uma versão simplificada daquele no QUIC. É projetado para codificar eficientemente um grande número de ACKs, junto com rajadas de NACKs.
  • Blocos ACK são usados para confirmar pacotes da fase de dados. Eles devem ser incluídos apenas para pacotes da fase de dados dentro da sessão.

Address

Porta de 2 bytes e endereço IP de 4 ou 16 bytes. Endereço da Alice, enviado para Alice pelo Bob, ou endereço do Bob, enviado para Bob pela 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

Isso pode ser enviado pela Alice em uma mensagem Session Request, Session Confirmed ou Data. Não é suportado na mensagem Session Created, pois Bob ainda não tem o RI da Alice e não sabe se Alice suporta relay. Além disso, se Bob está recebendo uma conexão de entrada, ele provavelmente não precisa de introducers (exceto talvez para o outro tipo ipv4/ipv6).

Quando enviado na Session Request, Bob pode responder com uma Relay Tag na mensagem Session Created, ou pode optar por aguardar o recebimento do RouterInfo de Alice na Session Confirmed para validar a identidade de Alice antes de responder em uma mensagem Data. Se Bob não deseja fazer relay para Alice, ele não envia um bloco Relay Tag.

+----+----+----+
  | 15 |    0    |
  +----+----+----+

  blk :: 15
  size :: 2 bytes, big endian, value = 0

Carga Útil

Isso pode ser enviado pelo Bob em uma mensagem Session Confirmed ou Data, em resposta a um Relay Tag Request da Alice.

Quando a Relay Tag Request é enviada na Session Request, Bob pode responder com uma Relay Tag na mensagem Session Created, ou pode escolher aguardar até receber o RouterInfo de Alice na Session Confirmed para validar a identidade de Alice antes de responder em uma mensagem Data. Se Bob não desejar fazer relay para Alice, ele não envia um bloco Relay Tag.

+----+----+----+----+----+----+----+
  | 16 |    4    |    relay tag      |
  +----+----+----+----+----+----+----+

  blk :: 16
  size :: 2 bytes, big endian, value = 4
  relay tag :: 4 bytes, big endian, nonzero

Notas

Para uma conexão subsequente. Geralmente incluído nas mensagens Session Created e Session Confirmed. Também pode ser enviado novamente na mensagem Data de uma sessão de longa duração se o token anterior expirar.

+----+----+----+----+----+----+----+----+
  | 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

Um Ping com dados arbitrários a serem retornados em uma Path Response, usado como keep-alive ou para validar uma mudança de IP/Porta.

+----+----+----+----+----+----+----+----+
  | 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:

É recomendado, mas não obrigatório, um tamanho mínimo de dados de 8 bytes, contendo dados aleatórios.

Path Response

Um Pong com os dados recebidos no Path Challenge, como resposta ao Path Challenge, usado como keep-alive ou para validar uma mudança de IP/Porta.

+----+----+----+----+----+----+----+----+
  | 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 incluído no handshake em cada direção, para especificar o primeiro número de pacote que será enviado. Isso fornece mais segurança para a criptografia do cabeçalho, similar ao TCP.

Não totalmente especificado, atualmente não suportado.

+----+----+----+----+----+----+----+
  | 20 |  size   |  First pkt number |
  +----+----+----+----+----+----+----+

  blk :: 20
  size :: 4
  pkt num :: The first packet number to be sent in the data phase

Congestion

Este bloco foi projetado para ser um método extensível para trocar informações de controle de congestionamento. O controle de congestionamento pode ser complexo e pode evoluir conforme ganhamos mais experiência com o protocolo em testes reais, ou após a implementação completa.

Isso mantém qualquer informação de congestionamento fora dos blocos I2NP, First Fragment, Followon Fragment e ACK de alto uso, onde não há espaço alocado para flags. Embora existam três bytes de flags não utilizados no cabeçalho do pacote Data, isso também fornece espaço limitado para extensibilidade e proteção de criptografia mais fraca.

Embora seja um tanto desperdiçador usar um bloco de 4 bytes para dois bits de informação, ao colocar isso em um bloco separado, podemos facilmente estendê-lo com dados adicionais como tamanhos de janela atuais, RTT medido, ou outras flags. A experiência mostrou que apenas bits de flag é frequentemente insuficiente e inconveniente para implementação de esquemas avançados de controle de congestionamento. Tentar adicionar suporte para qualquer recurso possível de controle de congestionamento no, por exemplo, bloco ACK, desperdiçaria espaço e adicionaria complexidade à análise desse bloco.

As implementações não devem presumir que o outro router suporte qualquer bit de flag específico ou funcionalidade incluída aqui, a menos que a implementação seja exigida por uma versão futura desta especificação.

Este bloco provavelmente deve ser o último bloco sem padding na 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

Payload

Isto é para preenchimento dentro de payloads AEAD. O preenchimento para todas as mensagens está dentro de payloads AEAD.

O padding deve aderir aproximadamente aos parâmetros negociados. Bob enviou seus parâmetros tx/rx min/max solicitados em Session Created. Alice enviou seus parâmetros tx/rx min/max solicitados em Session Confirmed. Opções atualizadas podem ser enviadas durante a fase de dados. Veja as informações do bloco de opções acima.

Se presente, este deve ser o último bloco no payload.

+----+----+----+----+----+----+----+----+
  |254 |  size   |      padding           |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 254
  size :: 2 bytes, big endian, size of padding to follow
  padding :: random data

Notas:

  • Tamanho = 0 é permitido.

  • Estratégias de padding a serem definidas.

  • Padding mínimo a ser definido.

  • Payloads contendo apenas padding são permitidos.

  • Padrões de padding a serem definidos.

  • Consulte o bloco de opções para negociação de parâmetros de padding

  • Consulte o bloco de opções para parâmetros de padding mín/máx

  • Não exceda o MTU. Se mais padding for necessário, envie múltiplas mensagens.

  • Resposta do router em caso de violação do padding negociado depende da implementação.

  • O comprimento do padding deve ser decidido por mensagem com base em estimativas da distribuição de comprimento, ou atrasos aleatórios devem ser adicionados. Essas contramedidas devem ser incluídas para resistir ao DPI, pois os tamanhos das mensagens revelariam que o tráfego I2P está sendo transportado pelo protocolo de transporte. O esquema exato de padding é uma área de trabalho futuro, o Apêndice A do NTCP2 fornece mais informações sobre o tópico.

Replay Prevention

SSU2 é projetado para minimizar o impacto de mensagens reproduzidas por um atacante.

As mensagens Token Request, Retry, Session Request, Session Created, Hole Punch e Peer Test fora de sessão devem conter blocos DateTime.

Tanto Alice quanto Bob validam que o tempo para essas mensagens está dentro de um desvio válido (recomendado +/- 2 minutos). Para “resistência a sondagem”, Bob não deve responder a mensagens Token Request ou Session Request se o desvio for inválido, pois essas mensagens podem ser um ataque de replay ou sondagem.

Bob pode optar por rejeitar mensagens duplicadas de Token Request e Retry, mesmo que o skew seja válido, através de um filtro Bloom ou outro mecanismo. No entanto, o tamanho e o custo de CPU para responder a essas mensagens é baixo. Na pior das hipóteses, uma mensagem Token Request reproduzida pode invalidar um token enviado anteriormente.

O sistema de tokens minimiza significativamente o impacto de mensagens Session Request repetidas. Como os tokens só podem ser usados uma vez, uma mensagem Session Request repetida nunca terá um token válido. Bob pode escolher rejeitar mensagens Session Request duplicadas, mesmo se o skew for válido, através de um filtro Bloom ou outro mecanismo. No entanto, o tamanho e o custo de CPU de responder com uma mensagem Retry é baixo. Na pior das hipóteses, enviar uma mensagem Retry pode invalidar um token enviado anteriormente.

Mensagens duplicadas de Session Created e Session Confirmed não irão validar porque o estado do handshake Noise não estará no estado correto para descriptografá-las. Na pior das hipóteses, um peer pode retransmitir um Session Confirmed em resposta a um aparente Session Created duplicado.

Mensagens de Hole Punch e Peer Test repetidas devem ter pouco ou nenhum impacto.

Os routers devem usar o número do pacote da mensagem de dados para detectar e descartar mensagens duplicadas da fase de dados. Cada número de pacote deve ser usado apenas uma vez. Mensagens reenviadas devem ser ignoradas.

Handshake Retransmission

Session Request

Se nenhuma Session Created ou Retry for recebida por Alice:

Mantenha os mesmos IDs de origem e conexão, chave efêmera e número de pacote 0. Ou, apenas retenha e retransmita o mesmo pacote criptografado. O número do pacote não deve ser incrementado, pois isso alteraria o valor de hash encadeado usado para criptografar a mensagem Session Created.

Intervalos de retransmissão recomendados: 1,25, 2,5 e 5 segundos (1,25, 3,75 e 8,75 segundos após o primeiro envio). Timeout recomendado: 15 segundos no total

Session Created

Se nenhum Session Confirmed for recebido por Bob:

Mantenha os mesmos IDs de origem e conexão, chave efêmera e número de pacote 0. Ou, simplesmente retenha o pacote criptografado. O número do pacote não deve ser incrementado, pois isso alteraria o valor hash encadeado usado para criptografar a mensagem Session Confirmed.

Intervalos de retransmissão recomendados: 1, 2 e 4 segundos (1, 3 e 7 segundos após o primeiro envio). Timeout recomendado: 12 segundos no total

Session Confirmed

No SSU 1, Alice não muda para a fase de dados até que o primeiro pacote de dados seja recebido de Bob. Isso faz do SSU 1 uma configuração de duas viagens de ida e volta.

Para SSU 2, intervalos de retransmissão Session Confirmed recomendados: 1,25, 2,5 e 5 segundos (1,25, 3,75 e 8,75 segundos após o primeiro envio).

Existem várias alternativas. Todas são 1 RTT:

  1. Alice assume que Session Confirmed foi recebido, envia mensagens de dados imediatamente, nunca retransmite Session Confirmed. Pacotes de dados recebidos fora de ordem (antes de Session Confirmed) serão indecifráveis, mas serão retransmitidos. Se Session Confirmed for perdido, todas as mensagens de dados enviadas serão descartadas.

  2. Como em 1), envie mensagens de dados imediatamente, mas também retransmita Session Confirmed até que uma mensagem de dados seja recebida.

  3. Poderíamos usar IK em vez de XK, já que possui apenas duas mensagens no handshake, mas usa um DH extra (4 em vez de 3).

A implementação recomendada é a opção 2). Alice deve manter as informações necessárias para retransmitir a mensagem Session Confirmed. Alice também deve retransmitir todas as mensagens Data após a mensagem Session Confirmed ser retransmitida.

Ao retransmitir Session Confirmed, mantenha os mesmos IDs de origem e conexão, chave efêmera e número de pacote 1. Ou apenas retenha o pacote criptografado. O número do pacote não deve ser incrementado, pois isso alteraria o valor do hash encadeado que é uma entrada para a função split().

Bob pode reter (enfileirar) as mensagens de dados recebidas antes da mensagem Session Confirmed. Nem as chaves de proteção de cabeçalho nem as chaves de descriptografia estão disponíveis antes da mensagem Session Confirmed ser recebida, então Bob não sabe que são mensagens de dados, mas isso pode ser presumido. Após a mensagem Session Confirmed ser recebida, Bob consegue descriptografar e processar as mensagens de dados enfileiradas. Se isso for muito complexo, Bob pode simplesmente descartar as mensagens de dados não descriptografáveis, já que Alice irá retransmiti-las.

Nota: Se os pacotes de sessão confirmada forem perdidos, Bob retransmitirá a sessão criada. O cabeçalho da sessão criada não será decifrável com a chave de introdução de Alice, pois está definido com a chave de introdução de Bob (a menos que seja realizada a descriptografia de fallback com a chave de introdução de Bob). Bob pode retransmitir imediatamente os pacotes de sessão confirmada se não foram previamente confirmados, e um pacote não decifrável é recebido.

Token Request

Se nenhum Retry for recebido pela Alice:

Mantenha os mesmos IDs de origem e conexão. Uma implementação pode gerar um novo número de pacote aleatório e criptografar um novo pacote; Ou pode reutilizar o mesmo número de pacote ou apenas reter e retransmitir o mesmo pacote criptografado. O número do pacote não deve ser incrementado, porque isso alteraria o valor do hash encadeado usado para criptografar a mensagem Session Created.

Intervalos de retransmissão recomendados: 3 e 6 segundos (3 e 9 segundos após o primeiro envio). Timeout recomendado: 15 segundos no total

Retry

Se nenhuma Solicitação de Sessão for recebida pelo Bob:

Uma mensagem Retry não é retransmitida em timeout, para reduzir os impactos de endereços de origem falsificados.

No entanto, uma mensagem Retry pode ser retransmitida em resposta a uma mensagem Session Request repetida sendo recebida com o token original (inválido), ou em resposta a uma mensagem Token Request repetida. Em ambos os casos, isso indica que a mensagem Retry foi perdida.

Se uma segunda mensagem Session Request for recebida com um token diferente mas ainda inválido, descarte a sessão pendente e não responda.

Se reenviar a mensagem de Retry: Mantenha os mesmos IDs de origem e conexão e token. Uma implementação pode gerar um novo número de pacote aleatório e criptografar um novo pacote; Ou pode reutilizar o mesmo número de pacote ou apenas reter e retransmitir o mesmo pacote criptografado.

Total Timeout

O timeout total recomendado para o handshake é de 20 segundos.

Duplicates and Error Handling

As duplicatas das três mensagens de handshake Noise Session Request, Session Created e Session Confirmed devem ser detectadas antes do MixHash() do cabeçalho. Embora o processamento AEAD do Noise provavelmente falhe depois disso, o hash do handshake já estaria corrompido.

Se qualquer uma das três mensagens for corrompida e falhar no AEAD, o handshake não pode ser recuperado posteriormente mesmo com retransmissão, porque MixHash() já foi chamado na mensagem corrompida.

Tokens

O Token no cabeçalho Session Request é usado para mitigação de DoS, para prevenir falsificação de endereço de origem e como resistência a ataques de replay.

Se Bob não aceitar o token na mensagem Session Request, Bob NÃO descriptografa a mensagem, pois isso requer uma operação DH custosa. Bob simplesmente envia uma mensagem Retry com um novo token.

Se uma mensagem Session Request subsequente for então recebida com esse token, Bob procede para descriptografar essa mensagem e continuar com o handshake.

O token deve ser um valor de 8 bytes gerado aleatoriamente, se o gerador do token armazenar os valores e o IP e porta associados (na memória ou persistentemente). O gerador não pode gerar um valor opaco, por exemplo, usando o SipHash (com uma semente secreta K0, K1) do IP, porta e hora ou dia atual, para criar tokens que não precisam ser salvos na memória, porque este método torna difícil rejeitar tokens reutilizados e ataques de replay.

Os tokens só podem ser usados uma vez. Um token enviado de Bob para Alice numa mensagem Retry deve ser usado imediatamente, e expira em alguns segundos. Um token enviado num bloco New Token numa sessão estabelecida pode ser usado numa conexão subsequente, e expira no momento especificado nesse bloco. A expiração é especificada pelo remetente; valores recomendados são mínimo de uma hora, máximo de várias horas.

Se o IP ou porta de um router mudar, ele deve excluir todos os tokens salvos (tanto de entrada quanto de saída) para o IP ou porta antigo, pois eles não são mais válidos. Os tokens podem opcionalmente ser mantidos entre reinicializações do router, dependendo da implementação. A aceitação de um token não expirado não é garantida; se Bob esqueceu ou excluiu seus tokens salvos, ele enviará um Retry para Alice. Um router pode escolher limitar o armazenamento de tokens, e remover os tokens mais antigos armazenados mesmo que eles não tenham expirado.

Novos blocos de Token podem ser enviados de Alice para Bob ou de Bob para Alice. Eles normalmente seriam enviados uma vez, durante ou logo após o estabelecimento da sessão. O token pode ser reenviado antes ou após a expiração com um novo tempo de expiração, ou um novo token pode ser enviado. Os routers devem assumir que apenas o último token recebido é válido; não há requisito para armazenar múltiplos tokens de entrada ou saída para o mesmo IP/porta.

Um token está vinculado à combinação de IP/porta de origem e IP/porta de destino. Um token recebido em IPv4 não pode ser usado para IPv6 ou vice-versa.

Se qualquer peer migra para um novo IP ou porta durante a sessão (veja a seção Connection Migration), quaisquer tokens previamente trocados são invalidados, e novos tokens devem ser trocados.

As implementações podem, mas não são obrigatórias a, salvar tokens no disco e recarregá-los na reinicialização. Se persistidos, a implementação deve garantir que o IP e a porta não mudaram desde o desligamento antes de recarregá-los.

I2NP Message Fragmentation

Diferenças do SSU 1

Nota: Como no SSU 1, o fragmento inicial não contém informações sobre o número total de fragmentos ou o comprimento total. Fragmentos subsequentes não contêm informações sobre seu deslocamento. Isso proporciona ao remetente a flexibilidade de fragmentar “em tempo real” com base no espaço disponível no pacote. (O Java I2P não faz isso; ele “pré-fragmenta” antes do primeiro fragmento ser enviado) No entanto, isso sobrecarrega o receptor para armazenar fragmentos recebidos fora de ordem e atrasar a remontagem até que todos os fragmentos sejam recebidos.

Como no SSU 1, qualquer retransmissão de fragmentos deve preservar o comprimento (e o deslocamento implícito) da transmissão anterior do fragmento.

SSU 2 separa os três casos (mensagem completa, fragmento inicial e fragmento subsequente) em três tipos de blocos diferentes, para melhorar a eficiência de processamento.

I2NP Message Duplication

Este protocolo NÃO previne completamente a entrega duplicada de mensagens I2NP. Duplicatas da camada IP ou ataques de replay serão detectados na camada SSU2, porque cada número de pacote só pode ser usado uma vez.

Quando mensagens I2NP ou fragmentos são retransmitidos em novos pacotes, no entanto, isso não é detectável na camada SSU2. O router deve impor a expiração I2NP (tanto muito antiga quanto muito distante no futuro) e usar um filtro Bloom ou outro mecanismo baseado no ID da mensagem I2NP.

Mecanismos adicionais podem ser usados pelo router, ou na implementação SSU2, para detectar duplicatas. Por exemplo, o SSU2 poderia manter um cache dos IDs de mensagem recebidos recentemente. Isso é dependente da implementação.

Congestion Control

Esta proposta especifica o protocolo para numeração de pacotes e blocos ACK. Isso fornece informações em tempo real suficientes para um transmissor implementar um algoritmo de controle de congestionamento eficiente e responsivo, enquanto permite flexibilidade e inovação nessa implementação. Esta seção discute objetivos de implementação e fornece sugestões. Orientações gerais podem ser encontradas na RFC 9002. Veja também a RFC 6298 para orientações sobre temporizadores de retransmissão.

Pacotes de dados apenas com ACK não devem contar para bytes ou pacotes em trânsito e não são controlados por congestionamento. Ao contrário do TCP, o SSU2 pode detectar a perda desses pacotes e essa informação pode ser usada para ajustar o estado de congestionamento. No entanto, este documento não especifica um mecanismo para fazer isso.

Pacotes contendo alguns outros blocos não-dados também podem ser excluídos do controle de congestionamento se desejado, dependente da implementação. Por exemplo:

  • Teste de Peer
  • Solicitação/introdução/resposta de relay
  • Desafio/resposta de caminho

É recomendado que o controle de congestionamento seja baseado na contagem de bytes, não na contagem de pacotes, seguindo a orientação nos RFCs do TCP e QUIC RFC 9002. Um limite adicional de contagem de pacotes também pode ser útil para prevenir overflow de buffer no kernel ou em middleboxes, dependente da implementação, embora isso possa adicionar complexidade significativa. Se a saída de pacotes por sessão e/ou total for limitada por largura de banda e/ou controlada por ritmo, isso pode mitigar a necessidade de limitação da contagem de pacotes.

Packet Numbers

No SSU 1, ACKs e NACKs continham números de mensagem I2NP e bitmasks de fragmento. Os transmissores rastreavam o status de ACK das mensagens de saída (e seus fragmentos) e retransmitiam fragmentos conforme necessário.

No SSU 2, ACKs e NACKs contêm números de pacotes. Os transmissores devem manter uma estrutura de dados com um mapeamento dos números de pacotes para seus conteúdos. Quando um pacote é ACKed ou NACKed, o transmissor deve determinar quais mensagens I2NP e fragmentos estavam naquele pacote, para decidir o que retransmitir.

Session Confirmed ACK

Bob envia um ACK do pacote 0, que reconhece a mensagem Session Confirmed e permite que Alice prossiga para a fase de dados, e descarte a grande mensagem Session Confirmed que estava sendo salva para possível retransmissão. Isso substitui a DeliveryStatusMessage enviada por Bob no SSU 1.

Bob deve enviar um ACK o mais rápido possível após receber a mensagem Session Confirmed. Um pequeno atraso (não mais que 50 ms) é aceitável, já que pelo menos uma mensagem Data deve chegar quase imediatamente após a mensagem Session Confirmed, para que o ACK possa reconhecer tanto a Session Confirmed quanto a mensagem Data. Isso impedirá que Bob tenha que retransmitir a mensagem Session Confirmed.

Generating ACKs

Definição: Pacotes que provocam ACK: Pacotes que contêm blocos que provocam ACK elicitam um ACK do receptor dentro do atraso máximo de acknowledgment e são chamados de pacotes que provocam ACK.

Os routers reconhecem todos os pacotes que recebem e processam. No entanto, apenas pacotes que solicitam confirmação fazem com que um bloco ACK seja enviado dentro do atraso máximo de confirmação. Pacotes que não solicitam confirmação só são reconhecidos quando um bloco ACK é enviado por outros motivos.

Ao enviar um pacote por qualquer motivo, um endpoint deve tentar incluir um bloco ACK se um não foi enviado recentemente. Fazer isso ajuda na detecção oportuna de perda no peer.

Em geral, feedback frequente de um receptor melhora a resposta à perda e ao congestionamento, mas isso deve ser equilibrado contra a carga excessiva gerada por um receptor que envia um bloco ACK em resposta a cada pacote que solicita confirmação. A orientação oferecida abaixo busca encontrar esse equilíbrio.

Pacotes de dados dentro da sessão contendo qualquer bloco EXCETO os seguintes provocam ack:

  • Bloco ACK
  • Bloco de endereço
  • Bloco DateTime
  • Bloco de preenchimento
  • Bloco de terminação
  • Quaisquer blocos no mesmo pacote que um bloco de terminação
  • Outros?

Pacotes contendo um bloco de Termination com um motivo diferente de “termination received” são confirmados com um pacote contendo um bloco de Termination com “termination received”.

Pacotes fora de sessão, incluindo mensagens de handshake e mensagens de teste de peer 5-7, têm seus próprios mecanismos de confirmação. Veja abaixo.

Handshake ACKs

Estes são casos especiais:

  • Token Request é implicitamente confirmado por Retry
  • Session Request é implicitamente confirmado por Session Created ou Retry
  • Retry é implicitamente confirmado por Session Request
  • Session Created é implicitamente confirmado por Session Confirmed
  • Session Confirmed deve ser confirmado imediatamente

Sending ACK Blocks

Os blocos ACK são usados para confirmar os pacotes da fase de dados. Eles devem ser incluídos apenas para pacotes da fase de dados dentro da sessão.

Todo pacote deve ser confirmado pelo menos uma vez, e pacotes que exigem confirmação devem ser confirmados pelo menos uma vez dentro de um atraso máximo.

Um endpoint deve reconhecer todos os pacotes de handshake que exigem confirmação imediatamente dentro de seu atraso máximo, com a seguinte exceção. Antes da confirmação do handshake, um endpoint pode não ter as chaves de criptografia do cabeçalho do pacote para descriptografar os pacotes quando eles são recebidos. Portanto, pode armazená-los em buffer e reconhecê-los quando as chaves necessárias se tornarem disponíveis.

Uma vez que pacotes contendo apenas blocos ACK não são controlados por congestionamento, um endpoint não deve enviar mais de um desses pacotes em resposta ao recebimento de um pacote que solicita confirmação.

Um endpoint não deve enviar um pacote que não solicita ACK em resposta a um pacote que não solicita ACK, mesmo que existam lacunas de pacotes que precedem o pacote recebido. Isso evita um loop infinito de confirmações, que poderia impedir que a conexão jamais fique inativa. Pacotes que não solicitam ACK são eventualmente confirmados quando o endpoint envia um bloco ACK em resposta a outros eventos.

Um endpoint que está apenas enviando blocos ACK não receberá confirmações de seu peer a menos que essas confirmações sejam incluídas em pacotes com blocos que provocam ack. Um endpoint deve enviar um bloco ACK com outros blocos quando há novos pacotes que provocam ack para confirmar. Quando apenas pacotes que não provocam ack precisam ser confirmados, um endpoint PODE escolher não enviar um bloco ACK com blocos de saída até que um pacote que provoca ack tenha sido recebido.

Um endpoint que está apenas enviando pacotes que não requerem confirmação (non-ack-eliciting) pode escolher ocasionalmente adicionar um bloco que requer confirmação (ack-eliciting) a esses pacotes para garantir que receba uma confirmação. Nesse caso, um endpoint NÃO DEVE enviar um bloco que requer confirmação em todos os pacotes que de outra forma não requereriam confirmação, para evitar um loop infinito de confirmações.

Para auxiliar a detecção de perda no remetente, um endpoint deve gerar e enviar um bloco ACK sem demora quando receber um pacote que elicita ACK em qualquer um destes casos:

  • Quando o pacote recebido tem um número de pacote menor que outro pacote ack-eliciting que foi recebido

  • Quando o pacote tem um número de pacote maior que o pacote ack-eliciting com numeração mais alta que foi recebido e há pacotes perdidos entre esse pacote e este pacote.

  • Quando a flag ack-immediate no cabeçalho do pacote estiver definida

Os algoritmos devem ser resilientes a receptores que não seguem as orientações oferecidas acima. No entanto, uma implementação deve desviar-se destes requisitos apenas após consideração cuidadosa das implicações de desempenho de uma mudança, para conexões feitas pelo endpoint e para outros usuários da rede.

ACK Frequency

Um receptor determina com que frequência enviar confirmações de recebimento em resposta a pacotes que exigem confirmação. Esta determinação envolve um compromisso.

Os endpoints dependem de confirmações oportunas para detectar perdas. Os controladores de congestionamento baseados em janela dependem de confirmações para gerenciar sua janela de congestionamento. Em ambos os casos, atrasar as confirmações pode afetar adversamente o desempenho.

Por outro lado, reduzir a frequência de pacotes que carregam apenas acknowledgments reduz o custo de transmissão e processamento de pacotes em ambos os endpoints. Isso pode melhorar o throughput da conexão em links severamente assimétricos e reduzir o volume de tráfego de acknowledgment usando a capacidade do caminho de retorno; veja a Seção 3 de RFC 3449.

Um receptor deve enviar um bloco ACK após receber pelo menos dois pacotes que solicitam confirmação. Esta recomendação é de natureza geral e consistente com as recomendações para comportamento de endpoint TCP RFC 5681. Conhecimento das condições da rede, conhecimento do controlador de congestionamento do peer, ou pesquisa e experimentação adicionais podem sugerir estratégias alternativas de confirmação com melhores características de desempenho.

Um receptor pode processar múltiplos pacotes disponíveis antes de determinar se deve enviar um bloco ACK em resposta. Em geral, o receptor não deve atrasar um ACK por mais de RTT / 6, ou 150 ms no máximo.

A flag ack-immediate no cabeçalho do pacote de dados é uma solicitação para que o receptor envie um ack logo após a recepção, provavelmente dentro de alguns ms. Em geral, o receptor não deve atrasar um ACK imediato por mais de RTT / 16, ou 5 ms no máximo.

Immediate ACK Flag

O receptor não conhece o tamanho da janela de envio do remetente e, portanto, não sabe quanto tempo aguardar antes de enviar um ACK. A flag de ACK imediato no cabeçalho do pacote de dados é uma forma importante de manter o throughput máximo ao minimizar o RTT efetivo. A flag de ACK imediato está no byte 13 do cabeçalho, bit 0, ou seja, (header[13] & 0x01). Quando definida, um ACK imediato é solicitado. Consulte a seção de cabeçalho curto acima para detalhes.

Existem várias estratégias possíveis que um remetente pode usar para determinar quando definir a flag immediate-ack:

  • Definido uma vez a cada N pacotes, para algum N pequeno
  • Definido no último de uma rajada de pacotes
  • Definido sempre que a janela de envio está quase cheia, por exemplo, mais de 2/3 cheia
  • Definido em todos os pacotes com fragmentos retransmitidos

As flags de ACK imediato só devem ser necessárias em pacotes de dados que contenham mensagens I2NP ou fragmentos de mensagem.

ACK Block Size

Quando um bloco ACK é enviado, uma ou mais faixas de pacotes confirmados são incluídas. Incluir confirmações para pacotes mais antigos reduz a chance de retransmissões espúrias causadas pela perda de blocos ACK enviados anteriormente, ao custo de blocos ACK maiores.

Os blocos ACK devem sempre confirmar os pacotes recebidos mais recentemente, e quanto mais fora de ordem os pacotes estiverem, mais importante é enviar um bloco ACK atualizado rapidamente, para evitar que o peer declare um pacote como perdido e retransmita erroneamente os blocos que ele contém. Um bloco ACK deve caber dentro de um único pacote. Se não couber, então os intervalos mais antigos (aqueles com os menores números de pacote) são omitidos.

Um receptor limita o número de intervalos ACK que lembra e envia em blocos ACK, tanto para limitar o tamanho dos blocos ACK quanto para evitar esgotamento de recursos. Após receber confirmações para um bloco ACK, o receptor deve parar de rastrear esses intervalos ACK confirmados. Os remetentes podem esperar confirmações para a maioria dos pacotes, mas este protocolo não garante o recebimento de uma confirmação para cada pacote que o receptor processa.

É possível que reter muitos intervalos de ACK possa fazer com que um bloco ACK se torne muito grande. Um receptor pode descartar intervalos de ACK não confirmados para limitar o tamanho do bloco ACK, ao custo de aumentar as retransmissões do remetente. Isso é necessário se um bloco ACK for muito grande para caber em um pacote. Os receptores também podem limitar ainda mais o tamanho do bloco ACK para preservar espaço para outros blocos ou para limitar a largura de banda que as confirmações consomem.

Um receptor deve manter um intervalo ACK a menos que possa garantir que não irá posteriormente aceitar pacotes com números nesse intervalo. Manter um número mínimo de pacote que aumenta conforme os intervalos são descartados é uma forma de conseguir isso com estado mínimo.

Os receptores podem descartar todos os intervalos ACK, mas devem reter o maior número de pacote que foi processado com sucesso, pois isso é usado para recuperar números de pacotes de pacotes subsequentes.

A seção seguinte descreve uma abordagem exemplar para determinar quais pacotes devem ser reconhecidos em cada bloco ACK. Embora o objetivo deste algoritmo seja gerar um reconhecimento para cada pacote que é processado, ainda é possível que os reconhecimentos sejam perdidos.

Limiting Ranges by Tracking ACK Blocks

Quando um pacote contendo um bloco ACK é enviado, o campo Ack Through nesse bloco pode ser salvo. Quando um pacote contendo um bloco ACK é confirmado, o receptor pode parar de confirmar pacotes menores ou iguais ao campo Ack Through no bloco ACK enviado.

Um receptor que envia apenas pacotes que não geram ACK, como blocos ACK, pode não receber uma confirmação por um longo período de tempo. Isso poderia fazer com que o receptor mantenha estado para um grande número de blocos ACK por um longo período de tempo, e os blocos ACK que ele envia poderiam ser desnecessariamente grandes. Nesse caso, um receptor poderia enviar um PING ou outro pequeno bloco que gere ACK ocasionalmente, como uma vez por round trip, para obter um ACK do peer.

Em casos sem perda de blocos ACK, este algoritmo permite um mínimo de 1 RTT de reordenação. Em casos com perda de blocos ACK e reordenação, esta abordagem não garante que cada confirmação seja vista pelo remetente antes que não seja mais incluída no bloco ACK. Os pacotes podem ser recebidos fora de ordem, e todos os blocos ACK subsequentes que os contêm podem ser perdidos. Neste caso, o algoritmo de recuperação de perda pode causar retransmissões espúrias, mas o remetente continuará fazendo progresso.

Congestion

Os transportes I2P não garantem a entrega em ordem das mensagens I2NP. Portanto, a perda de uma mensagem Data contendo uma ou mais mensagens I2NP ou fragmentos NÃO impede que outras mensagens I2NP sejam entregues; não há bloqueio de cabeça de linha. As implementações devem continuar a enviar novas mensagens durante a fase de recuperação de perda se a janela de envio permitir.

Retransmission

Um remetente não deve reter o conteúdo completo de uma mensagem, para ser retransmitida de forma idêntica (exceto para mensagens de handshake, veja acima). Um remetente deve montar mensagens contendo informações atualizadas (ACKs, NACKs, e dados não confirmados) toda vez que enviar uma mensagem. Um remetente deve evitar retransmitir informações de mensagens uma vez que elas são confirmadas. Isso inclui mensagens que são confirmadas após serem declaradas perdidas, o que pode acontecer na presença de reordenação de rede.

Window

A definir. Orientações gerais podem ser encontradas na RFC 9002.

Connection Migration

O IP ou porta de um peer pode mudar durante o tempo de vida de uma sessão. Uma mudança de IP pode ser causada por rotação de endereço temporário IPv6, mudança periódica de IP dirigida pelo ISP, um cliente móvel fazendo transição entre IPs WiFi e celular, ou outras mudanças de rede local. Uma mudança de porta pode ser causada por uma nova vinculação NAT após a vinculação anterior ter expirado.

O IP ou porta de um peer pode parecer mudar devido a vários ataques on-path e off-path, incluindo modificação ou injeção de pacotes.

A migração de conexão é o processo pelo qual um novo endpoint de origem (IP+porta) é validado, ao mesmo tempo que previne mudanças que não são validadas. Este processo é uma versão simplificada daquele definido no QUIC RFC 9000. Este processo é definido apenas para a fase de dados de uma sessão. A migração não é permitida durante o handshake. Todos os pacotes de handshake devem ser verificados para confirmar que são do mesmo IP e porta dos pacotes enviados e recebidos anteriormente. Em outras palavras, o IP e a porta de um peer devem ser constantes durante o handshake.

Threat Model

(Adaptado de QUIC RFC 9000)

Notas

Um peer pode falsificar seu endereço de origem para fazer com que um endpoint envie quantidades excessivas de dados para um host não disposto. Se o endpoint enviar significativamente mais dados do que o peer que está falsificando, a migração de conexão pode ser usada para amplificar o volume de dados que um atacante pode gerar em direção a uma vítima.

Fragmentação de Sessão Confirmada

Um atacante no caminho poderia causar uma migração de conexão espúria copiando e encaminhando um pacote com um endereço falsificado de modo que chegue antes do pacote original. O pacote com o endereço falsificado será visto como proveniente de uma conexão em migração, e o pacote original será visto como duplicado e descartado. Após uma migração espúria, a validação do endereço de origem falhará porque a entidade no endereço de origem não possui as chaves criptográficas necessárias para ler ou responder ao Path Challenge que é enviado a ela, mesmo que quisesse.

Off-Path Packet Forwarding

Um atacante fora do caminho que consegue observar pacotes pode encaminhar cópias de pacotes genuínos para os endpoints. Se o pacote copiado chegar antes do pacote genuíno, isso aparecerá como um rebinding de NAT. Qualquer pacote genuíno será descartado como duplicado. Se o atacante conseguir continuar encaminhando pacotes, pode conseguir causar migração para um caminho via o atacante. Isso coloca o atacante no caminho, dando-lhe a capacidade de observar ou descartar todos os pacotes subsequentes.

Privacy Implications

QUIC RFC 9000 especificou a alteração de IDs de conexão ao mudar caminhos de rede. Usar um ID de conexão estável em múltiplos caminhos de rede permitiria que um observador passivo correlacionasse atividade entre esses caminhos. Um endpoint que se move entre redes pode não querer ter sua atividade correlacionada por qualquer entidade além de seu peer. No entanto, QUIC não criptografa os IDs de conexão no cabeçalho. SSU2 faz isso, então o vazamento de privacidade exigiria que o observador passivo também tivesse acesso ao banco de dados de rede para obter a chave de introdução necessária para descriptografar o ID de conexão. Mesmo com a chave de introdução, este não é um ataque forte, e não alteramos IDs de conexão após migração no SSU2, pois isso seria uma complicação significativa.

Initiating Path Validation

Durante a fase de dados, os peers devem verificar o IP de origem e a porta de cada pacote de dados recebido. Se o IP ou porta for diferente do recebido anteriormente, E o pacote não for um número de pacote duplicado, E o pacote descriptografar com sucesso, a sessão entra na fase de validação de caminho.

Além disso, um peer deve verificar se o novo IP e porta são válidos de acordo com as regras de validação locais (não bloqueados, não são portas ilegais, etc.). Os peers NÃO são obrigados a suportar migração entre IPv4 e IPv6, e podem tratar um novo IP na outra família de endereços como inválido, já que este não é um comportamento esperado e pode adicionar complexidade significativa na implementação. Ao receber um pacote de um IP/porta inválido, uma implementação pode simplesmente descartá-lo, ou pode iniciar uma validação de caminho com o IP/porta antigo.

Ao entrar na fase de validação de caminho, execute as seguintes etapas:

  • Iniciar um timer de timeout de validação de caminho de vários segundos, ou várias vezes o RTO atual (a ser definido)
  • Reduzir a janela de congestionamento ao mínimo
  • Reduzir o PMTU ao mínimo (1280)
  • Enviar um pacote de dados contendo um bloco Path Challenge, um bloco Address (contendo o novo IP/porta), e, tipicamente, um bloco ACK, para o novo IP e porta. Este pacote usa o mesmo connection ID e chaves de criptografia da sessão atual. Os dados do bloco Path Challenge devem conter entropia suficiente (pelo menos 8 bytes) para que não possam ser falsificados.
  • Opcionalmente, também enviar um Path Challenge para o IP/porta antigo, com dados de bloco diferentes. Veja abaixo.
  • Iniciar um timer de timeout Path Response baseado no RTO atual (tipicamente RTT + um múltiplo de RTTdev)

Durante a fase de validação de caminho, a sessão pode continuar a processar pacotes recebidos. Seja do IP/porta antigo ou novo. A sessão também pode continuar a enviar e confirmar pacotes de dados. No entanto, a janela de congestionamento e PMTU devem permanecer nos valores mínimos durante a fase de validação de caminho, para evitar serem usados para ataques de negação de serviço através do envio de grandes quantidades de tráfego para um endereço falsificado.

Uma implementação pode, mas não é obrigatório, tentar validar múltiplos caminhos simultaneamente. Isso provavelmente não vale a complexidade. Ela pode, mas não é obrigatório, lembrar de um IP/porta anterior como já validado, e pular a validação de caminho se um peer retornar ao seu IP/porta anterior.

Se uma Path Response for recebida, contendo os dados idênticos enviados no Path Challenge, a Path Validation foi bem-sucedida. O IP/porta de origem da mensagem Path Response não precisa ser o mesmo para o qual o Path Challenge foi enviado.

Se uma Path Response não for recebida antes do timer de Path Response expirar, envie outro Path Challenge e duplique o timer de Path Response.

Se uma Path Response não for recebida antes do timer de Path Validation expirar, a Path Validation falhou.

Message Contents

As mensagens Data devem conter os seguintes blocos. A ordem não é especificada, exceto que o Padding deve ser o último:

  • Bloco de Path Validation ou Path Response. Path Validation contém dados opacos, recomendado mínimo de 8 bytes. Path Response contém os dados do Path Validation.
  • Bloco de endereço contendo o IP aparente do destinatário
  • Bloco DateTime
  • Bloco ACK
  • Bloco de preenchimento

Não é recomendado incluir outros blocos (por exemplo, I2NP) na mensagem.

É permitido incluir um bloco Path Validation na mensagem contendo a Path Response, para iniciar uma validação na outra direção.

Os blocos Path Challenge e Path Response são ACK-eliciting. O Path Challenge será ACKed por uma mensagem Data contendo os blocos Path Response e ACK. O Path Response deve ser ACKed por uma mensagem Data contendo um bloco ACK.

Routing during Path Validation

A especificação QUIC não é clara sobre onde enviar pacotes de dados durante a validação de caminho - para o IP/porta antigo ou novo? Há um equilíbrio a ser alcançado entre responder rapidamente a mudanças de IP/porta e não enviar tráfego para endereços falsificados. Além disso, pacotes falsificados não devem ser permitidos a impactar substancialmente uma sessão existente. Mudanças apenas de porta provavelmente são causadas por reassociação NAT após um período inativo; mudanças de IP podem acontecer durante fases de alto tráfego em uma ou ambas as direções.

Estratégias estão sujeitas a pesquisa e refinamento. Possibilidades incluem:

  • Não enviar pacotes de dados para o novo IP/porta até ser validado
  • Continuar enviando pacotes de dados para o antigo IP/porta até que o novo IP/porta seja validado
  • Revalidar simultaneamente o antigo IP/porta
  • Não enviar dados até que o antigo ou novo IP/porta seja validado
  • Estratégias diferentes para mudança apenas de porta do que para mudança de IP
  • Estratégias diferentes para mudança de IPv6 no mesmo /32, provavelmente causada por rotação de endereço temporário

Responding to Path Challenge

Ao receber um Path Challenge, o peer deve responder com um pacote de dados contendo um Path Response, com os dados do Path Challenge. TODO Talvez???: O Path Response deve ser enviado para o IP/porta de onde o Path Challenge foi recebido. Isso NÃO É NECESSARIAMENTE o IP/porta que foi previamente estabelecido para o peer. Isso garante que a validação de caminho por um peer só seja bem-sucedida se o caminho for funcional em ambas as direções. Veja a seção Validação após Mudança Local abaixo.

A menos que o IP/porta seja diferente do IP/porta previamente conhecido para o peer, trate um Path Challenge como um ping simples, e simplesmente responda incondicionalmente com um Path Response. O receptor não mantém ou altera qualquer estado baseado em um Path Challenge recebido. Se o IP/porta for diferente, um peer deve verificar que o novo IP e porta são válidos de acordo com as regras de validação locais (não bloqueados, não são portas ilegais, etc.). Peers NÃO são obrigatórios a suportar respostas cross-address-family entre IPv4 e IPv6, e podem tratar um novo IP na outra família de endereços como inválido, já que este não é um comportamento esperado.

A menos que seja restringida pelo controle de congestionamento, a Path Response deve ser enviada imediatamente. As implementações devem tomar medidas para limitar a taxa de Path Responses ou a largura de banda utilizada, se necessário.

Um bloco Path Challenge geralmente é acompanhado por um bloco Address na mesma mensagem. Se o bloco de endereço contém um novo IP/porta, um peer pode validar esse IP/porta e iniciar testes de peer desse novo IP/porta, com o peer da sessão ou qualquer outro peer. Se o peer pensa que está atrás de firewall, e apenas a porta mudou, essa mudança provavelmente é devido ao rebinding do NAT, e testes adicionais de peer provavelmente não são necessários.

Successful Path Validation

Em uma validação de caminho bem-sucedida, a conexão é totalmente migrada para o novo IP/porta. Em caso de sucesso:

  • Sair da fase de validação de caminho
  • Todos os pacotes são enviados para o novo IP e porta.
  • As restrições na janela de congestionamento e PMTU são removidas, e elas são permitidas a aumentar. Não simplesmente restaure-as aos valores antigos, pois o novo caminho pode ter características diferentes.
  • Se o IP mudou, defina RTT calculado e RTO para valores iniciais. Como mudanças apenas de porta são comumente o resultado de rebinding NAT ou outra atividade de middlebox, o peer pode em vez disso manter seu estado de controle de congestionamento e estimativa de round-trip nesses casos em vez de reverter para valores iniciais.
  • Deletar (invalidar) quaisquer tokens enviados ou recebidos para o IP/porta antigo (opcional)
  • Enviar um novo bloco de token para o novo IP/porta (opcional)

Cancelling Path Validation

Durante a fase de validação de caminho, quaisquer pacotes válidos e não duplicados que sejam recebidos do IP/porta antigo e sejam descriptografados com sucesso farão com que a Validação de Caminho seja cancelada. É importante que uma validação de caminho cancelada, causada por um pacote falsificado, não cause o término ou interrupção significativa de uma sessão válida.

Em validação de caminho cancelada:

  • Sair da fase de validação de caminho
  • Todos os pacotes são enviados para o IP e porta antigos.
  • As restrições na janela de congestionamento e PMTU são removidas, e elas podem aumentar, ou, opcionalmente, restaurar os valores anteriores
  • Retransmitir quaisquer pacotes de dados que foram previamente enviados para o novo IP/porta para o IP/porta antigo.

Failed Path Validation

É importante que uma validação de caminho falhada, causada por um pacote falsificado, não cause o encerramento de uma sessão válida ou sua interrupção significativa.

Em falha de validação de caminho:

  • Sair da fase de validação de caminho
  • Todos os pacotes são enviados para o IP e porta antigos.
  • As restrições na janela de congestionamento e PMTU são removidas, e elas podem aumentar.
  • Opcionalmente, iniciar uma validação de caminho no IP e porta antigos. Se falhar, terminar a sessão.
  • Caso contrário, seguir as regras padrão de timeout e terminação de sessão.
  • Retransmitir quaisquer pacotes de dados que foram previamente enviados para o novo IP/porta para o IP/porta antigo.

Validation After Local Change

O processo descrito acima é definido para peers que recebem um pacote de um IP/porta alterado. No entanto, também pode ser iniciado na direção oposta, por um peer que detecta que seu IP ou porta mudaram. Um peer pode ser capaz de detectar que seu IP local mudou; porém, é muito menos provável que detecte que sua porta mudou devido a um rebinding de NAT. Portanto, isso é opcional.

Ao receber um path challenge de um peer cujo IP ou porta foi alterado, o outro peer deve iniciar um path challenge na direção oposta.

Segurança de Relay

Blocos de Validação de Caminho e Resposta de Caminho podem ser utilizados a qualquer momento como pacotes Ping/Pong. A recepção de um bloco de Validação de Caminho não altera nenhum estado no receptor, a menos que seja recebido de um IP/porta diferente.

Multiple Sessions

Os peers não devem estabelecer múltiplas sessões com o mesmo peer, seja SSU 1 ou 2, ou com os mesmos ou diferentes endereços IP. No entanto, isso pode acontecer, seja devido a bugs, ou a uma mensagem de encerramento de sessão anterior sendo perdida, ou em uma condição de corrida onde a mensagem de encerramento ainda não chegou.

Se o Bob tiver uma sessão existente com a Alice, quando o Bob receber o Session Confirmed da Alice, completando o handshake e estabelecendo uma nova sessão, o Bob deve:

  • Migrar todas as mensagens I2NP de saída não enviadas ou não confirmadas da sessão antiga para a nova
  • Enviar uma terminação com código de motivo 22 na sessão antiga
  • Remover a sessão antiga e substituí-la pela nova

Session Termination

Segurança do Teste de Pares

Sessões na fase de handshake geralmente são terminadas simplesmente por timeout, ou não respondendo mais. Opcionalmente, elas podem ser terminadas incluindo um bloco de Terminação na resposta, mas a maioria dos erros não é possível de responder devido à falta de chaves criptográficas. Mesmo se as chaves estiverem disponíveis para uma resposta incluindo um bloco de terminação, geralmente não vale a pena o CPU para realizar o DH para a resposta. Uma exceção PODE ser um bloco de Terminação em uma mensagem de retry, que é barata de gerar.

Objetivos de Design de Relay e Peer Test

As sessões na fase de dados são terminadas enviando uma mensagem de dados que inclui um bloco de Terminação. Esta mensagem também deve incluir um bloco ACK. Pode, se a sessão esteve ativa por tempo suficiente para que um token enviado anteriormente tenha expirado ou esteja prestes a expirar, um bloco New Token. Esta mensagem não solicita confirmação. Ao receber um bloco de Terminação com qualquer motivo exceto “Termination Received”, o peer responde com uma mensagem de dados contendo um bloco de Terminação com o motivo “Termination Received”.

Após enviar ou receber um bloco de Termination, a sessão deve entrar na fase de fechamento por algum período máximo de tempo a ser determinado. O estado de fechamento é necessário para proteger contra a perda do pacote que contém o bloco de Termination, e pacotes em trânsito na outra direção. Enquanto estiver na fase de fechamento, não há requisito para processar pacotes adicionais recebidos. Uma sessão no estado de fechamento envia um pacote contendo um bloco de Termination em resposta a qualquer pacote de entrada que ela atribua à sessão. Uma sessão deve limitar a taxa na qual ela gera pacotes no estado de fechamento. Por exemplo, uma sessão poderia aguardar por um número progressivamente crescente de pacotes recebidos ou quantidade de tempo antes de responder aos pacotes recebidos.

Para minimizar o estado que um router mantém para uma sessão em encerramento, as sessões podem, mas não são obrigadas a, enviar exatamente o mesmo pacote com o mesmo número de pacote como está em resposta a qualquer pacote recebido. Nota: Permitir a retransmissão de um pacote de terminação é uma exceção ao requisito de que um novo número de pacote seja usado para cada pacote. Enviar novos números de pacote é principalmente vantajoso para recuperação de perda e controle de congestionamento, que não devem ser relevantes para uma conexão fechada. Retransmitir o pacote final requer menos estado.

Após receber um bloco de Terminação com o motivo “Termination Received”, a sessão pode sair da fase de fechamento.

Cleanup

Após qualquer terminação normal ou anormal, os routers devem zerar quaisquer dados efêmeros em memória, incluindo chaves efêmeras de handshake, chaves de criptografia simétrica e informações relacionadas.

MTU

Os requisitos variam, com base em se o endereço publicado é compartilhado com SSU 1. O mínimo atual do SSU 1 IPv4 é 620, que é definitivamente muito pequeno.

O MTU mínimo do SSU2 é 1280 para IPv4 e IPv6, que é o mesmo especificado na RFC 9000. Veja abaixo. Ao aumentar o MTU mínimo, mensagens de tunnel de 1 KB e mensagens curtas de construção de tunnel caberão em um datagrama, reduzindo drasticamente a quantidade típica de fragmentação. Isso também permite um aumento no tamanho máximo de mensagem I2NP. Mensagens de streaming de 1820 bytes devem caber em dois datagramas.

Um router não deve habilitar SSU2 ou publicar um endereço SSU2 a menos que o MTU para esse endereço seja de pelo menos 1280.

Os routers devem publicar um MTU não-padrão em cada endereço de router SSU ou SSU2.

Resumo

Endereço compartilhado com SSU 1, deve seguir as regras do SSU 1. IPv4: Padrão e máximo é 1484. Mínimo é 1292. (MTU IPv4 + 4) deve ser um múltiplo de 16. IPv6: Deve ser publicado, mínimo é 1280 e máximo é 1488. MTU IPv6 deve ser um múltiplo de 16.

Garantias de Entrega

IPv4: Padrão e máximo é 1500. Mínimo é 1280. IPv6: Padrão e máximo é 1500. Mínimo é 1280. Não há regras de múltiplos de 16, mas provavelmente deveria ser um múltiplo de 2 pelo menos.

Noise Protocol Framework

Para SSU 1, o Java I2P atual realiza descoberta de PMTU começando com pacotes pequenos e aumentando gradualmente o tamanho, ou aumentando com base no tamanho do pacote recebido. Isso é rudimentar e reduz muito a eficiência. Continuar esse recurso no SSU 2 está TBD.

Estudos recentes PMTU sugerem que um mínimo para IPv4 de 1200 ou mais funcionaria para mais de 99% das conexões. QUIC RFC 9000 requer um tamanho mínimo de pacote IP de 1280 bytes.

citação RFC 9000:

O tamanho máximo do datagrama é definido como o maior tamanho de payload UDP que pode ser enviado através de um caminho de rede usando um único datagrama UDP. QUIC NÃO DEVE ser usado se o caminho de rede não puder suportar um tamanho máximo de datagrama de pelo menos 1200 bytes.

QUIC assume um tamanho mínimo de pacote IP de pelo menos 1280 bytes. Este é o tamanho mínimo do IPv6 [IPv6] e também é suportado pela maioria das redes IPv4 modernas. Assumindo o tamanho mínimo do cabeçalho IP de 40 bytes para IPv6 e 20 bytes para IPv4 e um tamanho de cabeçalho UDP de 8 bytes, isso resulta em um tamanho máximo de datagrama de 1232 bytes para IPv6 e 1252 bytes para IPv4. Assim, espera-se que as redes IPv4 modernas e todos os caminhos de rede IPv6 sejam capazes de suportar QUIC.

Nota: Este requisito de suportar um payload UDP de 1200 bytes limita o espaço disponível para cabeçalhos de extensão IPv6 a 32 bytes ou opções IPv4 a 52 bytes se o caminho suportar apenas o MTU mínimo IPv6 de 1280 bytes. Isso afeta pacotes Initial e validação de caminho.

fim da citação

Adições ao Framework

QUIC exige que os datagramas Initial em ambas as direções tenham pelo menos 1200 bytes, para prevenir ataques de amplificação e garantir que o PMTU suporte isso em ambas as direções.

Poderíamos exigir isso para Session Request e Session Created, com custo substancial em largura de banda. Talvez pudéssemos fazer isso apenas se não tivermos um token, ou após uma mensagem Retry ser recebida. A definir

QUIC requer que Bob não envie mais de três vezes a quantidade de dados recebida até que o endereço do cliente seja validado. SSU2 atende a este requisito inerentemente, porque a mensagem Retry tem aproximadamente o mesmo tamanho da mensagem Token Request, e é menor que a mensagem Session Request. Além disso, a mensagem Retry é enviada apenas uma vez.

Estimativa de overhead de processamento

QUIC requer que mensagens contendo blocos PATH_CHALLENGE ou PATH_RESPONSE tenham pelo menos 1200 bytes, para prevenir ataques de amplificação e garantir que o PMTU suporte isso em ambas as direções.

Poderíamos exigir isso também, a um custo substancial em largura de banda. No entanto, esses casos devem ser raros. TBD

Max I2NP Message Size

IPv4: Não é assumida fragmentação de IP. O cabeçalho IP + datagrama tem 28 bytes. Isso assume que não há opções IPv4. O tamanho máximo da mensagem é MTU - 28. O cabeçalho da fase de dados tem 16 bytes e o MAC tem 16 bytes, totalizando 32 bytes. O tamanho do payload é MTU - 60. O payload máximo da fase de dados é 1440 para um MTU máximo de 1500. O payload máximo da fase de dados é 1220 para um MTU mínimo de 1280.

IPv6: Não é permitida fragmentação de IP. O cabeçalho IP + datagrama é de 48 bytes. Isso assume que não há cabeçalhos de extensão IPv6. O tamanho máximo da mensagem é MTU - 48. O cabeçalho da fase de dados é de 16 bytes e o MAC é de 16 bytes, totalizando 32 bytes. O tamanho do payload é MTU - 80. O payload máximo da fase de dados é 1420 para um MTU máximo de 1500. O payload máximo da fase de dados é 1200 para um MTU mínimo de 1280.

No SSU 1, as diretrizes eram um máximo rigoroso de cerca de 32 KB para uma mensagem I2NP baseada em 64 fragmentos máximos e um MTU mínimo de 620. Devido ao overhead para leaseSets agrupados e chaves de sessão, o limite prático no nível da aplicação era cerca de 6KB menor, ou aproximadamente 26KB. O protocolo SSU 1 permite 128 fragmentos, mas as implementações atuais limitam a 64 fragmentos.

Ao elevar o MTU mínimo para 1280, com um payload de fase de dados de aproximadamente 1200, uma mensagem SSU 2 de cerca de 76 KB é possível em 64 fragmentos e 152 KB em 128 fragmentos. Isso permite facilmente um máximo de 64 KB.

Devido à fragmentação em túneis e à fragmentação em SSU 2, a chance de perda de mensagens aumenta exponencialmente com o tamanho da mensagem. Continuamos a recomendar um limite prático de cerca de 10 KB na camada de aplicação para datagramas I2NP.

Peer Test Process

Consulte Segurança do Teste de Peer acima para uma análise do Teste de Peer SSU1 e os objetivos para o Teste de Peer SSU2.

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

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

Quando rejeitado por Bob:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
4.      <------------------ PeerTest (reject)

Quando rejeitado 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: O RI pode ser enviado tanto como mensagens I2NP Database Store em blocos I2NP, ou como blocos RI (se pequeno o suficiente). Estes podem estar contidos nos mesmos pacotes que os blocos de teste de peer, se pequenos o suficiente.

As mensagens 1-4 estão em sessão usando blocos Peer Test em uma mensagem Data. As mensagens 5-7 estão fora de sessão usando blocos Peer Test em uma mensagem Peer Test.

NOTA: Como no SSU 1, as mensagens 4 e 5 podem chegar em qualquer ordem. A mensagem 5 e/ou 7 podem não ser recebidas se Alice estiver atrás de firewall. Quando a mensagem 5 chega antes da mensagem 4, Alice não pode enviar imediatamente a mensagem 6, porque ela ainda não tem a chave de introdução de Charlie para criptografar o cabeçalho. Quando a mensagem 4 chega antes da mensagem 5, Alice não deve enviar imediatamente a mensagem 6, porque ela deve esperar para ver se a mensagem 5 chega sem abrir o firewall com a mensagem 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

O teste de peers entre versões diferentes não é suportado. A única combinação de versão permitida é onde todos os peers são versão 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

Estabelecimento de Sessão

As mensagens 1-4 estão em sessão e são cobertas pelos processos de ACK da fase de dados e retransmissão. Os blocos de Peer Test exigem confirmação (ack-eliciting).

As mensagens 5-7 podem ser retransmitidas, inalteradas.

Cabeçalho do Pacote

Assim como no SSU 1, o teste de endereços IPv6 é suportado, e a comunicação Alice-Bob e Alice-Charlie pode ser via IPv6, se Bob e Charlie indicarem suporte com uma capacidade ‘B’ em seu endereço IPv6 publicado. Veja a Proposta 126 para detalhes.

Como no SSU 1 anterior à versão 0.9.50, Alice envia a solicitação para Bob usando uma sessão existente sobre o transporte (IPv4 ou IPv6) que ela deseja testar. Quando Bob recebe uma solicitação de Alice via IPv4, Bob deve selecionar um Charlie que anuncia um endereço IPv4. Quando Bob recebe uma solicitação de Alice via IPv6, Bob deve selecionar um Charlie que anuncia um endereço IPv6. A comunicação real Bob-Charlie pode ser via IPv4 ou IPv6 (ou seja, independente do tipo de endereço de Alice). Este NÃO é o comportamento do SSU 1 a partir da versão 0.9.50, onde solicitações IPv4/v6 mistas são permitidas.

Processing by Bob

Ao contrário do SSU 1, Alice especifica o IP e porta de teste solicitados na mensagem 1. Bob deve validar este IP e porta, e rejeitar com código 5 se inválidos. A validação de IP recomendada é que, para IPv4, ele coincida com o IP de Alice, e para IPv6, pelo menos os primeiros 8 bytes do IP coincidam. A validação de porta deve rejeitar portas privilegiadas e portas para protocolos conhecidos.

Relay Process

Consulte Segurança de Relay acima para uma análise do SSU1 Relay e os objetivos para o 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 ------------------------------------------>

Quando rejeitado por Bob:

Alice                         Bob                  Charlie
     lookup Bob RI

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

1. RelayRequest ---------------------->
4.      <-------------- RelayResponse

Quando rejeitado por Charlie:

Alice                         Bob                  Charlie
     lookup Bob RI

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

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

NOTA: RI pode ser enviado tanto como mensagens I2NP Database Store em blocos I2NP, ou como blocos RI (se pequeno o suficiente). Estes podem estar contidos nos mesmos pacotes que os blocos de retransmissão, se pequenos o suficiente.

No SSU 1, as informações do router do Charlie contêm o IP, porta, chave intro, tag de relay e expiração de cada introducer.

No SSU 2, as informações do router do Charlie contêm o hash do router, relay tag e expiração de cada introducer.

Alice deve reduzir o número de viagens de ida e volta necessárias primeiro selecionando um introducer (Bob) ao qual ela já tem uma conexão. Em segundo lugar, se não houver nenhum, selecionar um introducer para o qual ela já possui as informações do router.

O relay entre versões também deve ser suportado, se possível. Isso facilitará uma transição gradual do SSU 1 para o SSU 2. As combinações de versões permitidas são (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 e Relay Response estão todos dentro da sessão e são cobertos pelos processos de ACK da fase de dados e retransmissão. Os blocos Relay Request, Relay Intro e Relay Response requerem confirmação de recebimento (ack-eliciting).

O hole punch pode ser retransmitido, como no SSU 1.

IPv4/v6

Todos os recursos do relay SSU 1 são suportados, incluindo aqueles documentados na Proposta 158 e suportados a partir da versão 0.9.50. Introduções IPv4 e IPv6 são suportadas. Uma Solicitação de Relay pode ser enviada por uma sessão IPv4 para uma introdução IPv6, e uma Solicitação de Relay pode ser enviada por uma sessão IPv6 para uma introdução IPv4.

Processing by Alice

Seguem as diferenças do SSU 1 e recomendações para implementação do SSU 2.

Notas

No SSU 1, a introdução é relativamente barata, e Alice geralmente envia Relay Requests para todos os introdutores. No SSU 2, a introdução é mais cara, pois uma conexão deve primeiro ser estabelecida com um introdutor. Para minimizar a latência e sobrecarga da introdução, os passos de processamento recomendados são os seguintes:

  • Ignore qualquer introducer que esteja expirado com base no valor iexp no endereço
  • Se uma conexão SSU2 já estiver estabelecida para um ou mais introducers, escolha um e envie o Relay Request apenas para esse introducer.
  • Caso contrário, se um Router Info for conhecido localmente para um ou mais introducers, escolha um e conecte apenas a esse introducer.
  • Caso contrário, procure os Router Infos para todos os introducers, conecte ao introducer cujo Router Info for recebido primeiro.

Notas

Em ambos SSU 1 e SSU 2, a Relay Response e o Hole Punch podem ser recebidos em qualquer ordem, ou podem não ser recebidos de forma alguma.

No SSU 1, Alice geralmente recebe o Relay Response (1 RTT) antes do Hole Punch (1 1/2 RTT). Pode não estar bem documentado nessas especificações, mas Alice deve receber o Relay Response do Bob antes de continuar, para receber o IP do Charlie. Se o Hole Punch for recebido primeiro, Alice não o reconhecerá, porque não contém dados e o IP de origem não é reconhecido. Após receber o Relay Response, Alice deve aguardar OU o recebimento do Hole Punch do Charlie, OU um pequeno atraso (recomendado 500 ms) antes de iniciar o handshake com Charlie.

No SSU 2, Alice geralmente receberá o Hole Punch (1 1/2 RTT) antes da Relay Response (2 RTT). O SSU 2 Hole Punch é mais fácil de processar do que no SSU 1, porque é uma mensagem completa com IDs de conexão definidos (derivados do relay nonce) e conteúdo incluindo o IP do Charlie. A Relay Response (mensagem Data) e a mensagem Hole Punch contêm o bloco Relay Response assinado idêntico. Portanto, Alice pode iniciar o handshake com Charlie após OU receber o Hole Punch do Charlie, OU receber a Relay Response do Bob.

A verificação da assinatura do Hole Punch inclui o hash do router do introdutor (Bob). Se Relay Requests foram enviadas para mais de um introdutor, há várias opções para validar a assinatura:

  • Tente cada hash para o qual uma solicitação foi enviada
  • Use nonces diferentes para cada introducer, e use isso para determinar qual introducer este Hole Punch foi em resposta a
  • Não revalide a assinatura se o conteúdo for idêntico ao do Relay Response, se já recebido
  • Não valide a assinatura de forma alguma

Se Charlie estiver atrás de um NAT simétrico, sua porta reportada no Relay Response e Hole Punch pode não ser precisa. Portanto, Alice deve verificar a porta de origem UDP da mensagem Hole Punch e usá-la se for diferente da porta reportada.

Tag Requests by Bob

No SSU 1, apenas Alice podia solicitar uma tag, na Session Request. Bob nunca podia solicitar uma tag, e Alice não podia fazer relay para Bob.

No SSU2, Alice geralmente solicita uma tag na Session Request, mas tanto Alice quanto Bob também podem solicitar uma tag na fase de dados. Bob geralmente não está atrás de firewall após receber uma solicitação de entrada, mas pode estar após um relay, ou o estado de Bob pode mudar, ou ele pode solicitar um introducer para o outro tipo de endereço (IPv4/v6). Então, no SSU2, é possível que tanto Alice quanto Bob sejam simultaneamente relays para a outra parte.

Published Router Info

Address Properties

As seguintes propriedades de endereço podem ser publicadas, inalteradas do SSU 1, incluindo mudanças na Proposta 158 suportadas a partir da API 0.9.50:

  • caps: capacidades [B,C,4,6]

  • host: IP (IPv4 ou IPv6). Endereço IPv6 abreviado (com “::”) é permitido. Pode ou não estar presente se estiver atrás de firewall. Nomes de host não são permitidos.

  • iexp[0-2]: Expiração deste introdutor. Dígitos ASCII, em segundos desde a época. Presente apenas se estiver atrás de firewall, e introdutores forem necessários. Opcional (mesmo se outras propriedades para este introdutor estiverem presentes).

  • ihost[0-2]: IP do introdutor (IPv4 ou IPv6). Endereço IPv6 abreviado (com “::”) é permitido. Presente apenas se protegido por firewall, e introdutores são obrigatórios. Nomes de host não são permitidos. Apenas endereço SSU.

  • ikey[0-2]: Chave de introdução Base 64 do introducer. Presente apenas se estiver atrás de firewall e introducers forem necessários. Apenas endereço SSU.

  • iport[0-2]: Porta do introdutor 1024 - 65535. Presente apenas se protegido por firewall, e introdutores são necessários. Apenas endereço SSU.

  • itag[0-2]: Tag do introdutor 1 - (2**32 - 1) Dígitos ASCII. Presente apenas se estiver atrás de firewall e introdutores forem necessários.

  • key: Chave de introdução Base 64.

  • mtu: Opcional. Consulte a seção MTU acima.

  • port: 1024 - 65535 Pode ou não estar presente se protegido por firewall.

Published Addresses

O RouterAddress publicado (parte do RouterInfo) terá um identificador de protocolo de “SSU” ou “SSU2”.

O RouterAddress deve conter três opções para indicar suporte SSU2:

  • s=(Chave Base64) A chave pública estática Noise atual (s) para este RouterAddress. Codificada em Base 64 usando o alfabeto I2P Base 64 padrão. 32 bytes em binário, 44 bytes como Base 64 codificado, chave pública X25519 little-endian.

  • i=(Base64 key) A chave de introdução atual para criptografar os cabeçalhos para este RouterAddress. Codificada em Base 64 usando o alfabeto Base 64 padrão do I2P. 32 bytes em binário, 44 bytes como Base 64 codificado, chave ChaCha20 big-endian.

  • v=2 A versão atual (2). Quando publicado como “SSU”, suporte adicional para a versão 1 está implícito. Suporte para versões futuras será com valores separados por vírgula, por exemplo v=2,3 A implementação deve verificar compatibilidade, incluindo múltiplas versões se uma vírgula estiver presente. Versões separadas por vírgula devem estar em ordem numérica.

Alice deve verificar se todas as três opções estão presentes e válidas antes de se conectar usando o protocolo SSU2.

Quando publicado como “SSU” com as opções “s”, “i” e “v”, e com as opções “host” e “port”, o router deve aceitar conexões de entrada naquele host e porta para ambos os protocolos SSU e SSU2, e detectar automaticamente a versão do protocolo.

Quando publicado como “SSU2” com as opções “s”, “i” e “v”, e com as opções “host” e “port”, o router aceita conexões de entrada nesse host e porta apenas para o protocolo SSU2.

Se um router suporta conexões SSU1 e SSU2 mas não implementa detecção automática de versão para conexões de entrada, ele deve anunciar endereços “SSU” e “SSU2”, e incluir as opções SSU2 apenas no endereço “SSU2”. O router deve definir um valor de custo menor (prioridade mais alta) no endereço “SSU2” do que no endereço “SSU”, para que SSU2 seja preferido.

Se múltiplos RouterAddresses SSU2 (seja como “SSU” ou “SSU2”) forem publicados no mesmo RouterInfo (para endereços IP ou portas adicionais), todos os endereços que especificarem a mesma porta devem conter as opções e valores SSU2 idênticos. Em particular, todos devem conter a mesma chave estática “s” e chave de introdução “i”.

Introducers

Quando publicado como SSU ou SSU2 com introducers, as seguintes opções estão presentes:

  • ih[0-2]=(Base64 hash) Um hash de router para um introducer. Codificado em Base 64 usando o alfabeto Base 64 padrão do I2P. 32 bytes em binário, 44 bytes codificado em Base 64

  • iexp[0-2]: Expiração deste introducer. Inalterado do SSU 1.

  • itag[0-2]: Tag do introdutor 1 - (2**32 - 1) Inalterado do SSU 1.

As seguintes opções são apenas para SSU e não são usadas para SSU2. No SSU2, Alice obtém esta informação do RI do Charlie.

  • ihost[0-2]
  • ikey[0-2]
  • itag[0-2]

Um router não deve publicar host ou porta no endereço ao publicar introducers. Um router deve publicar caps 4 e/ou 6 no endereço ao publicar introducers para indicar suporte para IPv4 e/ou IPv6. Isso é o mesmo que a prática atual para endereços SSU 1 recentes.

Nota: Se publicado como SSU, e há uma mistura de introducers SSU 1 e SSU2, os introducers SSU 1 devem estar nos índices menores e os introducers SSU2 devem estar nos índices maiores, para compatibilidade com routers mais antigos.

Unpublished SSU2 Address

Se Alice não publicar seu endereço SSU2 (como “SSU” ou “SSU2”) para conexões de entrada, ela deve publicar um endereço de router “SSU2” contendo apenas sua chave estática e versão SSU2, para que Bob possa validar a chave após receber o RouterInfo de Alice na parte 2 do Session Confirmed.

  • s=(chave Base64) Como definido acima para endereços publicados.

  • i=(chave Base64) Conforme definido acima para endereços publicados.

  • v=2 Como definido acima para endereços publicados.

Este endereço do router não conterá as opções “host” ou “port”, pois estas não são necessárias para conexões SSU2 de saída. O custo publicado para este endereço não importa estritamente, já que é apenas de entrada; no entanto, pode ser útil para outros routers se o custo for definido mais alto (menor prioridade) do que outros endereços. O valor sugerido é 14.

Alice também pode simplesmente adicionar as opções “i”, “s” e “v” a um endereço “SSU” publicado existente.

Integridade de Pacotes

Usar as mesmas chaves estáticas para NTCP2 e SSU2 é permitido, mas não recomendado.

Devido ao cache de RouterInfos, os routers não devem rotacionar a chave pública estática ou IV enquanto o router estiver ativo, seja em um endereço publicado ou não. Os routers devem armazenar persistentemente esta chave e IV para reutilização após uma reinicialização imediata, para que as conexões de entrada continuem funcionando e os tempos de reinicialização não sejam expostos. Os routers devem armazenar persistentemente, ou de outra forma determinar, o horário do último desligamento, para que o tempo de inatividade anterior possa ser calculado na inicialização.

Sujeito a preocupações sobre a exposição de horários de reinicialização, os routers podem rotacionar esta chave ou IV na inicialização se o router esteve previamente inativo por algum tempo (pelo menos vários dias).

Se o router tiver quaisquer SSU2 RouterAddresses publicados (como SSU ou SSU2), o tempo mínimo de inatividade antes da rotação deve ser muito mais longo, por exemplo um mês, a menos que o endereço IP local tenha mudado ou o router execute um “rekeys”.

Se o router tem qualquer RouterAddresses SSU publicados, mas não SSU2 (como SSU ou SSU2) o tempo mínimo de inatividade antes da rotação deve ser maior, por exemplo um dia, a menos que o endereço IP local tenha mudado ou o router faça “rekeys”. Isso se aplica mesmo se o endereço SSU publicado tiver introducers.

Se o router não tiver nenhum RouterAddresses publicado (SSU, SSU2, ou SSU), o tempo mínimo de inatividade antes da rotação pode ser de apenas duas horas, mesmo que o endereço IP mude, a menos que o router faça “rekeys”.

Se o router “rekeys” para um Router Hash diferente, ele deve gerar também uma nova chave noise e chave intro.

As implementações devem estar cientes de que alterar a chave pública estática ou IV impedirá conexões SSU2 de entrada de routers que armazenaram em cache um RouterInfo mais antigo. A publicação de RouterInfo, seleção de peers de tunnel (incluindo tanto OBGW quanto o hop mais próximo IB), seleção de tunnel de zero-hop, seleção de transporte e outras estratégias de implementação devem levar isso em consideração.

A rotação de chave de introdução está sujeita às mesmas regras da rotação de chaves.

Nota: O tempo mínimo de inatividade antes da regeneração de chaves pode ser modificado para garantir a saúde da rede e para prevenir reseeding por um router inativo por um período moderado de tempo.

Identity Hiding

A negação plausível não é um objetivo. Veja a visão geral acima.

Cada padrão recebe propriedades que descrevem a confidencialidade fornecida à chave pública estática do iniciador e à chave pública estática do respondedor. As suposições subjacentes são que as chaves privadas efêmeras são seguras, e que as partes abortam o handshake se receberem uma chave pública estática da outra parte na qual não confiam.

Esta seção considera apenas o vazamento de identidade através de campos de chave pública estática em handshakes. Naturalmente, as identidades dos participantes do Noise podem ser expostas através de outros meios, incluindo campos de payload, análise de tráfego, ou metadados como endereços IP.

Alice: (8) Criptografado com forward secrecy para uma parte autenticada.

Bob: (3) Não transmitida, mas um atacante passivo pode verificar candidatos para a chave privada do respondente e determinar se o candidato está correto.

Bob publica sua chave pública estática no netDb. Alice pode não fazê-lo, mas deve incluí-la no RI enviado para Bob.

Packet Guidelines

Criptografia Autenticada

Mensagens de handshake (Session Request/Created/Confirmed, Retry) passos básicos, em ordem:

  • Criar cabeçalho de 16 ou 32 bytes
  • Criar payload
  • mixHash() do cabeçalho (exceto para Retry)
  • Criptografar o payload usando Noise (exceto para Retry, usar ChaChaPoly com o cabeçalho como AD)
  • Criptografar o cabeçalho e, para Session Request/Created, a chave efêmera

Passos básicos das mensagens da fase de dados, em ordem:

  • Criar cabeçalho de 16 bytes
  • Criar payload
  • Criptografar o payload usando ChaChaPoly usando o cabeçalho como AD
  • Criptografar o cabeçalho

Inbound Packet Handling

Payload

Processamento inicial de todas as mensagens de entrada:

  • Descriptografar os primeiros 8 bytes do cabeçalho (o Destination Connection ID) com a chave de introdução
  • Procurar a conexão pelo Destination Connection ID
  • Se a conexão for encontrada e estiver na fase de dados, ir para a seção da fase de dados
  • Se a conexão não for encontrada, ir para a seção de handshake
  • Nota: Mensagens de Peer Test e Hole Punch também podem ser procuradas pelo Destination Connection ID criado a partir do nonce de teste ou relay.

Processamento de mensagens de handshake (Session Request/Created/Confirmed, Retry, Token Request) e outras mensagens fora de sessão (Peer Test, Hole Punch):

  • Descriptografar os bytes 8-15 do cabeçalho (o tipo de pacote, versão e ID da rede) com a chave de introdução. Se for um Session Request, Token Request, Peer Test ou Hole Punch válido, continue
  • Se não for uma mensagem válida, procurar uma conexão de saída pendente pelo IP/porta de origem do pacote, tratar o pacote como Session Created ou Retry. Re-descriptografar os primeiros 8 bytes do cabeçalho com a chave correta, e os bytes 8-15 do cabeçalho (o tipo de pacote, versão e ID da rede). Se for um Session Created ou Retry válido, continue
  • Se não for uma mensagem válida, falhar, ou enfileirar como um possível pacote da fase de dados fora de ordem
  • Para Session Request/Created, Retry, Token Request, Peer Test e Hole Punch, descriptografar os bytes 16-31 do cabeçalho
  • Para Session Request/Created, descriptografar a chave efêmera
  • Validar todos os campos do cabeçalho, parar se não for válido
  • mixHash() do cabeçalho
  • Para Session Request/Created/Confirmed, descriptografar o payload usando Noise
  • Para Retry e fase de dados, descriptografar o payload usando ChaChaPoly
  • Processar o cabeçalho e payload

Processamento de mensagens da fase de dados:

  • Descriptografar os bytes 8-15 do cabeçalho (o tipo de pacote, versão e ID da rede) com a chave correta
  • Descriptografar a carga útil usando ChaChaPoly usando o cabeçalho como AD
  • Processar o cabeçalho e a carga útil

Details

No SSU 1, a classificação de pacotes de entrada é difícil, porque não há cabeçalho para indicar o número da sessão. Os routers devem primeiro combinar o IP de origem e a porta com um estado de peer existente, e se não for encontrado, tentar múltiplas descriptografias com chaves diferentes para encontrar o estado de peer apropriado ou iniciar um novo. No caso de o IP de origem ou porta para uma sessão existente mudar, possivelmente devido ao comportamento do NAT, o router pode usar heurísticas caras para tentar combinar o pacote com uma sessão existente e recuperar o conteúdo.

SSU 2 foi projetado para minimizar o esforço de classificação de pacotes de entrada mantendo a resistência a DPI e outras ameaças no caminho. O número de Connection ID é incluído no cabeçalho para todos os tipos de mensagem e criptografado (ofuscado) usando ChaCha20 com uma chave e nonce conhecidos. Além disso, o tipo de mensagem também é incluído no cabeçalho (criptografado com proteção de cabeçalho para uma chave conhecida e depois ofuscado com ChaCha20) e pode ser usado para classificação adicional. Em nenhum caso é necessária uma operação criptográfica assimétrica de teste DH ou outra para classificar um pacote.

Para quase todas as mensagens de todos os peers, a chave ChaCha20 para a criptografia do Connection ID é a chave de introdução do router de destino conforme publicada no netDb.

As únicas exceções são as primeiras mensagens enviadas do Bob para Alice (Session Created ou Retry) onde a chave de introdução da Alice ainda não é conhecida pelo Bob. Nestes casos, a chave de introdução do Bob é usada como a chave.

O protocolo foi projetado para minimizar o processamento de classificação de pacotes que possa exigir operações de criptografia adicionais em múltiplas etapas de fallback ou heurísticas complexas. Além disso, a grande maioria dos pacotes recebidos não exigirá uma consulta de fallback (possivelmente custosa) por IP/porta de origem e uma segunda descriptografia de cabeçalho. Apenas Session Created e Retry (e possivelmente outros TBD) exigirão o processamento de fallback. Se um endpoint mudar de IP ou porta após a criação da sessão, o ID de conexão ainda é usado para localizar a sessão. Nunca é necessário usar heurísticas para encontrar a sessão, por exemplo, procurando por uma sessão diferente com o mesmo IP, mas uma porta diferente.

Portanto, os passos de processamento recomendados na lógica do loop receptor são:

  1. Descriptografe os primeiros 8 bytes com ChaCha20 usando a chave de introdução local, para recuperar o ID de Conexão de Destino. Se o ID de Conexão corresponder a uma sessão de entrada atual ou pendente:

a) Usando a chave apropriada, descriptografar os bytes 8-15 do cabeçalho

  to recover the version, net ID, and message type.

b) Se o tipo de mensagem for Session Confirmed, é um cabeçalho longo.

  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) Se o tipo de mensagem for válido mas não 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) Se o ID de conexão for uma sessão de entrada pendente

  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) Se b) ou c) falhar, descartar a mensagem.

  1. Se o ID da conexão não corresponder a uma sessão atual: Verificar se o cabeçalho de texto simples nos bytes 8-15 é válido (sem executar qualquer operação de proteção de cabeçalho). Verificar se o ID de rede e a versão do protocolo são válidos, e se o tipo de mensagem é Session Request, ou outro tipo de mensagem permitido fora de sessão (TBD).

a) Se tudo for válido e o tipo de mensagem for Session Request,

  decrypt bytes 16-31 of the header and the 32-byte X value
  with ChaCha20 using the local intro key.
  • Se o token nos bytes 24-31 do cabeçalho for aceito, então MixHash() o cabeçalho de 32 bytes descriptografado e descriptografe a mensagem com Noise. Envie uma Session Created em resposta.
    • Se o token não for aceito, envie uma mensagem Retry para o IP/porta de origem com um token. Não tente descriptografar a mensagem com Noise para evitar ataques DDoS.

b) Se o tipo de mensagem for alguma outra mensagem que é válida

  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) Se a) ou b) falhar, vá para o passo 3)

  1. Procurar uma sessão de saída pendente pelo IP/porta de origem do pacote.

a) Se encontrado, descriptografar novamente os primeiros 8 bytes com ChaCha20 usando a chave de introdução do Bob

  to recover the Destination Connection ID.

b) Se o ID da conexão corresponder à sessão pendente:

  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).
  • Se tudo for válido e o tipo de mensagem for Session Created, descriptografe os próximos 16 bytes do cabeçalho e o valor Y de 32 bytes com ChaCha20 usando a chave de intro do Bob. Então execute MixHash() no cabeçalho de 32 bytes descriptografado e descriptografe a mensagem com Noise. Envie um Session Confirmed em resposta.

    • Se tudo for válido e o tipo de mensagem for Retry, descriptografe os bytes 16-31 do cabeçalho com ChaCha20 usando a chave de intro do Bob. Descriptografe e valide a mensagem usando ChaCha20/Poly1305 usando TBD como chave e TBD como nonce e o cabeçalho de 32 bytes descriptografado como AD. Reenvie um Session Request com o token recebido em resposta.
    • Se o tipo de mensagem for alguma outra mensagem válida fora de sessão, presumivelmente com um cabeçalho curto, descriptografe o resto da mensagem com ChaCha20/Poly1305 usando a chave de intro, e usando o cabeçalho de 16 bytes descriptografado como AD. Processe a mensagem.

    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. Se executando SSU 1 na mesma porta, tente processar a mensagem como um pacote SSU 1.

Error Handling

Em geral, uma sessão (na fase de handshake ou de dados) nunca deve ser destruída após receber um pacote com um tipo de mensagem inesperado. Isso previne ataques de injeção de pacote. Esses pacotes também serão comumente recebidos após a retransmissão de um pacote de handshake, quando as chaves de descriptografia do cabeçalho não são mais válidas.

Na maioria dos casos, simplesmente descarte o pacote. Uma implementação pode, mas não é obrigatória, retransmitir o pacote enviado anteriormente (mensagem de handshake ou ACK 0) em resposta.

Após enviar Session Created como Bob, pacotes inesperados são comumente pacotes Data que não podem ser descriptografados porque os pacotes Session Confirmed foram perdidos ou estão fora de ordem. Coloque os pacotes na fila e tente descriptografá-los após receber os pacotes Session Confirmed.

Depois de receber Session Confirmed como Bob, pacotes inesperados são comumente pacotes Session Confirmed retransmitidos, porque o ACK 0 do Session Confirmed foi perdido. Os pacotes inesperados podem ser descartados. Uma implementação pode, mas não é obrigatória, enviar um pacote Data contendo um bloco ACK em resposta.

Notes

Para Session Created e Session Confirmed, as implementações devem validar cuidadosamente todos os campos de cabeçalho descriptografados (Connection IDs, número do pacote, tipo de pacote, versão, id, frag e flags) ANTES de chamar mixHash() no cabeçalho e tentar descriptografar a carga útil com Noise AEAD. Se a descriptografia Noise AEAD falhar, nenhum processamento adicional pode ser feito, pois mixHash() terá corrompido o estado do handshake, a menos que uma implementação armazene e “reverta” o estado do hash.

Version Detection

Pode não ser possível detectar eficientemente se os pacotes recebidos são da versão 1 ou 2 na mesma porta de entrada. Os passos acima podem fazer sentido executar antes do processamento SSU 1, para evitar tentar operações DH experimentais usando ambas as versões do protocolo.

A determinar se necessário.

  • Timeout de retransmissão de handshake de saída: 1,25 segundos, com backoff exponencial (retransmissões em 1,25, 3,75 e 8,75 segundos)
  • Timeout total de handshake de saída: 15 segundos
  • Timeout de retransmissão de handshake de entrada: 1 segundo, com backoff exponencial (retransmissões em 1, 3 e 7 segundos)
  • Timeout total de handshake de entrada: 12 segundos
  • Timeout após envio de retry: 9 segundos
  • Atraso de ACK: max(10, min(rtt/6, 150)) ms
  • Atraso de ACK imediato: min(rtt/16, 5) ms
  • Faixas de ACK máximas: 256?
  • Profundidade de ACK máxima: 512?
  • Distribuição de padding: 0-15 bytes, ou maior

Variants, Fallbacks, and General Issues

A definir

Packet Overhead Analysis

Assume IPv4, não incluindo padding extra, não incluindo tamanhos de cabeçalho IP e UDP. Padding é padding mod-16 apenas 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 o tamanho mínimo de pacote em Session Request e Created seja aplicado para PMTU.