Привет, посетитель сайта ZametkiNaPolyah.ru! Продолжаем изучать основы работы компьютерных сетей и протокол сетевого уровня IP, а если быть более точным, то его версию IPv4. Хватит ходить вокруг да около, пора браться за дело основательно. В этой теме мы с вами заберем структуру IP-пакета и его заголовка в протоколе IPv4 и поговорим о назначение каждого поля в заголовке. Эта тема может показаться скучной и чтобы не уснуть, мы немного попрактикуемся: запустим Wireshark и посмотрим как выглядят настоящие IP-пакеты, а не те, что рисуются в книжках и учебниках.

Если тема компьютерных сетей вам интересна, то можете ознакомиться с другими записями курса.

Оглавление первой части: «Основы взаимодействия в компьютерных сетях».

Оглавление четвертой части: «Сетевой уровень: протокол IP и его версия IPv4».

4.3.1 Введение

Заголовок любого протокола на 80% определяет функционал и возможности протокола, чтобы понять возможности протокола IP четвертой версии, нам нужно разобраться с заголовком IP-пакета. Да, нудная тема, в которой требуется не столько понимания сути физических или природных процессов, сколько внимание и память. Ведь придется запомнить полтора десятка полей и их назначение, хотя в реальной работе это может вам никогда и не пригодится. Вообще, если говорить про компьютерные сети, построенные на стеки протоколов TCP/IP, то все физические и природные процессы, а также ограничения, связанные с законами физики, заканчиваются на канальном уровне (вы же помните, что канальный уровень в модели TCP/IP является компиляцией физического уровня и канального эталонной модели сетевого взаимодействия).

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

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

4.3.2 Общий взгляд на структуру IP-пакета

На сетевом уровне модели TCP/IP или модели OSI 7 устройства обмениваются единицами данных, которые называются пакетами. Если мы говорим про протокол IP, то IP-пакетами, здесь и в дальнейшем, если вы встретите слово пакет, то в 99 случаях из 100 будет иметься в виду IP-пакет, если речь будет не про IP, я буду это явно указывать. Давайте посмотрим на две большие части, из которых состоит IP-пакет, они показаны на рисунке 4.3.1.

4.3.1 Общая структура IP-пакета

Рисунок 4.3.1 Общая структура IP-пакета

Да, этот рисунок в общем-то практически бессмысленный, на нем просто показан какой-то непонятный заголовок и какое-то непонятное поле данных. В протоколе IPv4, как и во многих других протоколах, заголовок определяет функционал и гибкость, а в поле данных передается какая-то полезная информация, чаще всего это будет: UDP, TCP или ICMP (немного познакомиться с этим протоколом можете в публикациях из цикла командная строка Windows 10: ping, winmtr, tracert, pathping). Список протоколов, которые можно инкапсулировать в IP-пакеты будет ниже. То есть сообщения этих протоколов помещаются в поле данных IP-пакета.

Заголовок же IP-пакета делится на несколько полей и каждое поле имеет свое строго определенное назначение, анализируя эти поля, маршрутизаторы и узлы понимают: что и как делать с пакетом.

4.3.3 Заголовок IP-пакета и его поля

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

Поэтому не будем затягивать и посмотрим на Рисунок 4.3.2, на котором показана структура IP-пакета со всеми полями заголовка.

4.3.2 Заголовок IP-пакета (eng)

Рисунок 4.3.2 Заголовок IP-пакета (eng)

Как видите, все подписи на английской, если для вас это не комфортно, то ниже та же самая структура с русскими подписями.

4.3.3 Заголовок IP-пакета

Рисунок 4.3.3 Заголовок IP-пакета

Но и это еще не всё. На самом деле структура IP-пакета в протоколе IPv4 на данный момент выглядит немного не так. Дело в том, что раньше было поле «Тип сервиса» или ToS, под которое было выделено 8 бит, но этого оказалось слишком много, поэтому его разделили на два более мелких: первое поле указывает приоритет при обработке пакетов на узлах, а второе поле позволяет сигнализировать о том, что сеть перегружена, со вторым полем умеют работать далеко не все устройства. Структура современного IP-пакета показана на Рисунке 4.3.4. Честно признаюсь, что рисовать мне было лень, а поиск по Рунету не дал положительного результата, поэтому только английская версия.

