☞ Le but de cette section va être de pouvoir parler à un serveur en faisant passer les paquet par l’intermédiaire de plusieurs routeurs. Pour cela, il est nécessaire d’avoir à sa disposition un contrôleur qui va choisir un chemin, puis encapsuler les données du client vers le premier routeur. Le rôle du routeur se contentant pour l’instant de jouer le rôle d’intermédiaire. |
☞ Une attention toute particulière devra être apportée aux logs de vos serveurs. Il faut qu’ils soient de la meilleure qualité possible pour pouvoir débugger facilement. De plus un système devra exister qui permette de récupérer les logs de vos serveurs. |
☞ Dans tout le projet, les paquets que vous allez traiter auront tous le format suivant :
Nous considèrerons que la version sera 0. |
☞ Pour les utilisateurs de Python, l’utilisation de la librairie asyncore est autorisée et conseillée. Dans les autres langages, la methode par select devrait être la plus efficace mais souvent plus difficile à programmer. Quelquefois, selon le système d’exploitation, l’utilisation de fork() peut se révéler plus efficace que l’utilisation de threads. A vous de justifier votre choix de programmation. |
Celui-ci offre plusieurs services :
Les services que proposent le routeur sont accessibles par les clients avec les requêtes : SUIV, CONN FLUX, FERM et BKDR.
À partir du moment où la connexion est acceptée, le routeur envoi vers son client tout ce qu’il reçoit de son successeur en encapsulant les données dans un paquet normalisé. La partie requête du paquet étant DATA.
Voici un exemple de paquet pouvant être reçu par le routeur :
Par convention j’écris entre guillements (") les valeurs codées sous forme de chaîne de caractères et sans guillemet les valeurs décimales. Par exemple le paquet précédent se voit de la façon suivante :
Offset ------------ notation hexadecimale ------------- ---- ASCII -----
00000000 00 53 55 49 56 00 18 72 6f 75 74 65 75 72 31 2e | SUIV routeur1.| 00000010 64 79 6e 64 6e 73 2e 6f 72 67 3a 39 30 39 31 |dyndns.org:9091| |
Un paquet de retour possible est :
Les paquets de retours comme COOK et ERRC doivent aussi être modifiés de la même façon.
Si le sucesseur d’un routeur ferme la connexion alors, le routeur envoie à son client utilisant ce successeur la commande CLOS (CLOSed). Si la connexion a été obtenue avec CONN plutôt que SUIV alors le paquet contiendra aussi le n∘ de session dans la partie données.
☞ Le contrôleur sera un serveur qui devra dans le cas général être lancé sur le même poste que le client en tant que démon. Il va se comporter soit comme le serveur cible soit comme un proxy http . Le contrôleur joue un rôle similaire à celui des routeurs, mais en plus il contrôle la création des chemins et les encapsulation des données. C’est le contôleur qui va créer un tunnel de routeur. C’est au contrôleur de décider quelle sera la longueur des chemins et qui gèrera les numéros de session. Le contrôleur décidera aussi par la suite les clés à utiliser pour le chiffrement. |
Le contrôleur doit pouvoir fonctionner selon deux modes : un mode simulation de serveur et un mode proxy http .
Le routeur doit posséder les fonction internes suivantes :
De plus, pour le début du projet, nous considérons que le contrôleur possède la liste des routeurs accessibles ; soit dans une structure de données remplie manuellement, soit dans un fichier qui sera chargé à chaque démarrage du contrôleur. Ajouter un système de publication des routeur fera partie des dernières étapes du projet.
La conception du contrôleur sera très proche de celle des routeurs. Voici les requêtes que peuvent formuler les clients au contrôleur et les services qui leur sont alors fournis :
Fait la même chose que CONN suivit de la requête FLUX qui transmet l’ensemble de la requête au serveur cible. Cette dernière requête est utile pour pouvoir utiliser un navigateur internet à travers le réseaux. Il suffira d’utiliser le contrôleur comme un proxy http .
Pour résumer voici la table qui résume l’ensemble des requêtes pour les routeurs et les contrôleurs :
Pour le routeur :
Requête | Données | Retour requête |
SUIV | "adresse:port" | "COOK" ou "ERRC" |
CONN | n∘session"adresse:port" | "COOK" ou "ERRC" |
FLUX | données brutes | - |
FERM | - | "CLOS" |
BKDR | - | logs |
Pour le contrôleur :
Requête | Données | Retour requête |
CONN | n∘session"adresse:port" | "COOK" ou "ERRC" |
FLUX | données brutes | - |
BKDR | - | logs |
Requête proxy | - | - |
Pour fixer les idées nous donnons un exemple des paquets passant sur le réseaux. Le réseau concerné est le suivant :
Sont écrit entre parenthèse les commande qui ne nécessitent pas d’entrée ou de sortie sur les sockets comme les connexions et les "close". Les paquets sont écrit selon la notation suivante : v."req".l."data" avec :
--- Creation du tunnel avant la connexion du client ---
C -> R1 : (connect) R1 -> C : (accept) C -> R1 : 0."SUIV".19."147.94.66.131:34500" R1 -> R2 : (connect) R2 -> R1 : (accept) R1 -> C : 0."COOK".0. --- Creation de la connexion --- A -> C : (connect) C -> A : (accept) C -> R1 : 0."FLUX".30.[0."CONN".23.2345"serverecho:2000"] R1 -> R2 : 0."CONN".23.2345"serverecho:2000" R2 -> B : (connect) B -> R2 : (accept) R2 -> R1 : 0."COOK".4.2345 R1 -> C : 0."DATA".11.[0."COOK".4.2345] --- Envoi des données vers le serveur --- A -> C : 0."FLUX".6."coucou" C -> R1 : 0."FLUX".17.[0."FLUX".10.2345"coucou"] R1 -> R2 : 0."FLUX".10.2345"coucou" R2 -> B : "coucou" B -> R2 : "coucou" R2 -> R1 : 0."DATA".10.2345"coucou" R1 -> C : 0."DATA".17.[0.DATA.10.2345"coucou"] C -> A : "coucou" --- Fermeture de la session --- A -> C : (close) C -> R1 : 0."FLUX".11.[0."FERM".4.2345] R1 -> R2 : 0."FERM".4.2345 R2 -> B : (close) |
2.1. Écrivez le même type de conversation en utilisant le même réseaux mais en ajoutant un deuxième client echo D qui se connecte en même temps à un autre serveur echo E.
(a) Pourraient-ont se passer des numéros de session ? Si oui, quelles fonctionnalités du réseau anonyme perdraient-on ? Si non, expliquez en quoi ces numéros de sessions sont absolument nécessaires à la bonne utilisation du réseau anonyme.
Voici un autre exemple de dialogue possible entre un client http A et un serveur http B qui se parlent par l’intermédiaire d’un contrôlleur C et de deux routeurs R1 et R2. L’adresse IP de R2 est 147.94.66.131 l’adresse de B est servhttp.com et écoute sur le port 80.
C -> R1 : 0."SUIV".19."147.94.66.131:34500"
R1 -> R2 : (connect) R2 -> R1 : (accept) R1 -> C : 0."COOK".0 A -> C : GET http://servhttp.com HTTP/1.0\r\n C -> R1 : 0."FLUX".26.[0."CONN".19.456"servhttp.com:80"] R1 -> R2 : 0."CONN".19.456"servhttp.com:80" R2 -> B : (connect) B -> R2 : (accept) R2 -> R1 : 0."COOK".4.456 R1 -> C : 0."DATA".11.[0."COOK".4.456] C -> R1 : 0."FLUX".49.[0."FLUX".42.456"GET http://servhttp.com HTTP/1.0\r\n"] R1 -> R2 : 0."FLUX".42.456"GET http://servhttp.com HTTP/1.0\r\n" R2 -> B : "GET http://servhttp.com HTTP/1.0\r\n" B -> R2 : HTTP/1.0 200 OK ... R2 -> R1 : 0."DATA".231.456"HTTP/1.0 200 OK ... " R1 -> C : 0."DATA".238.[0."DATA".231.456"HTTP/1.0 200 OK ... "] C -> A : "HTTP/1.0 200 OK ... " B -> R2 : (close) R2 -> R1 : 0.CLOS.4.456 R1 -> C : 0."DATA".11.[0."CLOS".4.456] C -> A : (close) |
Remarquez que la connexion entre R1 et R2 n’a pas été fermée.
2.2. Dans un premier temps programmez un routeur sans gérer la requête CONN.
(a) En utilisant telnet, vérifiez que vous pouvez vous connecter à travers plusieurs routeurs. Pour cela utilisez comme destination un serveur echo.
2.3. Programmez un contrôleur qui ne gére pas CONN et vérifiez que tout fonctionne. En particulier vérifiez, en utilisant ethereal, que les message sont bien ceux attendus. Essayez l’ensemble des cas suivants :
(a) contrôleur en mode simulation vers un serveur echo en utilisant un, deux et trois routeurs.
2.4. Ajoutez le service CONN au routeur et au contrôleur. Vérifiez que tout fonctionne correctement :
(a) Soit le tunnel suivant : un contrôleur sur 127.0.0.1:9090, le routeur sur 127.0.0.1:9091, un serveur echo sur 127.0.0.1:3000. En utilisant ethernet donnez les trames qui correspondent à la connexion de deux clients echo qui se connectent au serveur echo via le tunnel.
(b) Recommencez en ajoutant un second routeur, puis un troisième (toujours sur l’ordinateur local).
(c) Vérifiez que les connexions fonctionnent toujours même lorsque les ordinateurs sont différents.
2.5. Ajoutez la fonctionnalité mode proxy http au contrôleur.
(a) Vérifiez en vous connectant via le contrôleur vers votre site personnel ou sur n’importe quel site hébergé par daumier. N’oubliez pas de vérifier avec ethereal que les paquets sont bien envoyés via le contrôleur.