Как правило, обнаружение максимальной единицы передачи в тракте (PMTUD) происходит всякий раз, когда хост считает, что пакет был отброшен из-за его слишком большого размера.
Это может быть ответом на запрос требуемой фрагментации ICMP (тип 3, код 4), явно указывающий, что пакет был отброшен. В обычной практике все пакеты IPv4 устанавливаются с установленным флагом «не фрагментировать» (DF), поэтому любой пакет, превышающий MTU, вызовет такой ответ. IPv6 вообще не поддерживает фрагментацию.
Некоторые маршрутизаторы или межсетевые экраны хоста часто сбрасывают все ICMP, потому что наивный администратор считает ICMP угрозой безопасности . Или, некоторые схемы агрегации ссылок могут нарушить доставку ICMP . Был превышен альтернативный механизм обнаружения MTU, который не зависит от ICMP, предложенный в RFC4821 .
tracepath
мой любимый инструмент Linux для исследования MTU. Вот пример с хоста с 9001 MTU в локальной сети, но который должен пройти через IPsec VPN, чтобы достичь 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]
Ошибки ICMP можно наблюдать при 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
Открытия MTU кэшируются. В Linux это можно наблюдать и очищать ip
(остерегайтесь изменений после 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
Для TCP превышение MTU можно избежать как часть настройки соединения. В SYN, отправляемый каждым концом, включен максимальный размер сегмента (MSS). Заголовок TCP (20 байтов без учета опций ) и заголовок IP (20 байтов) означают MSS и MTU, связанные разницей в 40 байтов.
Вот пример настройки соединения между этими двумя хостами при передаче большого файла с помощью 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
В первом пакете локальный хост предлагает MSS 8961. Это настроенный MTU 9001, меньше 40 байтов. Возвращенный SYN / ACK имеет MSS 1379, что означает MTU 1419. Я знаю, что в этой сети удаленный хост также отправил 8961, но значение было изменено маршрутизатором, так как он знает, что путь включает в себя интернет-путь ( MTU 1500) служебная информация из туннеля IPsec. Этот маршрутизатор также изменил нашу отправленную MSS 8961, чтобы появиться как 1419 на другом хосте. Это называется зажимом MSS .
Таким образом, в некотором смысле, PMTUD происходит все время. На практике это может фактически никогда не случиться, если ограничение MSS на месте и весь трафик происходит по TCP, или если ни один из маршрутизаторов не имеет MTU меньше, чем настроено на конечных точках. Даже без ограничения MSS это может происходить очень редко, когда срок действия кэша истекает.