Назад | Перейти на главную страницу

IPv6 и ESP как следующий заголовок

Я хотел бы знать, как анализировать заголовок IPv6 и получать смещение заголовка TCP и его полезной нагрузки.

Я знаю, что IPv6 имеет фиксированный базовый заголовок. Я также знаю, что в IPv6 есть несколько заголовков расширений - среди прочего: маршрутизация, фрагмент, параметры назначения, ESP и т. Д.

У меня есть указатель на буфер с Ethernet-фреймом. Теперь я могу найти начало заголовка IPv6, но не могу вычислить начало заголовка TCP и его полезную нагрузку в случае, если есть заголовок ESP. Есть какой-то rfc2406, описывающий ESP, но мне он непонятен. Я не могу рассчитать размер заголовка ESP и его данных, поэтому не могу узнать смещение TCP.

У меня вопрос: как рассчитать длину заголовка расширения ESP в случае IPv6?

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

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

Поле длины интерпретируется в IPSec несколько иначе, чем в других заголовках расширения IPv6.

Для обычного заголовка расширения IPv6 вы получаете от байтового значения к длине заголовка, сначала прибавляя 1, а затем умножая на 8.

для заголовка IPSec вы получаете от байтового значения к длине заголовка, сначала прибавляя 2, а затем умножая на 4.

Почему это было так разработано

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

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

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

Но, требуя от получателя прибавить 1 и умножить на 8, две проверки больше не требуются, потому что независимо от того, к какому байтовому значению в диапазоне от 0 до 255 вы применяете это вычисление, он даст результат, который будет не менее 8 и кратно 8. В качестве дополнительного преимущества он увеличивает возможный размер заголовка расширения с 255 до 2048 байтов.

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

Почему IPSec отличается

IPSec используется как в IPv4, так и в IPv6. Но IPv4 в целом требует только 4-байтового выравнивания (оптимизировано для 32-битных ЦП), тогда как IPv6 требует 8-байтового выравнивания (оптимизировано для 64-битных ЦП). По этой причине множитель в этом случае равен 4. Хотя минимальная длина заголовка по-прежнему составляет 8 байтов.

Это означает, что когда IPSec используется поверх IPv6, получатель должен проверить, что поле длины является четным байтовым значением. Однако если предположить, что архитектура ЦП способна получить доступ к невыровненным значениям (при пониженной производительности), риск в случае, если разработчик забыл об этой конкретной проверке, незначителен. В худшем случае для обработки поврежденного пакета потребуется еще несколько циклов ЦП.

Используя это, чтобы найти заголовок полезной нагрузки

Следующий псевдокод показывает, как обрабатывать заголовки.

Initialize a pointer to the first byte of the IPv6 header.
Initialize the header type to 41.
While the header type is a known IP or extension header:
    Compute current header length
    Process current header if applicable
    Copy next header field from current header
    Move pointer forward by current header length

В этом алгоритме типы заголовков 4 и 41 являются особенными, поскольку они указывают заголовок IPv4 и заголовок IPv6.