Giblets IPsec, medimos em relação a TLS 1.3, GOST e Go

Saudações! Eu gostaria de dizer-lhe sobre o dispositivo do moderno IPsec pilha das ESPv3 e protocolos IKEv2 . O IPsec, parece-me, ignora injustamente muitos lados e não vi uma análise detalhada de seu trabalho, seus protocolos e recursos em russo. Além disso, farei algo estranho - comparar o IPsec ESPv3 e o IKEv2 (ambos de 2005) com o TLS 1.3 moderno, moderno e de última geração de 2018.





Por que sou tão apaixonado por IPsec - sem dúvida a pilha de protocolo mais complexa para proteger redes? Afinal, a complexidade é o principal inimigo da confiabilidade e segurança! Em primeiro lugar, quanto mais você aprende sobre seus protocolos, especialmente IKEv2, mais você entende quantas possibilidades foram colocadas nele e você fica impressionado com sua consideração, em contraste com a abordagem comum dos desenvolvedores "uma muleta impulsiona uma muleta" e uma solução para problemas sérios "até que o trovão estourar". Em segundo lugar, os protocolos IPsec são bem pensados ​​do ponto de vista criptográfico, e mesmo o antigo ESP / IKEv1, de fato, são os únicos protocolos industriais usados ​​em massa nos quais não havia vulnerabilidades graves. O mesmo SSL (ano de 1995) tornou-se decentemente pensado apenas a partir da versão 1.3. E muitas pessoas não gostam de IPsec devido à monstruosa complexidade do IKEv1,que não está mais na v2.



Idealmente, se os desenvolvedores de sistemas operacionais não atrasassem seu tempo com a implementação e implementação de IPsec e IPv6 (para a disponibilidade de computadores, para que não houvesse NAT), então nenhum SSL / TLS deveria ter aparecido em princípio. O mundo acabou não sendo perfeito, mas agora o IPsec pronto para uso (pelo menos SA / SP + ESP parte da pilha) está em pelo menos algum sistema operacional difundido (pessoalmente, eu só conheço o DragonFly BSD , que bebeu IPsec devido à falta de desenvolvedores para suportá-lo), e o IPv6 em alguns países desenvolvidos está imediatamente disponível para a grande maioria das pessoas.



O IPsec é uma pilha de protocolos, chamadas API, estrutura para que os aplicativos e / ou o administrador possam dizer qual a segurança de que precisam durante a comunicação e seria garantida de forma transparente no nível da rede ( IP securidade). Podemos falar sobre os dois pacotes IP de apenas um soquete (por exemplo, conexões TCP) e sobre o tráfego entre redes inteiras.



Segurança de tráfego significa: garantir a confidencialidade dos dados, sua autenticidade / integridade e proteção contra ataques de repetição . Como quase todos os protocolos, o IPsec tem uma parte de transporte que protege os pacotes IP, e uma parte de handshake relacionada à negociação de chaves, parâmetros, configuração e autenticação das partes.



TLS 1.3 : fornece apenas proteção de dados por soquete para conexões TCP. O DTLS pode fornecer proteção para datagramas (DTLS 1.3 ainda não é um padrão), mas nem todas as bibliotecas oferecem suporte para isso.



Protocolos de transporte



O transporte IPsec usa protocolos IP:



  • AH (cabeçalhos de autenticação). Não vou falar mais sobre o AH, já que ele não fornece confidencialidade de dados e, pelo que ouvi, foi feito apenas para "tolerar" de alguma forma as leis de alguns países da década de 1990 sobre restrições ao uso de criptografia. A criptografia é tão leve em relação a tudo o mais que não faz sentido sacrificá-la. Mas em quase todos os lugares onde ESP é mencionado, AH também se refere.
  • ESP (encapsulando cargas úteis de segurança). O ESP evoluiu ligeiramente ao longo do tempo e agora está usando sua versão ESPv3, que geralmente é compatível com versões anteriores e não difere da versão anterior.


O tráfego IP é protegido apenas pela camada de transporte. E uma vez que podemos falar sobre muitos milhões de pacotes por segundo, o ESP de fato é implementado no nível do kernel do sistema operacional, em sua pilha de rede, pelo menos, para não tornar dispendiosa a troca de contexto entre o kernel e o espaço do usuário (como normalmente acontece com TLS , SSH, OpenVPN e outros).



Enfatizo que AH e ESP são protocolos de camada IP, rede, não transporte. Por que não UDP? A soma de verificação é redundante e queima a CPU, e a criptografia garantirá a integridade de qualquer maneira. Mas, se o seu NAT não sabe nada sobre ESP (e ele não sabe), então tudo isso não funcionará para ele. Mais tarde, eles vieram com muletas NAT-T (NAT traversal), quando o tráfego IPsec é envolvido em um pacote UDP na porta 4500 e será capaz de passar pelo NAT, mas isso é uma sobrecarga desnecessária e a necessidade de editar a pilha IPsec no kernel, porque ele já deve entender esses pacotes UDP especiais e extrair ESP deles para isso processamento regular.



SP, SA, SPI e nossa primeira criptografia IPsec



Como o kernel sabe o que fazer com um pacote IP: criptografá-lo usando alguma chave, descriptografar o ESP de entrada ou deixá-lo passar sem tocá-lo? Para fazer isso, o kernel possui Políticas de Segurança ( SP ). Essas são regras como em um firewall. Além deles, existem Security Associations ( SA ) no kernel : contextos para realizar operações criptográficas (chaves, contadores, replay de janela, etc.). Em geral, nem SPs são específicos de IPsec, nem SAs - eles podem ser usados ​​para outras tarefas / protocolos (por exemplo, OSPF).



O SP / SA pode ser configurado por meio de uma API especial ( PF_KEYv2 ) ou manualmente por meio de algum utilitário setkey . Por exemplo, se queremos dizer ao kernel que todos os pacotes IP vindos deOs endereços fc :: 123 em fc :: 321 devem ser protegidos por ESP, então isso pode ser feito facilmente chamando a partir da linha de comando:



$ echo "spdadd fc00::123 fc00::321 any -P out ipsec esp/transport//require;" | setkey -c


Antes desse comando, vimos pings:



IP6 fc00::123 > fc00::321: ICMP6, echo request, seq 0, length 16
IP6 fc00::321 > fc00::123: ICMP6, echo reply, seq 0, length 16
IP6 fc00::123 > fc00::321: ICMP6, echo request, seq 1, length 16
IP6 fc00::321 > fc00::123: ICMP6, echo reply, seq 1, length 16


Não o veremos mais tarde, pois o kernel ainda não sabe "o que" criptografar. É necessário adicionar um SA e isso também pode ser feito manualmente, configurando a facilidade de criptografia AEAD do algoritmo AES-GCM-16 e uma chave aleatória de 160 bits:



echo "add fc00::123 fc00::321 esp 0xdeadbabe -E aes-gcm-16 0x0c09d1d90f804b0b4cef80e255e29c0894db1928 ;" | setkey -c


Se executarmos os mesmos comandos no host remoto (sem esquecer de especificar -P in ), veremos:



IP6 fc00::123 > fc00::321: ESP(spi=0xdeadbabe,seq=0x1), length 52
IP6 fc00::321 > fc00::123: ICMP6, echo reply, seq 0, length 16
IP6 fc00::123 > fc00::321: ESP(spi=0xdeadbabe,seq=0x2), length 52
IP6 fc00::321 > fc00::123: ICMP6, echo reply, seq 1, length 16


A solicitação é criptografada pelo ESP, mas a resposta não. Como o ESP funciona "em um sentido" por padrão e para comunicação bidirecional, é necessário adicionar outro SP / SA para o sentido oposto.



