Network Education
КаталогГлоссарийПрогресс
Протокол IPv4
  1. 1Основы
  2. 2Формат пакета
  3. 3Классовая адресация
  4. 4Бесклассовая адресация
  5. 5Задачи на IP-адресацию
  6. 6ARP
  7. 7DHCP
  8. 8ICMP
  9. 9NAT
Каталог/Сетевые основы/Протокол IPv4/Формат пакета

Формат пакета

2Урок 2 из 9

О чём этот урок

Поля заголовка IPv4-пакета, механизм фрагментации и Path MTU Discovery. Демонстрация в Wireshark.

Ключевые выводы

  • Минимальный заголовок IPv4 — 20 байт (5 машинных слов); поле Options на практике не используется, и 100% современных пакетов имеют заголовок ровно 20 байт
  • TTL фактически является счётчиком прыжков: каждый маршрутизатор вычитает единицу, при достижении нуля пакет уничтожается — это защита от петель маршрутизации
  • Фрагментация — процессорно-затратная операция, которую следует избегать; механизм Path MTU Discovery с флагом DF позволяет определить максимальный размер пакета на всём маршруте
  • Header Checksum защищает только от случайных ошибок передачи, но не от умышленной модификации — это не цифровая подпись

Проверьте себя

Вопрос 1 из 6

Каков минимальный размер заголовка IPv4?

Вопрос 2 из 6

Что происходит с полем TTL при прохождении пакета через маршрутизатор?

Вопрос 3 из 6

Почему фрагментации IP-пакетов следует избегать?

Вопрос 4 из 6

Какую защиту обеспечивает поле Header Checksum?

Вопрос 5 из 6

Какой механизм позволяет определить максимальный размер пакета на всём маршруте без фрагментации?

Вопрос 6 из 6

Зачем нужно поле TTL, если маршрутизаторы и так выбирают правильный путь?

🔗Связанные уроки

🔗Смотрите также

Формат заголовка IPv4 и его обработкаCisco ICND1: основы сетей и Cisco IOS
→

Оба урока разбирают поля заголовка IPv4, фрагментацию и механизмы TTL/Protocol — в разных контекстах

Формат заголовка IPv6Протокол IPv6
→

Сравнение заголовков IPv4 и IPv6: упрощённая структура, Flow Label и отсутствие контрольной суммы в IPv6

ОсновыКлассовая адресация

Транскрипция

Все поля IPv4-заголовка выровнены по границе 32 бит (4 байта). Сделано это для того, чтобы процессорам было легче обрабатывать заголовки.

Машина работает с ноликами и единичками, но она не обрабатывает их по одному. Процессор берет сразу пачку бит и оперирует ими одновременно. Размер этой пачки определяет разрядность процессора. 32-разрядный процессор за один такт обрабатывает 32 бита, 64-разрядный -- 64 бита.

IPv4-пакеты выровнены по 32 битам именно для удобства обработки:

  • 32-разрядный процессор берет всю строчку заголовка целиком
  • 16-разрядный обрабатывает строчку по частям: сначала левую половину, потом правую
  • 8-битный берет по одному байту за раз: первые 8 бит, вторые 8 бит, третьи, четвертые

Все поля, как правило, выровнены и по границе 8 бит, так что даже 8-битный процессор сможет относительно легко работать с таким заголовком.

Пачку из 32 бит мы будем называть машинным словом.


Первое машинное слово

Поле Version (4 бита)

Первые 4 бита заголовка -- поле версии. В него можно вписать число от 0 до 15.

Краткая история версий:

Значение Протокол
0 Первая версия протокола IP (тогда ещё назывался TCP)
1 TCP версии 3
2 IP версии 2 (отдельно выделенный)
3 IP версии 3 (отдельно выделенный)
4 IPv4 -- тот, которым мы пользуемся до сих пор

Версии 0, 1, 2, 3 вы в продакшене не увидите никогда. Это были экспериментальные версии, которые не прижились -- меньше чем через пару месяцев выходила новая, и каждый раз говорили "нет, предыдущая плохая, давайте новую". Четвёртая версия устоялась.

Когда к вам приходит последовательность бит, обработчик Ethernet видит EtherType 0x0800 и передаёт данные обработчику IP. Тот смотрит на первые 4 бита: если там число 4 (двоичное 0100), значит это действительно IPv4-пакет.

Поле IHL -- Internet Header Length (4 бита)

