Quand exactement PMTUD est-il exécuté? (Découverte de Path MTU)

21

Dans les discussions qui ont découlé d' autres questions sur ce site , je me suis rendu compte que je ne comprenais pas bien quand Path MTU Discovery (PMTUD) était effectué.

Je sais ce qu'il fait - découvrez le MTU le plus bas sur un chemin allant du client au serveur).
Je sais comment cela fonctionne: envoyez des paquets de plus en plus gros avec leur ensemble de bits "Ne pas fragmenter" et voyez la taille d'un paquet que vous pouvez passer sans obtenir une erreur "Besoin de fragmentation ICMP".

Ma question est alors précisément, quand un hôte effectuera-t-il PMTUD?

Je recherche des cas spécifiques. Pas seulement quelque chose de générique comme "quand un hôte veut découvrir le chemin MTU". Points bonus si vous pouvez fournir une capture de paquets d'un hôte en train de le faire, ou fournir des instructions pour générer une telle capture de paquets.

En outre, je me réfère spécifiquement à IPv4. Je sais que les routeurs transitoires IPv6 ne sont pas responsables de la fragmentation, et je peux imaginer que PMTUD se produit beaucoup plus fréquemment. Mais pour l'instant, je recherche des exemples spécifiques de PMTUD dans IPv4. (bien que si la seule capture de paquets que vous pouvez assembler de PMTUD soit en IPv6, j'aimerais toujours le voir)

Eddie
la source
Le PMTUD est-il effectué du MTU pris en charge le plus bas au plus élevé? Ou l'appareil exécutant PMTUD essaie-t-il le plus grand MTU en premier, puis diminue-t-il par un grand incrément jusqu'à ce que le paquet passe, puis augmente-t-il par petits incréments, puis alterne-t-il jusqu'à ce qu'une décision finale soit prise?
cpt_fink
@cpt_fink, il existe quelques stratégies. Les implémentations modernes du message ICMP Fragmentation Needed incluent dans la charge utile ICMP elle-même le MTU du lien pour lequel la fragmentation était requise. Cela facilite les choses, car l'hôte de départ sait tout de suite quel est le chemin MTU. Les implémentations plus anciennes doivent utiliser diverses stratégies pour «rechercher» le bon MTU à utiliser. Ces stratégies sont décrites dans la RFC1191 de la section 5. Elles vont de la valeur par défaut automatique à IP Minimum (576), à l'utilisation d'un tableau de MTU «communs» pour rechercher plus efficacement (voir RFC1191 section 7.1).
Eddie
2
C'est une question intéressante. Je faisais des recherches sur PMTUD et j'ai trouvé cela. Même si c'est vieux, j'ai décidé de répondre parce que j'avais exactement la même question et après quelques heures de recherche, je pourrais trouver une réponse assez décente (je suppose). J'essaierai de mettre à jour et de soutenir ma réponse avec une capture de paquets demain, si possible.
Filipe Gonçalves

Réponses:

15

La réponse est simple: chaque fois que l'hôte le souhaite. Vraiment. C'est si simple.

L'explication ci-dessous suppose un environnement IPv4 uniquement, car IPv6 supprime la fragmentation des routeurs (forçant l'hôte à toujours gérer la fragmentation et la découverte MTU).

Il n'y a pas de règle stricte qui régit quand (ou même si) un hôte effectue la découverte Path MTU. La raison pour laquelle PMTUD a fait surface est que la fragmentation est considérée comme nuisible pour diverses raisons. Pour éviter la fragmentation des paquets, le concept de PMTUD a été concrétisé comme solution de contournement. Bien sûr, un bon système d'exploitation devrait utiliser PMTUD pour minimiser la fragmentation.

Ainsi, naturellement, la sémantique exacte de l'utilisation de PMTUD dépend du système d'exploitation de l'expéditeur - en particulier, de l'implémentation du socket. Je ne peux parler que pour le cas spécifique de Linux, mais les autres variantes UNIX ne sont probablement pas très différentes.

Sous Linux, PMTUD est contrôlé par l' IP_MTU_DISCOVERoption socket. Vous pouvez récupérer son état actuel avec getsockopt(2)en spécifiant le niveau IPPROTO_IPet l' IP_MTU_DISCOVERoption. Cette option est valide pour les SOCK_STREAMsockets uniquement (un SOCK_STREAMsocket est un socket fiable, orienté connexion et bidirectionnel; en pratique, c'est un socket TCP, bien que d'autres protocoles soient possibles), et lorsqu'il est défini, Linux exécutera PMTUD exactement comme défini dans RFC 1191.

Notez que dans la pratique, le PMTUD est un processus continu; les paquets sont envoyés avec le jeu de bits DF - y compris les paquets de prise de contact à 3 voies - vous pouvez le considérer comme une propriété de connexion (bien qu'une implémentation puisse accepter un certain degré de fragmentation à un moment donné et arrêter d'envoyer des paquets avec le DF ensemble de bits). Ainsi, PMTUD n'est qu'une conséquence du fait que tout sur cette connexion est envoyé avec DF.

Et si vous ne vous asseyez pas IP_MTU_DISCOVER?

Il y a une valeur par défaut. Par défaut, IP_MTU_DISCOVERest activé sur les SOCK_STREAMsockets. Cela peut être lu ou modifié en lisant /proc/sys/net/ipv4/ip_no_pmtu_disc. Une valeur nulle signifie qu'elle IP_MTU_DISCOVERest activée par défaut dans les nouveaux sockets; un non nul signifie le contraire.

