Menudillos IPsec, medimos contra TLS 1.3, GOST y Go

¡Saludos! Me gustaría hablarles sobre el dispositivo de la pila IPsec moderna de los protocolos ESPv3 e IKEv2 . IPsec, me parece, pasa inmerecidamente por muchos lados y no he visto un análisis detallado de su trabajo, sus protocolos y capacidades en ruso. Además, haré algo extraño: compare IPsec ESPv3 e IKEv2 (ambos de 2005) con el TLS 1.3 moderno, moderno y de última generación de 2018.





¿Por qué me apasiona tanto IPsec, posiblemente la pila de protocolos más compleja para proteger redes? Después de todo, ¡la complejidad es el principal enemigo de la fiabilidad y la seguridad! En primer lugar, cuanto más aprendes sobre sus protocolos, especialmente IKEv2, más comprendes cuántas posibilidades se pusieron en él y te impresiona su consideración, en contraste con el enfoque común de los desarrolladores "una muleta conduce una muleta" y una solución a problemas serios "hasta que estalla el trueno". En segundo lugar, los protocolos IPsec están bien pensados ​​desde un punto de vista criptográfico, e incluso el antiguo ESP / IKEv1, de hecho, son los únicos protocolos industriales de uso masivo en los que no había una vulnerabilidad grave. El mismo SSL (1995) se pensó decentemente solo a partir de la versión 1.3. Y a muchas personas no les gusta IPsec debido a la monstruosa complejidad de IKEv1,que ya no está en v2.



Idealmente, si los desarrolladores de sistemas operativos no se hubieran ralentizado en su tiempo con la implementación e implementación de IPsec e IPv6 (para la disponibilidad de computadoras, para que no haya NAT), entonces no debería haber aparecido SSL / TLS en principio. El mundo resultó no ser perfecto, pero ahora IPsec listo para usar (al menos SA / SP + ESP parte de la pila) está en al menos algún sistema operativo generalizado (personalmente solo conozco DragonFly BSD , que bebió IPsec debido a la falta de desarrolladores que lo admitieran), e IPv6 en algunos países desarrollados está inmediatamente disponible para la gran mayoría de personas.



IPsec es una pila de protocolos, llamadas API, marco para que las aplicaciones y / o el administrador puedan decir qué seguridad necesitan durante la comunicación y se garantizaría de manera transparente a nivel de red ( IP securidad). Podemos hablar tanto de paquetes IP de un solo socket (por ejemplo, conexiones TCP) como de tráfico entre redes completas.



La seguridad del tráfico significa: garantizar la confidencialidad de los datos, su autenticidad / integridad y protección contra ataques de repetición . Como casi todos los protocolos, IPsec tiene una parte de transporte que asegura los paquetes IP y una parte de protocolo de enlace relacionada con la negociación de claves, parámetros, configuración y autenticación de las partes.



TLS 1.3 : solo proporciona protección de datos por socket para conexiones TCP. DTLS puede proporcionar protección para datagramas (DTLS 1.3 aún no es un estándar), pero no todas las bibliotecas lo admiten.



Protocolos de transporte



El transporte IPsec utiliza protocolos IP:



  • AH (encabezados de autenticación). No hablaré más sobre AH, ya que no proporciona confidencialidad de los datos y, por lo que escuché, se hizo únicamente para "aguantar" de alguna manera las leyes de algunos países en la década de 1990 sobre las restricciones al uso de cifrado. El cifrado es tan ligero en relación con todo lo demás que no tiene sentido sacrificarlo. Pero en casi todas partes se menciona ESP, también se hace referencia a AH.
  • ESP (encapsulando cargas útiles de seguridad). ESP ha evolucionado ligeramente con el tiempo y ahora usa su versión ESPv3, que a menudo es compatible con versiones anteriores y no difiere de la versión anterior.


El tráfico IP está protegido solo por la capa de transporte. Y como podemos hablar de muchos millones de paquetes por segundo, el ESP de facto se implementa a nivel del kernel del sistema operativo, en su pila de red, al menos, para no hacer costosos cambios de contexto entre el kernel y el espacio de usuario (como sucede normalmente con TLS , SSH, OpenVPN y otros).



Hago hincapié en que AH y ESP son protocolos de capa IP, red, no transporte. ¿Por qué no UDP? La suma de comprobación es redundante y quema la CPU, y la criptografía garantizará la integridad de todos modos. Pero, si su NAT no sabe nada sobre ESP (y él no lo sabe), entonces todo esto no funcionará para él. Más tarde se les ocurrieron las muletas NAT-T (NAT transversal), cuando el tráfico IPsec está envuelto en un paquete UDP en el puerto 4500 y podrá pasar a través de NAT, pero esto es una sobrecarga innecesaria y la necesidad de editar la pila IPsec en el kernel, porque ya debería comprender estos paquetes UDP especiales y extraer ESP para ello. procesamiento regular.



SP, SA, SPI y nuestro primer cifrado IPsec



¿Cómo sabe el kernel qué hacer con un paquete IP: si cifrarlo con alguna clave, descifrar el ESP entrante o dejarlo pasar sin tocarlo? Para hacer esto, el kernel tiene políticas de seguridad ( SP ). Estas son reglas como en un firewall. Además de ellos, el núcleo contiene Asociaciones de seguridad ( SA ): contextos para realizar operaciones criptográficas (claves, contadores, reproducción de ventanas, etc.). En general, ni los SP son específicos de IPsec ni los SA; pueden usarse para otras tareas / protocolos (por ejemplo, OSPF).



SP / SA se puede configurar a través de una API especial ( PF_KEYv2 ) o manualmente a través de alguna utilidad setkey . Por ejemplo, si queremos decirle al kernel que todos los paquetes IP provenientesLas direcciones fc :: 123 en fc :: 321 deben asegurarse a través de ESP, luego esto se puede hacer fácilmente llamando desde la línea de comando:



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


Antes de este 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


