Заголовок IPv6: фиксированный размер 40 байт, упрощённая структура, Flow Label и механизм Extension Headers.
Каков размер заголовка IPv6?
Кто выполняет фрагментацию в IPv6?
Для чего предназначено поле Flow Label в IPv6?
Какой минимальный MTU определён для IPv6?
Какие Extension Headers обрабатываются маршрутизаторами?
Когда мы отсылаем IP-пакеты, мы знаем, что IP-пакеты содержат некий заголовок, куда пишутся всякие разные служебные данные, и в IPv6 ситуация абсолютно точно такая же. Каждый пакет имеет некий заголовок, и в этом заголовке указывается служебная информация: кто, чего, кому. И по сравнению с IPv4 этот заголовок упростили. То, что было откровенно не нужно, убрали. То, что было нужно иногда, но не всегда, вынесли в опциональные заголовки. И идею, которая изначально была у IPv4 — давайте сделаем какое-то место, куда можно написать что-нибудь при необходимости, но чтобы не каждый раз это посылать, а только когда надо, то, что предлагали сделать в поле опций — в IPv6 эту идею развили, сделали её жизнеспособной. В IPv4, мы знаем, поле опций не использовалось, хотя оно было предназначено для того, чтобы туда класть что-нибудь, но транзитные узлы должны были уметь это читать,
потому что это поле находится в заголовке, и весь заголовок вы должны были понять для того, чтобы осмыслить, нужно вам это читать или не нужно. В IPv6 сказали, что у нас не будет этого поля options, у нас будет красивый заголовок фиксированного размера, но если вдруг нам нужно будет что-то добавить в этот заголовок, чего нормально передавать не надо, у нас будут так называемые опциональные заголовки. И эти опциональные заголовки будут иметь предсказуемый формат, из которого будет понятно, кто должен читать этот заголовок — только транзитный узел или конечный абонент. Если вдруг транзитный роутер получает IPv6-пакет и видит какой-то дополнительный заголовок, который он не может понять, он его может пропустить, если там будет написано, что это ему не нужно читать. Если у нас есть какой-то фиксированный заголовок, а дальше идёт опциональный заголовок, и в нём написано: это для конечного абонента, и следующий заголовок тоже только для конечного абонента — транзитный узел может не пытаться понять, что там написано.
Да, это расширение функции протокола IP. Да, это та самая идея, которая изначально закладывалась в поле опций. Но поле опций было монолитное для всех, и поэтому все узлы — и получатель, и исходный отправитель, и все транзитные роутеры — должны были его уметь понимать. А в этой штуке будет написано, кто должен её уметь понимать. Если вдруг какой-то транзитный роутер видит заголовок, который написано, что он должен обработать, но он его обработать не может, он его, конечно, выкинет. Но количество таких ситуаций будет экстремально редкое, потому что транзитным роутерам очень редко требуется указывать что-то, что они не понимают. А конечные абоненты уже смогут друг другу какую-то дополнительную информацию, которая к IP относится, передавать. Давайте рассмотрим, что у нас есть в каждом из этих заголовков — в фиксированном и в опциональных. Во-первых, у нас есть первые 4 бита — поле версии. Так же, как в IPv4 мы вкладывали 0100, число 4,
здесь мы вкладываем число 6. Это, соответственно, 0110. В первые 4 бита мы вкладываем шестёрку для того, чтобы понять, что это именно IPv6-пакет. Делаем мы это больше в целях сохранения традиций, чем потому, что это действительно нужно. Но почему бы не сделать так? Когда-то давным-давно могла быть ситуация вида: вы получили нечто, и вам, перед тем как тратить ресурсы, надо понять, это вообще является протоколом IP или нет. Потому что если вы начнёте обрабатывать как IP-пакет любую битовую колбасу, которая к вам прилетает, есть шанс того, что вы что-то не то дообрабатываетесь, и ценные ресурсы, которые у вас были бы потрачены на что-то полезное, вы вынуждены тратить на что-то бесполезное. В 70-х годах, когда это придумывалось, это было очень актуально. Сегодня, как вы понимаете, никаких проблем нет с тем, чтобы гигагерц лишний процессора просто выдать под то, чтобы он всё подряд считал, а то, что не нужно, просто отбрасывал.
Поле Traffic Class, которое то же самое по смыслу, что Type of Service в IPv4, который потом переименовали в DSCP и ECN. Здесь тоже есть два подполя — DSCP и ECN. Те же самые, которые в IPv4 есть, это то же самое поле, оно никак не изменилось. Далее. 20-битовая метка потока Flow Label, про неё отдельно расскажу. Указание того, сколько данных лежит внутри после фиксированного заголовка. Это нечто, напоминающее Total Length в заголовке IPv4, но разница заключается в том, что Total Length в IPv4 указывал размер пакета вместе с заголовком, а эта штука указывает размер содержимого после того, как фиксированный заголовок закончится. Она указывает размер payload фиксированного заголовка. Поэтому у вас есть отдельно заголовок и отдельно всё, что в него вложено.
Здесь указывается то, сколько вложено данных. Если вы помните, в заголовке IPv4 было поле IHL, которое указывало на размер заголовка в машинных словах, и было поле Total Length, которое указывало на суммарный размер данных. Поэтому вы размер полезной нагрузки могли вычислить. Вы брали Total Length, вычитали из него IHL, умноженное на 4, и получали результат. Здесь у вас сразу написано, сколько полезных данных, потому что размер самого пакета вы, как правило, можете увидеть. К вам прибегают 48 байт — это 48 байт пакета. Здесь никаких сложностей с этим нет. Самого поля IHL в IPv6 тоже нету. По очевиднейшей причине — оно не нужно. IHL было нужно для того, чтобы указать, что в поле опций что-то лежит. Здесь поля опций нету, заголовок фиксированного размера, всегда одинаковый, обрабатывать его легче и проще. Поэтому поле IHL не нужно.
Поле NextHeader. Это то же самое, что раньше было поле Protocol. Только поле Protocol фактически указывало на то, что лежит внутри, и предполагалось, что это уже сразу полезная нагрузка. И в IPv4 появлялись всякие разные нехорошие пограничные ситуации, когда у вас есть заголовок IP, есть какое-то дополнительное содержимое, которое нужно для того, чтобы расширить функциональность IP, потому что поля опций нету, но как-то выходить из ситуации надо, и есть уже полезные данные. И у вас было поле Protocol, которое указывало, что внутри лежит. Но само название «протокол» намекает на то, что вы указываете тип полезных данных. И по факту, когда у вас была такая схема-матрёшка — заголовок IP, потом какой-то служебный заголовок, например IPsec, и потом уже полезные данные — вы в поле Protocol вкладывали не тип полезных данных, а этот самый IPsec. И получалось, что смысл немножко терялся. Вы говорили, что у вас вложены данные формата IPsec, протокол IPsec.
Здесь переименовали это поле. Оно делает точно то же самое — указывает на следующее вложение, которое есть сразу после заголовка IP. У нас есть опциональный заголовок, возможно, а может быть, его и нет. И поле NextHeader указывает на то, какого типа этот заголовок будет. И у каждого опционального заголовка тоже есть такое же поле. NextHeader указывает на то, какого типа следующий заголовок будет. И так этих заголовков может быть много, но у самого последнего NextHeader будет указывать на то, какого типа будут полезные данные. Это то же самое, что поле Protocol раньше. NextHeader указывает на заголовок, у которого тоже есть поле NextHeader, которое указывает на следующий заголовок. И когда всё это дело приходит к полезным данным, и здесь будет какой-то ICMP, к примеру, в NextHeader будет указываться тип следующего заголовка, который, по сути, уже не опциональный заголовок, а заголовок от полезных данных — это заголовок ICMP.
HopLimit, бывшее поле TTL. Переименовали его, чтобы лучше отражать смысл, потому что даже в 92-м году, когда начались работы над IPv6, и тем более в 98-м году, когда его стандартизовали, уже абсолютно все роутеры с абсолютно любыми скоростями, с которыми в реальности приходилось работать, обрабатывали любой пакет меньше чем за секунду. Поэтому любой роутер в современном мире из поля TTL вычитает не больше единицы. Поэтому, по факту, поле TTL превратилось в количество прыжков между роутерами, и здесь его так и назвали. HopLimit — это количество прыжков между роутерами, которое пакет может пройти. Это уже не про время, а про количество роутеров. Смысл не изменился, и каждый раз мы вычитаем из него единичку, и если вдруг получается ноль, убиваем пакет. То же самое, только переименованное. Про версию рассказал, про Traffic Class рассказал. Это те же самые DSCP и ECN.
Поле может меняться маршрутизаторами. Если вы заказываете какой-то Traffic Class, то совершенно не факт, что такой же Traffic Class долетит до конечного получателя. В каждом домене Quality of Service это поле может быть изменено. Flow Label — здесь опечатка, всё руки не доходят её исправить. 20 бит. Это поле метки потока. Смысл заключается вот в чём. В IPv6 практически обязательна поддержка IPsec. И вы можете на уровне IPv6 сказать, что любые данные, которые мы отправляем, будут зашифрованы. И если вы это делаете, то содержимого вложения в IPv6 не видно. Если у вас есть компьютер-отправитель, компьютер-получатель и транзитные роутеры в цепочке, вы, отправляя какие-то полезные данные, скрываете, что там внутри лежит. Если у вас есть вариант, допустим, пойти одной трассой и пойти другой трассой, трафик может пойти напрямую, может пойти в обход.
И гипотетически может быть такое, что какой-то конкретный роутер говорит: я буду в целях оптимизации нагрузки балансировать трафик — часть пускать в одну сторону, часть в другую. Если вы будете все свои пакеты одинаковым образом шифровать, то не будет понятно, какой пакет к какому приложению относится. Если у вас здесь есть приложение Telnet и приложение SMTP, электронная почта, и на другой стороне тоже Telnet и SMTP, то трафик, который у вас будет ходить в рамках одного и того же приложения, может в итоге разбрасываться по разным трассам, потому что не видно, какое приложение задействовано в конкретном пакете. Все пакеты монолитные, все пакеты одинаковые. Но если вы используете метку потока, вы, отправляя пакет, в нём делаете это 20-битное указание, что это поток номер 199. Это не поля заголовка TCP, которые не видны, потому что он зашифрован,
а это некая отсылка к полезному приложению, которое использует определённые данные. И все данные, которые идут в рамках конкретного приложения, допустим Telnet, будут иметь одинаковый номер потока. И все пакеты, которые будут отправляться в рамках одного и того же приложения, в предположении, что все роутеры анализируют эту метку потока, они будут идти одной и той же трассой. И у нас Telnet будет идти одной трассой, а SMTP, возможно, в рамках балансировки будет идти другой трассой. И трафик в рамках одного и того же приложения не будет разбрасываться между разными трассами. Таким образом получится, что мы можем облегчить жизнь транзитным роутерам и в то же время не пострадать в части направления трафика одного и того же приложения разными трассами, которое приведёт к resequencing. У нас сменится порядок следования пакетов, к непредсказуемым задержкам и всякие разные другие подобные вещи. Поэтому эта штука нужна для упрощения жизни транзитным узлам.
Отправитель её проставляет. Для каждого приложения генерируется эта метка потока. И таким образом транзитные узлы могут определить, что некоторые пакеты с непонятным, но зашифрованным содержимым относятся к одному и тому же приложению, к одной и той же сессии. И пакеты, которые относятся к разным сессиям, могут идти по разным трассам. Пакеты, которые относятся к одному и тому же приложению, пойдут по одной и той же трассе. Это улучшает качество обслуживания и иногда используется для облегчения маршрутизации. Далее. Payload Length — тоже уже всё про неё рассказал. Если вы указываете размер полезных данных, то это без учёта фиксированного заголовка. Но если есть опциональные заголовки, то они сюда тоже включаются. Размер поля 16 бит, такой же, как в IPv4, то есть 65 535 байт полезной нагрузки вы можете впихать. Есть нюанс. Если вы очень сильно хотите,
вы можете воспользоваться опцией, которая называется Jumbo Payload. Вы в дополнительный опциональный заголовок уложите размер вашего пакета, и он там может быть сильно больше, чем 65 535 байт, если вам это будет нужно. Если вы это заказываете, то в Payload Length вы выставляете 0, и это предполагает, что дальше обязательно последует заголовок Jumbo Payload. И там уже можно указать размер пакета до гигабайта. Опять же, голубиная почта: взяли голубя, приклеили к нему на лапку microSD-карточку и отправили в путешествие, он у вас долетел до получателя. Очень в некоторых ситуациях полезная вещь, но сугубо в некоторых. В реальности опции очень редко используются. HopLimit, бывшее поле TTL, по сути то же самое поле, которое мы используем сегодня, но переименованное. NextHeader — это бывшее поле Protocol. По сути то же самое поле, только, опять же, переименованное.
Что касается классических стандартных значений для этого поля: 6, 17 — TCP, UDP — всё то же самое, ничего не изменилось. 50, 51 — это тоже всё то же самое. Конечные приложения, которые используют напрямую инкапсуляцию в IP, будут иметь точно такие же номера. Есть небольшие новые заголовки, которые вы должны будете знать. Во-первых, ICMP, который в IPv6 тоже есть, он там немножко отличается от ICMP классического. Поэтому если вы хотите указать, что в IPv6 у вас вкладывается именно ICMP для IPv6, у вас там новое число будет 58. И если вы хотите, чтобы у вас работала фрагментация, то это всё вынесено в отдельную опцию, которая называется опция 44. С фрагментацией в IPv4 всё было плохо, потому что она позволяла в любом месте сети гипотетически взять ваш пакет и порезать на части.
Эта штука причиняла много неудобств. Да, она позволяла без оглядки на размер пакета передавать данные практически любого размера, но она приносила больше проблем, чем пользы. В IPv6 эту самую фрагментацию не то чтобы прямо убрали совсем. IPv6 фрагментацию имеет. Но фрагментация в IPv6 выполняется только на отправителе, она не выполняется где попало. Не транзитные узлы будут её делать, как в IPv4, а только отправитель. Если он хочет отправить большие данные, которые где-то в сеть не пролезают, он должен резать пакет на части. Если он отправляет какой-то пакет, который не пролезает где-то в транзитном роутере в интерфейс назначения, роутер обязательно прибивает пакет и отправляет сообщение «я прибил твой пакет, потому что он слишком жирный». Packet Too Big — ICMP тип 3, код 4. И в этом Packet Too Big обязательно пишется размер MTU, который такой роутер может пропустить.
И узел, который должен отправить большие пакеты, но не может это сделать, свой большой пакет будет обязательно резать на мелкие части и отправлять по частям. Это предполагает, что у вас ведётся учёт всех назначений, куда вы отправляете IP-пакеты, и для каждого места назначения вы храните максимальный размер пакета, который пролезает до каждого отдельного узла. Немножко усложняет эта конфигурация, но тем не менее заметно упрощает жизнь транзитному роутеру, который больше не заботится о том, что в какой-то момент его внезапно могут напрячь фрагментацией. Фрагментация — штука очень затратная, она действительно отъедает очень много ресурсов у роутера, поэтому то, что в IPv6 её на транзитных роутерах нет, это очень сильно упрощает им жизнь. Вот такой заголовок в IPv6, формат заголовка другой,
размер IP-адреса другой, но в целом всё остальное в IPv6 работает точно так же. Единственное, что служебный протокол ICMP — сейчас мы посмотрим и убедимся, что некоторые вещи, которые появились, стали сильно лучше, чем были в IPv4. Примечание: фрагмент с [18:00] по [18:29] содержит нераспознаваемый текст (ошибка транскрипции) и был исключён.