0xdeadbabe neste exemplo é o Índice de Parâmetros de Segurança ( SPI ) - um identificador exclusivo para o "túnel" ESP entre dois endereços IP, no qual o kernel pode encontrar o contexto SA correspondente e obter a chave de descriptografia dele. E esp / transport // require é um requisito para usar ESP no modo de transporte (mais sobre isso abaixo).



Giblets ESP



O pacote ESP é esquematicamente estruturado da seguinte forma:



  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---
|               Security Parameters Index (SPI)                 | ^
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | A
|                      Sequence Number                          | | u
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | t
~                       IV (variable)                           ~ | h
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | e -----
|                    Payload Data  (variable)                   | | n   ^ E
~                                                               ~ | t   | n
|                                                               | | i   | c
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | c   | r
|               |         TFC Padding * (optional, variable)    | | a   | y
+-+-+-+-+-+-+-+-+         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | t   | p
|                         |        Padding (0-255 bytes)        | | e   | t
+-+-+-+-+-+-+-+-+-+-+-+-+-+     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | d   | e
|                               |  Pad Length   | Next Header   | v     v d
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---------
~         Integrity Check Value-ICV   (variable)                ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


  • SPI - identificador exclusivo de 32 bits para a sessão / túnel / conexão ESP entre endereços IP. Normalmente, {SrcIP, DstIP, SPI} é o SA e o contexto criptográfico.
  • SeqNum — 32- . . , replay attack.
  • payload — ESP, .
  • TFC padding — (Traffic Flow Confidentiality), , - , . TFC , , payload , . , payload IP , . TFC - , .
  • Padding — ESP payload 32- , . , ( CBC) . . .
  • Pad Length — 8- Padding .
  • Next Header — 8- IP payload. «no next header», ESP- — , . TFC — .
  • ICV — Integrity Check Value, (MAC).


Toda a parte do pacote, desde a carga útil até o próximo cabeçalho, é criptografada. Tudo, exceto o MAC, é autenticado. O comprimento do ICV, a presença de um IV (vetor de inicialização) depende dos modos / algoritmos de criptografia e autenticação usados.



TLS 1.3 : preenchimento opcional de dados para um determinado tamanho apareceu apenas na versão 1.3. Caso contrário, a criptografia e a autenticação são completamente semelhantes. O TLS 1.3 obriga a usar apenas algoritmos AEAD, o que é correto e bom. ESP suporta AEAD, mas há uma escolha de soluções mais arcaicas. Digite campos SPI ou SeqNumnão, visto que o TCP garante a sequência e a entrega, além disso, na prática, nenhum vetor de inicialização é transmitido explicitamente - o pacote da camada de registro TLS é, portanto, ligeiramente mais curto. O DTLS já contém SeqNum , bem como dados de fragmentação de mensagem.



O número do pacote de 32 bits pode ser muito curto na prática. Isso é apenas 4+ bilhões de pacotes IP, que em velocidades de 10+ Mpps podem voar em minutos. O que acontece quando o contador transborda? Ele será zerado. Mas, isso significa que o valor de SPI + SeqNum começará a se repetir para nós e os pacotes ESP interceptados anteriormente podem ser usados ​​para repetir o ataque. Para resolver este problema, ESN foi inventado(Número de sequência estendida). Este é um contador de 64 bits, mas apenas os 32 bits "inferiores" são transferidos para o campo SeqNum e os 32 bits superiores são armazenados na memória. O valor total do ESN é autenticado - portanto, as partes são obrigadas a concordar com o uso do ESN com antecedência.



Criptografia ESP



Como exatamente a criptografia / autenticação de um pacote ESP acontece, por exemplo, ao usar AES-GCM-16? Para trabalhar com ESP, ele usa um vetor de inicialização de 64 bits localizado no início da carga útil . Ele também usa sal de 32 bits como parte do material principal. No exemplo de setkey, não forneci uma chave de 128 bits, mas sim uma chave de 128 + 32 bits. Pode haver situações em que a chave é reutilizada e o IV é preenchido com um gerador de números pseudoaleatórios (PRNG) inválido, cujos valores podem ser repetidos. O sal é projetado para proteger contra esse caso mais perigoso, que potencialmente leva à descriptografia de pacotes interceptados. A criptografia / autenticação ESP em si no modo AES-128-GCM-16-ESP é a seguinte:



AES-GCM(
    key             = 128-bit key,
    plaintext       = 64-bit IV || payload || TFC || pad || padLen || NH,
    nonce           = 32-bit salt || IV,
    associated-data = SPI || {ESN  SeqNum},
) -> encrypted-payload || 128-bit ICV

ESP = SPI || SeqNum || IV || encrypted-payload || ICV


Para algoritmos GOST russos (cifras de Magma ou Grasshopper), os dados de entrada são semelhantes. Ambas as cifras são usadas no modo MGM (eu diria uma versão melhorada do GCM ) e a rotação regular do material da chave ESPTREE é aplicada usando HMAC-Stribog-256. Isso reduz a carga da chave. Principalmente no contexto do IPsec, isso não é tanto para aumentar seu tempo de uso, mas para reduzir a superfície de ataque através de canais laterais. Por exemplo, devido à malha de chave (uma tecnologia semelhante de rotação constante de chave), a cifra de bloco GOST 28147-89 com tamanho de bloco de 64 bits acabou sendo invulnerável a ataques SWEET32 .



Do ponto de vista da segurança, não há queixas sobre ESP com algoritmos AEAD. Mas para algoritmos AEAD, IV é apenas um contador de 64 bits, explicitamente passado com cada pacote que desperdiça espaço no pacote. SeqNum é muito curto e o ESN não é totalmente transmitido, embora se encaixe completamente como um IV. Para algoritmos não AEAD, IV pode já ser necessário e carregar um valor imprevisível, mas de forma alguma um contador. Isso é legado, consumindo espaço precioso na embalagem e o peso não afetam a confiabilidade aqui.







Se IV para AEADs pudesse ter valores de 128 bits, seria possível usar algoritmos como XSalsa20 / XChaCha20 com nonce de 192 bits, 128 bits dos quais são gerados pseudo-aleatoriamente na inicialização e os 64 bits restantes podem ser usados ​​para o contador ... Isso pode ser um salva-vidas para sistemas que perderam seu estado de contador, mas desejam continuar usando as chaves existentes.



TLS 1.3 : XOR é usado como um nonce entre o contador de mensagens e o vetor de inicialização gerado com a chave. Como nem o medidor nem o IV são transmitidos explicitamente, o TLS 1.3 é um pouco mais compacto. Se o ESP usar algoritmos não AEAD, eles podem exigir a geração de um IV imprevisível, que pode consumir muito a CPU.



Túnel e meios de transporte



O que está incluído na carga útil do pacote? Depende se o ESP está operando no modo de transporte ou modo de túnel . O modo de transporte substitui a carga útil do pacote IP transmitido por um ESP com esta carga útil. Ou seja, foi:



---------------------------------------
| orig IP hdr |[ext hdrs]| TCP | Data |
---------------------------------------


passou a ser:



---------------------------------------------------------
| orig |hop-by-hop,dest*,|   |dest|   |    | ESP   | ESP|
|IP hdr|routing,fragment.|ESP|opt*|TCP|Data|Trailer| ICV|
---------------------------------------------------------
                             |<--- encryption ---->|
                         |<---- authenticity ----->|


No modo de túnel, todo o pacote IP é completamente empacotado no ESP e um novo pacote IP é formado, geralmente com novos cabeçalhos e endereços SrcIP / DstIP. Este modo é usado para criar um túnel de pacotes entre redes.



----------------------------------------------------------
| new* |new ext|   | orig*|orig ext|   |    | ESP   | ESP|
|IP hdr| hdrs* |ESP|IP hdr| hdrs * |TCP|Data|Trailer| ICV|
----------------------------------------------------------
                   |<--------- encryption --------->|
               |<---------- authenticity ---------->|