No lo veremos más adelante, ya que el kernel aún no sabe "qué" cifrar. Es necesario agregar una SA y esto también se puede hacer manualmente, configurando la facilidad del cifrado AEAD del algoritmo AES-GCM-16 y una clave aleatoria de 160 bits:



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


Si ejecutamos los mismos comandos en el host remoto (sin olvidar 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


La solicitud está encriptada por ESP, pero la respuesta no. Debido a que ESP funciona en "un sentido" de forma predeterminada y para la comunicación bidireccional, es necesario reflejar la adición de SP / SA para la dirección opuesta.



0xdeadbabe en este ejemplo es el índice de parámetros de seguridad ( SPI ), un identificador único para el "túnel" ESP entre dos direcciones IP, en el que el kernel puede encontrar el contexto SA correspondiente y tomar la clave de descifrado. Y esp / transport // require es un requisito para usar ESP en modo de transporte (más sobre eso a continuación).



Menudillos ESP



El paquete ESP está estructurado esquemáticamente de la siguiente manera:



  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 único de 32 bits para la sesión / túnel / conexión ESP entre direcciones IP. Normalmente, {SrcIP, DstIP, SPI} es la SA y el 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).


La parte completa del paquete desde la carga útil hasta el siguiente encabezado está cifrada. Todo excepto el MAC está autenticado. La longitud del ICV, la presencia de un IV (vector de inicialización) depende de los modos / algoritmos de cifrado y autenticación utilizados.



TLS 1.3 : el relleno opcional de datos a un tamaño determinado apareció solo en la versión 1.3. De lo contrario, el cifrado y la autenticación son completamente similares. TLS 1.3 obliga a utilizar solo algoritmos AEAD, lo cual es correcto y bueno. ESP es compatible con AEAD, pero hay una opción de soluciones más arcaicas. Escriba los campos SPI o SeqNumno, dado que TCP garantiza la secuencia y la entrega, además, en la práctica, no se transmite explícitamente ningún vector de inicialización; por lo tanto, el paquete de la capa de registro TLS es un poco más corto. DTLS ya contiene SeqNum , así como datos de fragmentación de mensajes.



El número de paquete de 32 bits puede ser demasiado corto en la práctica. Esto es solo 4+ mil millones de paquetes IP, que a velocidades de 10+ Mpps pueden volar en minutos. ¿Qué pasa cuando el mostrador se desborda? Se restablecerá a cero. Pero, esto significará que el valor de SPI + SeqNum comenzará a repetirse para nosotros y los paquetes ESP previamente interceptados se pueden usar para reproducir el ataque. Para resolver este problema, se inventó ESN(Número de secuencia ampliado). Este es un contador de 64 bits, pero sólo los 32 bits "inferiores" se transfieren al campo SeqNum , y los 32 bits superiores se almacenan en la memoria. El valor total del ESN está autenticado; por lo tanto, las partes están obligadas a acordar el uso del ESN por adelantado.



Cifrado ESP



¿Cómo ocurre exactamente el cifrado / autenticación de un paquete ESP, por ejemplo, cuando se usa AES-GCM-16? Para trabajar con ESP, utiliza un vector de inicialización de 64 bits ubicado al comienzo de la carga útil . También utiliza sal de 32 bits como parte del material clave. En el ejemplo de setkey, proporcioné no una clave de 128 bits, sino una clave de 128 + 32 bits. Puede haber situaciones en las que la clave se reutiliza y el IV se llena con un generador de números pseudoaleatorios (PRNG) incorrecto cuyos valores se pueden repetir. La sal está diseñada para proteger contra este caso más peligroso, que potencialmente conduce al descifrado de los paquetes interceptados. El cifrado / autenticación ESP en sí mismo en el modo AES-128-GCM-16-ESP es el siguiente:



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 los algoritmos GOST rusos (cifrados Magma o Grasshopper), los datos de entrada son similares. Ambos cifrados se usan en modo MGM (yo diría que una versión mejorada de GCM ), y la rotación de material de clave ESPTREE regular se aplica usando HMAC-Stribog-256. Esto reduce la carga de la llave. Principalmente en el contexto de IPsec, esto no es tanto para aumentar su tiempo de uso como para reducir la superficie de ataque a través de canales laterales. Por ejemplo, debido al mallado de claves (una tecnología similar de rotación de claves constante), el cifrado de bloque GOST 28147-89 con un tamaño de bloque de 64 bits resultó ser invulnerable a los ataques SWEET32 .



Desde el punto de vista de la seguridad, no hay quejas sobre ESP con algoritmos AEAD. Pero para los algoritmos AEAD, IV es solo un contador de 64 bits, pasado explícitamente con cada paquete que desperdicia espacio en el paquete. SeqNum es demasiado corto y ESN no se transmite completamente, aunque encajaría completamente como un IV. Para los algoritmos que no son AEAD, es posible que IV ya sea necesario y tenga un valor impredecible, pero de ninguna manera un contador. Esto es un legado, consumiendo un espacio precioso en el paquete y el peso no afecta la confiabilidad aquí.







Si IV para AEADs pudiera tener valores de 128 bits, entonces sería posible usar algoritmos como XSalsa20 / XChaCha20 con un nonce de 192 bits, de los cuales 128 bits se generan pseudoaleatoriamente al inicio, y los 64 bits restantes se pueden usar para el contador ... Esto podría salvar la vida de los sistemas que han perdido su estado de contador, pero quieren seguir usando las claves existentes.



TLS 1.3 : XOR se usa como un nonce entre el contador de mensajes y el vector de inicialización generado con la clave. Dado que ni el medidor ni el IV se transmiten explícitamente, TLS 1.3 es un poco más compacto. Si ESP usa algoritmos que no son AEAD, entonces pueden requerir generar un IV impredecible, que puede ser notablemente intensivo en la CPU.



Modos de transporte y túneles



¿Qué se incluye en la carga útil del paquete? Depende de si el ESP está funcionando en modo transporte o en modo túnel . El modo de transporte reemplaza la carga útil del paquete IP transmitido con un ESP con esta carga útil. Es decir, fue:



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


convirtió:



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