Qu'en est-il des prises sans connexion?

Ceci est délicat car les sockets sans connexion et non fiables ne retransmettent pas les segments perdus. Il incombe à l'utilisateur de regrouper les données en morceaux de taille MTU. De plus, l'utilisateur doit effectuer les retransmissions nécessaires en cas d' erreur de message trop importante . Ainsi, le code utilisateur doit essentiellement réimplémenter PMTUD. Néanmoins, si vous êtes prêt à relever le défi, vous pouvez forcer le bit DF en passant le IP_PMTUDISC_DOdrapeau à setsockopt(2).

Le résultat

  • L'hôte décide quand (et si) utiliser PMTUD
  • Lorsqu'il utilise PMTUD, c'est comme un attribut de connexion, cela se produit en continu (mais à tout moment, l'implémentation est libre de cesser de le faire)
  • Différents systèmes d'exploitation utilisent des approches différentes, mais généralement, les sockets fiables et orientés connexion exécutent PMTUD par défaut, tandis que les sockets peu fiables et sans connexion ne le font pas
Filipe Gonçalves
la source
4

En règle générale, la découverte d'unité de transmission maximale de chemin (PMTUD) se produit chaque fois qu'un hôte pense qu'un paquet a été abandonné en raison de sa trop grande taille.

Cela peut être en réponse à la fragmentation ICMP requise (type 3, code 4) réponse indiquant explicitement que le paquet a été abandonné. Dans la pratique courante, tous les paquets IPv4 sont définis avec l'indicateur "ne pas fragmenter" (DF), de sorte que tout paquet dépassant la MTU provoquera une telle réponse. IPv6 ne prend pas du tout en charge la fragmentation.

Certains routeurs ou pare-feu hôtes suppriment souvent tous les protocoles ICMP car un administrateur naïf estime que les protocoles ICMP constituent un risque pour la sécurité . Ou, certains schémas d'agrégation de liens peuvent interrompre la livraison ICMP . Un autre mécanisme pour découvrir le MTU a été dépassé qui ne repose pas sur ICMP est proposé dans la RFC4821 .

tracepathest mon outil Linux préféré pour sonder MTU. Voici un exemple d'un hôte avec un MTU 9001 sur le LAN, mais qui doit traverser un VPN IPsec pour atteindre 10.33.32.157:

$ tracepath -n 10.33.32.157
 1?: [LOCALHOST]                                         pmtu 9001
 1:  10.1.22.1                                             0.122ms pmtu 1500
 1:  169.254.3.1                                           1.343ms pmtu 1422
 1:  10.255.254.61                                        23.790ms 
 2:  no reply
^C [this host won't return an ICMP port unreachable, so tracepath won't terminate]

Les erreurs ICMP peuvent être observées avec tcpdump:

$ sudo tcpdump -p -ni eth0 'icmp and icmp[0] == 3 and icmp[1] == 4'
14:46:57.313690 IP 10.1.22.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1500), length 36
14:46:57.315080 IP 169.254.3.1 > 10.1.22.194: ICMP 10.33.32.157 unreachable - need to frag (mtu 1422), length 556

Les découvertes MTU sont mises en cache. Sous Linux, cela peut être observé et vidé ip(attention aux changements depuis Linux 3.6 ):

$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache  expires 591sec mtu 1422
$ sudo ip route flush cache
$ ip route get 10.33.32.157
10.33.32.157 via 10.1.22.1 dev eth0  src 10.1.22.194 
    cache

Pour TCP, le dépassement du MTU peut être évité dans le cadre de la configuration de la connexion. La taille maximale de segment (MSS) est incluse dans le SYN envoyé par chaque extrémité. L'en-tête TCP (20 octets hors options ) et l'en-tête IP (20 octets) signifient que MSS et MTU sont liés par une différence de 40 octets.

Voici un exemple de configuration de connexion entre ces deux hôtes lors du transfert d'un gros fichier avec scp:

$ sudo tcpdump -p -ni eth0 'host 10.33.32.157 and tcp[13]&2 == 2'
IP 10.1.22.194.45853 > 10.33.32.157.22: Flags [S], seq 634040018, win 26883, options [mss 8961,sackOK,TS val 10952240 ecr 0,nop,wscale 7], length 0
IP 10.33.32.157.22 > 10.1.22.194.45853: Flags [S.], seq 1371736848, ack 634040019, win 26847, options [mss 1379,sackOK,TS val 10824267 ecr 10952240,nop,wscale 7], length 0

Dans le premier paquet, l'hôte local propose un MSS de 8961. Il s'agit du 9001 MTU configuré, moins 40 octets. Le SYN / ACK retourné a un MSS de 1379, ce qui implique un MTU de 1419. Il se trouve que dans ce réseau, l'hôte distant a également envoyé 8961, mais la valeur a été modifiée par un routeur car il sait que le chemin comprend un chemin Internet ( MTU 1500) une surcharge d'un tunnel IPsec. Ce routeur a également modifié notre MSS envoyé de 8961 pour apparaître comme 1419 sur l'autre hôte. C'est ce qu'on appelle le serrage MSS .

Donc, dans un sens, PMTUD se produit tout le temps. En pratique, cela peut en fait ne jamais se produire, si le serrage MSS est en place et que tout le trafic se produit via TCP, ou si aucun des routeurs n'a une MTU plus petite que celle configurée sur les points de terminaison. Même sans serrage MSS, cela ne peut se produire que rarement, lorsque le cache expire.

Phil Frost
la source