У IPv4 есть фиксированные поля заголовка и необязательное поле Options. Поле IHL указывает размер всего заголовка, включая опции.

Минимальный заголовок -- 5 машинных слов (5 строчек по 32 бита = 20 байт). Меньше 20 байт заголовок IPv4 быть не может.

Максимальный заголовок -- ограничен 4 битами поля IHL. Максимальное значение 15, то есть 15 x 4 = 60 байт. Из них 20 байт -- штатные поля, и ещё до 40 байт может занимать поле опций.

В реальности поле Options никто особо не использует, поэтому в подавляющем большинстве пакетов заголовок будет ровно 20 байт.

Поля DSCP и ECN (6 + 2 бита)

Современные названия:

  • DSCP (Differentiated Services Code Point) -- 6 бит
  • ECN (Explicit Congestion Notification) -- 2 бита

Оба поля нужны для управления качеством обслуживания.

Изначально на месте этих двух полей было одно 8-битное поле -- Type of Service (ToS). Оно не имело строго определённого смысла: можно было что-нибудь туда записать, а узлы могли это читать и принимать решения о маршрутизации, а могли и не читать. По умолчанию туда не нужно было смотреть, и обычно туда писали восемь нулей.

Наиболее популярная реализация использовала только первые 3 бита для указания приоритета трафика (число от 0 до 7, где 7 -- самый важный). Остальные биты широкого распространения не получили.

Модель с Type of Service оказалась не очень жизнеспособной, поэтому 8-битное поле разбили на две части:

  • DSCP (6 бит) -- указывает, насколько важный трафик. Никто не гарантирует, что в это число кто-то будет заглядывать
  • ECN (2 бита) -- для управления перегрузками. Можно дать понять другой стороне, что с трафиком есть проблемы

Большинство узлов не смотрят ни в DSCP, ни в ECN. Просто игнорируют эти 8 бит и идут дальше.

Поле Total Length (16 бит)

Указывает суммарный размер IPv4-пакета: заголовок + опции + данные.

Зачем это нужно? Представьте: IPv4-пакет с 4 байтами полезной нагрузки (20 + 4 = 24 байта) приходит в Ethernet-кадре. Минимальный размер Ethernet-кадра -- 64 байта, полезная нагрузка -- минимум 46 байт. Значит, к 24 байтам IP-пакета добавляется мусор (padding), чтобы добить кадр до минимального размера.

Когда получатель получает такой кадр, обработчику IP передаётся 46 байт. По полю Total Length он понимает, что полезных из них только 24, а остальное -- мусор.

Максимум в 16 бит можно вписать 65 535 байт. Но далеко не любой узел способен принять пакет такого размера. Спецификация говорит, что любое устройство обязано поддерживать пакеты до 576 байт -- это минимальный MTU (Maximum Transmission Unit) на уровне IP.

На практике большинство современных систем поддерживают пакеты до 32 килобайт.


Четвёртое и пятое машинное слово: адреса

Source Address и Destination Address (по 32 бита)

Здесь всё просто: 32 бита адреса отправителя и 32 бита адреса получателя.

Эти поля не меняются при маршрутизации. Отправитель пишет свой IP и IP получателя. Как на почтовом конверте: от кого и кому. Вы не указываете, через какие промежуточные почтовые отделения пройдёт конверт.

То же самое и в IP-пакете: нигде не указываются IP-адреса или MAC-адреса промежуточных узлов. Промежуточная адресация работает на канальном уровне -- в Ethernet-кадре указывается MAC-адрес следующего маршрутизатора.

Да, в поле Options можно указать маршрутное пожелание, чтобы пакет прошёл через определённые маршрутизаторы, но в реальности этого не происходит.

Разумеется, всё это -- при отсутствии NAT. NAT будет менять адреса источника и получателя, но это отдельная тема.


Третье машинное слово: TTL, Protocol, Header Checksum

Поле Time to Live -- TTL (8 бит)

В это поле вписывается число, которое постоянно уменьшается. Пока оно не дошло до нуля -- пакет живёт. Дошло -- пакет "протух".

История поля. Первые маршрутизаторы работали очень медленно, обработка одного пакета могла занимать секунды. Поэтому в TTL хранилось время жизни пакета в секундах. Каждый маршрутизатор вычитал время обработки из этого поля. Но существовало правило: вычитать нужно минимум единицу.