Por exemplo, por meio de setkey posso especificar que todos os pacotes entre as redes 2001: ac :: / 64 e 2001: dc :: / 64 devem passar criptografados por dois terminais de túneis com endereços 2001 :: 123 , 2001 :: 321 ...



spdadd 2001:ac::/64 2001:dc::/64 any -P out ipsec esp/tunnel/2001::123-2001::321/require ;
spdadd 2001:dc::/64 2001:ac::/64 any -P in  ipsec esp/tunnel/2001::321-2001::123/require ;


O modo de transporte costuma ser chamado de conexão host-a-host. Se algum protocolo GRE ou IPv * -over-IPv * for usado para encapsulamento, que já está funcionando entre dois pontos de extremidade, não faz sentido, neste caso, usar o modo de encapsulamento no nível de IPsec. No entanto, o modo de transporte não autentica o cabeçalho IP. Como regra, isso não é importante nem crítico, mas se você quiser ter certeza de que nenhum cabeçalho IPv6 estendido ou rótulos de fluxo de pacotes foram alterados, você deve usar o modo de túnel, mesmo se entre dois hosts, ao custo de sobrecarga.



ISAKMP



O que acontece se eu reiniciar os computadores, SA com todos os valores do contador desaparecerem de sua memória e eu carregar novamente os comandos SP / SA antigos com minhas mãos? Em primeiro lugar, os pacotes que correspondem ao IV podem ser descriptografados, pois isso equivale a usar o teclado de criptografia duas vezes. Em segundo lugar, como SPI / salt / ESN / SeqNum combinam, todos os pacotes interceptados anteriormente serão autenticados de forma válida e você pode reproduzi-los. Reutilizar essas SAs setkey é desastroso para a segurança. Em terceiro lugar, especialmente se ESN não for usado (por exemplo, no FreeBSD no momento em que este livro foi escrito, ele ainda não é suportado), com operação SA longa, você pode não notar que o contador está "esgotado".



Tudo isso significa que precisamos mudar regularmente as chaves ESP. E também negociar um algoritmo de criptografia, a presença de ESN, TFC, modo de transporte / túnel, valores SPI. De fato, o protocolo ISAKMP (Internet Security Association e Key Management Protocol) é usado para isso . Porém, você pode facilmente confundir algumas mensagens instantâneas com criptografia autenticada OTR / PGP / OMEMO e apenas enviar os comandos setkey do script de shell para o servidor, no qual as chaves são geradas lendo / dev / urandom . Não importa para o kernel como foi acordado. Como no OpenVPN: a autenticação X.509 com certificados e negociação de chave geralmente ocorre por TLS, e o próprio protocolo de transporte VPN já é seu.



Em sua forma "pura", ISAKMP não é usado, uma vez que não há criptografia nele. Para autenticar interlocutores e gerar material de chave, um protocolo de terceiros é usado que encapsula ISAKMP dentro de si mesmo. Eu sei:



  • KINK - Negociação de Chaves da Internet Kerberizada , onde um terceiro KDC Kerberos confiável é usado para autenticação e negociação. Além da descrição da Wikipedia, não sei mais nada sobre o KINK e não o vi ao vivo.
  • IKE (v1) - Internet Key Exchange . Provavelmente ainda é o protocolo mais popular, embora tenha sido criado em 1998.
  • IKEv2 é a segunda versão do IKE, 2005, sobre a qual falarei.


Os protocolos IKE são muito extensíveis devido ao grande número de diferentes tipos de carga útil. O IKEv1 possui um grande número de opções para configurar apenas um túnel para funcionar. Mais de uma dúzia de RFCs que descrevem todo o grupo de ISAKMP e IKEv1 com cargas úteis comuns. Complexidade intimidante. Além da capacidade de confundir facilmente configurações não infalíveis e o conhecido mito, em parte merecidamente verdadeiro, de que o IKEv1 funcionará apenas se, quase completamente, copiar o arquivo de configuração.



Felizmente, o IKEv2 apareceu: um RFC conveniente (para a maioria dos recursos), um protocolo significativamente simplificado para a negociação de parâmetros e, consequentemente, sua configuração. Como regra, ele tem menos viagens de ida e volta para todo o processo de handshake e acordo de chave do que no IKEv1. Portanto, só ele será considerado, já que não há mais sentido no IKEv1 (mas dificilmente vale a pena correr atrás de instâncias já em execução e em funcionamento, uma vez que estão funcionando). O IKEv2, ao contrário do IKEv1, usa algoritmos e abordagens absolutamente semelhantes para criptografar suas próprias mensagens como o ESP faz. Ele também introduziu a autenticação EAP e a capacidade de cada parte autenticar com métodos diferentes (por exemplo, o cliente usa PSK e o servidor X.509 usa certificados).



Daemon IKE



      +-------------+
      |  |
      +-------------+
       |           |
       |           |
       |           |      /userspace
=====[PF_KEY]====[PF_INET]====================
       |           |                    
+-----------+   +-------------+
| |   |TCP/IP,      |
|  SA  SP  |---| IPsec|
+-----------+   +-------------+
                     |
                 +-----------+
                 |    |
                 |  |
                 +-----------+


Esta parte da pilha IPsec já está em execução, geralmente no espaço do usuário. Em primeiro lugar, esses daemons não são muito carregados: eles podem se comunicar uns com os outros pelo menos uma vez por dia, e o handshake inicial leva algumas viagens de ida e volta sobre o UDP. Em segundo lugar, o número de recursos ISAKMP / IKE é tal que há centenas de vezes mais código do que na implementação SA / SP / ESP completa. Existem muitos daemons ISAKMP: strongSwan (IKEv1 / v2) (bem como Openswan , Libreswan ), isakmpd (IKEv1), OpenIKED (IKEv2), racoon (IKEv1), racoon2 (IKEv1 / v2, KINK) e outros.



Nota: correto escrever e falar "Daemons» ( daemons), como tenho visto em traduções de ficção. Mas nos círculos técnicos de língua russa, os "demônios" já criaram raízes.



TLS 1.3 : em geral, toda a pilha TLS é composta por funções de biblioteca que funcionam em cada aplicativo individual e armazenam o material da chave em sua própria memória. Toda a criptografia é feita com a mudança para o espaço do usuário, o que é uma grande sobrecarga. No entanto, pelo menos FreeBSD e Linux já possuem implementações de descarregamento nuclear de TLS, quando, de maneira semelhante ao IPsec, a parte de transporte é processada inteiramente no kernel e o handshake ocorre no espaço do usuário.



IKEv2 é executado em UDP, na porta 500 por padrão ( isakmpserviço). Daemons criam um canal seguro, autenticam uns aos outros, negociam / criam / excluem ESP SA / SPs, atualizam chaves, fazem pulsação (Dead Peer Detection ( DPD )) e muito mais. Toda a comunicação entre daemons ocorre na forma de uma troca de um par de mensagens de solicitação / resposta. Qualquer pedido deve ser respondido. Como este é o UDP, o que fazer se um pacote for perdido? Leve isso em consideração no seu estado, reenvie as solicitações após o tempo limite para as quais nenhuma resposta foi recebida, reenvie as respostas às solicitações repetidas, ignore as respostas repetidas. Os pacotes podem chegar em uma ordem caótica, eles podem desaparecer de forma imprevisível - muito é levado em consideração no padrão IKEv2 e é descrito como se comportar em várias condições de corrida.



