mardi 29 mars 2016

Acquittements sélectifs (SACK)

Contexte


Dans la présentation du protocole TCP, nous avons vu que les acquittements sont cumulatifs.
Par conséquent, la pile TCP ne peut acquitter qu'une suite continue d'octets. Le problème se pose si un segment est perdu et que les suivants arrivent à destination.

De plus, la pile TCP ne peut pas transmettre à l'application les données reçues avec des « trous », de par le modèle de flux d'octet.

Perte du premier segment dans un burst TCP


Que faire des segments 20 à 23 pour le récepteur ? De même, quelle stratégie de retransmission à appliquer pour l'émetteur des données ?
Car d'après la RFC 793, aucun des segments n'aura été reçu du point de vue de l'émetteur. En effet, le récepteur des données devra acquitter en premier le segment 19 (ci­-dessus) qui a été perdu.
Le risque est que l'émetteur retransmette les segments 19 à 23.

Le mécanisme d'acquittement sélectif (« Selective Acknowledgement » ou SACK) permet de répondre à cette problématique.
Le destinataire des données peut indiquer à l'émetteur quels sont les segments reçus, et ainsi permettre à ce dernier de ne retransmettre que les segments manquants.

Fonctionnement


La RFC 2018 définit 2 options.

La première permet d'indiquer au destinataire que l'émetteur implémente cette fonctionnalité. Le type est 0x04 et de longueur 2 (octets).

Elle ne peut être envoyée que lors de l'établissement de la connexion (Lorsque le drapeau SYN est activé).



La deuxième option informe l'émetteur de l'existence de blocs de données non contigus dans les segments reçus.

L'option liste tous les blocs reçus valides (contenus dans la fenêtre de réception) et isolés dans le flux d'octets. Pour N éléments dans la liste, la longueur de cette option est N*8+2.



Chaque bloc est constitué de 2 entiers non signés de 32 bits :

• celui de gauche indique le premier numéro de séquence de ce bloc.

• celui de droite indique le prochain numéro de séquence après ce bloc.

Chaque bloc constitue un ensemble d'octets reçus, contigus et isolés dans la fenêtre de réception. Les octets juste autour de ce bloc n'ont pas été reçus.

Dans la mesure où l'en­-tête TCP ne peut pas avoir une longueur supérieure à 60 octets, il ne peut y avoir que 4 éléments dans la liste, au maximum. Dans la pratique, avec l'utilisation des timestamps, ce nombre est plutôt de 3 au maximum.

Il est à noter que le champ d'acquittement dans l'en­tête ne change pas de signification, il pointe toujours vers le premier octet attendu dans la fenêtre de réception. Dans l'exemple ci-­dessus, le champ ACK pointe toujours vers le segment 19.

N.B. : cette option est uniquement informative, elle n'engage pas le récepteur à garder ces blocs de données.
Ce dernier peut notifier l'émetteur au moyen de l'option SACK et quand même supprimer ces blocs de ses files d'attente (par manque de mémoire), même si cela n'est pas recommandé.
Toutefois, à part le dernier segment reçu isolé, le récepteur des données ne doit pas signaler de blocs de données supprimés.

Règles d'envoi de l'option SACK


• Le destinataire de cette option doit avoir indiqué son acceptation lors de l'établissement de la connexion.

• Chaque segment d'acquittement (avec le drapeau ACK activé) peut contenir l'option SACK. Par contre, le premier bloc de la liste doit contenir les numéros de séquence du dernier segment reçu.

• Le destinataire des données devrait lister autant de blocs de données qu'il est nécessaire. Néanmoins, cette liste peut être tronquée par les limites de la taille maximale de l'en­tête.

• La liste des blocs devrait être remplie dans l'ordre inverse d'ancienneté (le plus récent d'abord). Ce qui assure à chaque bloc d'être transmis au moins 3 fois (4 sans timestamps) si nécessaire.


L'idée principale est d'indiquer à l'émetteur des données l'état le plus récent de la fenêtre de réception du destinataire.
De plus, ces segments d'acquittement SACK peuvent être perdus eux aussi. Le fait de transmettre chaque bloc au moins 3 fois diminue le risque qu'un bloc ne soit pas signalé à l'émetteur des données.


Exemple d'envoi de plusieurs blocs SACK
Exemple d'envoi de plusieurs blocs SACK
Dans l'exemple ci-dessus, le récepteur des données (10.8.0.22) indique à l'émetteur qu'il se retrouve avec un bloc isolé de données (paquet n° 131) puis avec un deuxième (paquet n° 132).
A noter que le premier bloc (n° 132) fait référence au dernier segment reçu (paquet n° 130).


Stratégie de retransmission


L'émetteur des données est supposé tenir à jour une liste des segments à retransmettre (les segments qui n'ont toujours pas été acquittés).

