Опубликован: 30.07.2013 | Уровень: для всех | Доступ: платный
Лекция 4:

Пакет IPv6

Заголовок IPv6

Итак, каждый пакет IPv6 начинается с заголовка IPv6 (неожиданно, правда?) Но теперь, в отличие от IPv4, все необязательные элементы мы можем перенести из основного заголовка в заголовки расширения. Без каких полей мы абсолютно не сможем обойтись в основном заголовке? Используя наш опыт IPv4, а также не забывая сказанное в §1 и §3.1, составим предварительный неупорядоченный список:

  • версия IP
  • адрес источника
  • адрес назначения;
  • длина пакета;
  • следующий заголовок.

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

Целочисленные поля, "созданные" нами по ходу нашей работы, будут по умолчанию в беззнаковом коде. Как вы думаете, почему отрицательные и дробные числа редко встречаются в сетевых протоколах?

Как мы уже обсудили в §1, поле версии IP поможет надежно отличить пакет IPv6 от пакета IPv4 в переходных условиях, пока новая версия будет работать наряду со старой. Учитывая масштабы применения IPv4 и финансовые вложения в технологии на его основе, этот переходный период может растянуться на многие годы. Очевидно, что длина и позиция поля версии обязаны быть такими же, как в заголовке IPv4. То есть длина этого поля — 4 бита, а находится оно в самом начале заголовка (учитывая сетевой порядок битов и байтов). Теперь его новое значение — 6.

Также нам никуда не деться без двух адресов IPv6, источника и назначения. Вместе они занимают 256 бит, или 32 байта, что весьма немало. Не надо ли нам попытаться сжать их двоичное представление путем какого-то кодирования, подобно тому как мы поступили с текстовым представлением? Нет, делать этого ни в коем случае не стоит; иначе ради выигрыша в несколько байтов мы пожертвуем простотой заголовка и затрудним его обработку, особенно на аппаратном уровне. Что мы еще должны сказать об этих адресах? Прежде всего, у пакета ровно один интерфейс источника, и поэтому адрес источника не может быть групповым. Если узел принял пакет с групповым адресом источника, его необходимо отбросить, никак не реагируя на него, потому что любая реакция по групповому адресу может открыть лазейку для атаки типа "отказ в обслуживании" против других узлов. Далее, адрес обратной связи ::1 можно использовать только в трафике через интерфейс типа "петля", будь то адрес источника или назначения, — прийти в пакете извне узла он не имеет права. Прочие требования к адресам в заголовке IPv6 мы сформулируем по ходу работы.

Кстати, именно благодаря тому, что адрес источника в пакете IP не бывает групповым, мы можем говорить о типе всего пакета в зависимости от типа его адреса назначения, как то "индивидуальный пакет" и "групповой пакет".

Без поля TTL или аналогичного ему возникает риск бесконечного зацикливания пакетов в сети. При неудачном стечении обстоятельств это может также сопровождаться дублированием пакетов, что означает экспоненциальный рост паразитного трафика и полный крах сети. Так что без эквивалента TTL нам никак не обойтись. Однако, перенося поле TTL в заголовок IPv6, мы внесем в его свойства долгожданную поправку. Как показал опыт работы с IPv4 [§5.3.1 RFC 1812], измерить время удержания транзитного пакета на узле затруднительно и, к тому же, оно редко превышает одну секунду. Де-факто поле TTL ведет обратный отсчет не секунд жизни пакета, а его шагов по транзитным узлам. Мы не можем не учесть этот опыт в IPv6, и нам остается только переименовать поле сообразно его функции: "предельное число шагов" (Hop Limit). Длина его по-прежнему будет 8 бит. По смыслу это поле не может быть дробным или отрицательным, поэтому оно целое беззнаковое.

