Nota del autor: los ataques mencionados en este artículo no son posibles contra las versiones actuales de I2P.
Como una red peer-to-peer autoorganizada, I2P depende de los routers que participan en la red para disponer de una forma de compartir información sobre qué hay en la red y cómo acceder a ello. Los routers de I2P logran este intercambio de información utilizando la NetDB, una DHT (tabla hash distribuida) basada en Kademlia pero modificada para funcionar en I2P. La NetDB necesita compartir dos tipos principales de entradas, “RouterInfos”, que los pares usarán para comunicarse directamente con otros routers, y “LeaseSets”, que otros pares usarán para comunicarse con clientes de I2P a través de tunnels anónimos. Los routers se comunican con frecuencia entradas de la NetDB entre sí, ya sea enviando la información a un router o a un cliente, o solicitando información a un router o a un cliente. Esto significa que las entradas pueden llegar directa o indirectamente, de forma anónima o no anónima, según las necesidades de la red y las capacidades del cliente. Sin embargo, al tratarse de una red de anonimato, también es importante que siga siendo imposible que la información enviada de forma anónima pueda solicitarse de vuelta de forma no anónima. También es importante que la información enviada de forma no anónima sea imposible de solicitar de vuelta de forma anónima. Si llega a ser posible que se dé cualquiera de esas situaciones, entonces se podría llevar a cabo un ataque de vinculación que permita a un atacante determinar si clientes y routers comparten una vista común de la NetDB. Si puede determinarse de manera fiable que los 2 objetivos comparten una vista común de la NetDB, entonces hay muchas probabilidades de que estén en el mismo router, lo que debilita drásticamente el anonimato del objetivo. Debido a que hay tan pocas redes de anonimato, y I2P es la única en la que la tabla de enrutamiento se comparte mediante el funcionamiento de una DHT, esta clase de ataque es casi exclusiva de I2P y su resolución es importante para el éxito de I2P.
Considere el siguiente escenario: Hay un router I2P que aloja a un cliente I2P. El router publica un RouterInfo y el cliente I2P publica su LeaseSet. Como ambos están publicados en el NetDB, otros routers I2P pueden consultar el NetDB para descubrir cómo comunicarse con ellos. Esto es normal y esencial para el funcionamiento de una red superpuesta del tipo implementado por I2P. Un atacante ejecuta un router I2P y consulta el NetDB para obtener el RouterInfo de destino y el LeaseSet de destino. Luego forja un nuevo LeaseSet que es único y potencialmente incluso falso, y lo envía a través de un tunnel al LeaseSet del cliente que es su objetivo de ataque. El cliente procesa el LeaseSet forjado y lo añade a su propio NetDB. El atacante entonces solicita el LeaseSet forjado de vuelta directamente, desde el router, usando el RouterInfo que obtuvo del NetDB. Si el LeaseSet forjado se recibe de vuelta como respuesta, entonces el atacante puede concluir que el cliente de destino y el router de destino comparten una vista común del NetDB.
Ese es un ejemplo sencillo de una clase de ataque de desanonimización de NetDB que se basa en añadir una entrada en la NetDB de otra persona con una identidad, y luego recuperarla con otra identidad. En este caso, las identidades en cuestión son la de “router” y la de “cliente”. Sin embargo, la vinculación de cliente a cliente, que es menos dañina, también es posible en algunos diseños. Diseñar una defensa contra esta clase de ataque requiere darle al router una manera de determinar si es o no seguro compartir un dato con una identidad potencial.
Entonces, ¿cómo deberíamos abordar este problema? De lo que realmente se trata aquí tiene que ver con la capacidad de vincular diferentes “identities” en la red. La posibilidad de vincular surge porque todas estas identidades comparten una estructura de datos común que “recuerda” con quién se ha comunicado dicha identidad y quién se ha comunicado con ella. También “recuerda” cómo ocurrió esa comunicación.
Por un momento, imaginémonos como un atacante. Imagina que estás tratando de descubrir la identidad de un maestro del disfraz. Sabes con certeza que has visto su rostro real, y sabes con certeza que te comunicas regularmente con una de sus identidades disfrazadas. ¿Cómo te las arreglarías para establecer que la identidad disfrazada y la identidad real pertenecen a la misma persona? Podría contarle un secreto a la persona disfrazada. Si la persona no disfrazada responde utilizando la información secreta, entonces puedo determinar que la persona no disfrazada conoce el secreto. Partiendo de la suposición de que la persona disfrazada no comunicó el secreto a nadie más, puedo suponer que la persona no disfrazada y la persona disfrazada son, de hecho, la misma persona. No importa cuántas máscaras lleve el maestro del disfraz, no tiene más que una sola mente.
Para proteger con éxito las identidades de los clientes de I2P, I2P debe ser capaz de actuar como un maestro del camuflaje mejor que el descrito arriba. Debe poder “recordar” varios datos importantes sobre cómo ha participado en la NetDB y responder adecuadamente en función de esos detalles. Debe ser capaz de recordar:
- Whether a NetDB Entry was received directly, or received down a client tunnel
- Whether a NetDB Entry was sent by a peer in response to our lookup, or sent unsolicited
- Which NetDB Entry was received down Which client Tunnel
- Multiple versions of the same entry for different client tunnels
Estructuralmente, la forma más comprensible y confiable de manejar este patrón es usar “Sub-DBs.” Los Sub-DB (sub-bases de datos) son NetDB en miniatura que ayudan al NetDB a organizar entradas sin perder el rastro. Cada cliente obtiene un Sub-DB para su propio uso, y el propio router obtiene un NetDB plenamente funcional. Usando Sub-DB, le damos a nuestro maestro del disfraz un tarjetero de secretos organizado por quién compartió esos secretos con él. Cuando se envía una solicitud a un cliente, solo se buscan entradas que hayan sido comunicadas al cliente, y cuando se envía una solicitud a un router, solo se utiliza el NetDB a nivel de router. Al hacerlo de esta manera, resolvemos no solo la forma más simple del ataque, sino que también debilitamos la efectividad de toda la clase de ataques.