4.3.4 Правильный заголовок IP пакета

4.3.4 Правильный заголовок IP пакета

Давайте сразу скажем, что для маршрутизаторов и конечных узлов IP-пакеты выглядят не так, как на рисунке. Естественно, для них это последовательность бит. При этом маршрутизатор не работает с отдельными битами пакета, он их обрабатывает целыми строками. Условно заголовок делится на строки, так, например, первая строка содержит поля: «Номер версии», «Длина заголовка», «Тип сервиса» и «Общая длина». Суммарно четыре этих поля дают 32 бита или 4 байта и это не случайное число. Эта строка имеет не случайную длину, более того, у этой строки есть название — машинное слово. Давайте сейчас коротко об этом поговорим, а за более полной информацией обращайтесь к литературе по архитектуре процессоров. Вспомните разрядность своего процессора, тут два варианта: или 32-а или 64-е бита. Что означают эти цифры? Эти цифры означают количество бит, которые может обработать процессор за один такт, или иначе длина машинного слова. А теперь вспомните, что все сетевые железяки — это те же самые компьютеры (немного особенные, но все же). У коммутаторов и маршрутизаторов (про разницу между коммутаторами и роутерами можете прочитать здесь) тоже есть  свои CPU и они тоже оперируют машинными словами. Так, например, если ваш маршрутизатор имеет процессор с машинным словом 8 бит, то одна строка IP-пакета будет обработана за четыре такта, если 16 бит, то за два, а если 32 бита, то за один.

По причине, описанной выше, все поля в заголовке IP пакета выравнены по границе 32-а бита, потому что так удобнее машине, а не человеку.

Если вы посчитаете количество полей на Рисунке 4.3.4, то их получится ровно четырнадцать, при этом, когда конечное устройство формирует IP-пакет, чтобы отправить его в сеть, оно обязательно должно заполнить 13 полей, поле «Опции» не является обязательным, более того, на данный момент у этого поля нет нормального применения и вы его не встретите. Например, в этом поле есть такая опция, которая позволяет задать транзитные узлы, по которым должен будет пройти пакет, двигаясь из пункта А в пункт Б, но ни один нормальный провайдер не даст своему абоненту возможность управлять маршрутизацией на своей сети, также как этого не даст сделать ни один нормальный сетевой администратор сотрудникам компании, которую он обслуживает.

Не все опции имеют длину 32-а бита, некоторые могут быть меньше, в этом случае используется специальная конструкция, которая дополняет опцию до 32-ух бит, эту конструкцию называют выравниванием. В качестве заполнителя при выравнивание используются нули. Теперь давайте пройдемся по оставшимся полям заголовка IP-пакета. Будем двигаться слева направо и сверху вниз.

Версия (Version)

Самое первое поле в заголовке IP пакета – это версия, под него выделено четыре бита, для протокола IPv4 здесь всегда неизменное значение – 4. Хочу заметить, что в IPv4 четверка не связана с количество октетов в IP-адресе, просто такое совпадение.

Размер заголовка (Internet Header Length)

Поле размер заголовка нужно для того, чтобы маршрутизатор или конечный узел понимали: где заканчивается заголовок и начинаются данные. Также мы помним, что поле Опции не является обязательным, собственно из-за этого и появилась необходимость в поле «Размер заголовка», под это поле выделено четыре бита и оно служит для указания количества слов в заголовке. Таким образом получается, что минимальный размер заголовка IP-пакет равен пяти словам, каждое слово 32 бита, следовательно, обычный заголовок без дополнительных опций равен 160 бит или 20 байт. Максимальное количество слов в заголовке равно пятнадцати.

Тип обслуживания (Type of Service), DSCP и ECN