TLS 1.3: A natureza TCP do TLS cuida do pedido e da entrega das mensagens. Mas o TCP consome recursos significativos no kernel do sistema operacional e um grande número de sessões TCP pode ser um problema (ao contrário do UDP). Mas no DTLS todos os problemas semelhantes surgirão da mesma forma que no IKE, mais hemorróidas com o processamento de mensagens fragmentadas serão adicionadas. Alterar os endereços IP dos terminais para UDP não é um problema. As conexões IKE, como regra, duram muito (o estado IKE é pequeno e é armazenado apenas na memória do daemon do espaço do usuário) e, portanto, requerem menos handshake, enquanto no TLS, depois de perder uma conexão TCP, você terá que fazer isso (embora haja também métodos acelerados de continuar as sessões se o estado for perdido, por exemplo, ao reiniciar o programa). Uma vez que o daemon IKE é um para todo o sistema (como regra), então, se algum aplicativo quiser se comunicar com segurança com elecom alguém que já tem uma conexão IKE, ele pode usá-la imediatamente ou o daemon, em uma viagem de ida e volta, criará um SA de ESP adicional para o aplicativo.



Miúdos IKE



A primeira troca (solicitação-resposta) dos daemons será IKE_SA_INIT , que cria uma IKE SA para comunicação mais segura. Observe que o ESP SA está "armazenado" no kernel e o IKE SA está no daemon do espaço do usuário. Em seguida, vem a troca IKE_AUTH , onde as partes são autenticadas. Na mesma troca, é criada uma criança SA ( Criança SA ), que é utilizada para ESP SA. Em geral, essas duas trocas são suficientes para autenticar as partes e negociar os parâmetros ESP SA com as chaves e, em seguida, conduzir o tráfego ESP criptografado entre computadores. Ao mesmo tempo, um IKE SA funcional permanece entre os daemons por um longo tempo. Além disso, a qualquer momento, eles podem fazer uma troca CREATE_CHILD_SA , para criar mais SAs filho, bem como INFORMATIONALintercâmbio (uma variedade de finalidades).



Todos os cabeçalhos de mensagens IKEv2 têm a seguinte estrutura:



                     1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       IKE SA Initiator's SPI                  |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       IKE SA Responder's SPI                  |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Next Payload |    Version    | Exchange Type |     Flags     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Message ID                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Length                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


  • SPIi - SPI do iniciador IKE SA de 64 bits. Um identificador gerado aleatoriamente pelo iniciador da sessão IKE.
  • SPIr - Respondente SA IKE de 64 bits SPI. Da mesma forma, mas apenas o SPI do lado do respondente. Na primeira mensagem do iniciador, este campo é preenchido com zero bytes.
  • NP - próxima carga útil de 8 bits. Identificador de carga útil após o cabeçalho.
  • Versão - versão de 8 bits do protocolo IKE.
  • ExchType - tipo de troca IKE de 8 bits: IKE_SA_INIT , IKE_AUTH , CREATE_CHILD_SA ou INFORMATIONAL .
  • Flags — 8- . .
  • MsgID — 32- . , , replay-. — request/response MsgID. , .
  • Len — 32- ( + ).


SPIi + SPIr são 128 bits. Por que tanto quando o ESP tem apenas 32 bits? Em primeiro lugar, como não combinam, mas são gerados pseudo-aleatoriamente, 64 bits para um lado será suficiente para evitar colisões. Em segundo lugar, o ESP também está vinculado aos endereços IP, enquanto uma sessão IKE geralmente não - as partes podem facilmente alterar seus endereços IP (cliente móvel) e continuar a se comunicar.



TLS 1.3: Alterar o endereço IP desconectará a conexão. Você precisará fazer o rehandshake, mesmo com iPSK, economizando recursos para criptografia assimétrica, isso é 1,5 viagens de ida e volta mais viagens de ida e volta para estabelecer uma conexão TCP. A criação de SAs ESP filhos em novos endereços IP, em uma conexão IKE já estabelecida (desvinculada de endereços), levará apenas uma viagem de ida e volta (+ ida e volta para remover os antigos, mas isso já acontecerá no plano de fundo de uma nova ESP SA em funcionamento).



O cabeçalho IKE é seguido por uma ou mais cargas úteis. Cada carga útil tem um cabeçalho de formato geral, seguido por conteúdo específico para seu tipo. O conteúdo é alinhado a 32 bits. Um cabeçalho comum para todos:



                     1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Next Payload  |C|  RESERVED   |         Payload Length        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


  • Next Payload — 8- . payload- . payload. payload IKE . Encrypted Payload, payload- NP ( payload IKE ), payload- .
  • C — «» payload. IKEv2 payload , IKE . payload . IKE vendor-specific , .
  • Len — 16- payload ( + ).


Assim, as mensagens IKE consistem em um cabeçalho IKE e cargas úteis vinculadas em uma cadeia. Daemons podem ignorar cargas úteis desconhecidas e não críticas. O conteúdo da carga útil do tipo Nonce (após o cabeçalho) é apenas um conjunto aleatório de dados, não um tamanho fixo. Mas também existem estruturas muito mais complexas. Nos padrões IKE, designações curtas de tipos de carga útil são aceitas (por exemplo, N * para mensagens nonce, onde "*" é "i" (iniciador) ou "r" (respondedor)).



SIGMA



Do ponto de vista criptográfico, IKEv1 / IKEv2 pertence à classe STS, ISO / IEC IS 9798-3 e SIGMA (SIGn-and-MAc) de protocolos de troca de chave autenticados. Estas são soluções muito bem pesquisadas e matematicamente verificadas (SIGMA). No meu artigo "P2P F2F E2EE IM em uma noite" , já descrevi o princípio de operação e implementação do protocolo SIGMA-I. IKEv2 é completamente semelhante. Quando discutimos a segurança do protocolo de handshake, o que esperamos?



  • confidencialidade das mensagens transmitidas;
  • autenticidade e integridade das mensagens transmitidas - sua alteração deve ser detectada;
  • proteção contra ataques de replay - o fato de perda ou replay de mensagens deve ser detectado;
  • ;

    perfect forward secrecy (PFS) — PSK ( IKE ESP SA). ;

    / ( ) IKE . / ( ) ;

    , , . .



Após essa troca IKE_SA_INIT , os daemons têm os endereços uns dos outros, SPIi + SPIr o valor da sessão IKE, os algoritmos negociados de SA (no caso do IKE, são o acordo de chave ( DH ), criptografia / autenticação de mensagem ( ENCR ), algoritmos de geração de chave ( PRF )), a chave pública (DH) do lado oposto. Isso é suficiente para salvar o estado na memória e realizar o acordo de chave (Diffie-Hellman, GOST R 34.10-VKO, curve25519 e semelhantes), gerando uma chave simétrica para criptografar a carga das mensagens IKE subsequentes.



TLS 1.3: o formato das mensagens de handshake é muito diferente, há muito legado, mas fundamentalmente nada se destaca. O campo aleatório é usado em vez de nonce. Em vez de cargas úteis, várias extensões. Em vez de uma estrutura de proposta de SA complexa, são usados ​​identificadores ciphersuites, que são mais compactos e simples. Na minha opinião, a flexibilidade das propostas SA é excessiva, mas no IKEv2 isso ainda não é um problema e valores semelhantes ao ciphersuite são escritos no arquivo de configuração. Apenas com o TLS 1.3 versão DH a troca torna-se obrigatória.



Material chave IKE



Após IKE_SA_INIT , SKEYSEED é gerado :

SKEYSEED = PRF (Ni [: 8] || Nr [: 8], DH-KEY)


O algoritmo PRF é selecionado no IKE SA. Por exemplo, para GOST IKEv2, esta é a função HMAC-Stribog-512. A chave PRF é um pedaço de 64 bits de cada nonce.