Сегодня обработка пакета занимает ничтожно малое время, и хранить секунды бессмысленно. Поэтому каждый маршрутизатор просто вычитает единицу. Фактически это поле стало счётчиком прыжков (hops). В IPv6 его так и переименовали -- Hop Limit.

Зачем TTL нужен в современном мире? Для защиты от петель маршрутизации. Если два маршрутизатора по ошибке считают, что другой ближе к получателю, они начнут перекидывать пакет друг другу, как волейбольный мячик. Без TTL такой пакет бегал бы бесконечно. С TTL он рано или поздно обнулится, и маршрутизатор скажет: "Стоп, этот пакет протух -- стираем".

Кто формирует TTL? Отправитель. Он может вписать любое значение от 0 до 255:

  • 0 -- бессмысленно, пакет протух ещё при создании
  • 1 -- пакет не пройдёт ни через один маршрутизатор (но дойдёт до соседнего)
  • 64 -- достаточно для большинства маршрутов в интернете (реально между двумя узлами редко бывает больше 40 маршрутизаторов)
  • 128, 255 -- гарантированно дойдёт, но при петле будет дольше нагружать оборудование

Некоторые провайдеры ставят TTL в сторону абонента равным 1, чтобы тот не мог раздавать интернет через свой роутер -- маршрутизатор абонента вычтет единицу, получит 0, и пакет будет отброшен.

Поле Protocol (8 бит)

Указывает, что лежит внутри пакета -- какому обработчику передать данные после заголовка.

Основные значения:

Код Протокол
1 ICMP
6 TCP
17 UDP
47 GRE
50 ESP (IPsec)

Значения присваивает IANA (Internet Assigned Numbers Authority). Поскольку в 8 бит помещается всего 256 значений, от балды туда вписывать ничего нельзя.

Поле Header Checksum (16 бит)

Нужно для проверки целостности заголовка. Первые 4 бита (поле версии) позволяют быстро, но очень грубо определить, похоже ли это на IP-пакет -- вероятность случайного совпадения около 6%. Header Checksum даёт более надёжную проверку.

Используется алгоритм Internet Checksum:

  1. Разделить заголовок на 16-битные слова
  2. Сложить их все как числа
  3. Если результат больше 16 бит -- разбить его на 16-битные части и снова сложить
  4. Повторять, пока не останется одно 16-битное слово
  5. Вычесть результат из 0xFFFF (инвертировать)

Пример:

Данные:     45 00  00 2C  70 7E  00 00
Сумма:      1E4FF
Разбиваем:  0001 + E4FF = E500
Инверсия:   FFFF - E500 = 1AFF
Checksum:   0x1AFF

Проверка: если сложить оригинальные данные вместе с контрольной суммой, всегда должно получиться 0.

Механизм очень простой -- достаточно уметь складывать и вычитать. Он защищает от случайных ошибок (перевернулся бит по дороге), но не защищает от умышленных искажений -- злоумышленник легко пересчитает checksum. Это не электронно-цифровая подпись.

Этот же алгоритм используется в TCP и UDP -- потому он и называется Internet Checksum.


Второе машинное слово: фрагментация

Три поля: Identification, Flags и Fragment Offset. Все три используются для управления фрагментацией.

Что такое фрагментация

Фрагментация -- это разделение IP-пакета на несколько маленьких пакетов. Допустим, вы создали пакет размером 32 килобайта. Отправили его, ближайший маршрутизатор принял, а дальше нужно передать в Ethernet-интерфейс с MTU 1500 байт. Пакет не пролезает. Тогда маршрутизатор режет его на части.

При разрезании:

  • У первого фрагмента сохраняется оригинальный заголовок
  • Ко всем остальным фрагментам приделывается новый IP-заголовок
  • Каждый фрагмент становится отдельным IP-пакетом

Накладные расходы фрагментации:

  1. Нагрузка на процессор. Фрагментация выполняется на центральном процессоре, не ускоряется специальными схемами. Реальный пример: D-Link с 100-мегабитным каналом выдавал 70 Мбит/с, а после включения jumbo frames на внутреннем интерфейсе -- упал до 15 Мбит/с

  2. Дополнительные байты. Вместо одного пакета с одним заголовком вы получаете несколько, каждый со своим заголовком, Ethernet-заголовком, преамбулой, interframe gap

Вывод: избегайте фрагментации. Протокол IP умеет её выполнять, но это не значит, что стоит.

