Le protocole BitTorrent et ses extensions
Extensions
Dans la partie précédente, on a vu comment les choses se passaient du point de vue de la spécification BitTorrent de base. De nombreuses extensions existent, à l'état de draft mais néanmoins supportées par la plupart des clients logiciels pour BitTorrent.µTP
Le peer protocol est très fréquemment remplacé dans les faits par µTP (Micro Transport Protocol) pour au moins deux raisons :- Le peer protocol utilise TCP ; si on communique avec N peers, on a N connexions TCP ouvertes simulanément. En général, l'allocation de la bande passante par l'OS se fait de manière équitable entre les différentes connexions TCP. Si 10 sessions TCP sont ouvertes par BitTorrent, une autre application comme HTTP qui n'en utilise qu'une sera fortement défavorisée par rapport à BitTorrent. Du point du vue application, la répartition des ressources n'est pas équitable, le peer protocol "mange" toute la bande passante. C'est d'autant plus problématique que le comportement qu'on attend a priori d'un client logiciel BitTorrent est de fonctionner en tâche de fond et de ne pas perturber pas tout le réseau.
- Une raison moins officielle est de contourner les politiques de traffic shaping des fournisseurs d'accès. Il ne voient en effet pas d'un bon oeil ces protocoles qui sont destinés à occuper toute la bande passante inutilisée et qui tournent en permanence. L'exemple le plus extrême est celui de Comcast en 2007 aux USA qui forgeait des datagrammes TCP Reset pour fermer les connexions BitTorrent de leurs clients. Pour identifier les sessions BitTorrent, ils cherchaient des sessions TCP longues où les paquets étaient de taille importante. Pour contourner cette identification, µTP utilise UDP comme protocole de transport. Cela oblige le FAI à regarder au niveau application dans le paquet, ce qui n'est pas toujours évident à mettre en place et n'est pas forcément légal.
La spécification de µTP est assez indigeste. Il ré-implémente un algorithme de contrôle de flux similaire à celui de TCP (mais avec des paquets UDP ): une fenêtre d'émission va définir le nombre maximal d'octets en transit (pas encore acquittés). A la différence de TCP, la taille de cette fenêtre va être basée sur une estimation du délai d'aller retour des paquets dans le réseau. Les modems ont en général des buffers suffisants pour stocker plusieurs secondes de trafic ; toutefois dans l'idéal un paquet µTP n'est jamais bufferisé. Le principe est que si d'autre flux (qui n'ont pas ce mécanisme) remplissent les buffers, le temps d'aller-retour va augmenter et µTP va diminuer sa fenêtre d'émission. Dans les faits, le trafic µTP va donc être moins prioritaire que les autres flux.
La courbe suivante (trouvée dans une étude de µTP sur le blog officiel de BitTorrent) présente un flux µTP qui cède sa bande passante à un flux TCP qui arrive (pour avoir eu l'immense joie d'essayer de mettre en oeuvre de la QoS au niveau client, je trouve cette courbe un peu trop propre pour être honnête)

Magnet links
Dans ce que j'ai détaillé jusqu'ici, il y a encore deux éléments qui ne sont pas encore distribués. Il faut télécharger un fichier torrent sur un serveur et contacter un tracker qui est un serveur central. Deux extensions permettent de distribuer ces éléments ; la première défini les magnet links.
Sur le web, il est de plus en plus courant de rencontrer des magnet links en lieu et place des des fichier torrent. Ce sont des liens du type :
On y retrouve l'info_hash du torrent, le nom du torrent et l'URL du tracker. En utilisant ce lien dans un client logiciel BitTorrent, on va contacter le tracker pour obtenir une liste de peers. La première chose que l'on va faire avec ces peers est de télécharger le ficher torrent.
Depuis février 2012, The Pirate Bay n'utilise que des magnet links. A l'époque il avait été calculé qu'on pouvait alors stocker un mirroir complet des torrent référencés sur 90MB
Mainline DHT
Seul le tracker nécessite encore un serveur. Il existe toutefois un système dit trackerless (l'adjectif n'est pas très heureux puisqu'en réalité c'est l'inverse : chaque peers devient un tracker) qui utilise un mécanisme de table de hachage distribuée. Ce système c'est Mainline DHT, qui est l'implémentation pour BitTorrent d'un protocole plus général appelé Kademlia.
Pour être d'accord sur les termes employés : dans la suite, un noeud sera une station participant au protocole DHT et les peers seront toujours celles participant aux échanges BitTorrent
Mainline DHT repose sur plusieurs principes de base :
- Chaque noeud choisi un identifiant au hasard sur 20 octets (dans le même espace que les info_hash de torrent) ;
- On défini une distance sur cet espace : la distance entre un noeud A et un noeud B est le XOR entre leurs identifiants ;
- Dans cette table de hachage (distribuée) on stocke comme clés l'info_hash des torrent et comme valeur la liste des peers qui participent à la diffusion du fichier ;
Pour communiquer entre eux, les noeuds de DHT maintiennent des tables de routage. Tout l'espace [0, 2^160 [ (ensemble des mots de 20 octets) est découpé en buckets. Au départ on a qu'un seul bucket qui rempli tout l'espace et on choisi notre ID au hasard (point rouge) :

En communiquant, on rencontre deux nouveaux noeuds. On les ajoute dans le bucket :

Imaginons que le protocole définisse un bucket contenant deux noeuds comme "plein". Lorsqu'on rencontre un troisième noeud, il faut scinder le bucket :

Ensuite, lorsqu'on rencontrera un nouveau noeud, on ne le stockera que si il appartient au même bucket que nous. En continuant à ajouter des noeuds, on finira par connaitre beaucoup de noeuds proches de notre propre ID et peu de noeuds éloignés
On représente souvent l'espace des id/info_hash sous la forme d'un cercle :

Imaginons que l'on soit la station avec l'ID 8, et que l'on souhaite télécharger un fichier dont l'info_hash est 42. Si on connait (dans notre table de routage) la station 12, on va lui demander la liste des peers qui participent à la diffusion du ficher 42 :

Elle va nous répondre qu'elle ne connait aucune peers pour le info_hash 42 mais qu'en revanche elle connait des noeuds DHT plus proches de l'ID 42 qu'elle ne l'est elle même (en l'occurence ici, 40 et 48) :

On retransmet donc cette demande de peers au noeuds 40 et 48 :

Les noeuds 40 et 48 vont nous répondre que eux non plus ne connaissent pas de peers pour ce torrent en particulier :

La station 48 nous réponds qu'il connait 40. On a déjà reçu 40 en réponse à une précédente requête (sur la station 12), cela constitue une condition d'arrêt de la recherche de peers (la condition est plus complexe en réalité, j'ai simplifié pour les besoins de l'explications). La règle fondamentale est de toujours terminer une recherche (fructueuse ou non) en s'annonçant en tant que peer vers le noeud connu le plus proche de l'ID de notre torrent (ici le noeud 40). Le noeud 40 va stocker cette information

Maintenant, imaginons que le noeud d'ID 50 souhaite télécharger le fichier 42. Il peut commencer par demander des peers au noeud 48 :

Le noeud 48 lui répond qu'il ne connait pas de peers mais qu'il connait le noeud 40 :

Le noeud 50 va ré-itérer sa demande vers le noeud 40 :

Le noeud 40 va enfin pouvoir répondre que oui, il connait une peers pour le fichier 42.

L'échange du fichier par peer protocol où µTP peut commencer. Mais attention, puisqu'il vient de terminer sa recherche, il doit également s'annoncer en temps que peer :

Les prochaines requêtes sur le noeud 40 retournerons deux peers.
Les plus perspicaces se poseront la question de "comment connaître le premier noeud (le bootstrap node) ?" Plusieurs solutions :
- Dans certains fichier torrents ou certains magnet links on trouve un champs nodes qui indique les noeuds a priori joignable pour rejoindre Mainline DHT.
- Le ou les boostrap nodes peuvent être codés en dur dans le client logiciel. Par exemple dans le code source de Transmission on va trouver la ligne suivante : bootstrap_from_name ("dht.transmissionbt.com" , 6881 , .... Toutes les recherches sur mainline DHT commencerons sur un noeud derrière une entrée DNS si aucun autre noeud n'est connu.
- Durant les échanges en peer protocol, les peers peuvent annoncer quelle supportent DHT.
- Dans tout les cas, la spécification recommande de sauvegarder la table de routage quand on quitte le client logiciel. On aura ainsi une liste de noeud à essayer à la prochaine session.
Des chercheurs se sont amusé à mesurer Mainline DHT. La procédure (statistique) permettant de compter le nombre de noeud est un peu complexe mais le résultat principal est le suivant :

Mainline DHT est donc une table de hachage distribuée sur plusieurs millions de noeuds (entre 15 et 28 millions de noeuds selon l'heure de la journée).
(Ces même chercheurs ont également conduit une étude intéressante sur la sécurité de MainlineDHT et des attaques qui s'y déroulent. Ils ont identifié des attaques permanentes en provenance d'un ISP international et d'un inconnu louant une architecture AWS)