Le suivi d’une connexion TCP avec Wireshark

I. Présentation

Dans ce tutoriel, nous allons voir comment les numéros de séquence et d'acquittement permettent d'effectuer le suivi d'une connexion TCP, en analysant une capture Wireshark.

La fiabilité est l'un des atouts du protocole de transport TCP, notamment en comparaison de l'UDP. Pour assurer un bon suivi des échanges entre les deux hôtes, le protocole TCP a besoin que des informations soient présentent au sein de chaque segment TCP des différents paquets : le numéro de séquence et le numéro d'acquittement. Nous allons voir comment il fonctionne au travers d'un exemple simple, mais concret, afin d'explorer un peu plus le protocole TCP.

Pour générer une connexion TCP, c'est tout simple : à partir d'une machine Windows 11 avec l'adresse IP 192.168.100.101, je me suis connecté à mon serveur Web avec l'adresse IP 192.168.100.120, via un navigateur. Cette connexion à la page Web, via le protocole HTTP, a été capturée dans une trace Wireshark.

Avant de suivre ce tutoriel, je vous recommande de lire cet article (ou de regarder la vidéo associée) en guise d'introduction : Les protocoles UDP et TCP. Cet article est en quelque sorte une suite.

Ressources :

II. Wireshark : numéro de séquence, numéro d'acquittement, taille des segments TCP

Suite à la capture du trafic, j'obtiens une trace Wireshark avec 11 paquets correspondants à l'initialisation de la connexion TCP, le transfert des données entre les deux hôtes, et la fermeture de la connexion TCP.

Ce qui donne le résultat suivant dans Wireshark, tout en sachant que :

  • Les paquets surlignés en noir correspondent aux paquets du poste client vers le serveur Web
  • Les paquets surlignés en vert correspondent aux paquets du serveur Web vers le poste client
Wireshark : capture de trafic HTTP avec le protocole de transport TCP
Wireshark : capture de trafic HTTP avec le protocole de transport TCP

Le numéro de séquence, le numéro d'acquittement et la taille du segment TCP sont visibles au sein de chaque paquet. Il suffit de sélectionner un paquet et de regarder au sein de l'en-tête TCP :

  • TCP Segment Len : taille du segment TCP en octets
  • Sequence Number : numéro de séquence relatif
  • Acknowledgment Number : numéro d'acquittement
Wireshark : Voir le numéro de séquence, le numéro d'acquittement et la taille du segment TCP
Wireshark : Voir le numéro de séquence, le numéro d'acquittement et la taille du segment TCP

Pour que ce soit plus pratique, nous allons ajouter trois colonnes supplémentaires pour afficher directement ces informations. Effectuez un clic droit sur "Sequence Number" et cliquez sur "Appliquer en Colonne". Répétez l'opération pour les deux autres champs.

Wireshark : ajouter une nouvelle colonne
Wireshark : ajouter une nouvelle colonne

Afin de pouvoir condenser un peu plus l'affichage (comme sur l'image ci-dessous), nous allons renommer ces trois nouvelles colonnes. Effectuez un clic droit sur la colonne "Sequence Number" et cliquez sur "Edit Column" afin de donner un nouveau nom. Là encore, répétez l'opération pour les deux autres colonnes.

Wireshark : modifier le nom d'une colonne
Wireshark : modifier le nom d'une colonne

Dans mon cas :

  • TCP Segment Len devient "TCP - Lenght"
  • Sequence Number devient "# Seq"
  • Acknowledgment Number devient "# Ack"

Comme ceci :

Voilà, un bon point de départ : Wireshark affiche désormais des informations indispensables pour permettre de suivre la connexion TCP. Même si ces informations sont visibles via la colonne "Info", c'est plus pratique de cette façon.

III. TCP : fonctionnement des numéros de séquence et d'acquittement

Le protocole TCP s'appuie sur un numéro de séquence qui lui permet d'indiquer le début du segment TCP et un numéro d'acquittement qui indique la taille des données reçues.

A. Analyse de l'initialisation de la connexion TCP

Commençons par l'analyse des trois premiers paquets puisqu'ils correspondent à l'initialisation de la connexion TCP entre les deux hôtes. Je vous rappelle que ce processus s'appelle le three-way handshake.

Sur l'image ci-dessous, je vous propose une représentation des paquets n°1, n°2 et n°3 de la capture Wireshark afin que l'on puisse analyser les numéros de séquence (SEQ), les numéros d'acquittement (ACK) et la taille du segment (LEN) de ces trois paquets.

Le paquet n°1 correspond à la demande d'initialisation du client vers le serveur, donc nous avons : le flag SYN, un numéro de séquence à 0 correspondant au premier segment, un numéro d'acquittement à 0 et une taille de segment à 0 (aucune donnée transférée). Le numéro d'acquittement est à 0, car il n'y a pas eu d'échange de données entre les deux hôtes : nous sommes en phase d'initialisation.

