Copyright © www.efarm-project.net Protocole documentation
Transcription
Copyright © www.efarm-project.net Protocole documentation
Protocole documentation version 1.1 Copyright © www.efarm-project.net Sommaire 1- Fonctionnement général 1.1- Fonctions du serveur 1.2- Ports de communication 1.3- LowID et HighID 2- Etapes de communication entre le client et le serveur 2.12.22.32.42.5- Etape Login Etape Search File Etape Search User Etape Get Sources Etape Callback 3- Contenu théorique des packets 3.1- Unités de données 3.2- Composition des différents packets 4- Exemples de packets envoyés par eMule 4.1- Packet Login 4.2- File Info List 5- Communication spéciales UDP 6- Remerciements 7- Changements Copyright © www.efarm-project.net 1- Fonctionnement général 1.1- Fonctions du serveur Le serveur eDonkey ne sert pas à grand-chose à vrai dire. En tout cas il n’a pas beaucoup de fonctions mais il doit supporter une grande charge de connexions. Son principal travail est de stocker et gérer des informations sur les connexions des clients notamment : - Comment les joindre ? - La liste des fichiers qu’ils mettent à disposition - Eventuellement, devenir un tunnel de communication entre deux clients dans le cas d’une communication LowID <-> HighID (voir section 1.3) Ensuite il doit pouvoir répondre à un certain nombre de requêtes notamment les requêtes de Login et surtout, les requêtes de recherche de fichier. Dans ce dernier cas, nous le verrons plus tard, le serveur renvoie une liste de client ayant le fichier recherché et c’est tout. 1.2- Ports de communication 4661 : port de communication principal de communication client <-> serveur par où passent toutes les requêtes. 4662 : port de communication entre deux clients et entre un client et un serveur pour l’attribution du ID. 4665 : port utilisé en cas de communication entre un client HighID et un client LowID Pour plus de précisions sur l’utilisation des ports, passez à la section suivante. 1.3- LowID et HighID Voici un copier/coller d’une page Internet Suisse qui me semblait excellente pour comprendre le système des ID dans le protocole. On s’aperçoit vite que la gestion de ces ID est primordiale. Comment est attribué l'ID L'ID est attribué par le serveur en début de connexion. Quand un client se connecte au serveur Edonkey, le serveur tente d'ouvrir une connexion TCP vers le port 4662 du client. Si cette connexion se passe bien, le serveur attribue un High ID au client. Si la connexion échoue (à cause d'un parefeu ou d'un problème de délai réseau) le serveur attribue un 'Low ID', grosso modo un numéro interne du serveur. Un Low ID ne permet pas de retrouver l'adresse IP alors qu'un High ID le permet. Si un High ID est attribué par le serveur, ce High ID est exactement l'adresse IP du client réécrite différemment : Si l'adresse IP du client est A.B.C.D, on écrit sous forme hexadécimale aa.bb.cc.dd , puis on inverse l'ordre des octets et on met sous la forme : ddccbbaa, puis on passe en décimal : on obtient l'ID. L'opération peut se faire dans l'autre sens. Ce mécanisme explique que si un client change de serveurs Edonkey, en général il conserve son ID, car son adresse IP ne change pas pendant une session Internet. Pour que l'adresse IP change, il faut se déconnecter du réseau Internet, se reconnecter et supposer que le provider ne vous re-attribue pas l'IP précédente et en choisisse une autre. Quel rôle joue l'ID dans les connexions ? Copyright © www.efarm-project.net Un client Edonkey B doit contacter un autre client A (peer to peer) pour obtenir une 'source' ou morceau de fichier. Or pour contacter un peer, il faut connaître son adresse IP. Cette adresse IP, le donkey la détermine grâce à l'ID du peer A que le serveur lui a communiqué, dans le résultat d'un search. Si le ID de A est un 'HighID', B tente directement une connexion TCP vers le port 4662 de A. Le peer to peer en natif ! Si le ID de A est 'faible' (par opposition à High ID), l'adresse IP ne peut pas être calculée, le peer n'est pas joignable directement. Pour le joindre, il faut que le client B envoie une trame spéciale au serveur du client A (sur son port UDP 4665).Sur réception d'une demande de ce type, le serveur envoie au client A sur sa liaison TCP 4661 la demande du client B, en indiquant l'adresse IP et le port du client B. Le client A peut ensuite essayer de contacter le client B sur son port 4662. Ce mécanisme est impossible si A et B sont en LowID. De plus, la demande du client B est envoyée en UDP au serveur de A, or UDP est un protocole moins fiable que TCP. Les serveurs étant saturés, une bonne partie des trames UDP 4665 sont perdues sur le réseau Internet. Conclusion: • • si un client Edonkey obtient un Low ID, il n'est pas joignable par un autre client LowID. Il réduit donc les probabilités de croisement des sources. Il engendre une surcharge de son serveur qui sera sollicité par les clients Edonkey désireux d'obtenir des sources chez le LowID. Les serveurs ayant une bande passante limitée sont obligés de réduire leur nombre maximal d'utilisateurs. le réseau Edonkey fonctionne moins bien. L'expérimentation commencée le 22 mai sur lugdunum et ed2k.ch a permis de constater la baisse du trafic engendrée lorsque le taux de LowID diminue sur un serveur. Fran_48 a fait une étude mathématique à ce sujet. Si trop de gars ont un LowID, les téléchargements ne peuvent plus se faire, c'est mathématique (par le jeu des probabilités) • • Deux clients ayant un LowID ne peuvent pas communiquer entre eux. Deux clients ayant un High ID peuvent communiquer dans les deux sens : situation optimale pour eux mais aussi pour la bonne santé du réseau Edonkey. Les serveurs ne sont pas sollicités pour jouer le rôle de relais. Les serveurs effectuent des recherches, ce pour quoi ils sont faits. Qu'est-ce qui peut expliquer un low ID ? • • • • Un parefeu, quelque part, bloque le port 4662 du client. Merci de consulter la FAQ pour configurer proprement votre parefeu si vous en avez un (Windows XP intègre un parefeu en standard) Lien pour configurer le parefeu de Windows XP Vous avez une adresse IP de la forme A.B.C.O (dernier chiffre nul). Ce cas est fort heureusement exceptionnel. Un routeur ADSL n'a pas été configuré pour mapper le port 4662 en provenance du réseau Internet vers la machine Edonkey intérieure, sur le port 4662. Vous pouvez vous rendre dans notre section Rubriques sous Config des Routeurs pour apprendre à configurer votre routeur. Le serveur a sa bande passante saturée, et n'arrive pas à contacter le client en moins de huit secondes. Le serveur edonkey attend très peu de temps pour prendre sa décision. Ed2k.ch essaie de contrer ce problème en utilisant le 'traffic shaping' de linux : le port 4662 a Copyright © www.efarm-project.net • • été mis en classe prioritaire pour passer devant les autres paquets Edonkey : Ed2k.ch alloue plus souvent un High ID que d'autres serveurs. Votre port 4662 est mappé non pas sur votre client edonkey mais vers une autre application. Par exemple le port 80 arrive en général sur un serveur HTTP. Depuis la version 16.38.p63 (17 octobre 2002) le serveur détecte ce cas de figure et vous attribue un LOWID. Le serveur détecte même les cas où le port 4662 arrive sur un autre client edonkey... Attention donc à bien configurer vos clients pour ceux qui en utilisent plusieurs sur la même adresse IP. Le client a sa bande passante saturée. Ceci peut arriver pour de multiples raisons. o o o • Mauvais paramètres edonkey (MaxUpload, MaxDownload, MaxConnections). Utilisation simultannée de plusieurs logiciels p2p. Cela est possible uniquement si les réglages sont très bien faits. Parasitage du PC par un virus ou spyware. Utilisez un antivirus remis à jour régulièrement, et utilisez AdWare pour retirer les spyware. Utilisation d'emule Ce logiciel comporte de nombreux bugs. Pour se connecter à un serveur (bouton Connecter), il ne trouve rien de mieux à faire que de lancer dix connexions simultannées vers dix serveurs. L'inventeur de cette stupidité s'est dit que puisque les serveurs sont en général pleins, il aurait plus de chance de tomber sur un serveur avec une place de libre ! Si cette stratégie est en effet gagnante à l'echelle individuelle (comme dans la vie courante, si vous allez dans dix boulangeries vers 18h30 vous avez plus de chances de trouver du pain que si vous allez dans une seule), elle a de gros inconvénients : o o Il y a de fortes chances que les serveurs tentent la connexion vers le port 4662 a peu près au même instant, et que le client soit débordé par les demandes des serveurs (Upload saturé) et que tout parte en timeout. Quand une connexion reussi, les 9 autres connexions sont coupées : les serveurs ont du faire du travail pour rien. Depuis qu'Emule est devenu majoritaire sur le réseau, les serveurs edonkey sont asaillis par des demandes de connexions qui sont annulées au bout de 3 à 10 secondes. La surcharge de travail est énorme. Et les utilisateurs se plaignent d'obtenir des LOWID ! Quelle est la formule pour calculer l'ID ? Par exemple j'ai une IP fixe: 62.4.18.116. Mon ID est TOUJOURS le même: 1947337790. Vous allez me dire, pkoi c'est toujours 1947337790 et pas un autre? pkoi quand je suis déconnecté d'Edonkey quelqu'un d'autre ne prend pas mon ID à ma place?... Et bien tout simplement parce que c'est mon IP justement et qu'elle est fixe ... Regardez plutôt: 1947337790 (en décimal) = 7412043E (en héxadécimal) Copyright © www.efarm-project.net Groupons mon ID par blocs de 2 digits: 74.12.04.3E Maintenant inversons le: 3E.04.12.74 Convertissons chaque bloc hexa en décimal à nouveau: on tombe sur.... 62.4.18.116 !! MAGIQUE Evidemment, les personnes dont l'IP est dynamique, c'est différent: lorsque vous changez d'IP, la personne qui prend votre ancienne IP aura votre ancien ID... Ca explique pkoi dans votre liste de "Friends" vous entrez un jour une personne, et 3 semaines plus tard, ce n'est plus le même nick qui apparaît!!! forcément, même ID, mais personne différente... Là encore ça n'arrive que pour les IP dynamiques: moi par exemple comme je suis la seule personne au monde à avoir mon IP, si vous m'ajoutez dans votre Friend List, ce sera toujours mon nick qui apparaît... Maintenant prenons l'exemple d'une personne avec un LowID! souvenez-vous ma FAQ: le serveur alloue une IP virtuelle de type "107.0.0.0" si c'est le 107e connecté.. et bien on fait le même principe mais vous voyez tout de suite que la conversion en hexa, l'inversion, puis la conversion encore en décimal va donner un tout petit chiffre! ... et bien voilà... quand vous changez de serveur, votre numéro de file change, donc l'IP virtuelle attribuée par le serveur change aussi, donc le calcul donne un ID lui aussi différent, d'où le fameux message "Your ID has changed, you've been removed from all upload queue" .. Logique: ID différent = utilisateur différent pour eDonkey... donc tout repart à zero. CQFD. Là vous allez me dire, le N-ième connecté avec un LowID sur un serveur A et sur un serveur B vont avoir le même ID alors?... et bien non, car le serveur est lui aussi identifié de manière unique sur le réseau, et donc il ajoute cette information dans le calcul, ce qui fait que les ID sont différents d'un serveur à l'autre.. mais là j'avoue je n'ai pas vraiment cherché la formule (car j'ai pas de LowID justement..) Copyright © www.efarm-project.net 2- Etapes de communication entre le client et le serveur Ce chapitre n’est absolument pas complet. Il s’agit d’une première version qu’il faudra étoffer au fur et à mesure du développement ou même avant. Il dégrossit largement le fonctionnement du protocole. Je pense que ça pourrait suffire pour sortir une première version potable mais c’est à voire. 2.1- Etape de Login Copyright © www.efarm-project.net 2.2- Etape Search File Copyright © www.efarm-project.net 2.3- Etape Search User Copyright © www.efarm-project.net 2.4- Etape Get sources Copyright © www.efarm-project.net 2.5- Etape Callback Cette étape est très mystérieuse pour moi. J’émets deux hypothèses que je n’ai pas encore réussi à départager : - Soit un client désire vérifier si son ID n’a pas changer et demande au serveur de le re-contacter et, le cas échéant, si le test ne fonctionne pas, obtenir son nouvel ID sur le serveur ce qui me parait être l’hypothèse la plus probable. - Soit d’après les sources d’eMule, cette commande sert à mettre à jour la liste des clients dispo voir même faire un test sur chaque client obtenu dans une liste de clients disponibles pour le téléchargement d’un fichier (vous me suivez ?). Car dans les sources d’eMule on trouve le code suivant dans la fonction Processpacket de la class CServerSocket : case OP_CALLBACKREQUESTED:{ if (size == 6){ uint32 dwIP; memcpy(&dwIP,packet,4); uint16 nPort; memcpy(&nPort,packet+4,2); CUpDownClient* client = theApp.clientlist>FindClientByIP(dwIP,nPort); if (client) client->TryToConnect(); else{ client = new CUpDownClient(nPort,dwIP,0,0,0); theApp.clientlist->AddClient(client); client->TryToConnect(); } Copyright © www.efarm-project.net } } eMule ne se sert que d’une partie de cette étape car dans la liste de ces OPCODES ne figurent que les suivants : 0x35 et 0x1C soit les deux premières requêtes de cette étape. eMule demande au serveur l’adresse IP et le port correspondant au client dont l’ID est celui contenu dans <Client ID>. Le serveur lui renvoie ces informations et eMule ce charge de vérifier si ce client n’est pas dans sa liste. S’il l’est il essaie de s’y connecter, s’il ne l’est pas, il le créé et essaie de s’y connecter. Je pense cependant que eMule essaie de décharger le serveur d’une partie du travail car si 10 000 clients faisaient une requêtes callback sur un Client ID et que le serveur devait se charger de toutes les mener à bien, on peut facilement imaginer la charge de trafic que cela pourrait générer au niveau de la bande passante du serveur. Je n’ai pas finis d’explorer cette étape en particulier dans eMule. A approfondir dans la prochaine version de la documentation. 3- Contenu théorique des packets 3.1- Unités de données uint32 : unsigned int 32 bits uchar : unsigned char uint16 : unsigned int 16 bits int8 : int 8 bits uint8 : unsigned int 8 bits DWORD = uint32 WORD = uint32 BYTE = 1 octet (on l’aura deviné …) FLOAT = float (idem …) HASH = uchar[16] rempli de différentes manières (voir plus loin) [Client HASH] = HASH [Server HASH] = HASH [File HASH] = HASH [Client ID] = DWORD [Port] = WORD [IP] = DWORD [Nusers] = DWORD [Nfiles] = DWORD 3.2- Composition des différents packets <Client Info> [Client Hash] + [Client ID] + [Port] + <Meta Tag List> <File Info List> DWORD + <File Info>* <File Info> Copyright © www.efarm-project.net [File Hash] + [Client ID] + [Port] + <Meta Tag List> <Adress list> BYTE + <Adress>* <Adress> [IP] + [PORT] <Server Info> [Server Hash] + [IP] + [Port] + <Meta Tag List> Copyright © www.efarm-project.net <Server Status> [Nusers] + [Nfiles] <Meta Tag List> DWORD + <Meta Tag>* <Meta Tag> 0x02 + <Meta Tag Name> + DWORD ou 0x03 + <Meta Tag Name> + [String] ou 0x04 + <Meta Tag Name> + FLOAT <Meta Tag Name> [String] ou WORD + <Special Tag>* <Special Tag> Code 0x01 0x02 0x03 0x04 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x20 0x21 Contenu [Name] [Size] [Type] Audio, Video, … [Format] file extension [Copied] contenu déjà copié [GAP start] ????????? [GAP end] ????????? [Description] [Ping] [Fail] [Preference] [Port] [IP] [Version] [Tempfile] nom du fichier temporaire de download [Priority] 0 = low, 1 = normal et 2 = high [Status] 0 = looking, 1 = paused [Availabitlity] [QTime] a mon avis cela veut dire Queue Time [Parts] dans eMule il s’appelle ULPRIORITY [Compression] spécifique a eMule [Port UDP] port UDP du client spécifique à eMule Type String Uint32 String String Uint32 Uint32 Uint32 String Integer Uint32 Uint32 Ce tableau reste à compléter. <Search Query> 0x00 + <Operator> + <Search Query> + <Search Query> ou 0x01 + [String] + <Meta Tag Name> ou 0x02 + <Meta Tag> ou 0x03 + DWORD <MinMax> + <Meta Tag Name> <Operator> 0x00 (= AND) Copyright © www.efarm-project.net ou 0x01 (= OR) ou 0x02 (= AND NOT) <MinMax> 0x01 (= min) ou 0x02 (= max) <More> 0x00 ( ???????) 0x01 ( ???????) Le type HASH est un type bien particulier car il est calculé de différentes manières selon qu’il s’agit de celui du server, du client ou d’un fichier. Dans tous les cas il fait la même taille. J’ai trouvé la manière dont eMule fabrique son [Client Hash] : Uchar userhash[16] ; For (int i=0 ; i != 8; i++) { uint16 random = rand(); memcpy(&userhash[i*2], &random, 2); } // marques spéciales du client eMule userhash[5] = 14; userhash[14] = 111 ; C’est pas très compliqué et de toute façon, le serveur s’en bas les couille un peu. Le truc intéressant se sont les deux valeurs données arbitrairement à la fin qui permettent d’identifier un client eMule d’un autre. Ca pourrait être utile. Pour ce qui est des autres HASH, celui d’un fichier est une sorte de MD4 sur le fichier lui-même mais je n’ai pas encore fini de décortiquer la fonction dans eMule. Et celui du serveur pourra être, je pense, fabriqué comme bon nous semblera du moment qu’il a 16 caractères. Copyright © www.efarm-project.net 4- Exemple de packets envoyés par eMule 4.1- Packet Login uchar 16 uint 32 uint 16 uint 32 userhash clientID port nombre de Tags Tag 1 : int 8 uint 16 string [len] uint 8 tagtype = 2 len nickname Tag 2 : int 8 uint 32 tagtype = 3 edonkey version Tag 3 : int 8 uint 32 tagtype = 3 port opcode (OP_LOGINREQUEST) 4.2- File Info List uint 32 Nombre de fichiers Pour chaque fichier : uchar [16] filehash char [6] buffer rempli à 0 (pas de clientID ni de port) uint 32 file type uint 8 Tag 1 : int 8 uint 16 string [len] tagtype = 2 len filename Tag 2 : int 8 uint 32 tagtype = 3 filesize opcode (OP_OFFERFILES) Il y a des choses dont je ne suis pas encore totalement sûr comme le contenu des tags car le code source de eMule est assez ambigu. En effet, les tags sont codés sous la forme d’une classe CTag qui possède une flopé de constructeurs qui s’activent en fonction de ce qu’on passe en paramètres et c’est pas facile de faire la différence entre tous. De plus, il y a quelques aberrations dans le code eMule, par exemple : dans un packet login, eMule indique clairement le nombre de tags qui suivent ainsi que son clientId et son Copyright © www.efarm-project.net port alors que dans le packet File Info List, il n’envoie aucun de ces champs. Je ne sais pas si ça influe sur quelque chose ou non mais ça me semble bizarre. 5- Communication UDP Voici un premier aperçu des communications UDP entre client serveur. Je pense qu’elles ne servent que dans le cas ou le client est eMule. <UDP Server status request> ::= 0x96 DWORD <UDP Server status> ::= 0x97 DWORD Nusers Nfiles //le DWORD est le même qu’au dessus. <UDP Search file> ::= 0x98 <Search query> <UDP Search file result> ::= 0x99 <File info> <UDP Get sources> ::= 0x9a <File hash> <UDP Found sources> ::= 0x9b <File hash> <Address list> <UDP Callback request> ::= 0x9c <Address> <Client ID> <UDP Callback fail> ::= 0x9e <Client ID> <UDP ?> ::= 0xa0 ? <UDP Server list> ::= 0xa1 <Address list> <UDP Get server info> ::= 0xa2 <UDP Server info> ::= 0xa3 <String> <String> // description plus approfondie <UDP Get server list> ::= 0xa4 Copyright © www.efarm-project.net 6- Remerciements Remerciements au projet pDonkey dont vous pouvez trouver les sources sur sourceforge.net. Sa documentation m’a énormément servi dans celle-ci comme vous pourrez le constater. Remerciements aussi au site suisse de edonkey2000, ed2k.ch, pour les infos sur les HighID/LowID. 7- Changements Version 1.1 : - Ajout du chapitre 5 : communications UDP Ajout du chapitre 6 : je l’avais oublié dans la première version je m’en excuse. Ajout du chapitre 7 : nous y sommes puisque c’est la deuxième version. Ajout des sous-chapitres 2.3 et 2.5 pour les étapes de communication « Search user » et « Callback ». Ajout de quelques « Special Tag » dans le tableau. Version 1.0 : première du nom. Copyright © www.efarm-project.net
Documents pareils
Protocole V1.0
alloue une IP virtuelle de type "107.0.0.0" si c'est le 107e connecté.. et bien on fait le même principe
mais vous voyez tout de suite que la conversion en hexa, l'inversion, puis la conversion enc...