En el modo de túnel, todo el paquete IP está completamente envuelto en ESP y se forma un nuevo paquete IP, generalmente con nuevos encabezados y direcciones SrcIP / DstIP. Este modo se utiliza para hacer un túnel de paquetes entre redes.



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


Por ejemplo, a través de setkey puedo especificar que todos los paquetes entre las redes 2001: ac :: / 64 y 2001: dc :: / 64 deben pasar cifrados a través de dos extremos de túneles con direcciones 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 ;


El modo de transporte a menudo se denomina conexión de host a host. Si se utiliza algún protocolo GRE o IPv * sobre IPv * para la tunelización, que ya está funcionando entre dos puntos finales, entonces no tiene sentido, en este caso, utilizar el modo de tunelización a nivel de IPsec. Sin embargo, el modo de transporte no autentica el encabezado IP. Como regla general, esto no es importante ni crítico, pero si desea asegurarse de que no se hayan cambiado los encabezados IPv6 extendidos o las etiquetas de flujo de los paquetes, entonces debe usar el modo de túnel, incluso entre dos hosts, a costa de gastos generales.



ISAKMP



¿Qué pasa si reinicio las computadoras, SA con todos los valores de los contadores desaparecen de su memoria y vuelvo a cargar los antiguos comandos SP / SA con mis manos? En primer lugar, los paquetes que coinciden con el IV se pueden descifrar, ya que esto equivale a usar dos veces el teclado de cifrado. En segundo lugar, dado que SPI / salt / ESN / SeqNum coinciden, todos los paquetes interceptados previamente se autenticarán de forma válida y podrá reproducirlos. Reutilizar tales SA de clave de configuración es desastroso para la seguridad. En tercer lugar, especialmente si no se usa ESN (por ejemplo, en FreeBSD en el momento de escribir este artículo, aún no se admite), con una operación larga de SA, es posible que no note que el contador está "agotado".



Todo esto significa que debemos cambiar regularmente las claves ESP. Y también acuerde el algoritmo de cifrado, la presencia de ESN, TFC, modo de transporte / túnel, valores SPI. De facto, el protocolo ISAKMP (Internet Security Association and Key Management Protocol) se utiliza para esto . Sin embargo, puede estropear fácilmente algunos mensajes instantáneos con cifrado autenticado OTR / PGP / OMEMO y simplemente enviar los comandos setkey del script de shell al servidor, en el que las claves se generan al leer / dev / urandom . No le importa al kernel cómo se acordó. Como en OpenVPN: la autenticación X.509 con certificados y la negociación de claves generalmente se realizan a través de TLS, y el protocolo de transporte VPN en sí ya es suyo.



En su forma "pura", ISAKMP no se utiliza, ya que no contiene criptografía. Para autenticar interlocutores y generar material clave, se utiliza un protocolo de terceros que encapsula ISAKMP dentro de sí mismo. Lo sé:



  • KINK : Negociación de claves de Internet kerberizada , donde se utiliza un tercer KDC Kerberos de confianza para la autenticación y la negociación. Además de la descripción de Wikipedia, no sé nada más sobre KINK y no lo he visto en vivo.
  • IKE (v1): intercambio de claves de Internet . Probablemente sigue siendo el protocolo más popular, a pesar de que fue creado en 1998.
  • IKEv2 es la segunda versión de IKE, 2005, de la que hablaré.


Los protocolos IKE son muy extensibles debido a la gran cantidad de diferentes tipos de carga útil. IKEv1 tiene una gran cantidad de opciones para configurar un solo túnel para que funcione. Más de una docena de RFC que describen todo el grupo de ISAKMP e IKEv1 con cargas útiles comunes. Complejidad intimidante. Además de la capacidad de estropear fácilmente configuraciones que no son infalibles y el mito bien conocido, en parte merecidamente cierto, de que se garantiza que IKEv1 solo funcionará si, casi por completo, se copia el archivo de configuración.



Afortunadamente, ha aparecido IKEv2: un RFC conveniente (para la mayoría de las funciones), un protocolo significativamente simplificado para negociar parámetros y, en consecuencia, su configuración. Como regla general, tiene menos viajes de ida y vuelta para todo el proceso de protocolo de enlace y acuerdo de claves que en IKEv1. Por lo tanto, solo se considerará a él, ya que ya no tiene ningún sentido en IKEv1 (pero no vale la pena perseguir para reemplazar las instancias que ya están en ejecución y en funcionamiento, ya que están funcionando). IKEv2, a diferencia de IKEv1, utiliza algoritmos y enfoques absolutamente similares para cifrar sus propios mensajes como lo hace ESP. También introdujo la autenticación EAP y la capacidad de cada parte para autenticarse con diferentes métodos (por ejemplo, el cliente usa PSK y el servidor X.509 usa certificados).



Demonio IKE



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


Esta parte de la pila de IPsec ya se está ejecutando, generalmente en el espacio de usuario. En primer lugar, estos no son demonios muy cargados: pueden comunicarse entre sí al menos una vez al día, y el apretón de manos inicial requiere algunos viajes de ida y vuelta a través de UDP. En segundo lugar, el número de capacidades ISAKMP / IKE es tal que hay cientos de veces más código que en la implementación completa de SA / SP / ESP. Hay muchas implementaciones de demonios ISAKMP: strongSwan (IKEv1 / v2) (así como Openswan , Libreswan ), isakmpd (IKEv1), OpenIKED (IKEv2), racoon (IKEv1), racoon2 (IKEv1 / v2, KINK) y otros.



Nota: correcto para escribir y hablar "Daemons» ( daemons), como he visto en traducciones de ficción. Pero en los círculos técnicos de habla rusa, los "demonios" ya han echado raíces.



TLS 1.3 : en general, toda la pila de TLS son funciones de biblioteca que funcionan en cada aplicación individual y almacenan material clave en su propia memoria. Toda la criptografía se realiza con el cambio al espacio de usuario, que es una gran sobrecarga. Sin embargo, al menos FreeBSD y Linux ya tienen implementaciones de descarga nuclear de TLS, cuando, de manera similar a IPsec, la parte de transporte se procesa completamente en el kernel y el protocolo de enlace tiene lugar en el espacio de usuario.