En cas de réception de l'option SACK, les segments concernés sont mis à part. Par exemple, avec l'utilisation d'un drapeau SACK qui indique la bonne réception par le destinataire.

Ce mécanisme permet de déterminer les segments à retransmettre, sans attendre l'expiration du temps d'attente (« retransmit timeout »).

Toutefois, en cas d'expiration de ce temps d'attente, tous les segments de cette liste, marqués ou non, sont considérés comme perdus et doivent être retransmis.

N'oublions pas que cette option SACK est informative. Le récepteur des données peut, pour des raisons diverses, ne pas avoir gardé en mémoire les segments déclarés dans l'option SACK.

Avec ou sans cette fonctionnalité SACK, LA seule façon d'enlever un segment de cette liste de retransmission, est que le récepteur des données ait acquitté ce segment grâce au champ d'acquittement dans l'en­tête TCP.


Toutes les copies écrans sont issues du logiciel d'analyse réseau de Comoe Networks.

mardi 15 mars 2016

Les options TCP


Les options ont plusieurs objectifs :

• Lors de l'établissement de la connexion, elles permettent de définir les capacités de la pile TCP implémentée (Selective Acknowledgement, Window Scale, ...) ainsi que les conditions de transmission (Maximum Segment Size, ...).

• Elles permettent aussi de fournir des moyens supplémentaires de correction d'erreurs (Selective Acknowledgement par exemple).

• Enfin, elles peuvent fournir des moyens supplémentaires pour améliorer la sécurité ou estimer la latence (Timestamps par exemple).

Les options sont de longueur variable et sont intégrées dans le checksum TCP. Elles se trouvent entre l'en-tête fixe et les éventuelles données.

La RFC 793 définit 3 options qui doivent être obligatoirement implémentées par toute pile TCP. Toutes les options sont répertoriées par l'IANA.

L'URL actuelle est ici. Elle peut changer, donc le mieux est d'utiliser l'outil de recherche de l'IANA avec les mots clés 'tcp parameter' (ou dans votre moteur de recherche favori).

Format des options


Il existe 2 formats pour les options :

• 1 seul octet pour l'option, qui correspond au code associé.

• un format TLV (Type/Longueur/Valeur) de longueur variable :

Type (1 octet) -Longueur (1 octet) -Données (variable)

La longueur inclut également les 2 octets pour le champ Type et le champ Longueur.

Les options standards à un seul octet


L'option « Fin d'option (End of Option List) » dont le code est 0x00. Elle n'est nécessaire que si la fin des options ne coïncide pas avec la longueur de l'en-tête. Elle se trouve uniquement à la fin de toutes les options.

L'option « Pas d'opération (No­ Operation) »  dont le code 0x01. Cette option est principalement utilisée pour aligner la longueur de l'en­tête sur des mots de 32 bits.
En effet, la longueur de l'en-­tête est donnée en mots de 32 bits.

L'option Maximum Segment Size (MSS)


Pour rappel, la taille maximale d'un datagramme (MTU) IPv4 DEVANT être accepté est de 576 octets (RFC 791).

Par conséquent, un hôte ne doit pas envoyer un segment avec une taille supérieure à 576 octets, à moins d'avoir la certitude que le destinataire acceptera de tels segments.

Dans le cas d'une fragmentation, la taille totale du datagramme réassemblé peut dépasser cette limite, mais chaque fragment doit respecter cette limite.

D'où l'intérêt de l'option MSS :

L'option « Taille maximale du segment » (Maximum Segment Size ou MSS) définit la longueur maximale des données dans un segment TCP acceptée par l'émetteur de cette option (RFC 793, 879 et 6691).

Cette option ne peut être envoyée qu'avec le drapeau SYN activé, par conséquent, uniquement lors de l'établissement de la connexion.

Son code est 0x02 et sa longueur fixe est de 4 octets (la valeur est codée sur 16 bits).

Il y a eu beaucoup de débat sur cette valeur (RFC 879, 6691, 1122) et, en particulier, sur comment la définir. Faut il prendre en compte les options qui peuvent ne pas être présentes ou non ?

Au départ, rien n'est spécifié (RFC 793). Puis, devant les incertitudes soulevées, la RFC 879 nous dit ceci :

THE TCP MAXIMUM SEGMENT SIZE IS THE IP MAXIMUM DATAGRAM SIZE MINUS FORTY

Donc, on enlève 40 octets à la MTU, sans être réellement sûr de savoir à quoi correspond ce chiffre.
Dans un souci de clarifier une bonne fois pour toute, la RFC 6691 nous donne la formule pour le calcul de cette valeur :

MSS = MTU – taille en­tête IP (sans options) – taille en­tête TCP (sans option).

Par contre, l'émetteur doit prendre en compte la taille des options pour calculer la taille du segment à envoyer.


