Я хотел бы знать, как анализировать заголовок 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.