IKEv2 se ejecuta en UDP, en el puerto 500 de forma predeterminada ( isakmpServicio). Los demonios crean un canal seguro, se autentican entre sí, negocian / crean / eliminan ESP SA / SP, actualizan claves, hacen latidos (Dead Peer Detection ( DPD )) y más. Toda la comunicación entre demonios tiene lugar en forma de intercambio de un par de mensajes de solicitud / respuesta. Cualquier solicitud debe ser respondida. Dado que se trata de UDP, ¿qué hacer si se pierde un paquete? Tenga esto en cuenta en su estado, vuelva a enviar las solicitudes después del tiempo de espera para el que no se hayan recibido respuestas, vuelva a enviar las respuestas a las solicitudes repetidas, ignore las respuestas repetidas. Los paquetes pueden llegar en un orden caótico, pueden desaparecer de manera impredecible; se tiene mucho en cuenta en el estándar IKEv2 y se describe cómo comportarse en diversas condiciones de carrera.



TLS 1.3: La naturaleza TCP de TLS se encarga del orden y la entrega de mensajes. Pero TCP consume importantes recursos en el kernel del sistema operativo y una gran cantidad de sesiones de TCP puede ser un problema (a diferencia de UDP). Pero en DTLS surgirán todos los problemas similares de la misma manera que en IKE, además se agregarán hemorroides con el procesamiento de mensajes fragmentados. Cambiar las direcciones IP de los puntos finales para UDP no es un problema. Las conexiones IKE, por regla general, son muy duraderas (el estado IKE es pequeño y se almacena solo en la memoria del demonio del espacio de usuario) y, por lo tanto, requieren un apretón de manos con menos frecuencia, mientras que en TLS, después de perder una conexión TCP, tendrá que hacerlo (aunque también existen métodos acelerados para continuar sesiones si el estado no era perdido, por ejemplo, al reiniciar el programa). Dado que el demonio IKE es uno para todo el sistema (como regla), si alguna aplicación desea comunicarse de forma segura con esecon alguien que ya tiene una conexión IKE, entonces puede usarla inmediatamente o el demonio, en un viaje de ida y vuelta, creará una SA ESP adicional para la aplicación.



Menudillos IKE



El primer intercambio (solicitud-respuesta) de los demonios será IKE_SA_INIT , que crea una SA IKE para una comunicación más segura. Tenga en cuenta que la SA ESP está "almacenada" en el kernel y la SA IKE está en el demonio del espacio de usuario. Luego viene el intercambio IKE_AUTH , donde se autentican las partes. En el mismo intercambio, se crea una SA secundaria ( Child SA ), que se utiliza para ESP SA. En general, estos dos intercambios son suficientes para autenticar a las partes y negociar los parámetros de ESP SA con las claves y luego impulsar el tráfico ESP cifrado entre computadoras. En este caso, una IKE SA en funcionamiento permanece entre los demonios durante mucho tiempo. Además, en cualquier momento, pueden realizar el intercambio CREATE_CHILD_SA , para crear más SA secundarias, así como INFORMACIONALintercambio (una variedad de propósitos).



Todos los encabezados de mensajes IKEv2 tienen la siguiente estructura:



                     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 : iniciador IKE SA de 64 bits SPI. Un identificador generado aleatoriamente por el iniciador de la sesión IKE.
  • SPIr - SPI de respuesta IKE SA de 64 bits. Del mismo modo, pero solo SPI del lado del respondedor. En el primer mensaje del iniciador, este campo se llena con cero bytes.
  • NP - Carga útil siguiente de 8 bits. El identificador de la carga útil que sigue al encabezado.
  • Versión : versión de 8 bits del protocolo IKE.
  • ExchType : tipo de intercambio IKE de 8 bits: IKE_SA_INIT , IKE_AUTH , CREATE_CHILD_SA o INFORMATIONAL .
  • Flags — 8- . .
  • MsgID — 32- . , , replay-. — request/response MsgID. , .
  • Len — 32- ( + ).


SPIi + SPIr son de 128 bits. ¿Por qué tanto cuando ESP solo tiene 32 bits? En primer lugar, dado que no coinciden, sino que se generan pseudoaleatoriamente, 64 bits para un lado serán suficientes para evitar colisiones. En segundo lugar, ESP también está vinculado a direcciones IP, mientras que una sesión IKE generalmente no lo está: las partes pueden cambiar fácilmente sus direcciones IP (cliente móvil) y continuar comunicándose.



TLS 1.3: Cambiar la dirección IP desconectará la conexión. Necesitará hacer un rehandshake, incluso con iPSK, ahorrando recursos para la criptografía asimétrica, esto es 1.5 viajes de ida y vuelta más viajes de ida y vuelta para establecer una conexión TCP. La creación de las SA ESP secundarias en nuevas direcciones IP, en una conexión IKE ya establecida (sin vincular a las direcciones), tomará solo un viaje de ida y vuelta (+ viaje de ida y vuelta para eliminar las antiguas, pero esto ya sucederá en el fondo de una SA ESP nueva en funcionamiento).



El encabezado IKE va seguido de una o más cargas útiles. Cada carga útil tiene un encabezado de formato general, seguido de contenido específico para su tipo. El contenido está alineado a 32 bits. Un encabezado común 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 ( + ).


Por lo tanto, los mensajes IKE consisten en un encabezado IKE y cargas útiles enlazadas en una cadena. Los demonios pueden ignorar cargas útiles desconocidas y no críticas. El contenido de la carga útil del tipo Nonce (después del encabezado) es solo un conjunto aleatorio de datos, no un tamaño fijo. Pero también hay estructuras mucho más complejas. En los estándares IKE, se aceptan designaciones cortas para los tipos de carga útil (por ejemplo, N * para mensajes nonce, donde "*" es "i" (iniciador) o "r" (respondedor)).



SIGMA