На самом деле на данный момент поля Type of Service в IP заголовке нет, изначально поле ToS использовалось для указания приоритетов при обработке трафика, сейчас это поле заменено на два:

  1. DSCP (Differentiated Services Code Point), под которое выделено 6 бит, это поле используется для разделения трафика на классы обслуживания. Сейчас мы не будем сильно вдаваться в подробности, поскольку на самом деле это очень сложная тема, в которой даже инженеры с опытом могут вполне себе неплохо плавать.
  2. Не трудно посчитать, что для второго поля у нас остается два бита, и это поле называется ECN (Explicit Congestion Notification) или указатель перегрузки. Как понятно из названия, это поле может пригодится в тех ситуациях, когда пропускная способность канала связи меньше, чем трафик, который в текущий момент передается по каналу (виды взаимодействия в компьютерных сетях). Это поле будет задействовано только в том случае, когда передающая и принимающая сторона умеют с ним работать.

Размер пакета (Total Length)

Это поле позволяет обрабатывающему устройству понять полный размер пакета, то есть заголовок плюс данные. Минимальный размер IP-пакета равен 20 байт, то есть это заголовок без опций и данных, а максимальный размер равен 65535 байт. Тут стоит заметить, что одним из параметров канала связи является максимально возможный размер пакета (субъективные и объективные характеристики компьтюерной сети), который по этому каналу можно передавать. И, например, бывают ситуации, когда в канале связи можно передавать пакеты, размером, скажем (точные цифры сейчас не очень важны) 1000 байт, а узел генерирует пакеты размером 2000 байт, в этом случае перед отправкой данных в канал связи пакеты будут фрагментироваться, то есть разбиваться на более мелкие, это поведение по умолчанию в протоколе IP.

Идентификатор (Identification)

Чаще всего это поле используется в тех ситуация, когда пакет фрагментируется, чтобы принимающая сторона понимала, как из полученных кусочков правильно собрать пакет. У фрагментированных пакетов значение в этом поле должны быть одинаковыми.

Флаги (Flags)

Под поле флаги выделено три бита, этих три бита используются для контроля над фрагментацией пакетов. Немного отвлечемся непосредственно от флагов и заметим, что нумерация бит в поле начинается с нуля, крайний левый бит старший, а крайний правый – младший. Тогда у нас в поле Флаги получается следующая картина:

  • нулевой бит зарезервирован и должен быть всегда равен нулю;
  • если значение первого бита ноль, то допускается фрагментация пакетов, если единица (бит DF или Do not Fragment), то устройства компьютерной сети не будут выполнять фрагментацию;
  • второй бит служит для того, чтобы конечные узлы понимали, где начинается последовательность фрагментированных пакетов, а где она заканчивается, если значение этого бита равно единице (MF More Fragments), то узел понимает, что этот пакет не последний и нужно ждать еще пакеты, чтобы собрать изначально разделенный пакет.

Тут стоит сказать: если вы запретите фрагментацию пакетов и их размер будет превышать максимально допустимый размер, то такие пакеты будут просто отбрасываться. Также стоит добавить пару слов о втором бите: у не фрагментированных пакетов его значение равно нулю. Чтобы убедиться в том, что пакеты, размер которых превышает максимально допустимый размер в канале связи, достаточно запустить командую строку Windows и выполнить команду ping с флагами –f и –l (первый запрещает фрагментацию, а второй позволяет задать размер пакета).

4.3.5 Команда ping в Windows

Рисунок 4.3.5 Команда ping в Windows

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

Смещение фрагмента (Fragment Offset)

Это поле используется в тех случаях, когда выполняется фрагментация пакетов, размер этого поля равен 13 бит. Нетрудно посчитать, что максимально возможное значение, которое можно записать в этом поле равно два в тринадцатой степени или 65528, смещение задается в байтах, то есть это поле говорит узлу или маршрутизатору на сколько байт нужно выполнять смещение от нуля (это для пакетов без фрагментации, в этом случае все тринадцать бит имеют значение 0) до 65528 байт (в этом случае все тринадцать бит выставлены в единицу). В том случае, если фрагментация выполняется, то первый пакет последовательности также имеет смещение равное нулю. У числовых значений, записываемых в поле «Смещение фрагмента» есть одно ограничение — это значение должно быть всегда кратно восьми.

Теперь о самом смещение, которое проще всего показать на примере. Давайте представим ситуацию, что между узлами А и Б мы хотим передавать IP-пакеты размером 7600 байт, но максимально допустимый размер пакета, который мы можем передать в канале связи равен 1500 байт, следовательно, при передаче исходного пакета будет выполняться фрагментация, а заодно будет задано и смещение для поля данных данных. Обратите внимание на Рисунок 4.3.6.

