Première version | [1] |
---|---|
Dernière version | 2.7.0 ()[2] |
Dépôt | github.com/i2p/i2p.i2p, [cvs://cvs.i2p.net/cvsroot/ cvs://cvs.i2p.net/cvsroot] et [cvs://cvs.invisiblenet.net:/cvsroot/freeweb cvs://cvs.invisiblenet.net:/cvsroot/freeweb] |
Assurance qualité | Intégration continue |
État du projet | Actif |
Écrit en | Java et C++ |
Système d'exploitation | Microsoft Windows, Linux, macOS, OpenBSD, FreeBSD et Android |
Environnement | indépendant |
Langues | Français, anglais, espagnol, et de nombreuses autres |
Type | Client P2P |
Politique de distribution | Gratuit |
Licence | Licence BSD, licence publique générale GNU, licence MIT et placé dans le domaine public par le détenteur des droits d'auteur (d) |
Site web | geti2p.net |
I2P (« Invisible Internet Project ») est un réseau anonyme offrant une simple couche réseau logicielle de type réseau overlay, que les applications peuvent employer pour envoyer de façon anonyme et sécurisée des informations entre elles. La communication est chiffrée de bout en bout.
Au total, quatre couches de chiffrement sont utilisées pour envoyer un message. L'anonymat est assuré par le concept de « mix network », qui consiste à supprimer les connexions directes entre les pairs qui souhaitent échanger de l'information. À la place, le trafic passe par une série d'autres pairs de façon qu'un observateur ne puisse identifier l'expéditeur ni le destinataire de l'information. Chaque pair peut, à sa décharge, dire que les données ne lui étaient pas destinées (déni plausible).
Sur Internet, on identifie un destinataire par une adresse IP et un port. Cette adresse IP correspond à une interface physique (modem ou routeur, serveur, etc.). Mais, sur I2P, on identifie un destinataire par une clef cryptographique.
Contrairement à l'adressage IP, on ne peut pas désigner la machine propriétaire de cette clef. Du fait que la clef est publique, la relation entre la clef et l'interface qui en est propriétaire n'est pas divulguée.
Les « destinations » (exemples : serveur Web, IRC, jeu, etc.) sont des identifiants cryptographiques (et non des adresses IP) définis par une paire de clefs asymétriques (couple clef privé/clef publique). La destination est déterminée par l'identifiant d'un hôte et le numéro de port à joindre. Ça peut être un serveur POP, un serveur SMTP, un serveur IRC, un serveur Web, un serveur SVN ou Git (Gitea, etc.), un serveur newsgroup, etc.
Le routeur construit des tunnels pour véhiculer les messages entrant et sortant. Pour créer un tunnel, le routeur demande à l'un des pairs auquel il est connecté de former ce tunnel. Ce pair va ensuite contacter à son tour un autre pair en lui demandant d'être le maillon suivant de la chaîne de pairs formant le tunnel. Pour joindre une destination cryptographique — et donc un pair — il faut savoir à quelle « sortie » de tunnel s'adresser, c'est pour résoudre ce problème qu'une certaine classe de routeurs particulière a été ajoutée au réseau. Il s'agit des Floodfill. Ceux-ci tiennent à jour une liste des correspondances entre les tunnels et les destinations. De cette façon, quand un routeur souhaite joindre une destination, il demande au Floodfill à quel tunnel il doit s'adresser pour contacter cette destination. Le nombre de routeurs Floodfill augmentera donc au fur et à mesure que le réseau grandira. Tout est automatique, si le réseau a besoin de nouveaux Floodfill, les routeurs remplissant les conditions de vitesse, stabilité et nombre de connexions le deviendront automatiquement.
Tous les routeurs du réseau participent au transport des messages des autres routeurs et permettent ainsi de rendre non distinguable le trafic que vous générez en le noyant dans le flux constant du réseau. Il est très complexe pour un attaquant de déterminer si les données vous étaient vraiment destinées ou si elles ne faisaient que transiter par vous.
Le poumon d'I2P est I2PTunnel, qui permet de gérer les tunnels entrants et sortants. On peut notamment y créer les siens comme un tunnel HTTP qui pointe vers le port 80 de votre machine pour héberger votre propre eepsite et un autre vers votre serveur Jabber ou POP3.
Il existe une implémentation du protocole en C++ nommée i2pd, qu'il est recommandable d'utiliser à cause des nombreuses failles de Java[réf. nécessaire].
Comme pour les VPN ou les darknet, I2P exploite la tunnelisation pour fournir un « réseau dans le réseau ». Contrairement à la majeure partie des logiciels de partage de fichiers en pair à pair en P2P anonyme, I2P se concentre sur une gestion autonome du réseau et sur la fourniture d'une couche de transport anonyme[3]. Quand il est utilisé seul, I2P ne fournit pas les services que l'on peut trouver sur Internet (courriel, téléchargement, web, etc.). I2P est toutefois livré avec quelques applications pour retrouver quelques services courants tout en conservant les qualités de confidentialité et d'anonymisation offertes par le réseau.
Le développement d'applications exploitant le réseau est donc réalisable sans avoir à modifier le projet I2P. De cette façon, on peut voir des applications exploitant le réseau I2P qui utilisent les mêmes protocoles que ce que l'on trouve sur Internet (ex : iMule).
I2P inclut d'origine un réseau IRC anonyme : on peut s'y connecter en utilisant un logiciel client IRC (peu importe lequel) pointant vers l'adresse serveur 127.0.0.1 et sur le port 6668.
Exemples de canaux les plus fréquentés : #i2p-fr, #i2p-help, #i2p, #anonops (Anonymous).
Il est fourni également une API, pour faciliter le développement de logiciels tels que de nouvelles applications reposant sur I2P (SDK, routeur, ...).
Les correspondants ne s'exposent pas directement. Ils utilisent chacun une série de routeurs I2P comme intermédiaires pour créer un I2PTunnel. Ces tunnels sont unidirectionnels et utilisés pour masquer le destinataire comme l'expéditeur[7]. On peut donc distinguer deux catégories d'I2PTunnel :
Pour contacter un membre du réseau, il faut trouver les routeurs I2P qui correspondent aux entrées des tunnels mis à disposition par le destinataire. Cette recherche se fait à l'aide du Network Database.
Un chiffrement, dit « en gousse d'ail » pour marquer sa différence avec le chiffrement en oignon de TOR[8], est utilisé sur les messages qui transitent par les I2PTunnel. Ce chiffrement assure :
Le point 1 empêche de pouvoir utiliser les informations contenues dans le message pour identifier les correspondants. Le point 2 empêche les intermédiaires de connaître leur position dans le tunnel et donc que ces intermédiaires puissent différencier correspondants et intermédiaires.
La taille des I2PTunnels est choisie par celui qui le crée. Elle influe de façon conséquente sur l'ensemble des mécanismes qui protège l'anonymat[7].
Un tunnel sans intermédiaire offre une protection puisqu'on ne peut pas distinguer correspondants et intermédiaires depuis l'intérieur du réseau ; un déni plausible les protège. Cependant un attaquant extérieur au réseau et possédant les ressources pour superviser le trafic d'un tel tunnel peut monter une attaque par analyse statistique[9],[10].
Lorsque des intermédiaires interviennent il faut compromettre l'ensemble des intermédiaires avant de monter une attaque par analyse statistique. Le mécanisme de mélange de trafic s'attaque à ce problème.
Si l'I2PTunnel est relativement efficace pour préserver l'anonymat à l'intérieur du réseau, seul il n'est plus suffisant pour qui peut avoir une vue globale du réseau I2P. Il suffirait d'observer le trafic pour constater où il commence et où il s'arrête.
Un tunnel, I2P ou autre, entraîne une limitation du débit et une augmentation de la latence. La multiplication des tunnels permet d'augmenter l'utilisation du débit inutilisé.
Pour communiquer, un correspondant doit créer un tunnel sans avoir à lever son anonymat (afin de faire transiter son message par des pairs). Le créateur du tunnel doit tout d'abord sélectionner les pairs qui participeront potentiellement à son tunnel. Ensuite il crée une requête de demande (TunnelBuildMessage) qui transitera par les pairs sélectionnés avant de revenir au créateur avec les réponses de chacun.
La sélection des pairs s'effectue sur la base de certains critères. Parmi ces critères figure entre autres, leurs temps de réponse et leurs bandes passantes. Cette sélection se fait en fonction du rendement, de la fiabilité ou du degré d'anonymat recherché par l'utilisateur[11].
Le TunnelBuildMessage est un message construit par le créateur du tunnel. Il va servir à recenser les réponses des pairs acceptant de participer ou non au tunnel. Si toutes les réponses sont positives alors le tunnel est créé. Ce message est composé de huit fiches d'enregistrement. Une fiche d'enregistrement contient la requête de participation d'un pair. Un tunnel peut donc avoir huit pairs maximum.
bytes 0-3: tunnel ID to receive messages as bytes 4-35: local router identity hash bytes 36-39: next tunnel ID bytes 40-71: next router identity hash bytes 72-103: AES-256 tunnel layer key bytes 104-135: AES-256 tunnel IV key bytes 136-167: AES-256 reply key bytes 168-183: reply IV byte 184: flags bytes 185-188: request time (in hours since the epoch) bytes 189-192: next message ID bytes 193-222: uninterpreted / random padding
Description d'une fiche d'enregistrement
AES-256 tunnel layer key et AES-256 tunnel IV key : clés de chiffrement qui seront utilisés lors des transactions dans le tunnel si celui-ci est construit.
AES-256 reply IV et AES-256 reply key : clé de chiffrement de la réponse et son vecteur d'initialisation, il permet au pair de chiffrer sa réponse avant de faire suivre le message.
next message ID : le pair suivant dans le tunnel. Celui à qui doit être envoyé le message après avoir répondu.
Les autres options permettent de vérifier l'intégrité du message mais aussi d'ajouter des informations supplémentaires à la réponse.
Avant d'envoyer le TunnelBuildMessage, le créateur du tunnel chiffre ce message de deux façons successives. Par le chiffrement asymétrique qui permet de garder la confidentialité de l'information sur le réseau, puis par le chiffrement symétrique qui permet de s'assurer que le message a transité dans l'ordre établi par le créateur :
Chiffrement asymétrique : chaque fiche d'enregistrement est chiffrée avec la clé publique du pair correspondant, de façon que chaque pair n'accède qu'à sa fiche d'enregistrement.
Chiffrement symétrique : le message est ensuite chiffré par plusieurs couches de façon à n'exposer la fiche qu'au moment opportun. Le chiffrement a lieu de telle manière que lorsqu'un pair chiffre le message avec sa réponse, alors la fiche d'enregistrement du pair suivant peut être déchiffrée par celui-ci. On peut voir cela comme un oignon auquel on enlève une couche à chaque transmission de l'un à l'autre. Par exemple, un tunnel avec trois pairs A, B et C :
La fiche du dernier pair du tunnel (C) est chiffrée avec la clé de réponse de l'avant dernier (B) de telle manière que lorsque B chiffre sa réponse alors la fiche d'enregistrement de C peut être déchiffrée par C. De même les fiches d'enregistrements de B et C sont chiffrées avec la clé de A afin que B ne puisse être lu qu'après A.
Lorsqu'un pair reçoit un TunnelBuildMessage, il n'y a qu'une seule fiche d'enregistrement n'étant pas chiffré symétriquement. Il déchiffre cette fiche avec sa clé privé afin de récupérer la demande de participation au tunnel.
Lorsque la fiche est déchiffrée, il remplace le contenu de la fiche par sa réponse, soit il participe au tunnel, soit non. S'il refuse, il donne son motif de rejet.
Une fois la réponse créée et écrite dans la fiche d'enregistrement, il chiffre symétriquement la fiche d'enregistrement avec la clé fournie dans la demande. Il chiffre ensuite les autres fiches d'enregistrements. Le chiffrement des autres fiches a pour conséquence de retirer une couche de chiffrement symétrique, ainsi la fiche du destinataire suivant n'a plus de chiffrement symétrique. Elle est prête à être déchiffré par le destinataire.
La dernière opération exécutée par le pair lors de la création du tunnel est de faire passer le TunnelBuildMessage au destinataire suivant. Le destinataire suivant est mentionné dans la fiche d'enregistrement lors de la requête.
Le dernier pair participant à la création du tunnel est le créateur du tunnel. Il déchiffre les fiches dans l'ordre inverse du chiffrement symétrique, effectué lors de la création du TunnelBuildMessage, pour récupérer les réponses.
L'I2P répond à la problématique du routage en essayant de ne pas compromettre l'anonymat, la qualité du réseau (latence et débit) et aux attaques de déni sur l'ensemble du réseau.
La notion est simple mais importante, la NetdB (pour network database) est une base de données contenant les identifiants des routeurs dans le réseau. Cette base est distribuée et s'apparente à une table de routage dans un routeur conventionnel (sauf qu'ici elle contient les clés d'identification des routeurs I2P). Elle utilisait le DHT de kademlia à la base comme solution de repli mais cette solution a été abandonnée.
Pour effectuer le partage des métadonnées du réseau, il est initialisé des pairs floodfill (un petit nombre des routeurs I2P utilise cet algorithme, les autres utilisaient un dérivé de kademlia mais qui n'est plus utilisé maintenant). Quand un pair floodfill entre une nouvelle clé de chiffrement dans la base de données du réseau, un autre pair floodfill choisi aléatoirement redemande cette clé, puis si elle est valide le pair se rapproche du premier et republie la clé. À la fin les pairs floodfill partagent leur clé en interrogeant sans cesse la base et en faisant une copie des clés valides dans leur mémoire locale, ce qui produit un effet de changement de proximité des pairs floodfill entre eux (les pairs se rapprochent). Toutes les données stockées dans la base s'auto-authentifient en vérifiant la signature de l'élément stocké. Les données sont vérifiées avec un horodatage, les routeurs vérifient régulièrement l'heure en interrogeant un serveur SNTP (pool.ntp.org) et détectent les incohérences au niveau de la couche transport (pour éviter les attaques). Pour faire simple, les routeurs floodfill assurent la correspondance des clés, le routage des informations et le transport des données dans le réseau (de 3 à 5 routeurs Floodfill assurent en théorie le bon fonctionnement d'un ensemble de 10 000 routeurs sur le réseau). L'algorithme utilisé n'est pas un algorithme complet mais a été ajusté pour correspondre au besoin d'I2P sans alourdir l'implémentation.
Les algorithmes de Kademlia étaient utilisés pour les échanges de métadonnées entre les routeurs. Cette solution fut abandonnée[Quand ?], à cause des difficultés de mise en place de l'algorithme. L'algorithme demandait un minimum de ressources (pc et processeur) que les routeurs ne pouvaient pas assumer (bonne idée sur le papier mais pas dans cette application).
Le routeur stocke uniquement les informations qui lui sont primordiales pour envoyer des messages sur le réseau. Il s'agit de son identité (une clé ElGamal de 2 048 bits publique, une clé DSA publique puis un certificat), et des adresses (une liste d'adresse IP, de port, et des ensembles d'options de publication). La clé de cette structure est un SHA256 de l'identité du routeurs. Tant que la version de l'I2P n'est pas en sa version 1.0 les options de publication sont des données de débogage.
Dans un tel système distribué, la recherche d'une information pourrait ressembler à une recherche dans une DHT traditionnelle (comme celle réalisée dans les réseaux en P2P). Mais étant donné que le réseau est volatil et en constante évolution (vu la durée de 10 minutes de validité des tunnels), la recherche itérative est facilitée du fait que l'information n'est pas sur le routeur le plus proche mais sur les routeurs ayant une clé d'identification proche du SHA256 (identité du routeur + un horodatage sous le format AAAAMMJJ), permettant d'avoir un ensemble de routeurs ayant l'information demandée. Ce qui permet également un renouvellement de la place des informations sur le réseau et une protection contre les attaques (car pour attaquer une machine avec ce principe, l'emplacement des informations change tous les jours, obligeant l'attaquant à recréer son attaque à chaque fois). Les données de recherche étant sensibles, elles transitent dans des tunnels d'exploration différents des tunnels de données.
L'immersion de la charge utile permet de cacher les données effectivement envoyées ou reçues par l'utilisateur d'un routeur I2P. L'immersion est très importante puisque c'est elle qui protège l'anonymat face à un attaquant extérieur qui dispose d'une vue d'ensemble du réseau.
Dans sa conception, les développeurs prennent en compte les attaques et les répertorient pour assurer une protection des utilisateurs et le réseau (pour éviter par exemple une surcharge des routeurs floodfills).