• 15 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 14/09/2023

Effectuez le suivi des connexions TCP

Le protocole TCP a donc pour rôle de suivre la connexion, octet par octet, et de s’assurer que les données sont bien transmises. Nous avons vu dans le précédent ouvrage comment les flags permettaient de donner l’état d’une connexion. Nous allons maintenant voir comment les numéros de séquence et d’acquittement vont nous permettre de suivre l’état précis de nos échanges.

Tout d’abord, revenons sur les numéros de séquence et d’acquittement.

Le numéro de séquence représente le numéro du premier octet des données du segment en cours.

Mais qu’est-ce que cela veut dire exactement ?

L’idée est de dire à la machine en face combien de données elle est censée avoir reçues. Par exemple, si je lui ai envoyé 100 octets, je lui dis que je lui en ai envoyé 100 grâce à mon numéro de séquence. Si jamais elle n’en a reçu que 50 de son côté, elle sait qu’elle n’a pas encore reçu toutes les données et pourra me demander de les réémettre si elle ne les reçoit pas au bout d’un certain temps.

De la même façon, le numéro d’acquittement indique le numéro du prochain octet des données attendues.

Il permet d’indiquer à la machine en face combien d’octets nous avons reçus de sa part. Ainsi, elle pourra savoir si tous les octets qu’elle a envoyés ont été reçus ou pas, et ainsi savoir si elle doit en réémettre certains qui ont pu être perdus.

Voici les principes, mais il est probable que cela ne soit pas encore très clair pour vous. Nous allons donc regarder ensemble un exemple concret et nous verrons donc comment aucune donnée ne sera perdue grâce aux mécanismes de TCP.

Établissement d’une connexion TCP

Nous allons représenter notre connexion sous forme de diagramme de temps. En gros, plus l’on descend dans le diagramme, plus le temps avance. Une flèche représentera donc l’envoi d’un segment TCP, et les éléments autour des flèches seront les éléments de l’en-tête qui nous intéressent.

Voici les échanges pour la mise en place d’une connexion TCP :

Initialisation d'une connexion TCP avec suivi
Initialisation d’une connexion TCP avec suivi

On voit ici que le client envoie un premier segment avec le flag SYN positionné. Son numéro de séquence est alors de 0 et son numéro d’acquittement est aussi de 0. En effet, le numéro de séquence représente le premier octet de données du segment actuel, mais comme il n’en contient pas, ce numéro est à 0. Pour le numéro d’acquittement, c’est un peu différent. Étant donné que celui-ci dépend des données envoyées par le serveur, et que celui-ci ne nous a pas encore parlé, on le met d’office à 0.

Puis, le serveur répond au client, en lui confirmant qu’il veut bien communiquer (ACK) et qu’il veut lui aussi ouvrir un canal de communication vers le client (SYN). Son numéro de séquence est à 0, pour la même raison que le client. Par contre, son numéro d’acquittement vaut 1, ce qui veut dire globalement qu’il prévient le client qu’il a reçu 1 octet de données de sa part...

C’est bien étrange, car il n’a pourtant pas reçu pour l’instant le moindre octet de données de la part du client.

Et pourtant ce comportement est juste.

Il faut que le serveur ait un moyen d’indiquer au client qu’il a reçu son premier segment. Et ce moyen est de mettre le numéro d’acquittement à 1.

Et de manière plus générale, il y a une règle pour cela :

Ainsi, le numéro d’acquittement de la réponse du serveur au client est bien à 1 et non à 0. De même que le numéro d’acquittement du troisième segment envoyé du client au serveur est bien aussi à 1.

Enfin, dans ce même troisième segment, le numéro de séquence du client est aussi à 1, bien qu’il n’ait pour l’instant toujours pas envoyé le moindre octet de données, car le client doit suivre le +1 que le serveur lui a envoyé. S’il mettait son numéro de séquence à 0, le serveur croirait qu’il n’a pas reçu son second segment.

Bref, si cela vous semble compliqué, n’hésitez pas à relire le dernier paragraphe jusqu’à bien le comprendre, car nous n’en avons pas encore fini avec le suivi des connexions...

Cependant, il y a une bonne nouvelle pour vous : l’initialisation d’une connexion TCP est toujours la même, mis à part quelques cas ultraspécifiques comme le four way handshake. Mais ces cas sont essentiellement théoriques.

Mais revenons à nos moutons...

Rétablissement de la vérité

Eh oui, car dans la vraie vie, le premier numéro de séquence ne vaut pas réellement 0, il vaut une valeur aléatoire !

Et il porte un nom, ISN ou Initial Sequence Number, numéro de séquence initial en français. À l’origine, son objectif était d’éviter des superpositions de connexions. En gros, que deux connexions puissent utiliser les mêmes numéros de ports ET des numéros de séquence proches.