4.3.6 Поле смещение в IP-пакете

Рисунок 4.3.6 Поле смещение в IP-пакете

Здесь как раз показана ситуация, описанная словами выше. Давайте поясним. Ноутбук генерирует IP-пакет в сторону ПК размером 7600 байт, из этих 7600 байт под данные выделено 7580 байт, а под заголовок 20 байт. Еще раз хочу напомнить, что смещение применяется к полю данных и это значение нужно, чтобы принимающая сторона смогла правильно собрать исходное поле данных из полученных кусочков. Получается, что у первого пакета смещение равно нулю и когда ПК его получит, он отрежет заголовок и поле данных первого пакета он поставит на первое место.

Но давайте сейчас немного уйдем в сторону. Компьютер поймет, что он получатель по IP-адресу назначения в первом пакете, если этот адрес будет совпадать с тем, что задан в его настройках. Получив первый пакет, компьютер посмотрит, на флаги и поймет, что этот пакет является не самостоятельной единицей, а частью чего-то большего, поэтому он выделит ресурсы своего буфера и будет ждать следующие кусочки. По сути у нас получается очередь из пакетов, которая обрабатывается получателем по методу FIFO (first in, first out) или первым пришел – первым ушел.

Буфер принимающей стороны можно представить себе в виде коробки, а поле данных приходящих пакетов в виде кубиков, которые принимающая сторона складывает в свою коробку. Если говорить о компьютерах, то сейчас у них достаточно производительности и памяти, чтобы считать размеры коробки (буфера) не ограниченными, с транзитными маршрутизаторами дела обстоят иначе, ведь их задача заключается не в том, чтобы собирать из кусочков единое целое, а в том, чтобы пересылать пакеты, поэтому нужно смотреть документацию к устройству, с которым вы работаете. Условно будем считать, что наш компьютер может выделить для фрагментированного пакета 65515 байт памяти (если вы еще не забыли, то 65535 байт – это максимально допустимый размер IP-пакета). Более наглядно ситуацию демонстрирует рисунок ниже.

4.3.7 Компьютер принимает фрагментированный пакет

Рисунок 4.3.7 Компьютер принимает фрагментированный пакет

Получается следующая ситуация: компьютер получает первый пакет, анализирует его заголовок и по полю флагов видит, что это не просто пакет, а фрагментированный пакет, по полю смещение компьютер видит, что это самый первый пакет из неизвестно насколько большой цепочки пакетов, а значит нужно выделять память и ждать, что там еще пришлют, при этом поле данных из самого первого пакета нужно поместить на самый верх буфера. Затем компьютеру пришел второй пакет, анализируя «Флаги» и "Смещение "он понимает, что это второй пакет из цепочки, в смещение он видит значение 1480 байт, а это значит, что нужно отсчитать 1480 байт от верхней границы буфера и туда поместить информацию из поля данных первого пакета. При этом нам даже не так уж страшна ситуация, при которой после второго пакета придет четвертый, компьютер просто бы отсчитал от верхней границы 4440 байт и записал бы фрагмент данных на это место, а когда придет третий пакет, то его поле данных попадет в интервал между вторым и четвертым.

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

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

Время жизни (Time to Live, TTL)