По поводу MTU в интернете: стандартные каналы сейчас -- 1500 байт (Ethernet). IP-пакет 1500 байт, вложение в IP -- 1480 байт, вложение TCP (MSS) без опций -- 1460 байт. Такие пакеты проходят нормально.

Если у провайдера добавляются дополнительные заголовки (VLAN, туннели), крупные пакеты могут не пролезать. Решение -- немного снизить MTU на своём интерфейсе (например, до 1480 или 1460 байт).

Поле Identification (16 бит)

Проставляется отправителем для каждого пакета. Каждый следующий пакет получает значение на единицу больше. При фрагментации у всех кусочков сохраняется одинаковое значение Identification -- так получатель понимает, что это части одного и того же оригинального пакета.

Изначально поле предполагалось использовать ещё и для обнаружения дублированных пакетов. Но сегодня это запрещено. Причина: на быстрых каналах одинаковые значения Identification появляются слишком часто. На 100-мегабитном канале при отправке минимальных пакетов можно генерировать около миллиона пакетов в секунду, а поле 16-битное (65 536 значений) -- значит, примерно 15 пакетов с одинаковым Identification каждую секунду. Отличить дубликат от нового пакета с совпавшим Identification невозможно.

Поле Fragment Offset (13 бит)

Указывает смещение данных фрагмента относительно начала оригинального пакета.

  • У нефрагментированного пакета -- 0
  • У первого фрагмента -- 0
  • У второго фрагмента -- номер байта, с которого начинаются его данные

Проблема: в 13 бит можно вписать только 8192 значения, а смещение может быть до 65 535. Решение: значение в поле Fragment Offset нужно умножить на 8. При фрагментации пакет всегда режется по границе 8 байт.

Пример: в заголовке записано 0xB9 (185 в десятичном). Умножаем на 8 -- получаем 1480. Значит, данные в этом фрагменте начинаются с 1480-го байта.

Поле Flags (3 бита)