Le paquet n°2 correspond à la réponse du serveur au client : la présence des flags "ACK" et "SYN" permet d'affirmer que le serveur a bien reçu la demande de connexion du client et qu'il souhaite également établir une connexion avec le client. Comme il s'agit du premier segment, nous avons un numéro de séquence à 0 également. Par contre, ce que l'on peut voir, c'est que le numéro d'acquittement (ACK) est égal à 1.

Pourquoi est-il égal à 1 alors que le client n'a pas transféré le moindre octet vers le serveur ? Bonne remarque. En fait, pour le serveur c'est une manière de dire au client qu'il a bien reçu sa demande de connexion TCP (SYN). Vous devez retenir que le numéro d'acquittement est incrémenté de 1 lorsqu'une réponse à un segment TCP contient le flag SYN.

Le paquet n°3 correspond à l'acquittement (flag ACK) du client à destination du serveur, pour lui indiquer qu'il a bien reçu la demande d'initialisation d'une connexion. Le numéro d'acquittement étant positionné à "1" par le serveur, le client doit suivre cette valeur pour le numéro de segment : c'est pour cette raison que le numéro de segment est à 1 pour le troisième paquet. Si le client réutilise le numéro de segment "0", le serveur pourrait croire que le client n'a pas reçu sa réponse.

C'est la fin du processus three-way handshake : la connexion TCP est établie entre les deux hôtes.

B. Analyse du transfert de données via TCP

La connexion TCP étant établie, nos deux hôtes vont pouvoir échanger des données via le protocole TCP. Puisque le client accède au serveur Web, il souhaite obtenir le contenu de la page Web. Au sein de notre trace ouverte dans Wireshark, cela correspond aux paquets n°4 à n°7.