Options TCP présentes lors de l'ouverture d'une connexion
Exemple d'options présentes lors de l'ouverture d'une connexion


Voilà pour les options définies par la RFC 793, nous verrons les autres options dans des articles dédiés.

mardi 16 février 2016

Connexions TCP


TCP est un protocole orienté connexion. Contrairement à UDP par exemple, il est nécessaire d'établir une connexion avant de pouvoir échanger des données.

Cette phase a pour but d'initialiser différents paramètres comme le numéro de séquence initial (ISN), la taille maximale de segment (MSS), ou le support de certaines implémentations (SACK, Window scaling, ...).

Le drapeau SYN est utilisé lors de cette phase appelée "Three Way Handshake".

De même, une fois le transfert de données terminé, il est nécessaire de fermer la connexion entre les 2 hôtes. Le drapeau FIN est utilisé à cette fin lors de cette phase appelée "Four Way Handshake".

Comme indiqué dans l'article d'introduction sur TCP, une connexion TCP entre 2 hôtes est définie de manière unique par le couple de "socket" (terme popularisé par l'université de Berkeley).

Établissement de la connexion


Regardons de plus près l'établissement d'une connexion TCP :

Etablissement d'une connexion TCP - Comoe Networks

  1. Le client initie la communication en envoyant un segment dont le drapeau SYN est activé (couramment appelé segment SYN). Il transmet par la même occasion son ISN, qui sera le numéro de séquence de référence pour le transfert de données dans le sens client vers serveur. De même, il indique ses conditions et ses capacités dans les options.
  2. Le serveur envoie alors son segment SYN, dans lequel il confirme avoir bien reçu l'ISN du client ainsi que ses capacités. Il envoie également son ISN ainsi que ses capacités.
  3. Le client confirme avoir bien reçu le segment SYN du serveur. Le transfert de données peut commencer.
Dans la mesure où l'établissement de la connexion doit être aussi fiable que le transfert de données, le drapeau SYN compte pour un octet dans les numéros de séquence.

On peut voir ici la capture de l'établissement d'une connexion avec le logiciel d'analyse réseau de Comoe Networks.
Etablissement d'une connexion TCP - analyse réseau Comoe Networks
Établissement d'une connexion TCP

Terminaison de la connexion


N'importe quel hôte peut fermer la connexion, ce n'est pas forcément le client. Cela dépend plutôt de l'application de la couche supérieure qui utilise le service TCP.
Il est même possible d'avoir une clôture simultanée, même si dans la pratique, c'est plutôt rare.

Terminaison d'une connexion TCP - Comoe Networks
Terminaison classique d'une connexion TCP
  1. L'hôte qui souhaite indiquer la fin de l'envoi de données (dans une situation normale), le signale en envoyant un segment avec le drapeau FIN (couramment appelé segment FIN).
  2. Son correspondant envoie un segment ACK pour confirmer la réception du segment FIN.
  3. Son correspondant envoie lui aussi un segment FIN pour signaler qu'il n'a plus de données à envoyer.
  4. L'hôte envoie un segment ACK à son correspondant pour confirmer la réception de son segment FIN.
De la même façon, pour confirmer la bonne réception du segment FIN, ce dernier compte pour un octet dans les numéros de séquence.

Note : les étapes 1 et 2 n’entraînent pas obligatoirement les étapes 3 et 4 dans la foulée. Le segment FIN indique juste que son émetteur n'a plus de données à envoyer. Le destinataire de ce segment peut lui avoir encore des données à transmettre.

De la même façon, on peut suivre le déroulement de la fermeture d'une connexion TCP ci-dessous :

Fermeture d'une connexion TCP - Comoe Networks
Fermeture d'une connexion TCP


Pour l'hôte qui a initié la terminaison de la connexion, comment savoir que le correspondant a bien recu le segment de l'étape 4 ci-dessus ?

Dans la pratique, c'est impossible. C'est pourquoi il est instauré un temps d'attente durant lequel, la socket sur cet  hôte ne peut être fermée et reste dans l'état CLOSE_WAIT (sur Linux).
On peut le voir ci-dessous pour la connexion TCP/IPv6

root@LAB-NODE2:~# netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address             State     
tcp     0           136       192.168.43.1:22        192.168.43.254:42642    ESTABLISHED
tcp6   1           0           ::1:50516                    ::1:631                            CLOSE_WAIT


Nous verrons plus en détail cet aspect lorsque nous regarderons les différents états d'une connexion TCP.

Merci.

Toutes les copies écrans sont issues du logiciel d'analyse réseau de Comoe Networks.

lundi 1 février 2016

Le protocole TCP


Le standard a été défini par la RFC 793 en 1981. Il se situe dans la couche Transport du modèle OSI (niveau 4).
Il permet :
  • un transport fiable des données,
  • un multiplexage de plusieurs communications simultanées entre 2 machines,
  • un contrôle de flux afin de prévenir les congestions,
  • de les gérer si elles se produisent.
Il est « orienté connexion », car TCP nécessite qu'un certain nombre d'informations soient initialisées et maintenues au cours de la session.
En plus de la détection d'erreur, il est capable de les corriger en organisant la retransmission des segments défectueux ou manquants.

Regardons maintenant comment ces fonctionnalités sont implémentées.

En-tête TCP


Les données transportées par le protocole TCP sont précédées par un en­tête dans chaque segment.
La taille minimale de l'en­tête est de 20 octets (sans options) et au maximum 60 octets. Sa longueur nous est donnée par le champs « Header Length » qui est le nombre de mots de 32 bits de l'en­tête.

L'en­tête doit être un multiple de mots de 32 bits, même avec les options (l'option « padding » est faite pour cela).