Desde un punto de vista criptográfico, IKEv1 / IKEv2 pertenecen a la clase STS, ISO / IEC IS 9798-3 y SIGMA (SIGn-and-MAc) de protocolos de intercambio de claves autenticados. Estas son soluciones muy bien investigadas y verificadas matemáticamente (SIGMA). En mi artículo "P2P F2F E2EE IM en una noche" ya he descrito el principio de funcionamiento e implementación del protocolo SIGMA-I. IKEv2 es completamente similar. Cuando hablamos de la seguridad del protocolo de protocolo de enlace, ¿qué esperamos?



  • confidencialidad de los mensajes transmitidos;
  • autenticidad e integridad de los mensajes transmitidos: se debe detectar su cambio;
  • protección contra ataques de repetición: se debe detectar el hecho de la pérdida o repetición de mensajes;
  • ;

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

    / ( ) IKE . / ( ) ;

    , , . .



Después de dicho intercambio IKE_SA_INIT , los demonios tienen las direcciones de los demás, SPIi + SPIr el valor de la sesión IKE, los algoritmos negociados por SA (en el caso de IKE, estos son acuerdos de claves ( DH ), cifrado / autenticación de mensajes ( ENCR ), algoritmos de generación de claves ( PRF )), la clave pública (DH) del lado opuesto. Esto es suficiente para guardar el estado en la memoria y realizar un acuerdo de claves (Diffie-Hellman, GOST R 34.10-VKO, curve25519 y similares), generando una clave simétrica para cifrar la carga útil de los mensajes IKE posteriores.



TLS 1.3: el formato de los mensajes de apretón de manos es muy diferente, hay mucho legado, pero fundamentalmente nada que se destaque. Se usa el campo aleatorio en lugar de nonce. En lugar de cargas útiles, numerosas extensiones. En lugar de una estructura de propuesta compleja de SA, se utilizan identificadores de conjuntos de cifrado, que es más compacto y simple. En mi opinión, la flexibilidad de las propuestas de SA es excesiva, pero en IKEv2 esto todavía no es un problema y los valores similares a ciphersuite están escritos en el archivo de configuración. Solo con TLS 1.3, el intercambio de DH se vuelve obligatorio.



Material de la llave IKE



Después de IKE_SA_INIT , se genera SKEYSEED :

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


El algoritmo PRF se selecciona en IKE SA. Por ejemplo, para GOST IKEv2, esta es la función HMAC-Stribog-512. La clave PRF es un fragmento de 64 bits de cada uno de los nonces.



Parece frívolo, porque los nonces se transmiten abiertamente, lo que significa que la clave de este PRF es conocida por cualquiera que haya interceptado el tráfico. Pero PRF se utiliza aquí exclusivamente para generar una clave a partir del resultado DH-KEY del cálculo de DH , ya desconocida para el atacante . El resultado de la función DH puede ser un valor de entropía enorme y desigual, puede ser un punto en una curva elíptica; todo esto no se puede usar como una clave simétrica corta de alta entropía. Por lo tanto, debe extraer la entropía de DH-KEY (esto es SKEYSEED ) y luego "expandir" (expandir ) a la cantidad requerida de claves:



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)


Todo esto es una operación clásica de derivación de clave con etapas de extracción / expansión , similar a la función HKDF . Pero si HKDF asume el uso de funciones hash, entonces esta construcción PRF / PRF + se puede usar simplemente con cifrados simétricos; en el caso del AES-GCM + AES-XCBC-PRF generalizado, no usaremos una función hash en ningún lugar, y un número pequeño los primitivos usados ​​son siempre buenos.



Se generan las siguientes claves:



  • SK_d clave para generar claves para las SA ESP secundarias.
  • Claves SK_a [ir] para la autenticación de mensajes IKE. No generado / no utilizado si se acuerda el algoritmo AEAD (AES-GCM, Grasshopper / Magma-MGM, ChaCha20-Poly1305, etc.).
  • SK_e[ir] IKE .
  • SK_p[ir] AUTH.


TLS 1.3: tiene una programación de claves mucho más compleja. La entropía se elimina de todos los mensajes de apretón de manos a la vez, en lugar de campos individuales. La secuencia extendida generada no solo se corta en una cantidad de claves (+ salt para ellas cuando sea necesario), sino que también se acompaña de transformaciones HMAC con etiquetas (etiquetas) para cada contexto de uso de estas claves o IV generados. El uso de etiquetas / aplicaciones / contextos textuales para cualquier tipo de valor generado es una buena práctica moderna y es más fácil de hacer siempre que preguntarse si lo necesita. Eliminar todo lo que aparece es también una muy buena práctica, "no empeorará". Sin embargo, esto no significa que la seguridad de IKEv2 sea peor, o que uno pueda llegar fácilmente con al menos una situación remotamente teórica en la que la ausencia de una etiqueta podría estar en manos de un atacante.En IKEv2, el enfoque es mínimo, mientras que en TLS 1.3 es "mejor anular" (¡porque cuántas jambs o dificultades se hicieron en versiones anteriores del protocolo!). IKEv2 todavía usa enfoques y primitivos probados, autentica todo lo que se necesita, exprime / toma en cuenta toda la entropía transferida, usa claves diferentes para cada lado y tarea.



IKE_AUTH



A continuación, se realiza un intercambio IKE_AUTH , autenticando a ambas partes y negociando la ESP SA:



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


  • Los mensajes IKE contienen una carga útil cifrada ( SK ), que contiene todos los demás.
  • El iniciador proporciona su identificador ( IDi ), autenticador ( AUTH ), oferta de SA para ESP ( SAi2 ) y un par iniciador / respondedor, los denominados selectores de tráfico ( TS * ). También puede enviar opcionalmente el identificador de respuesta esperado, que puede considerarse una especie de SNI análogo de TLS.
  • En respuesta, recibe el identificador del respondedor, la propuesta de ESP SA negociada, selectores de tráfico validados y un autenticador.
  • Después de eso, ambas partes se consideran autenticadas, tienen un acuerdo sobre ESP SA, tráfico que debe pertenecer a este ESP y ya pueden emitir un comando al kernel para crear SA y, posiblemente, SP (hay daemons que no tratan con SP en absoluto).


