Фрагментация и размер пакета, используя tcpdump
Я пытаюсь понять концепцию фрагментации:
У меня есть две виртуальные машины с публичным IP-адресом, подключенным к коммутатору.
tracepath показывает, что пакет не проходит через шлюз
из vm1: Попытка отправить icmp с 65507 байтами в vm2.
ping -M want -s 65507 vm2
но в выводе tcpdump на vm2: его показ
tcpdump -evvv icmp
12:48:44.635551 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 1480, flags [+], proto ICMP (1), length 1500)
VM1 > VM2: icmp
12:48:44.635568 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 2960, flags [+], proto ICMP (1), length 1500)
VM1 > Vm2: icmp
12:48:44.635572 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 4440, flags [+], proto ICMP (1), length 1500)
VM1>VM2 icmp
12:48:44.635575 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 5920, flags [+], proto ICMP (1), length 1500)
VM1>VM2: icmp
12:48:44.635578 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 7400, flags [+], proto ICMP (1), length 1500)
**Vm1 > VM2**: icmp
12:48:44.635581 42:43:30:b4:89:0c (oui Unknown) > b6:7a:6b:7d:54:32 (oui Unknown), ethertype IPv4 (0x0800), length 1514: (tos 0x0, ttl 64, id 10843, offset 8880, flags [+], proto ICMP (1), length 1500)
Это повторяется 31 раз, пока не будет получено полностью. полная вставка: http://pastebin.com/cnQhn8dK
Так почему же получается, что общее количество полученных данных составляет 1500*31=46500 байт, а то, что случилось с 65507-46500=19007 байт.
Может кто-нибудь, пожалуйста, уточнить это.
2 ответа
Да, используя tcpdump с опцией -s, результат теперь правильный. В качестве вашего результата мы считаем 45 пакетов. 44 пакета с 1500 байтами, 1 пакет 415 байтов.
44 * 1500 + 415 = 66415
66415 - 65507 = 908
908/45 = 20 плюс 8
Как видите, к каждому пакету добавляется 20 байтов для заголовка ip + 8 байтов для заголовка icmp для первого пакета.
Просто чтобы добавить ответ Gnouc.
Вы отправляете 65507
байты данных. Это не включает заголовки ICMP, которые составляют 8 байтов.
Самый распространенный размер MTU 1500
, Этот размер соответствует размеру уровня 3, поэтому вы видите ethertype IPv4 (0x0800), length 1514:
Это означает, что общий размер кадра на самом деле составляет 1514 байт. Эти 14 байтов составляют заголовок Ethernet. 12 байтов на mac-адрес + 2 для типа.
Минимальным и очень распространенным размером для заголовка IP является его минимальный размер 20 байтов (максимальный - 60 байтов).
Итак, мы имеем
1514 bytes - Ethernet header = 1500 bytes
1500 - IP header = 1480 bytes
1480 - ICMP header = 1472 bytes
Вы можете отправить максимум 1472 байта без фрагментации.
НО способ, которым IP фрагментирует пакеты, не требует отправки заголовка для каждого пакета, а только для первого пакета.
С фрагментацией максимальное количество байтов, которое вы можете отправить с MTU 1500, составляет 1480 байтов.
Мы знаем общий размер ваших данных и максимальный размер, который вы можете отправить.
Так что это займет как минимум 65507 / 1480 ~= 44.2 packets
, Т.е. 44 пакета по 1514, а затем окончательный пакет размером менее половины.
Что случилось с остальными пакетами?
Но почему 31 пакет? Ну, это все в размере буфера, который вы захватываете. В конце вашего tcpdump вы должны увидеть
31 packets captured
57 packets received by filter
14 packets dropped by kernel
Если вы добавите захваченные пакеты + пакеты, отброшенные ядром, вы получите правильный ответ, и вот что -s
это изменяет длину привязки.
Из руководства по tcpdump
-s Snarf Snaplen байтов данных из каждого пакета, а не по умолчанию 65535 байтов. Пакеты, усеченные из-за ограниченного снимка, указываются в выходных данных ``[|proto]'', где proto - это имя уровня протокола, на котором произошло усечение. Обратите внимание, что создание больших моментальных снимков увеличивает время обработки пакетов и фактически уменьшает объем буферизации пакетов. Это может привести к потере пакетов. Вы должны ограничить snaplen наименьшим числом, которое будет захватывать интересующую вас информацию о протоколе. При установке snaplen в 0 устанавливается значение по умолчанию 65535 для обратной совместимости с последними более старыми версиями tcpdump.
Почему ядро отбросило пакеты в первую очередь?
Снова из справочной страницы tcpdump
пакеты, отброшенные ядром (это количество пакетов, которые были отброшены из-за недостатка места в буфере механизмом захвата пакетов в ОС, в которой работает tcpdump, если ОС сообщает эту информацию приложениям; если нет, то будет сообщено как 0).