Бит Название Описание
0 Reserved Всегда 0, не используется
1 DF (Don't Fragment) 1 = запрет фрагментации
2 MF (More Fragments) 1 = есть ещё фрагменты после этого

Флаг DF -- отправитель запрещает резать пакет. Применения:

  • NTP (Network Time Protocol) -- всегда выставляет DF, потому что задержки фрагментации вносят погрешность в синхронизацию времени. Данные NTP мелкие и пролезают без фрагментации по любой сети
  • Path MTU Discovery -- отправляются пакеты возрастающего размера с флагом DF. Когда пакет не пролезает, маршрутизатор возвращает ICMP "Fragmentation Needed" с указанием MTU следующего хопа. Так определяется самое узкое место на трассе
  • TCP -- большинство TCP-реализаций выставляют DF и используют Path MTU Discovery для подбора оптимального размера сегмента

Флаг MF -- выставляется в 1 для всех фрагментов, кроме последнего.

Как определить состояние пакета по флагам и offset:

Fragment Offset MF Значение
0 0 Единственный (нефрагментированный) пакет
0 1 Первый фрагмент, есть ещё
> 0 1 Промежуточный фрагмент
> 0 0 Последний фрагмент

Не все реализации отправляют фрагменты в естественном порядке. Некоторые отправляют сначала последний, потом предпоследний и так далее. Логика: получив последний фрагмент первым, получатель сразу знает полный размер данных и может подготовить буферы. Впрочем, рекомендуется отправлять в естественном порядке.


Пример фрагментации

Исходный пакет: 2000 байт, ICMP.

Оригинальный заголовок:

Поле Значение
Version 4
IHL 20 байт (5 слов)
Total Length 2000
Identification (какое-то)
Flags 0, 0, 0 (фрагментация разрешена)
Fragment Offset 0
TTL 128
Protocol 1 (ICMP)

Данные: 20 байт заголовка + 8 байт ICMP-заголовка + 1972 байта данных ICMP = 2000 байт.

Фрагмент 1 (1500 байт):

Поле Значение
Total Length 1500
Identification (то же)
Flags 0, 0, 1 (MF = ещё есть)
Fragment Offset 0
Protocol 1 (ICMP)

Содержит: ICMP-заголовок (8 байт) + первые 1472 байта данных.

Фрагмент 2 (520 байт):

Поле Значение
Total Length 520 (500 данных + 20 заголовок)
Identification (то же)
Flags 0, 0, 0 (MF = последний)
Fragment Offset 0xB9 (185 x 8 = 1480)
Protocol 1 (ICMP)

Содержит: оставшиеся 500 байт данных. Обратите внимание: в заголовке написано Protocol = ICMP, но заголовка ICMP в этом фрагменте нет -- только хвост данных. Это нормально при фрагментации.


Поле Options (0--40 байт)

Необязательное поле переменного размера. Всегда кратно 4 байтам (если содержимое не кратно -- добивается мусором до границы).

Изначально предполагалось расширять функциональность заголовка. В RFC 791 были определены некоторые опции, позже выходили дополнительные RFC. Но почти все опции либо экспериментальны, либо устарели, либо небезопасны.

Например, есть опция Source Routing -- отправитель указывает маршрут прохождения пакета. Провайдеры такое не принимают: они не позволяют пользователям указывать, как маршрутизировать пакеты.

С нестандартными (вендорскими) опциями ещё хуже: оборудование другого производителя их не прочитает, а при нескольких опциях подряд невозможно понять, где заканчивается одна и начинается другая.

Итог: поле Options не используется в реальности. В 100% современных пакетов опций нет, заголовок -- ровно 20 байт. Если попытаться отправить пакет с опциями в интернет -- его либо отфильтруют, либо опции отрежут.


Демонстрация в Wireshark

Обычный пакет

В захваченном UDP-пакете (голосовой трафик Skype) видно:

  • Первый байт заголовка: 0x45 -- версия 4, IHL = 5 (20 байт)
  • DSCP: EF (Expedited Forwarding, значение 46 = 101110) -- метка приоритетного голосового трафика
  • ECN: 0
  • Total Length: 199 байт (20 заголовка + 179 данных)
  • Identification: 6076
  • Flags: все нули (не фрагментирован, фрагментация разрешена)
  • Fragment Offset: 0
  • TTL: 128
  • Protocol: 17 (UDP)
  • Header Checksum: 0xD30E

Фрагментированный ICMP-пакет (2000 байт)

При отправке ICMP-пакета размером 2000 байт через Ethernet (MTU 1500) пакет разрезается на два фрагмента:

  1. Первый фрагмент: 1500 байт, Fragment Offset = 0, MF = 1
  2. Второй фрагмент: 548 байт, Fragment Offset = 1480 (0xB9 x 8), MF = 0

Identification у обоих одинаковый. Интересно, что некоторые реализации (как в данном случае) отправляют последний фрагмент первым.

Фрагментация на три части (3000 байт ICMP)

При отправке 3000 байт данных ICMP (+ 8 байт заголовка ICMP + 20 байт IP = 3028 байт):

  1. Фрагмент 1: 1500 байт, Offset = 0, MF = 1
  2. Фрагмент 2: 1500 байт, Offset = 1480, MF = 1
  3. Фрагмент 3: 68 байт, Offset = 2960, MF = 0

DF и Path MTU Discovery

При отправке 1460-байтного пинга на Google с флагом DF:

  • Пакет проходит нормально (помещается в MTU)
  • Google отвечает с TTL = 64, до нас доходит TTL = 50, значит между нами 14 маршрутизаторов
  • Google ставит Identification = 0 для всех пакетов (не обязан следовать рекомендациям)

При попытке отправить 1500-байтный пакет с DF -- драйвер сам отказывается: пакет не пролезает в Ethernet.

При отправке 1472-байтного пакета с DF через VPN-туннель (MTU 1450):

  • Маршрутизатор возвращает ICMP Destination Unreachable (Fragmentation Needed) с указанием: MTU of next hop = 1450
  • Система запоминает Path MTU до этого адреса и больше не пытается отправлять крупные пакеты

Хорошие маршрутизаторы возвращают ICMP с указанием MTU. Плохие -- тихо отбрасывают пакет.

На оборудовании Cisco есть штатная возможность в расширенном ping отправлять пакеты возрастающего размера с DF для автоматического определения Path MTU. Windows такого не умеет.


Итоги

В заголовке IPv4-пакета нет ничего, кроме описанных полей. Там нет маски подсети, нет MAC-адресов маршрутизаторов -- только то, что видно в Wireshark. Никакой магии, всё достаточно простое и понятное.

Network Education

Бесплатная онлайн-академия сетевых технологий. Видеоуроки, транскрипции и структурированные треки обучения — от основ до продвинутого уровня.

ТрекиКаталогО проекте
© 2026 Network Education