en-tête TCP
En-tête TCP


Multiplexage


Les champs « Port Source » et « Port Destination » permettent de spécifier le canal entre les 2 machines et permet plusieurs sessions entre ces 2 machines (multiplexage).

Dans la RFC 793, il est mentionné que le couple « Adresse IP – Port » sur une machine, est appelé « socket ».
Le service est full­-duplex, c'est à dire qu'il peut y avoir un transfert de données dans les 2 sens, indépendamment de l'autre sens.

Séquencement des données


Chaque octet des données à transmettre est numéroté. Codé sur 32 bits, Le numéro de séquence (SEQ) indique la position du premier octet de donnée du segment dans le flux.
Il permet aussi de déterminer les segments dupliqués et de réordonner les données pour la couche supérieure (IP ne garantit pas de transfert ordonné).

Lorsque le drapeau SYN est activé lors de l'établissement de la connexion, le numéro de séquence initial est appelé « ISN » (Initial Sequence Number). Par mesure de sécurité, il ne peut être le chiffre zéro (0), mais il est plutôt déterminé de façon aléatoire.

Le numéro d'acquittement (ACK) permet d'indiquer à l'émetteur le prochain numéro de séquence attendu, pour les numéros inférieurs, il indique ainsi qu'il a bien reçu les données.
Dans le cas contraire, les données manquantes seront retransmises.

On peut voir ici le transfert de données et son acquittement sur le logiciel d'analyse réseau de Comoe Networks.

Exemple de progression du numéro de séquence et de son acquittement
Exemple de progression du numéro de séquence et de son acquittement

Contrôle de flux


Dans le cadre du contrôle de flux, le destinataire des données indique à l'émetteur le nombre d'octet maximum qu'il est prêt à accepter, encore appelée fenêtre de réception.

Le champ « Window » permet de définir cette valeur, le drapeau « ACK » doit être positionné pour que ce champ soit valide.

L'émetteur ne peut alors pas envoyer plus de données que cette valeur sans recevoir d'acquittement.

Cette fenêtre peut changer au cours de la session, ce qui permet aux deux hôtes de pouvoir s'adapter au contexte du ou des réseau(x) utilisé(s).
On peut le voir ici avec la variation de la fenêtre de l'hôte 10.247.96.133 (en rouge).

variation de la fenêtre (Comoe Networks)
Variation de la fenêtre au cours de la connexion

Drapeaux


Il y a actuellement 8 drapeaux (« flags ») définis dans l'en­tête TCP, nous les verrons en détail au fil de notre exploration.
Mais voici une brève présentation :

  • CWR (congestion Window Reduced) : l'émetteur a réduit son taux d'emission,
  • ECE (Explicit Congestion Echo) : Réponse à un message de congestion ECN (Explicit Congestion Notification),
  • URG (Urgent Pointer) : Le champ « Urgent Pointer » est valide. Rarement utilisé,
  • ACK : Le champ « Acknowledgement Number » est valide,
  • PSH (Push) : les données de ce segment devrait être envoyées immédiatement à la couche suppérieure,
  • RST (Reset) : l'émetteur de ce drapeau clôt la connection et n'accepte plus de données,
  • SYN (Synchronisation) : Synchronise les numéros de séquence et l'envoi de certaines options,
  • FIN : l'émetteur de ce drapeau indique qu'il n'a plus de données à envoyer.

Autres


Le champ « Urgent Pointer » dont la valeur doit être ajoutée au champ « Sequence Number », indique la fin de la zone de données urgentes dans le segment. Cette zone doit être traitée en priorité par la couche supérieure.

Afin d'augmenter la fiabilité et la détection d'erreur, un checksum internet est utilisé. Il couvre l'en­-tête TCP et les données transportées, ainsi que quelques champs de l'en-­tête IP (les 2 adresses en particulier et le numéro de protocole tcp).


Fin de cette introduction, à suivre la gestion des connexions.