Ahora, con más detalle sobre estas cargas útiles:



  • ID : identificador de la parte. Contiene el tipo de identificación y los datos que le son específicos. Las partes se pueden identificar de muchas maneras: dirección IPv4 / IPv6, FQDN (nombre de dominio completo, solo una cadena, la forma más popular), dirección de correo electrónico RFC822, nombre distinguido de ASN.1 DER (la forma más común cuando se usan certificados X.509) o nombre general así como específicos del proveedor.
  • 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 .



    La parte que responde envía su selección confirmada de selectores, que coincide o puede tener rangos de selección más estrechos.


Todas estas cargas útiles se cifran en la clave generada por IKE SA después del primer intercambio de mensajes. El cifrado es necesario para ocultar los identificadores transmitidos de las partes, sus certificados y otra información privada al aire libre. Sin embargo, un atacante activo puede ingresar al primer intercambio IKE_SA_INIT y ver esta información, aunque ya no puede continuar la sesión.



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


El cifrado de los cifrados AEAD de carga útil SK no es complicado y es completamente similar a ESP, por ejemplo, para AES-GCM (en el que, de manera similar a AES-GCM-ESP, la sal es parte del material clave):



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


Autenticación con EDS



¿Qué pasa si alguna de las partes desea autenticarse con firma y certificados X.509? Para ello, ya en IKE_SA_INIT , se puede enviar un payload CERTREQ , solicitando al lado opuesto que proporcione un certificado en forma de payloads CERT . CERT y CERTREQ contienen el identificador de formato de certificado y el contenido específico del formato. Normalmente, los certificados se pueden presentar como ASN.1 DER o como hash SHA1 del certificado + URL desde donde se puede descargar. Dado que el tamaño de UDP está limitado por MTU, y los tamaños de los certificados pueden ser mucho mayores, la opción hash + URL es beneficiosa aquí (aunque puede considerarse una muleta).



El RFC IKEv2 solo enumera, además de los certificados X.509 codificados en DER y las URL SHA1 +: certificado X.509 empaquetado PKCS # 7, certificado PGP, clave firmada por DNS, certificado SPKI, certificado de atributo X.509, claves públicas sin procesar. Si desea usar IPsec de la misma manera que el TLS de caso de uso más común: un servidor autenticado por un certificado X.509 y un cliente anónimo, entonces en IKEv2 no hay forma de no autenticar a una de las partes. Pero RFC 5386 describe un enfoque de seguridad mejor que nada en el que el "cliente" puede usar la clave pública y el servidor puede tratarla como anónima.



Además, la autenticación EAP es compatible de manera estándar, agregando viajes de ida y vuelta a IKE_AUTHintercambiar. EAP puede tanto decir si la parte está autenticada o no, como también generar una clave que IKEv2 tomará en cuenta y usará. Solo te mostraré un diagrama de cómo puede funcionar EAP:



                 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 : en él, la firma (o MAC en el mensaje Finalizado ) se coloca encima del hash de todos los mensajes vistos que participaron en el apretón de manos. También es un buen enfoque simple y confiable. No hay variedad de métodos de autenticación. Pero me gustaría ver algún protocolo sólido de Acuerdo de clave de contraseña autenticada (PAKE), como el ruso SESPAKE u OPAQUE .



Material clave ESP SA y su renovación



Entonces, hemos verificado la autenticación, verificado que el acuerdo de clave era correcto, negociado el ESP SA y los selectores de tráfico. Queda por generar claves simétricas para ESP y el SA / SP requerido se puede instalar en el kernel:

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


La comunicación bidireccional requiere dos SA ESP, por lo que IKEv2 genera dos materiales clave a la vez, que ya se transmiten directamente al núcleo en la SA correspondiente. La longitud del material depende del algoritmo ESP utilizado (por ejemplo, AES-GCM-ESP requiere, además de la clave, también sal de 32 bits). El valor de SPI es el valor de SPI especificado por cada parte en las propuestas de ESP SA.



¿Qué sucede si necesitamos acordar varios ESP SA / SP, por ejemplo, porque no todos los deseos se pueden especificar en un solo par TSi / TSr ? Para ello, se utilizan los intercambios CREATE_CHILD_SA que ocurren en cualquier momento posterior a IKE_AUTH . La creación de una SA secundaria se produce en el siguiente intercambio:



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


Se hace oferta SA, nonces, se envían selectores de tráfico. Todo es como antes. El material clave ya se genera utilizando estos nuevos nonces. Opcionalmente, puede usar cargas útiles de intercambio de claves, que agregan entropía y obligan a las partes a usar una criptografía aún más asimétrica. Puede ser necesario observar constantemente la propiedad PFS (en el protocolo OTR , se envían claves DH efímeras con cada mensaje). El material clave en este caso se elaborará de la siguiente manera:



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


¿Y si queremos renovar el IKE SA de la conexión? Hacemos el siguiente intercambio CREATE_CHILD_SA :



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


donde SA ya contendrá propuestas de IKE SA y se desarrollará un nuevo SKEYSEED :



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


La clave ESP SA se actualiza creando una nueva ESP SA (con un SPI diferente) y eliminando la anterior, o enviando una notificación especial (sobre esto a continuación). Cambiar el tráfico para usar el nuevo ESP SA será transparente y sin pérdidas. Por poco tiempo, las partes tendrán dos ESP SA activas, lo que permitirá procesar el tráfico que aún se encuentra en tránsito en los canales de comunicación.



La eliminación de una SA ESP se realiza mediante el envío de una carga útil DELETE en intercambios INFORMATIVOS posteriores que enumeran los SPI que se eliminarán. Dado que todas las ESP SA existen en pares (para la comunicación bidireccional), cada lado envía valores SPI solo a las ESP SA responsables del tráfico saliente. En respuesta, reciba los valores SPI ESP SA para el tráfico entrante.



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