Parece frívolo, porque os nonces são transmitidos abertamente, o que significa que a chave para este PRF é conhecida por qualquer pessoa que interceptou o tráfego. Mas o PRF é usado aqui exclusivamente para gerar uma chave a partir do resultado DH-KEY do cálculo de DH , já desconhecido para o invasor . O resultado da função DH pode ser um valor de entropia enorme e desigual, pode ser um ponto em uma curva elíptica - tudo isso não pode ser usado como uma chave simétrica curta de alta entropia. Portanto, você precisa extrair a entropia de DH-KEY (isso é SKEYSEED ) e, em seguida, "expandir" (expandir ) para o número necessário de chaves:



PRF+(SKEYSEED, Ni || Nr || SPIi || SPIr) ->
    SK_d || SK_ai || SK_ar || SK_ei || SK_er || SK_pi || SK_pr

PRF+(K,S) = T1 || T2 || T3 || T4 || ...
T1 = PRF(K,       S || 0x01)
T2 = PRF(K, T1 || S || 0x02)
T3 = PRF(K, T2 || S || 0x03)
T4 = PRF(K, T3 || S || 0x04)


Tudo isso é uma operação clássica de derivação de chave com estágios de extração / expansão , semelhante à função HKDF . Mas se HKDF assume o uso de funções hash, então esta construção PRF / PRF + pode ser usada simplesmente com cifras simétricas - no caso do AES-GCM + AES-XCBC-PRF comum, não usaremos uma função hash em qualquer lugar, mas um pequeno número primitivos usados ​​são sempre bons.



As seguintes chaves são geradas:



  • Chave SK_d para gerar chaves para SAs ESP filho.
  • Chaves SK_a [ir] para autenticação de mensagem IKE. Não gerado / não usado se o algoritmo AEAD for aprovado (AES-GCM, Grasshopper / Magma-MGM, ChaCha20-Poly1305, etc.).
  • SK_e[ir] IKE .
  • SK_p[ir] AUTH.


TLS 1.3: tem uma programação de teclas muito mais complexa. A entropia é comprimida de todas as mensagens de handshake de uma só vez, em vez de campos individuais. A sequência estendida gerada não é apenas cortada em um número de chaves (+ sal para elas quando necessário), mas também acompanhada por transformações HMAC com rótulos (rótulos) para cada contexto de uso dessas chaves ou IVs gerados. Usar rótulo textual / aplicativo / contexto para qualquer tipo de valor gerado é uma boa prática moderna e é mais fácil de sempre do que se perguntar se você precisa dele. Fazer hash em tudo que aparecer também é uma prática muito boa, "não vai ficar pior". No entanto, isso não significa que a segurança do IKEv2 seja pior, ou que alguém possa facilmente chegar a pelo menos uma situação remotamente teórica em que a ausência de um rótulo pode estar nas mãos de um invasor.No IKEv2, a abordagem é mínima, enquanto no TLS 1.3 é "melhor substituir" (porque quantas ombreiras ou dificuldades foram feitas nas versões anteriores do protocolo!). IKEv2 ainda usa abordagens e primitivas comprovadas, autentica tudo o que é necessário, comprime / leva em consideração toda a entropia transferida, usa chaves diferentes para cada lado e tarefa.



IKE_AUTH



Em seguida, uma troca IKE_AUTH é realizada , autenticando ambos os lados e negociando o SA ESP:



    SK{IDi, [CERT, ...], [CERTREQ], [IDr], AUTH, SAi2, TSi, TSr} -->
<-- SK{IDr, [CERT, ...],                   AUTH, SAr2, TSi, TSr}


  • As mensagens IKE contêm uma carga criptografada ( SK ), que contém todas as outras.
  • O iniciador fornece seu identificador ( IDi ), autenticador ( AUTH ), oferta SA para ESP ( SAi2 ) e um par iniciador / respondedor, os chamados seletores de tráfego ( TS * ). Ele também pode enviar opcionalmente o identificador de resposta esperado, que pode ser considerado um tipo de SNI analógico de TLS.
  • Em resposta, ele recebe o identificador do respondente, a proposta ESP SA negociada, seletores de tráfego validados e um autenticador.
  • Depois disso, ambas as partes se consideram autenticadas, têm um acordo sobre ESP SA, tráfego que deve pertencer a este ESP, e já podem emitir um comando para o kernel para criar SA e, possivelmente, SP (há daemons que não lidam com SP de forma alguma).


Agora com mais detalhes sobre essas cargas úteis:



  • ID - identificador da parte. Contém o tipo de identificação e dados específicos para ele. As partes podem ser identificadas de várias maneiras: endereço IPv4 / IPv6, FQDN (nome de domínio totalmente qualificado, apenas uma string, a forma mais popular), endereço de e-mail RFC822, Nome distinto ASN.1 DER (a forma mais comum ao usar certificados X.509) ou Nome geral bem como específico do fornecedor.
  • AUTH — . PRF ( MAC-), (pre-shared key (PSK)), . (TBS*):



    TBSi = Msg0 || Nr || PRF(SK_pi, IDi)
    TBSr = Msg1 || Ni || PRF(SK_pr, IDr)
    


    (Msg0), nonce (Nr), (IDi), «» . , SK_pi ( ). «».



    / . . ( Ni Nr), . , , .



    , . ( ), . , - . round-trip-. SIGMA- , IKEv2, ESP SA, . , , . SIGMA MAC c ( SK_*). IKEv2 PRF, . , PRF(ID*) , brute-force ( ) .



    PSK, :



    AUTHi = PRF(PRF(PSK, "Key Pad for IKEv2"), TBSi)
    AUTHr = PRF(PRF(PSK, "Key Pad for IKEv2"), TBSr)
    


    PRF(PSK) PSK ? PSK PRF . PSK , /. PRF() «» . PRF(PSK) PSK PSK , ( Argon2, Balloon ).

  • SA*2 — SA , ESP .
  • TS* — . : IPv4/IPv6 , IP (), / (), / . :



    TSi = ((proto=17, port=100, fc::123 - fc::123),
           (proto=17, port=200, fc::123 - fc::123))
    TSr = ((proto=17, port=300, :: - ffff:..:ffff),
           (proto=17, port=400, :: - ffff:..:ffff))
    


    , UDP ( = 17), 100- 200- fc::123 , UDP 300 400. , IP . , , IP , ( , ICMP ). , .



    UDP . , , , 100 300-, ESP SA .



    A parte respondente envia sua seleção confirmada de seletores, que correspondem ou podem ter faixas de seleção mais estreitas.


Todas essas cargas úteis são criptografadas na chave gerada pelo IKE SA após a primeira troca de mensagens. A criptografia é necessária para ocultar os identificadores da parte transmitida, seus certificados e outras informações privadas abertamente. No entanto, um invasor ativo pode entrar na primeira troca IKE_SA_INIT e ver essas informações, embora não seja mais capaz de continuar a sessão.



TLS 1.3 :



  • application ( ServerHello ||… || Finished, , , ), (Client Finished). IKEv2 ESP SA round-trip-, TCP/SCTP handshake.
  • , (IDr ), SNI, ClientHello . IKEv2 . ESNI, , DNS, DPI.
  • IKEv2 , «»/«» ( ), PSK, , EAP. TLS 1.3 X.509 . TLS 1.3 X.509 . RFC TLS 1.3 «» . IKEv2 / .
  • TLS 1.3 , , application ClientHello (EarlyData), application Client Finished . TLS 1.3 EarlyData .
  • TLS (session resumption), iPSK , , . IKEv2 , RFC 5723 . IKE , , ( TCP/SCTP/whatever ) IP .
  • TLS . IKEv2 IKE SA ESP SA . , () high-grade , . , , , . - ChaCha20-Poly1305, AES-256-GCM-16, -MGM . IKE SA ESP - NIST-.


A criptografia da carga útil do SK com cifras AEAD não é complicada e é completamente semelhante ao ESP, por exemplo, para AES-GCM (em que, da mesma forma que AES-GCM-ESP, o sal faz parte do material chave):