По первоначальному замыслу, поле TTL в IPv4 отсчитывало именно время, а не шаги, чтобы заодно управлять интервалами таймеров на узле назначения. Так, в первом эталонном алгоритме сборки пакета IPv4 из фрагментов интервал таймера сборки был функцией от остаточного значения TTL [§3.2 RFC 791]. Однако впоследствии от этого подхода отказались в пользу других методов. В частности, значение тайм-аута сборки стало постоянным [§3.3.2 RFC 1122].

Правила работы с полем "предельное число шагов" [§3 RFC 2460] не отличаются от общепринятой практики IPv4:

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

    В каких комментариях нуждаются эти простые требования?

  • Во-первых, если узел-источник намерен передать пакет в сеть, то пакету предстоит хотя бы один шаг. Поэтому начальное значение поля "предельное число шагов" обязано быть больше нуля.
  • Во-вторых, узел проверяет данное поле только после того, как он убедится, что пакет транзитный и подлежит дальнейшему продвижению. Напротив, если пакет только что создан текущим узлом или адресован ему, то узел это поле вообще не проверяет.
  • В-третьих, у транзитного пакета это поле может оказаться нулевым, например, из-за сбоя на предыдущем узле или по злому умыслу отправителя. Тогда в беззнаковой 8 битной арифметике декремент нулевого значения даст положительное значение 255, хотя пакет явно подлежит уничтожению. Следовательно, на практике значение поля "предельное число шагов" надо проверить перед декрементом, а не после него. Если его значение до декремента один или ноль, то пакет надо уничтожить.
Эталонная реализация IPv6 KAME2 http://www.kame.net/ хитрит: она сначала сравнивает значение поля с единицей и только затем уменьшает его (или уничтожает пакет, если значение уже единица или меньше, то есть ноль). Алгоритм, приведенный в стандарте [§4.4 RFC 2460], тоже применяет этот трюк. Тем не менее, основной текст стандарта [§3 RFC 2460] обходит молчанием случай, когда поле "предельное число шагов" заранее содержит ноль. Это, конечно же, недоработка.

Поле длины пакета необходимо на тот случай, если канальный уровень не сохраняет точную длину полезной нагрузки кадра. Хрестоматийный пример — это Ethernet, где длина полезной нагрузки не может быть ниже 46 байт из-за наследия CSMA/CD. Другой возможный пример — это канальный протокол, длина полезной нагрузки в котором должна быть кратна, скажем, восьми байтам.

Подобное ограничение можно встретить в защищенных протоколах с блочным шифрованием, но оно не всегда заметно их потребителям. Например, подсистема шифрования PPP маскирует ее, сохраняя и восстанавливая точную длину полезной нагрузки с помощью особой набивки, в которой закодирована информация о числе добавленных в конец полезной нагрузки байтов [§6.1 RFC 2419]. Располагая такой информацией, приемник PPP может точно "срезать" набивку без вреда для полезной нагрузки.

Трасса пакета заранее неизвестна, так что поле длины потребуется в каждом пакете — ведь никто знает, сквозь какие каналы ему придется пройти. Пусть единицей измерения длины пакета остается байт, а пакет состоит из целого числа байтов; ведь это очень удобно, учитывая ориентацию всей технологии обработки данных на байты.

Хотя исторически байт не всегда был одной и той же длины, и потому возник альтернативный термин "октет", обозначавший именно цепочку из 8 бит, по состоянию на сегодняшний день это полные синонимы. Мы предпочитаем термин "байт", так как он понятен большей аудитории, а "октет" уже звучит старомодно, почти как французские реплики героев Льва Толстого.

Сергей Субботин
Сергей Субботин

"Теоретически канал с адресацией EUI 64 может соединить порядка 2^63 "

запись вида 2^63  не понятна и отнимает время на попытку ее осмыслить.

ее можно заменить например на записи вида  264  или 1,8 * 1019

 

Павел Афиногенов
Павел Афиногенов

Курс IPv6, в тексте имеются ссылки на параграфы. Разбиения курса на параграфы нет.

Александр Худышкин
Александр Худышкин
Россия
Константин Второв
Константин Второв
Россия, Бокситогорск, ЛГОУ им. А.С.Пушкина, 2003