La eliminación de un IKE SA también se realiza mediante DELETE , pero con IKE SPI y aceptando una respuesta autenticada vacía:



    SK {D} ->
<- SK {}


TLS 1.3 : existe un mecanismo para rotar claves a través de mensajes KeyUpdate , pero no hay posibilidad de agregar entropía adicional o realizar DH. TLS claramente no está diseñado para conexiones de larga duración. En el mejor de los casos, solo puede interrumpir la sesión y continuar / crear una nueva con iPSK-ECDHE con un apretón de manos.



IKEv1 tiene un procedimiento de renovación de clave IKE separado y uno separado para la reautenticación. No hay una nueva autenticación en IKEv2. Para hacer esto, simplemente se crea una nueva IKE SA desde cero, la anterior se elimina a través de DELETE .



TLS 1.3 : tiene capacidad de autenticación de cliente posterior al protocolo de enlace cuando en cualquier momento después del protocolo de enlace ( Finalizadomensajes de ambos lados), el servidor puede enviar una solicitud de autenticación del cliente mediante un certificado X.509. Por ejemplo, un cliente, deambulando por el sitio, fue a la página de su cuenta personal. En IKEv2, esto no es posible: la autenticación se lleva a cabo solo en el momento del protocolo de enlace.



NOTIFICAR



Entonces, ¿cómo se negocian los modos de transporte / túnel, TFC? Para ello, se agregan a la solicitud cargas útiles de "notificaciones" NOTIFICAR ( N ). Hay docenas de tipos de notificaciones solo en IKEv2 RFC. Las alertas se utilizan para señalar errores, problemas al negociar SA para propuestas, selectores de tráfico, etc.



Para señalar el deseo de utilizar el modo de transporte en un ESP SA negociado, tanto el iniciador como el respondedor agregan una notificación N (USE_TRANSPORT_MODE) para confirmar la negociación del modo. La alerta N (ESP_TFC_PADDING_NOT_SUPPORTED) indica que TFC no es compatible. Y N (HTTP_CERT_LOOKUP_SUPPORTED) indica que se admite la descarga de un certificado desde una URL.



La capacidad de actualizar la clave ESP SA, sin crear nuevas ESP SA, es similar al procedimiento para crear una ESP SA secundaria, pero el iniciador agrega una alerta N (REKEY_SA) que contiene el SPI del ESP SA actual:

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





DPD



El intercambio INFORMATIVO con SK vacío se utiliza para la detección de pares muertos ( DPD ), como un latido entre demonios. Si el demonio IKE no está disponible durante mucho tiempo, lo más probable es que haya perdido su estado y, por lo tanto, nadie esté observando la SA ESP en el lado opuesto, o que ya no estén activos. Por lo tanto, cuando está claro que el par no está disponible, tiene sentido eliminar todas las SA ESP / IKE asociadas. Un SK vacío significa que no hay carga útil, pero tiene datos autenticados (al menos encabezados IKE con contadores), por lo que la autenticación de dicho paquete es una señal de vida confiable.



    SK {} ->
<- SK {}


Pero, ¿qué pasa si un lado se reinicia rápidamente, pierde el estado y comienza a establecer una conexión IKE desde cero? Es posible que el lado opuesto ni siquiera se dé cuenta de que el otro no está disponible, y pensaría que decidió volver a autenticarse o crear nuevas SA secundarias en otra conexión IKE. Nada catastrófico será, pero el antiguo ESP SA aún puede vivir un tiempo decente. Un iniciador PUEDE colocar una alerta N (INITIAL_CONTACT) en su intercambio IKE_AUTH , lo que indica que es la única conexión IKE conocida en ese lado. Al ver tal notificación autenticada, puede eliminar todas las SA IKE / ESP antiguas con la conciencia tranquila.



DoS y mal KE



Ya al principio de IKE_SA_INIT, un Kei carga útil se envía con una clave pública DH efímera. Pero el iniciador aún no ha intercambiado el IKE SA, y ¿cómo sabe qué algoritmo admite el lado receptor? Solo puede adivinar o recordar en la memoria a largo plazo lo que se usó anteriormente para asociar esta dirección. Si el respondedor no admite el algoritmo, enviará N (INVALID_KEY_PAYLOAD) una notificación, que indicará el identificador del algoritmo DH preferido. El iniciador deberá repetir su solicitud, pero con un nuevo KEi .



TLS 1.3: puede enviar varias claves públicas efímeras a la vez utilizando diferentes algoritmos, tal vez algunos sirvan. Pero estos son recursos y tráfico. Es posible que no envíe la clave pública en absoluto y el servidor le responderá con HelloRetryRequest con sus preferencias; la ventaja es que la costosa criptografía asimétrica no se usa en absoluto hasta que se conocen los algoritmos de servidor preferidos, pero a costa de un viaje de ida y vuelta adicional. Si el cliente proporcionó inicialmente un algoritmo de clave pública inapropiado, entonces, como en IKEv2, recibirá una HelloRetryRequest con los algoritmos para elegir.



¿Qué pasa si envía el mismo paquete inicial desde el iniciador? Es posible generar un nuevo SPIi allí cada vez... El respondedor, como mínimo, realizará cálculos DH con honestidad y responderá con IKE_AUTH . DH es una operación que consume muchos recursos, quema la CPU y la fuente de entropía; por lo tanto, el transpondedor puede desactivarse.



En IKEv2 (pero no IKEv1) hay una protección contra esto, en forma de una respuesta N (COOKIE) con una alerta que contiene una cadena de cookies, después de la cual el iniciador debe repetir su solicitud, pero agregando esta carga útil N (COOKIE) :



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


La solicitud debe tener el mismo SPI / Ni que la primera. Basta con complementarlo con carga útil. El respondedor puede guardar el estado de la conexión entre la solicitud y la cookie que se le envió, y solo después de que coincidan, después de completar este trabajo de agregar la cookie a la solicitud por parte del iniciador, el respondedor puede continuar el intercambio IKE_AUTH de manera regular .