AES-GCM(
    key             = SK_*e,
    plaintext       = 64-bit IV || payloads || pad || 8-bit padLen,
    nonce           = 32-bit salt || IV,
    associated-data = IKEHdr || unencrypted payloads
) -> ciphertext


Autenticação com EDS



E se alguma parte quiser autenticar com certificados de assinatura e X.509? Para isso, já em IKE_SA_INIT , pode ser enviada uma carga útil CERTREQ , solicitando ao lado oposto que forneça um certificado na forma de carga útil CERT . CERT e CERTREQ contêm o identificador do formato do certificado e conteúdo específico do formato. Normalmente, os certificados podem ser apresentados como ASN.1 DER ou como hash SHA1 do certificado + URL de onde podem ser baixados. Como o tamanho do UDP é limitado pela MTU e os tamanhos dos certificados podem ser muito maiores, a opção hash + URL é salutar aqui (embora possa ser considerada uma muleta).



O RFC IKEv2 sozinho lista, além dos certificados X.509 codificados por DER e URLs SHA1 +: certificado X.509 empacotado PKCS # 7, certificado PGP, chave assinada DNS, certificado SPKI, certificado de atributo X.509, chaves públicas brutas. Se você deseja usar IPsec semelhante ao TLS de caso de uso mais frequente: um servidor autenticado por um certificado X.509 e um cliente anônimo, então em IKEv2 não há como não autenticar uma das partes. Mas a RFC 5386 descreve uma abordagem de segurança melhor que nada, em que o "cliente" pode usar a chave pública vazia e o servidor pode tratá-la como anônima.



Além disso, a autenticação EAP é compatível com o padrão, adicionando viagens de ida e volta a IKE_AUTHtroca. O EAP pode dizer se a parte está autenticada ou não, bem como gerar uma chave que o IKEv2 levará em consideração e usará. Vou mostrar apenas um diagrama de como o EAP pode funcionar:



                 SAi1, KEi, Ni  -->
                                <--  SAr1, KEr, Nr
SK{IDi, [IDr], SAi2, TSi, TSr}  -->
                                <--  SK{IDr, AUTH, EAP}
                       SK{EAP}  -->
                                <--  SK{EAP(success)}
                      SK{AUTH}  -->
                                <--  SK{AUTH, SAr2, TSi, TSr}


TLS 1.3 : nele, a assinatura (ou MAC na mensagem Concluída ) é colocada acima do hash de todas as mensagens vistas que participaram do handshake. Também é uma boa abordagem simples e confiável. Não há variedade de métodos de autenticação. Mas eu gostaria de ver algum protocolo forte de Authenticated Password Key Agreement (PAKE), como o SESPAKE russo ou OPAQUE .



Material chave ESP SA e sua renovação



Assim, verificamos a autenticação, verificamos se o acordo de chave estava correto, negociamos o ESP SA e os seletores de tráfego. Resta gerar chaves simétricas para ESP e o SA / SP necessário pode ser instalado no kernel:

PRF + (SK_d, Ni || Nr) -> KEYMAT0 || KEYMAT1


A comunicação bidirecional requer dois SAs ESP, de modo que o IKEv2 gera dois materiais principais de uma vez, que já são transmitidos diretamente para o núcleo no SA correspondente. O comprimento do material depende do algoritmo ESP usado (por exemplo, AES-GCM-ESP requer, além da chave, também sal de 32 bits). O valor SPI é o valor SPI especificado por cada parte nas propostas ESP SA.



O que se precisa concordar em várias ESP SA / SPs, por exemplo, porque nem todos os desejos podem ser especificados em uma única TSi / TSR par ? Para isso, são utilizadas trocas CREATE_CHILD_SA que ocorrem a qualquer momento após IKE_AUTH . A criação de uma SA criança ocorre na seguinte troca:



    SK {SA, Ni, [KEi], TSi, TSr} ->
<- SK {SA, Nr, [KEr], TSi, TSr}


Oferta SA é feita, nonces, seletores de tráfego são enviados. Tudo está como antes. O material chave já é gerado usando esses novos nonces. Opcionalmente, você pode usar cargas úteis de troca de chaves, que adicionam entropia e forçam as partes a usar criptografia ainda mais assimétrica. Isso pode ser necessário para a observância constante da propriedade PFS (no protocolo OTR , chaves DH efêmeras são enviadas com cada mensagem). O material chave neste caso será trabalhado da seguinte forma:



PRF + (SK_d, DH-KEY || Ni || Nr) -> KEYMAT0 || KEYMAT1


E se quisermos renovar o IKE SA da conexão? Fazemos a seguinte troca de CREATE_CHILD_SA :



    SK {SA, Ni, KEi} ->
<- SK {SA, Nr, KEr}


onde SA já conterá propostas IKE SA e um novo SKEYSEED será desenvolvido :



PRF (SK_d_old, DH-KEY || Ni || Nr) -> SKEYSEED


A chave ESP SA é atualizada criando um novo ESP SA (com um SPI diferente) e excluindo o antigo, ou enviando uma notificação especial (sobre isso abaixo). Mudar o tráfego para usar o novo ESP SA será transparente e sem perdas. Por um curto período, as partes terão dois ESP SAs ativos, o que lhes permitirá processar o tráfego que ainda está em trânsito nos canais de comunicação.



A exclusão de um SA ESP é feita enviando uma carga útil DELETE em trocas INFORMAÇÕES subsequentes que listam os SPIs a serem excluídos. Uma vez que todos os SAs ESP existem em pares (para comunicação bidirecional), cada lado envia valores SPI apenas aos SAs ESP responsáveis ​​pelo tráfego de saída. Em resposta, receba valores SPI ESP SA para o tráfego de entrada.



    SK {D (SPIi)} ->
<- SK {D (SPIr)}


A exclusão de um IKE SA também é feita por meio de DELETE , mas com um IKE SPI e aceitando uma resposta autenticada vazia:



    SK {D} ->
<- SK {}


TLS 1.3 : existe um mecanismo de rotação de chaves através de mensagens KeyUpdate , mas não há possibilidade de adicionar entropia adicional ou realizar DH. O TLS claramente não foi projetado para conexões de longa duração. Na melhor das hipóteses, você só pode interromper a sessão e continuar / criar uma nova com o handshake iPSK-ECDHE.



O IKEv1 tem um procedimento de renovação de chave IKE separado e outro para reautenticação. Não há reautenticação no IKEv2. Para fazer isso, um novo IKE SA é simplesmente criado do zero, o antigo é excluído via DELETE .



TLS 1.3 : tem uma capacidade de autenticação de cliente pós-handshake a qualquer momento após o handshake ( Concluídomensagens de ambos os lados), o servidor pode enviar uma solicitação de autenticação de cliente usando um certificado X.509. Por exemplo, um cliente, vagando pelo site, foi até a página de sua conta pessoal. No IKEv2, isso não é possível - a autenticação é realizada apenas no momento do handshake.



NOTIFICAR



Então, como os modos de túnel / transporte são negociados, TFC? Para isso, cargas úteis de "notificações" NOTIFY ( N ) são adicionadas à solicitação . Existem dezenas de tipos de notificações apenas no RFC IKEv2. Os alertas são usados ​​para sinalizar erros, problemas de negociação de SA, seletores de tráfego, etc ...



Para sinalizar o desejo de usar o modo de transporte em um SA ESP negociado, uma notificação N (USE_TRANSPORT_MODE) é adicionada pelo iniciador e pelo respondente para confirmar a negociação do modo. O alerta N (ESP_TFC_PADDING_NOT_SUPPORTED) sinaliza que o TFC não é suportado. E N (HTTP_CERT_LOOKUP_SUPPORTED) indica que o download de um certificado de um URL é compatível.