Следующее поле имеет размер один байт или восемь бит и называется оно время жизни пакета, данное поле нужно, чтобы пакет не блуждал по сети до бесконечности в том случае, если конфигурация транзитных узлов некорректная и произошла петля маршрутизации. Для нас TTL – это число в диапазоне от 0 до 255, это число определяет максимально допустимое число узлов, через которое может пройти пакет перед тем, как он будет уничтожен. Время жизни для пакета задается узлом источником и изначально оно измерялось в секундах (то есть максимально возможное время жизни IP пакета раньше было 255 секунд), но дело в том, что современные маршрутизаторы обрабатывают пакеты гораздо быстрее, чем за секунду, поэтому сейчас TTL – это значение, которое определяет число транзитных узлов. Таким образом получается следующее: первый узел сформировал пакет и задал для него значение TTL равное 20, первый маршрутизатор, получивший этот пакет, вычтет единицу из двадцати, получит 19, запишет новое значение в поле TTL и отправит пакет дальше. Процесс вычитание и передачи будет происходить до тех пор, пока пакет не будет доставлен получателю, либо пока значение TTL не будет равным нулю, тот маршрутизатор, на котором TTL стало равным нулю, уничтожит пакет.
Воспользуемся Cisco Packet Tracer и посмотрим на этот процесс более наглядно (если вы не знакомы с Cisco Packet Tracer, то вот вам несколько материалов в помощь: установка Cisco Packet Tracer на Windows, установка Packet Tracer на Linux, как пользоваться Cisco Packet Tracer, стандартные физические компоненты компьютерной сети). На рисунке PC0 формирует пакет в сторону PC1 и отправляет его в сеть из трех маршрутизаторов.

4.3.8 TTL IP-пакета на узле, который его сформировал

Рисунок 4.3.8 TTL IP-пакета на узле, который его сформировал

Как видим из Рисунка, узел задал для пакета TTL=128 и отправил его на Router0. Когда пакет придет на входной интерфейс Router0, его TTL не изменится, это показано на Рисунке 4.3.9.

4.3.9 TTL IP-пакета на входном интерфейсе маршрутизатора

Рисунок 4.3.9 TTL IP-пакета на входном интерфейсе маршрутизатора

Но как только Router0 поймет куда отправлять этот пакет дальше, он вычет из 128 единицу и отправит пакет в выходной интерфейс в сторону Router1, показано на Рисунке 4.3.10.

4.3.10 TTL IP-пакета на выходном интерфейсе маршрутизатора

Рисунок 4.3.10 TTL IP-пакета на выходном интерфейсе маршрутизатора

Следующие роутеры будут поступать с пакетом аналогичным образом. Узел получатель PC1 примет этот пакет с TTL=125 и уже не будет вычитать единицу. Теперь давайте убедимся в том, что маршрутизатор, который получит пакет с TTL равным единице, просто прибьет бедолагу. Для этого со стороны PC0 я сформировал пакет с TTL=2 и направил его в сторону PC1, а это означает, что Router1 должен уничтожить пакет, показано на Рисунке 4.3.11.

4.3.11 IP-пакет пришел на маршрутизатор с TTL=1

Рисунок 4.3.11 IP-пакет пришел на маршрутизатор с TTL=1

К теме TTL , маршрутизации и петле маршрутизации мы еще вернемся.

Протокол (Protocol)

Иначе еще это поле называют «Протокол верхнего уровня» (хотя такое название неверно отображает суть поля), для этого поля выделено 8 байт. Вы же помните, что протокол IP используют в качестве транспорта протоколы транспортного уровня, в частности TCP и UDP, кроме того, в поле данных IP-пакета могут быть запакованы сообщения протоколов других уровней. Это поле нужно для того, чтобы конечный узел мог понять, какому процессу отдавать на обработку принятые IP-пакеты. И понятно, что в поле «Протокол» записывается не название протокола, а его цифровой код, таблицу кодов вложений в IP можно найти на сайте IANA.

Так, например, если внутри IP-пакета будет передаваться UDP-дейтаграмма, то в поле протокол будет записано значение 17 или 00010001 в двоичной системе счисления, а для протокола TCP используется десятичное число 6, в двоичной системе счисления 00000110.

Контрольная сумма заголовка (Header Checksum)

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

Стоит отметить, что если значение контрольной суммы, которую посчитал узел отличается от контрольной суммы, которая записана в пакете, то он просто отбрасывается.

IP-адрес источника

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

А по полю IP-адрес источника узел-получатель сможет понять кому нужно ответить, тут, кстати, стоит отметить такой момент: поле IP-адрес назначения определяет каким маршрутом пойдет пакет «туда», а поле IP-адрес источника определяет каким маршрутом пакет пойдет «обратно». И далеко не всегда маршрут «туда» совпадает с маршрутом «обратно».

IP-адрес назначения

Данное поле имеет размер 4-е байта, в него записывается IP-адрес конечного узла, для которого пакет предназначен, роутеры смотрят на этот поле при принятии решения о том куда направлять пакет.