Le schéma évolue également pour intégrer ces 4 paquets supplémentaires, avec à chaque fois les trois valeurs à analyser (numéro de séquence, numéro d'acquittement et taille du segment TCP).

Le paquet n°4 correspond à la requête HTTP émise par le client au serveur Web : une manière de lui demander le contenu de la page Web. Les numéros de séquence et d'acquittement restent identiques du côté du client puisqu'il n'a pas reçu de nouveaux segments TCP de la part du serveur. Par contre, on peut voir que le segment TCP n'est pas à 0, mais cette fois-ci il est égal à 368 octets.

Le paquet n°5 est une réponse du serveur Web au client pour lui confirmer qu'il a bien reçu sa demande. Cette réponse avec le flag ACK contient des informations importantes. En effet, le numéro de séquence est resté à 1, ce qui est normal puisque le serveur n'a pas encore envoyé de données au client depuis que la connexion TCP est ouverte. Par contre, le numéro d'acquittement est passé de "ACK = 1" à "ACK = 369" pourquoi ? Le serveur a reçu 368 octets de la part du client suite au dernier segment envoyé, donc cette information est ajoutée à la valeur actuelle (1), ce qui donne un total de 369 octets. Grâce au numéro d'acquittement, le serveur va communiquer cette information au client, ce qui va permettre au client de savoir si le serveur a bien reçu l'ensemble des données transférées ou non.

Imaginons que le serveur retourne au client un numéro d'acquittement égal à 300, alors que le client s'attend à recevoir la valeur 369. Cela permettrait au client d'identifier qu'il y a eu un incident lors du transfert des données et que le segment reçu par le serveur est incomplet puisqu'il manque 69 octets. Grâce à cette vérification, le client pourrait réémettre les données manquantes au serveur : voici l'une des forces de TCP.

Le paquet n°6 est toujours en direction du serveur vers le client, et cette fois-ci il correspond à l'envoi des données (contenu de la page Web) au client. Nous reprenons les numéros de séquence et d'acquittement précédents puisque le client n'a pas émis de segment TCP vers le serveur entre temps. Par contre, puisque nous envoyons des données, la taille du segment TCP est égale à 426 octets.

Le paquet n°7 correspond à la réponse du client au serveur pour lui indiquer qu'il a reçu des données de sa part. Le client utilise un nouveau numéro de séquence qui est "369" afin de reprendre l'échange là où il s'est arrêté dans le sens "client vers serveur". Le numéro d'acquittement est égal à 427 (1 + 426) : le serveur aura la confirmation que le client a bien reçu l'ensemble des données. Ce paquet étant un acquittement de la part du client, il est logique que la taille du segment soit de 0.

Il est à noter que les numéros de séquence et d'acquittement entre le client et le serveur sont différents. Le client gère son numéro de séquence et sa valeur évoluera en fonction des octets transférés dans le sens client vers serveur. Cela s'applique aussi au serveur pour les octets transférés dans le sens serveur vers client.

C. Analyse de la fermeture de la connexion TCP

Les données sont transmises et notre serveur souhaite fermer la connexion TCP avec le client, nous allons voir comment se traduit la fermeture de la connexion TCP au niveau des paquets capturés. Au sein de notre trace ouverte dans Wireshark, la fermeture de la connexion TCP correspond aux paquets n°8 à 11.

Le schéma évolue une dernière fois afin d'inclure ces nouveaux paquets correspondants à la fin de la connexion TCP entre notre poste client et notre serveur.

Le paquet n°8 correspond à une demande de fermeture de connexion TCP émise par le serveur à destination du poste client. Nous le savons, car ce paquet contient deux flags TCP : FIN et ACK. Le numéro de séquence "427" est utilisé dans la continuité des précédents échanges et le numéro d'ACK n'évolue pas, car le serveur n'a pas reçu d'octet supplémentaire de la part du client. La taille du segment est égale à 0, car il s'agit d'une demande de fermeture de connexion TCP.

Le paquet n°9 correspond à la réponse du client afin de préciser que la demande de fermeture de connexion TCP a bien été reçue. Même si le serveur n'a pas envoyé de données, on peut voir que le numéro d'acquittement est passé de 427 à 428, soit +1. Sur le même principe qu'avec le flag SYN lors de l'initialisation de la connexion TCP, le flag FIN implique que le numéro d'acquittement soit incrémenté de 1.

Le paquet n°10 est envoyé dans la foulée et il contient les flags "FIN + ACK" : le client indique au serveur qu'il est d'accord pour que la connexion TCP soit fermée. Effectivement, pour qu'une connexion TCP soit correctement fermée, il faut un accord des deux hôtes.

Le paquet n°11 est la confirmation de la part du serveur : la connexion TCP doit être fermée des deux côtés. Il est intéressant de voir que le numéro de séquence est passé à "428" puisqu'il suit le numéro d'acquittement du client. Quant au numéro d'acquittement envoyé par le serveur, il est passé de 369 à 370, ce qui est normal puisque le segment TCP émit par le client contient le flag "FIN".

Voilà, nous venons d'analyser un échange HTTP entre deux hôtes basés sur une connexion TCP, avec le fonctionnement des numéros de séquence et d'acquittement. Enfin, j'ai encore des choses à vous dire au sujet du numéro de séquence.

IV. TCP et le numéro de séquence initial (ISN)

Si l'on se réfère aux informations affichées par Wireshark, on pourrait croire que le numéro de séquence débute à 0 sur chacun des deux hôtes. C'est aussi ce que je vous ai dit, mais en fait, cela est faux !

Le numéro de séquence relatif (comme il est appelé dans Wireshark) est positionné à 0 pour faciliter la lecture et la compréhension lorsqu'un humain analyse la capture de paquets. En réalité, chaque hôte s'appuie sur un ISN, pour Initial Sequence Number, en français numéro de séquence initial, comme première valeur pour le numéro de séquence.

Ce numéro de séquence initial est généré aléatoirement par chaque hôte. Si l'on sélectionne les deux premiers paquets de notre trace ouverte dans Wireshark, et que l'on regarde l'en-tête TCP, on peut récupérer la valeur de l'ISN en regardant le champ "Sequence Number (raw)".

Voici l'ISN du client (en haut) et l'ISN du serveur (en dessous).

Wireshark - TCP : le numéro de séquence initial (ISN)
Wireshark - TCP : le numéro de séquence initial (ISN)

Cet ISN est codé sur 4 octets (32 bits), comme on peut le voir sur la copie d'écran ci-dessous.

L'objectif de ce numéro de séquence initial est d'éviter les conflits, les erreurs et les superpositions entre les connexions TCP.

En cas de plantage complet de l'un des deux hôtes liés par une connexion TCP, cela permet d'être sûr qu'une nouvelle connexion TCP sera initialisée si les deux hôtes cherchent à communiquer ensemble lorsque l'hôte HS est de nouveau opérationnel. Sinon, il pourrait y avoir comme une sorte d'incompréhension entre les deux hôtes : un hôte cherche à établir une nouvelle connexion, tandis que l'autre croit que c'est toujours la connexion précédente qui est en cours. Grâce au numéro ISN généré aléatoirement, les probabilités de retrouver les mêmes numéros de séquence sont faibles.

La vérité au sujet du numéro de séquence étant rétablie, je peux publier cet article l'esprit tranquille. 😉

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Florian BURNEL

Ingénieur système et réseau, cofondateur d'IT-Connect et Microsoft MVP "Cloud and Datacenter Management". Je souhaite partager mon expérience et mes découvertes au travers de mes articles. Généraliste avec une attirance particulière pour les solutions Microsoft et le scripting. Bonne lecture.

Nombre de posts de cet auteur : 5500.Voir tous les posts

5 thoughts on “Le suivi d’une connexion TCP avec Wireshark

  • Bonjour.
    Autodidacte, je suis vos cours très bien expliqués. Merci pour ce cours sur le fameux Wireshark.

    Bravo.

    Répondre
  • A chaque fois que je vois un article super intéressant, il est signé Florian Burnel. Bravo à lui !!!!! 🙂

    Répondre
  • Bonjour et merci pour l’article.
    Sur le schéma du paragraphe III C, la dernière flèche correspondant au segment 11 indique FIN+ACK, or si j’ai bien suivi, je pense qu’elle devrait indiquer seulement ACK.

    Répondre

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.