A capacidade de atualizar a chave ESP SA, sem criar novos ESP SAs, é semelhante ao procedimento para criar um ESP SA filho, mas o iniciador adiciona uma notificação N (REKEY_SA) contendo o SPI do ESP SA atual:

    SK {N (REKEY_SA), SA, Ni, [KEi], TSi, TSr} ->
<- SK {SA, Nr, [KEr], TSi, TSr}





DPD



A troca INFORMATIONAL com SK vazio é usada para detecção de pares mortos ( DPD ), como uma pulsação entre daemons. Se o daemon IKE ficar indisponível por um longo tempo, provavelmente ele perdeu seu estado e, portanto, ninguém está observando o ESP SA no lado oposto ou eles não estão mais ativos. Portanto, quando estiver claro que o par não está disponível, faz sentido remover todas as SAs ESP / IKE associadas. Um SK vazio significa que não há carga útil nele, mas tem dados autenticados (pelo menos cabeçalhos IKE com contadores), portanto, a autenticação de tal pacote é um sinal de vida confiável.



    SK {} ->
<- SK {}


Mas e se um lado reiniciasse rapidamente, perdesse o estado e começasse a estabelecer uma conexão IKE do zero? O lado oposto pode nem perceber que o outro não está disponível e pode pensar que decidiu reautenticar ou criar novas SAs filhas em outra conexão IKE. Nada catastrófico será, mas o velho ESP SA ainda pode viver um tempo decente. Um iniciador PODE colocar um alerta N (INITIAL_CONTACT) em sua troca IKE_AUTH , sinalizando que é a única conexão IKE conhecida para aquele lado. Ao ver essa notificação autenticada, você pode excluir todas as SAs IKE / ESP antigas com a consciência limpa.



DoS e KE ruim



Já no início de IKE_SA_INIT, uma carga útil KEi é enviada com uma chave pública DH efêmera. Mas o iniciador ainda não trocou o IKE SA, e como ele sabe qual algoritmo o lado receptor suporta? Ele só pode adivinhar ou lembrar na memória de longo prazo o que foi anteriormente usado para associar a este endereço. Se o respondente não oferecer suporte ao algoritmo, ele enviará a N (INVALID_KEY_PAYLOAD) uma notificação, que indicará o identificador do algoritmo DH preferido. O iniciador terá que repetir seu pedido, mas com um novo KEi .



TLS 1.3: pode enviar várias chaves públicas efêmeras de uma vez usando diferentes algoritmos, talvez alguns sirvam. Mas esses são recursos e tráfego. Ele pode não enviar a chave pública e o servidor responderá a ele com HelloRetryRequest com suas preferências - a vantagem é que a criptografia assimétrica cara não é usada até que os algoritmos de servidor preferidos sejam conhecidos, mas ao custo de uma viagem extra de ida e volta. Se o cliente inicialmente forneceu um algoritmo de chave pública inadequado, então, como no IKEv2, ele receberá um HelloRetryRequest com os algoritmos para escolher.



Mas e se você enviar o mesmo pacote inicial do iniciador? É possível gerar um novo SPIi lá sempre... O respondente irá, no mínimo, realizar cálculos de DH honestamente e responder com IKE_AUTH . DH é uma operação de uso intensivo de recursos que queima a CPU e a fonte de entropia - portanto, o transponder pode ser danificado.



Em IKEv2 (mas não IKEv1) há uma proteção contra isso, na forma de uma resposta N (COOKIE) com uma notificação contendo uma string de cookie, após a qual o iniciador deve repetir sua solicitação, mas adicionando esta carga útil N (COOKIE) a ela:



           SAi1, KEi, Ni -->
                         <-- N(COOKIE)
SAi1, KEi, Ni, N(COOKIE) -->
                         <-- SAr1, KEr, Nr, [CERTREQ]


A solicitação deve ter SPI / Ni idêntico ao primeiro. É bastante fácil complementá-lo com carga útil. O respondente pode salvar o estado sobre a conexão entre a solicitação e o cookie enviado a ele e, somente depois que eles correspondem, após concluir este trabalho de adicionar o cookie à solicitação pelo iniciador, o respondente pode continuar a troca IKE_AUTH de maneira regular .



Mas é possível armazenar o estado dentro do cookie, tornando-o "autoautenticado". Pode levar ao fato de que o entrevistado viu a solicitação do iniciador ( Ni e SPIi viram , pelo menos):

Cookie = MAC (algum segredo, Ni || SPIi || timestamp)


Assim, o amante do DoS terá que armazenar o estado e reciclar suas mensagens repetidas, o que torna o ataque muito mais caro. Faz sentido habilitar a proteção de cookies somente quando houver suspeita de um ataque DoS, para não forçar ninguém a realizar uma viagem extra de ida e volta.



TLS 1.3 : Possui segurança opcional semelhante. O servidor PODE responder com HelloRetryRequest com uma mensagem contendo a extensão Cookie , que o cliente deve inserir em seu ClientHello2 repetido .



PC



IKEv2 permite que você negocie a configuração de redes / endereços IP. Payload de configuração ( CP ) permite-lhe fazer um pedido para receber uma configuração ( CFG_REQUEST / CFG_REPLY tipos de pacotes) e definir a configuração para o lado oposto ( CFG_SET / CFG_ACK tipos). A solicitação de configuração contém os atributos que a parte deseja saber / definir. Os atributos podem ser: endereço "interno", endereço DNS, DHCP, conhecimento de sub-rede ou outros tipos descritos em RFCs relacionados. Por exemplo, o iniciador na troca IKE_AUTH pode fazer uma solicitação para emitir a ele um endereço de intranet (conectando-se à rede da empresa) e um servidor DNS:



    SK{IDi, [IDr], AUTH, CP(CFG_REQUEST), SAi2, TSi, TSr} -->
<-- SK{IDr,        AUTH, CP(CFG_REPLY),   SAr2, TSi, TSr}

CP(CFG_REQUEST) =
  INTERNAL_IP6_ADDRESS()
  INTERNAL_IP6_DNS()
TSi = (proto=0, port=0-65535, :: - ffff:...:ffff)
TSr = (proto=0, port=0-65535, :: - ffff:...:ffff)

CP(CFG_REPLY) =
  INTERNAL_IP6_ADDRESS(2001:db8::5/64)
  INTERNAL_IP6_DNS(2001:db8::1)
  INTERNAL_IP6_SUBNET(2001:db8:abcd::/64)
TSi = (proto=0, port=0-65535, 2001:db8::5 - 2001:db8::5)
TSr = (proto=0, port=0-65535, 2001:db8::0 - 2001:db8::ffff:ffff:ffff:ffff)


  • O endereço 2001: db8 :: 5 é alocado ao iniciador .
  • ESP SA 2001:db8::/64 .
  • 2001:db8::1 DNS .
  • 2001:db8:abcd::/64 , , ESP SA, 2001:db8:: .


Go?



Para testar as implementações domésticas modernas da pilha IPsec com algoritmos GOST, decidimos escrever uma implementação completamente independente (do Linux, FreeBSD, strongSwan e outras pilhas). E para velocidade e facilidade de desenvolvimento na linguagem Go , com a implementação já existente de algoritmos GOST da biblioteca GoGOST . Antes, eu já tinha experiência de integração de GOST na implementação TLS 1.3 das bibliotecas crypto / tls e crypto / x509 Go.



O projeto gostipsec é um software livre que consiste em dois daemons: ESPER (ESPv3) e IKER (IKEv2):



          ┌──────┐          ┌────┐          ┌─────┐          ┌────┐
          │remote│          │iker│          │esper│          │ipfw│
          └──┬───┘          └─┬──┘          └──┬──┘          └─┬──┘
             │                │                │               │