4.3.4 Поле данных в пакете IP и его размер (MTU)

Вообще, про MTU в протоколе IP у нас будет отдельная тема, сейчас на важно понять, что в поле данных IP пакета помещаются сообщения других протоколов, для которых IP является транспортом. Если учитывать, что максимально возможный размер IP пакета 65535 байт, то максимально возможный размер поля данных в IP пакете получается 65515 байт, следовательно, и наибольший MTU для протокола IP равен 65515 байт, хотя такое значение вы вряд ли встретите.

4.3.5 Посмотрим на IP-пакет в Wireshark

Нам осталось сделать одну важную вещь – посмотреть, как IP пакеты выглядят в реальном мире. Рисунки и ровные формочки – это здорово, но на самом деле при работе с реальной сетью вы такой наглядной картины не увидите, поэтому нужно привыкать пользоваться тем, что есть, а есть у нас замечательный сниффер трафика, который называется Wireshark (хотя вы можете воспользоваться утилитой командной строки tcpdump, результаты их работы во многом похожи). В общем, давайте посмотрим на IP пакет с помощь Wireshark, и я попытаюсь дать пояснения к увиденному.

4.3.12 Так выглядит IP-пакет в Wireshark

Рисунок 4.3.12 Так выглядит IP пакет в Wireshark

Для того чтобы сделать этот скрин, я запустил Wireshark, нажал на кнопку «Start», а затем выполнил команду Ping на адрес публичного DNS-сервера Google (к сожалению, пока нет возможности сделать подробный обзор Wireshark, а краткими мануалами тут не обойтись, поэтому пока вам могу предложить только Google в помощь). Интересная для нас информация начинается со строки Internet Protocol Version 4, Src: 8.8.8.8, Dst: 192.168.0.101, она выделена тёмно-голубым на Рисунке. Теперь, собственно, о самих полях:

  1. 0100 ... = Version: 4. Это первое поле, в котором указана версия протокола, обратите внимание, что к значению в двоичном виде (0100) есть пояснение.
  2. ... 0101 = Header Length: 20 bytes (5). Подпись к этому полю всё сказала за меня, это поле Длина заголовка, в данном случае она равна 20 байт.
  3. Differentiated Services Field: 0×00 (DSCP: CS0, ECN: Not-ECT)
    • 0000 00... = Differentiated Services Codepoint: Default (0)
    • ... ...00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
    • Третье поле DSCP + ECN, здесь мы видим, что используется приоритет по умолчанию, а также не используется указатель перегрузки.
  4. Размер IP-пакета 60 байт, об этом нам говорит вот эта строка: Total Length: 60.
  5. Identification: 0xeba8 (60328). В данном случае IP-пакет не фрагментировался и поле идентификатор не представляет для нас особого интереса.
  6. Flags: 0×00
    • o 0... ... = Reserved bit: Not set;
    • o .0... ... = Don't fragment: Not set;
    • o ...0. ... = More fragments: Not set;
    Убедиться в том, что пакет не фрагментировался нам поможет значение флагов, в данном случае все флаги выставлены в ноль, а значит фрагментации не было.
  7. Fragment offset: 0. Также мы видим, что смещение у нас тоже нулевое.
  8. Time to live: 118. В данном случае мой компьютер решил, что значение TTL=118 будет достаточным, чтобы добраться до конечного узла.
  9. Protocol: ICMP (1). Поле протокол говорит нам о том, что внутри IP-пакета находится ICMP вложение, у протокола ICMP числовой код 1.
  10. Header checksum: 0x87fb. После того, как пакет был сформирован, для его заголовка была посчитана контрольная сумма.
  11. Source: 8.8.8.8. IP-адрес назначения.
  12. Destination: 192.168.0.101. IP-адрес источника.

Обратите внимание, что поля Опции здесь нет, так как опции не использовались. Также мы не видим поле данных, но мы знаем, что у нас во вложении ICMP, при этом если посмотреть внимательнее на скрин, то внизу можно заметить строку с текстом «Internet Control Message Protocol», а слева от этого текста есть птичка, которую нужно нажать, чтобы увидеть, что находится внутри поля данных, но протокол ICMP – это отдельный разговор.