Cela peut se produire si une machine initialise une connexion, commence des échanges, puis redémarre inopinément, lors d’une coupure de courant par exemple. Le serveur avec qui la connexion a été établie continue à chercher à joindre le client. Si par le plus grand des hasards, après le redémarrage de la machine cliente, celle-ci réinitialise une connexion avec le serveur en utilisant le même port source, alors il peut y avoir un conflit dans les numéros de séquence et d’acquittement utilisés. En effet, la machine cliente se base sur une nouvelle connexion, alors que le serveur cherche encore à rétablir l’ancienne connexion.

Bref, ceci est de l’histoire et n’arrive jamais. Cependant, l’ISN a été créé pour éviter ce genre problème, il faut donc faire avec.

Aujourd’hui, l’ISN est une valeur complètement aléatoire.

L’ISN n’a cependant pas toujours été aléatoire et cela a causé de grosses failles de sécurité, mais nous nous pencherons dessus en fin de chapitre.

Revenons donc à nos échanges et à l’ISN. Pour vous prouver que je dis cette fois la vérité, je vais vous montrer une extraction Wireshark d’un échange pour mettre en avant la valeur de l’ISN :

Extraction Wireshark d'un échange avec valeur de l'ISN mise en valeur
Extraction Wireshark d'un échange avec valeur de l'ISN mise en valeur

Nous voyons ici le premier segment d’un échange (seul le flag SYN est positionné). Wireshark nous indique le numéro de séquence à 0, mais il écrit "relative sequence number", car en fait, il s’arrange pour nous le présenter à 0. Cependant, nous pouvons voir sa vraie valeur dans la trame qui est présentée en hexadécimal en dessous. Notamment la partie que j’ai surlignée en bleu, 47 73 08 03, qui est en fait le vrai ISN.

Cependant, comme Wireshark, il sera plus simple pour nos calculs de ne pas indiquer le vrai ISN, mais plutôt 0 ou alors une valeur X ou Y.

La vérité étant rétablie, nous allons continuer à explorer une connexion TCP, en regardant ce qui se passe après l’initialisation.

Suivi d’une connexion TCP

Notre connexion étant établie, nous allons imaginer un échange très très simple. Le client va faire une demande au serveur en envoyant 20 octets de données, et le serveur va lui répondre avec 200 octets de données :

Suite de la connexion TCP
Suite de la connexion TCP

Le client envoie donc 20 octets, son numéro de séquence reste à 1, car il doit représenter le premier octet des données du segment. Le numéro d’acquittement lui ne change pas, car nous n’avons encore rien reçu de la part du serveur.

Puis le serveur répond avec 200 octets. Son numéro de séquence est toujours à 1. Par contre, son numéro d’acquittement passe à 21, car il indique au client qu’il a reçu les 20 octets de données et qu’il attend le premier octet des données qui suivent.

Nous n’en avons pas encore tout à fait fini avec la connexion, car il faut maintenant la clore !

Clôture de la connexion TCP

Le client, qui a reçu ses informations, va demander la fermeture de la connexion. De même pour le serveur par la suite.

Fermeture de la connexion TCP
Fermeture de la connexion TCP

Le client envoie un segment avec le flag FIN positionné. Le flag ACK est aussi positionné, car il doit acquitter les données précédentes. Le numéro de séquence est bien à 21, le numéro d’acquittement passe à 201 pour prévenir le serveur que son envoi de 200 octets a bien été reçu.

Le serveur répond au client en acquittant sa demande de fermeture de connexion, et il demande à son tour la fermeture de l’autre sens de connexion. Le numéro de séquence n’a pas évolué. Par contre, le numéro d’acquittement du serveur augmente de 1, car il y avait le flag FIN positionné dans le segment précédent. Je vous rappelle la règle :

Enfin, le client acquitte la demande de fermeture du serveur. Le numéro de séquence reste à 22. Par contre, le numéro d’acquittement augmente de 1 et passe à 202 pour les mêmes raisons que précédemment.

Conclusion

Nous venons donc de voir en détail le suivi d’une connexion TCP. Ici, tout s’est bien déroulé, mais en cas de segment TCP perdu, chaque machine s’en rendra compte pour qu’il soit réémis. C’est ce qui permet à TCP d’être qualifié de protocole fiable sans perte de paquets. On pourrait même aller jusqu’à dire, sans perte d’octets !

Conclusion de la partie

Nous venons d’étudier ensemble le fonctionnement du suivi de connexion du protocole TCP. À l’inverse du protocole UDP qui ne garantit aucune perte de paquet, TCP vous assure que chaque octet envoyé sera reçu, même s’il faut le renvoyer 50 fois d’affilée s’il y a beaucoup de pertes.

Nous allons maintenant, comme pour le protocole IP et la fragmentation, voir comment détourner le fonctionnement normal du suivi des connexions avec TCP pour mener des attaques réseau.

Maintenant que vous êtes familier avec le suivi d’une connexion, cela va être à vous de travailler avec deux petits exercices !

Exemple de certificat de réussite
Exemple de certificat de réussite