╔══════╤═════╪════════════════╪════════════╗   │               │
║ UDP  │     │                │            ║   │               │
╟──────┘     │    IKEv2...    │            ║   │               │
║            │ <───────────────            ║   │               │
║            │                │            ║   │               │
║            │    IKEv2...    │            ║   │               │
║            │ ───────────────>            ║   │               │
╚════════════╪════════════════╪════════════╝   │               │
             │                │                │               │
             │                │                │               │
             │    ╔═══════════╪══╤═════════════╪════════════╗  │
             │    ║ UNIX-SOCKET  │             │            ║  │
             │    ╟─────────────setkey-commands│            ║  │
             │    ║           │ ───────────────>            ║  │
             │    ╚═══════════╪════════════════╪════════════╝  │
             │                │                │               │
             │                │                │               │
             │                │   ╔════════════╪═══╤═══════════╪════════════╗
             │                │   ║ DIVERT-SOCKET  │           │            ║
             │                │   ╟──────────────encrypted ESP │            ║
             │                │   ║            │ <──────────────            ║
             │                │   ║            │               │            ║
             │                │   ║            │ decrypted ESP │            ║
             │                │   ║            │ ──────────────>            ║
             │                │   ║            │               │            ║
             │                │   ║            │ unencrypted IP│            ║
             │                │   ║            │ <──────────────            ║
             │                │   ║            │               │            ║
             │                │   ║            │  encrypted IP │            ║
             │                │   ║            │ ──────────────>            ║
             │                │   ╚════════════╪═══════════════╪════════════╝
             │                │                │               │


No momento, ESPER funciona apenas com REENVIO soquetes (eu não encontrar nada tão simples sob Linux), portanto, é suportado apenas em FreeBSD (provavelmente OpenBSD, não verificar) OS. O ESPER, assim como o IKER, não usa PF_KEYv2 , que exigiria ligações C, como uma interface entre as ligações ESP <-> IKE , mas a interface semelhante a setkey de texto já mencionada no início do artigo. Portanto, o IKER também pode ser usado para negociar chaves para uma implementação de kernel ESP invocando o comando setkey real . Esses comandos para ESPER são assim:



add fc00::ac fc00::dc esp 0x12345678 -u 123 -E aes-gcm-16 0xd3537e657fde5599a2804fbb52d1aaed94b65d3e ;
add fc00::dc fc00::ac esp 0x12345679 -u 234 -E aes-gcm-16 0x9a2dae68e475eacb39d41f23c3cbef890e9f6276 tfc:1320 ;

spdadd fc00::ac/128 fc00::dc/128 all -P in ipsec esp/transport//unique:123 ;
spdadd fc00::dc/128 fc00::ac/128 all -P out ipsec esp/transport//unique:234 ;


ESPER suporta: AES-128/256-GCM-16, Magma / Grasshopper-MGM, ESN, TFC, modos de transporte / túnel, IPv6 / IPv4 (suporte para este último, muito mais complexo, não foi totalmente testado e quem precisa de IPv4 para novos projetos?), proteção contra ataques de repetição. IKER permite que você combine: AES-128/256-GCM-16 + AES-XCBC + curve25519, Magma / Grasshopper-MGM + HMAC-Stribog-512 + GOST R 34.10-2012-VKO-256/512, ESN / TFC / transporte / modos de túnel, autenticar usando assinaturas digitais PSK e X.509 (ECDSA, GOST R 34.10-2012). Configurado por um único arquivo Hjson :



{
    IKEAlgos: [
        gost128-vko512
        aes256gcm16-aesxcbc-curve25519
        aes128gcm16-aesxcbc-curve25519
    ]
    ESPAlgos: [
        gost128-esn
        gost64-esn
        aes256gcm16-esn
        aes256gcm16-noesn
        aes128gcm16-esn
        aes128gcm16-noesn
    ]
    SigHashes: [
        streebog512
        streebog256
        sha512
        sha256
    ]
    DPDTimeout: 300
    Peers: [
        {
            Autostart: true
            OurIP: fc00::dc
            TheirIP: fc00::ac
            OurId: our.company.net
            TheirId: CN=example.com
            OurTSS: [
                fc00::dc/128[tcp]
                fc00::dc/128[udp/53]
            ]
            TheirTSS: [
                fc00::ac/128
            ]
            Mode: transport
            # Won't be used, because of X.509 signature authentication
            PSK: DEADBABE
            TheirCertHash: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447
            OurCert: our.company.net.cer.pem
            OurPrvKey: our.company.net.key.pem
            TFC: 1200
        }
    ]
}


Neste exemplo, definimos o único membro que conhecemos:



  • A qual daemon se conectará automaticamente
  • Faça a detecção de pares mortos a cada cinco minutos
  • ESN, fallback- , TFC 1200 .
  • TCP DNS fc00::dc fc00::ac .
  • X.509 , CN=example.com subject- SHA256 SubjectPublicKeyInfo . OurId OurCert .
  • OurCert/OurPrvKey , PSK FQDN OurId.


O IKER ainda não oferece suporte ao conjunto completo de todos os recursos do IKEv2 ( CREATE_CHILD_SA , recriação de chaves), não controla a perda de pacotes e não se preocupa com o princípio NÃO ENTRE EM PÂNICO . Portanto, ainda não pode ser considerado um candidato para uso "industrial".



Tarball gostipsec já contém todas as dependências, documentação compilada .info e destinos para o sistema de redo build, embora a construção de executáveis ​​seja feita facilmente com uma chamada go build regular .



Hjson?



Tema da Holywar, mas darei meu phi de qualquer maneira:



  • O INI não permite que você especifique essas estruturas de varredura e não há um padrão para arquivos .ini .
  • capabilities database , termcap-like, BSD , (, , ), C. IKER .
  • XML — .
  • JSON — , Python Go . , . - !
  • YAML — , , . , . , YAML , , , . . . - . YAML ( ) - ( StrictYAML ).
  • TOML — : , , , . , :



    [[foo.bar]]
    baz = 123
    
    [[foo.bar]]
    abc = 123
    




    :



    {
      "foo": {
        "bar": [
          {"baz": 123 },
          {"abc": 123 }
        ]
      }
    }
    


    «» / , . , TOML, NNCP , . , , .
  • Hjson — JSON ( , ), Hjson. github.com/hjson/hjson-go Hjson JSON, . . , . , JSON Hjson.




Em geral, se você implementar um subconjunto de recursos semelhante ao TLS 1.3 (autenticação apenas usando certificados PSK e X.509, sem rechaveamento sério), então ESPv3 com IKEv2 e IPv6 (é muito mais fácil trabalhar com ele!), Do ponto de vista do programador, será um pouco mais difícil em implementação. O RFC nem mesmo obriga a apoiar trocas CREATE_CHILD_SA . A segurança será excelente, sem os modos de operação possíveis controversos e perigosos do TLS 1.3. O desempenho de uma solução IPsec geralmente será maior devido ao transporte no nível nuclear e às sessões IKE de longa duração.



Pode-se ver que no IPsec tudo é afiado para proteger a quantidade colossal de tráfego entre redes inteiras, mas BTNS(melhor do que nada segurança) o grupo de trabalho IETF escreveu vários RFCs demonstrando que o IPsec pode ser usado sem problemas para conexões por soquete, onde uma das partes (o cliente) é anônima, questionando assim completamente a conveniência de usar TLS. O travamento de conexão, neste caso, permitiria que qualquer aplicativo de rede, fazendo uma chamada de sistema trivial como setsockopt , indique que precisa de um ESP para o endereço FQDN = bank.com , apresentando-se como um certificado X.509 (ou permanecendo anônimo) e, em seguida, de forma transparente, rápida e trabalhar com segurança com este bank.com , sem muletas na forma de bibliotecas de transporte por aplicativo no espaço do usuário.



Sergey Matveev , cypherpunk, Desenvolvedor Python / Go / C, especialista chefe do FGUP STC Atlas.



All Articles