Теперь мы лучше посмотрим на пакеты, которые нужно фрагментировать перед отправкой. Для этого выполним команду ping 8.8.8.8 -l 4000 и сделаем дамп трафика в этот момент. Для начала давайте посмотрим на то, фрагментированные пакеты выглядят в Wireshark, показано на Рисунке 4.3.13.

4.3.13 Так выглядит фрагментированный IP-пакет в Wireshark

4.3.13 Так выглядит фрагментированный IP-пакет в Wireshark

Три пакета в красной рамке – это результат разбиение одного пакета, который сформировал Windows в процессе выполнения команды Ping, вообще, если пролистать этот дамп, то можно будет увидеть подобную картину еще три раза, так как Windows по умолчанию отправляет ICMP запрос к удаленному узлу четыре раза. Теперь давайте заглянем во внутрь каждого из этих трех пакетов (по порядку сверху вниз). Сначала первый пакет.

4.3.14 Первый пакет в цепочке фрагментированных пакетов

Рисунок 4.3.14 Первый пакет в цепочке фрагментированных пакетов

Обратите внимание: второй флаг (More Fragments) выставлен в единицу, а это означает, что после данного пакета будут еще, значение Fragment Offset равно нулю, то есть данные в этом пакете никуда смещать не нужно. Теперь посмотрим на второй пакет.

4.3.15 Второй пакет в цепочке фрагментированных пакетов

4.3.15 Второй пакет в цепочке фрагментированных пакетов

Второй бит флага по-прежнему равен единице, значит, удаленной стороне нужно быть готовой принять, как минимум, еще один пакет. А смещение на этот раз имеет значение 1480. И наконец третий пакет в списке показан ниже.

4.3.16 Третий пакет в цепочке фрагментированных пакетов

4.3.16 Третий пакет в цепочке фрагментированных пакетов

Здесь второй бит имеет значение 0, а это значит, что это последний фрагмент, в поле смещение записано значение 2960, а общая длина пакета 1068 байт, в отличие от двух предыдущих, где это значение было 1480 байт, давайте теперь посчитаем: 1480+1480+1068=4028 байт. Откуда взялись эти 28 байт? На этот вопрос вы сможете ответить, если разберетесь с тем, как работает команда Ping в Windows, дам сейчас лишь подсказку: это связано с заголовками ICMP и IP и тем, какое MTU использует Windows, когда вы задаете размер пакета при пинге.

Во всех трех пакетах поле Identification имеет значение 0×5392 (Wireshark показывает это значение в шестнадцатеричном виде), это говорит о том, что три пакета являются частью одного целого. И последний вопрос, на который вам следует обратить внимание: почему Wireshark отображает заголовок ICMP в третьем пакете? Ответ сможете найти самостоятельно.

4.3.6 Выводы

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

Возможно, эти записи вам покажутся интересными


Выберете удобный для себя способ, чтобы оставить комментарий

This article has 5 comments

  1. Борисов Reply

    Мужик, это очень подробно, очень понятно и доходчиво! С удовольствием изучаю по твоим материалам сети и протоколы. Вообще без разницы в каком порядке публикуешь, только продолжай.

  2. Nexus Reply

    Охренительная статья! Молодец, все очень подробно и понятно!

    Только не понял почему на картинке поле протокол 8 бит, а в описании 8 байт...

  3. гена Reply

    «Так, например, если ваш маршрутизатор имеет процессор с машинным словом 8 бит, то одна строка IP-пакета будет обработана за четыре такта, если 16 бит, то за два, а если 32 бита, то за один.»

    ну-ну, так держать)))

  4. Турал Reply

    Здравствуйте. Отличная статья! Но в описании 13 битного Fragment Offset 2 в степени 13 8192, а не 65528.

    • Кирилл Reply

      Да, ее чутка надо поправить. Fragment Offset определяет смещения не в байтах, а в блоках по восемь байт, т.е. 8192 — это количество 8-ми байтных блоков, а 65528 — это количество байт (8192*8=).

      Моя вина, корректора нанять не могу 🙂

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Loading Disqus Comments ...