Pero es posible almacenar el estado dentro de la cookie, haciéndola "auto-autenticable". Puede conllevar el hecho de que el encuestado vio la solicitud del iniciador ( Ni y SPIi lo vieron , al menos):

Cookie = MAC (algún secreto, Ni || SPIi || marca de tiempo)


Así, el amante del DoS tendrá que almacenar el estado y reciclar sus mensajes repetidos, lo que encarece mucho el ataque. Tiene sentido habilitar la protección de cookies solo cuando existe una sospecha de un ataque DoS, para no obligar a todos a realizar un viaje de ida y vuelta adicional.



TLS 1.3 : tiene una seguridad opcional similar. El servidor PUEDE responder con HelloRetryRequest con un mensaje que contiene la extensión Cookie , que el cliente debe insertar en su ClientHello2 repetido .



CP



IKEv2 le permite negociar la configuración de redes / direcciones IP. La carga útil de configuración ( CP ) le permite realizar una solicitud para recibir una configuración ( tipos de paquetes CFG_REQUEST / CFG_REPLY ) y establecer la configuración en el lado opuesto ( tipos CFG_SET / CFG_ACK ). La solicitud de configuración contiene los atributos que la parte desea conocer / configurar. Los atributos pueden ser: dirección "interna", dirección DNS, DHCP, conocimiento de subred u otros tipos descritos en RFC relacionados. Por ejemplo, el iniciador en el intercambio IKE_AUTH puede realizar una solicitud para emitirle una dirección de intranet (conectándose a la red de la empresa) y un 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)


  • La dirección 2001: db8 :: 5 se asigna al iniciador .
  • ESP SA 2001:db8::/64 .
  • 2001:db8::1 DNS .
  • 2001:db8:abcd::/64 , , ESP SA, 2001:db8:: .


Go?



Para probar las implementaciones domésticas modernas de la pila IPsec con algoritmos GOST, decidimos escribir una implementación completamente independiente (de Linux, FreeBSD, strongSwan y otras pilas). Y para la velocidad y facilidad de desarrollo en el lenguaje Go , con la implementación ya existente de la biblioteca GoGOST de algoritmos GOST . Anteriormente, ya tenía experiencia en la integración de GOST en la implementación de TLS 1.3 de las bibliotecas crypto / tls y crypto / x509 Go.



El proyecto gostipsec es un software gratuito que consta de dos demonios: 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 │            ║
             │                │   ║            │ ──────────────>            ║
             │                │   ╚════════════╪═══════════════╪════════════╝
             │                │                │               │


Por el momento, ESPER solo funciona con sockets DIVERT (no encontré nada tan simple en Linux), por lo tanto, solo es compatible con el sistema operativo FreeBSD (probablemente OpenBSD, no lo comprobé). ESPER, como IKER, no usa PF_KEYv2 , que requeriría enlaces C, como una interfaz entre enlaces ESP <-> IKE , sino la interfaz tipo setkey de texto que ya se mencionó al principio del artículo. Por lo tanto, IKER también se puede utilizar para negociar claves para una implementación de ESP del kernel invocando el comando setkey real . Estos comandos para ESPER tienen este aspecto:



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 ;


Soporta ESPER: AES-128/256-GCM-16, Magma / Grasshopper-MGM, ESN, TFC, modos de transporte / túnel, IPv6 / IPv4 (el soporte para este último, mucho más complejo, no ha sido probado a fondo y quién necesita IPv4 para nuevos proyectos?), protección contra ataques de repetición. IKER le permite hacer coincidir: 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 / tunnel-modes, autentica mediante firmas digitales PSK y X.509 (ECDSA, GOST R 34.10-2012). Configurado por un solo archivo 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
        }
    ]
}


En este ejemplo, hemos establecido el único miembro que conocemos:



  • A qué demonio se conectará automáticamente
  • Realice la detección de pares muertos 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.


IKER aún no es compatible con el conjunto completo de todas las funciones de IKEv2 ( CREATE_CHILD_SA , cambio de clave ), no monitorea la pérdida de paquetes y no se preocupa por el principio DON'T PANIC . Por tanto, todavía no puede considerarse candidato para uso "industrial".



Tarball gostipsec ya contiene todas las dependencias, documentación .info compilada y objetivos para el sistema de rehacer compilación, aunque la compilación de ejecutables se realiza fácilmente con una llamada regular a go build .



Hjson?



Tema Holywar, pero daré mi phi de todos modos:



  • INI no le permite especificar tales estructuras de barrido y no existe un estándar para los archivos .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.




En general, si implementa un subconjunto de capacidades similar a TLS 1.3 (autenticación solo por certificados PSK y X.509, sin cambios de clave serios), entonces ESPv3 con IKEv2 e IPv6 (¡es mucho más fácil trabajar con él!), Desde el punto de vista del programador, será un poco más difícil en ejecución. La RFC ni siquiera obliga a admitir intercambios CREATE_CHILD_SA . La seguridad será excelente, sin los posibles modos de funcionamiento controvertidos y peligrosos de TLS 1.3. El rendimiento de una solución IPsec generalmente será mayor debido al transporte a nivel nuclear y sesiones IKE de larga duración.



Se puede ver que en IPsec todo se agudiza para proteger la colosal cantidad de tráfico entre redes enteras, pero BTNS(seguridad mejor que nada) el grupo de trabajo de IETF escribió varios RFC demostrando que IPsec se puede usar sin problemas para conexiones por socket, donde una de las partes (el cliente) es anónima, por lo que cuestiona completamente la conveniencia de usar TLS. El bloqueo de la conexión, en este caso, permitiría que cualquier aplicación de red, al realizar una llamada trivial al sistema como setsockopt , indique que necesita un ESP a la dirección FQDN = bank.com , presentándose como un certificado X.509 (o permaneciendo anónimo), y luego de forma transparente, rápida y trabajar de forma segura con este bank.com , sin muletas en forma de bibliotecas por aplicación de transporte de espacio de usuario.



Sergey Matveev , cypherpunk, Desarrollador de Python / Go / C, especialista en jefe de FGUP STC Atlas.



All Articles