Криптографические алгоритмы транспортного уровня защищают датаграммы IP от перехвата и изменения содержимого. Современные шифры вычисляют контрольное значение целостности (ICV), подтверждающее подлинность каждого отдельного фрейма. Однако аутентификации изолированных пакетов недостаточно для защиты сетевых протоколов без установления соединения от атак повторного воспроизведения.

Без отслеживания строгой последовательности злоумышленник на промежуточном маршруте может перехватывать зашифрованные пакеты и передавать их дубликаты на шлюз назначения. Такие пакеты успешно проходят проверку контрольной суммы, расходуют ресурсы процессора, нарушают работу конечных автоматов и приводят к отказу в обслуживании. Для устранения этой угрозы стандарт IPsec Encapsulating Security Payload (ESP, RFC 4303) предписывает использование порядковых номеров и скользящего окна защиты от повторов.

Роль порядковых номеров в криптографических сетевых туннелях

Туннели без постоянного соединения инкапсулируют IP-пакеты 3-го уровня во внешние заголовки IP или UDP. Поскольку промежуточные маршрутизаторы передают пакеты по различным маршрутам, данные нередко приходят с нарушением очередности или дублируются в пути.

В рамках ассоциации безопасности IPsec (Security Association, SA) отправитель присваивает строго возрастающий порядковый номер каждому отправляемому пакету ESP. Этот номер выполняет две важные задачи:

  1. Служит уникальным материалом для векторов инициализации (IV) и одноразовых кодов AEAD, предотвращая повторное использование ключевых потоков.
  2. Позволяет принимающему узлу обнаруживать дубликаты и отбрасывать пакеты, находящиеся за пределами допустимого диапазона приема.
+-----------------------------------------------------------------------------+
|                ИНКАПСУЛЯЦИЯ ПАКЕТОВ IPSEC ESP (RFC 4303)                    |
+-----------------------------------------------------------------------------+
| Внешний IP-заголовок | SPI (32 бита) | Порядковый номер (32 бита) | Данные  |
+-----------------------------------------------------------------------------+

Отправитель никогда не уменьшает значение счетчика на протяжении всего жизненного цикла активной ассоциации SA. При достижении предельного значения счетчика система должна согласовать новую SA через протокол IKEv2 перед отправкой последующих данных.

Механика скользящего окна защиты от повторов IPsec ESP (RFC 4303)

Сетевая среда допускает доставку пакетов не по порядку, поэтому принимающий шлюз IPsec не может просто отбрасывать любой пакет с номером меньше предыдущего. Стандарт RFC 4303 определяет алгоритм скользящего окна на основе битовой маски шириной $W$, которая обычно настраивается в диапазоне от 32 до 1024 бит.

       <- Старые отбрасываются -> | <- Скользящее окно (Ширина W) -> | <- Будущие ->
  ... ----------------------------+----------------------------------+-------------> Номера
                                  ^                                  ^
                               (M - W + 1)                           M (Макс. принятый)

Принимающий узел отслеживает две переменные:

  • $M$: наибольший порядковый номер, успешно прошедший проверку подлинности.
  • Битовая маска размером $W$: отражает статус $W - 1$ номеров, предшествующих $M$.

Смещение окна и отслеживание состояния битовой маски

При поступлении входящего пакета ESP с номером $S$ шлюз проверяет $S$ относительно границ окна до выполнения ресурсоемкой операции дешифрования:

  • Случай 1 ($S > M$): Пакет новее всех ранее полученных. Шлюз проверяет ICV. При успешной проверке маска смещается влево на $(S - M)$ позиций, устанавливается $M = S$, а бит для $S$ отмечается единицей.
  • Случай 2 ($M - W + 1 \le S \le M$): Пакет попадает внутрь окна. Шлюз проверяет бит со смещением $(M - S)$. Если бит уже установлен, пакет отбрасывается как дубликат. Если бит чист, выполняется аутентификация ICV, и бит устанавливается в 1.
  • Случай 3 ($S < M - W + 1$): Пакет оказывается левее окна. Шлюз немедленно уничтожает пакет без дешифрования и увеличивает счетчик сброшенных повторов.

Логика отбрасывания устаревших и дублирующихся пакетов ESP

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

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

Исчерпание 32-битного пространства номеров на высоких скоростях

В исходной спецификации IPsec (RFC 2401) под номер ESP выделялось 32 бита. Это пространство рассчитано на $2^{32} - 1 \approx 4.29 \times 10^9$ пакетов до переполнения. На гигабитных и терабитных магистралях этот запас исчерпывается крайне быстро:

Скорость канала Размер пакета Интенсивность трафика Время до переполнения
1 Гбит/с 1400 байт 89.2 тыс. пак/с 13.3 часа
10 Гбит/с 1400 байт 892.8 тыс. пак/с 80.0 минут
40 Гбит/с 1400 байт 3.57 млн пак/с 20.0 минут
100 Гбит/с 1400 байт 8.92 млн пак/с 8.0 минут
100 Гбит/с 64 байта 148.8 млн пак/с 28.8 секунды

Если в ассоциации SA заканчиваются номера без поддержки расширенной нумерации, передача приостанавливается до повторного согласования через IKEv2. Частая смена ключей вызывает пиковые нагрузки на процессор и приводит к микропаузам.

Расширенные порядковые номера ESN: защита 64 бит без издержек

Стандарты RFC 4303 и RFC 4304 вводят расширенные порядковые номера (Extended Sequence Numbers, ESN), увеличивая пространство до 64 бит ($2^{64} - 1 \approx 1.84 \times 10^{19}$ пакетов). При скорости 100 Гбит/с со сверхмалыми фреймами счетчик способен непрерывно работать тысячелетиями без пересогласования.

При этом формат внешнего заголовка ESP сохраняется без изменений. По сетевому кабелю по-прежнему передаются только младшие 32 бита ($Seq_{low}$).

+-----------------------------------------------------------------------------+
|               АРХИТЕКТУРА РАСШИРЕННЫХ НОМЕРОВ (ESN, RFC 4303)               |
+-----------------------------------------------------------------------------+
| В заголовке пакета:      [ SPI (32 бита) ] [ Младшие 32 бита номера ]       |
| В памяти шлюза:          [ Старшие 32 бита номера ]                         |
| Аутентификация ICV:      [ Неявные старшие 32 бита ] + [ Весь кадр ESP ]    |
+-----------------------------------------------------------------------------+

Восстановление старших битов через неявное состояние счетчика

Поскольку по сети передается только $Seq_{low}$, получатель вычисляет старшие 32 бита ($Seq_{high}$) на основе позиции скользящего окна:

  1. Если $Seq_{low} \ge M_{low}$, пакет принадлежит текущей эпохе, и шлюз принимает $Seq_{high} = M_{high}$.
  2. Если $Seq_{low} < M_{low}$ в границах окна, шлюз сопоставляет $Seq_{low}$ со значением $M_{high}$.
  3. Когда $M_{low}$ приближается к границе переполнения $2^{32} - 1$, система определяет, перешел ли пакет в эпоху $M_{high} + 1$ или является запоздавшим кадром эпохи $M_{high}$.

Для защиты от десинхронизации контрольное значение ICV охватывает полный 64-битный номер. При попытке подделать номер на стыке эпох проверка целостности не проходит, и пакет отбрасывается.

Многоочередная маршрутизация NIC и переупорядочивание пакетов

Шлюзы распределяют входящую нагрузку между ядрами CPU с помощью технологии Receive Side Scaling (RSS). Для незашифрованных потоков RSS использует 5 параметров (протокол, IP источника, порт источника, IP назначения, порт назначения). Однако у пакетов ESP порты транспортного уровня скрыты внутри зашифрованного тела.

Сетевые адаптеры рассчитывают хеш ESP только по IP источника, IP назначения и 32-битному значению SPI.

[ Поток пакетов ESP ] ---> [ Аппаратный хеш RSS (IP + SPI) ]
                                    |
                    +---------------+---------------+
                    v                               v
             [ Ядро CPU 0 ]                  [ Ядро CPU 1 ]
             (Дешифрование)                  (Дешифрование)
                    \                               /
                     +-------------> <-------------+
                                    |
                    [ Нарушение очередности пакетов ]
                                    v
                 [ Проверка окна защиты от повторов ]

Конкуренция блокировок и потери пакетов при стандартных окнах

Когда несколько ядер параллельно обрабатывают пакеты одной ассоциации SA, разница в микрозадержках нарушает исходный порядок. Пакет на Ядре 1 может достичь блока проверки на сотни позиций раньше пакета на Ядре 0.

Если глубина окна $W$ оставлена на базовом значении 32 или 64 пакета, такое расхождение приводит к ложным сбросам:

  • Ядро 1 сдвигает $M$ вперед на 120 позиций.
  • Ядро 0 доставляет задержавшийся пакет с номером $S < M - W + 1$.
  • Шлюз ошибочно принимает легитимный пакет за повтор и отбрасывает его.

Ложные потери активируют механизмы повторной передачи TCP и резко снижают пропускную способность. Для проверки маршрутов сетевые инженеры могут использовать сервис узнать свой IP.

Масштабируемые битовые карты: оптимизация RFC 6479 для туннелей

Классические алгоритмы сдвигают массив маски линейно при получении каждого более нового номера. Для окон в 32 или 64 бита это выполняется за одну машинную операцию сдвига (bitmask <<= shift).

Однако устранение потерь на многоядерных шлюзах требует расширения окна $W$ до 1024 или 4096 пакетов. Сдвиг блока памяти в 4096 бит при каждом входящем кадре создает огромную нагрузку на шину памяти и вымывает процессорный кэш.

Стандарт RFC 6479 устраняет это узкое место за счет использования циклического буфера без сдвига битов:

+-----------------------------------------------------------------------------+
|              ЦИКЛИЧЕСКИЙ БУФЕР МАСКИ ПОВТОРОВ ПО RFC 6479                   |
+-----------------------------------------------------------------------------+
| Блок 0 (64 бита) | Блок 1 (64 бита) | ... | Блок N (64 бита)                |
+-----------------------------------------------------------------------------+
         ^                                      ^
   Индекс: (Seq / 64) % Число_блоков      Указатель текущей позиции

В реализации RFC 6479:

  • Битовая карта делится на фиксированные машинные слова по 32 или 64 бита.
  • Номер пакета проецируется в индекс слова через операцию деления по модулю: index = (seq / 64) % total_banks.
  • При продвижении окна очищаются только те промежуточные слова, через которые прошел указатель, без сдвига всего массива.
  • Проверка статуса выполняется за константное время $O(1)$ независимо от глубины окна.

Настройка окон защиты от повторов в стеках Linux XFRM и BSD

Современные операционные системы содержат необходимые параметры для регулирования размера окон и включения ESN.

В Linux стек XFRM управляет параметрами IPsec через утилиту iproute2. Для настройки SA с циклическим окном на 1024 пакета и 64-битными ESN используется команда:

# Настройка состояния XFRM с окном 1024 пакета и флагом ESN
ip xfrm state add src 198.51.100.1 dst 203.0.113.1 \
    proto esp spi 0x1a2b3c4d reqid 1 mode tunnel \
    replay-window 1024 flag esn \
    aead "rfc4106(gcm(aes))" 0x0123456789abcdef0123456789abcdef01234567 128

Для проверки статистики отброшенных пакетов на шлюзе Linux:

# Просмотр счетчиков сброса по защите от повторов
ip -s xfrm state show spi 0x1a2b3c4d

Вывод команды отображает текущий replay-window и счетчик replay. Если этот счетчик растет под нагрузкой при отсутствии атак, размер окна недостаточен для компенсации задержек между ядрами.

В FreeBSD и OpenBSD глубина окна настраивается через системные переменные ядра:

# Настройка глубины окна приема пакетов IPsec в BSD
sysctl net.inet.ipsec.esp_replaywindow=1024

В демонах IKEv2 (например, StrongSwan) поддержка ESN задается в описании Child SA второй фазы добавлением суффикса esn (esp=aes256gcm128-esn!).

Как RiceGuard устраняет переупорядочивание без риска повторов

VPNRice применяет специализированный механизм оптимизации RiceGuard на всех граничных серверах сети. Вместо компромисса между строгой фильтрацией повторов и многоядерной производительностью RiceGuard использует адаптивный конвейер обработки.

[ Пользовательский трафик ] -> [ Привязка потоков RiceGuard ] -> [ Ядра шифрования ]
                                      |
                                      v
            [ Матрица окон 4096 бит RFC 6479 ] -> [ Стабильная доставка без потерь ]
  1. Привязка потоков к ядрам процессора: RiceGuard анализирует идентификаторы внутренних соединений до инкапсуляции, направляя отдельные сессии TCP и UDP на закрепленные ядра CPU. Это исключает хаотичное перемешивание пакетов.
  2. Адаптивная матрица окна 4096 бит: При возникновении нестабильности на магистральных каналах BGP RiceGuard динамически увеличивает глубину окна до 4096 пакетов по алгоритму RFC 6479, предотвращая ложные сбросы.
  3. Аппаратная синхронизация ESN: Граничные шлюзы поддерживают целостность 64-битного счетчика непосредственно в криптографических ускорителях, устраняя паузы пересогласования на скорости 100 Гбит/с.

Для безопасного и надежного подключения на рабочих станциях и смартфонах доступно официальное приложение.

Скачать VPNRice.

Сетевым инженерам, проектирующим магистральные каналы, рекомендуем ознакомиться с разбором субсекундного обнаружения сбоев BFD и материалом о скользящих окнах в WireGuard. Также полезно изучить руководство по алгоритму управления перегрузками TCP BBR.

Контрольный список внедрения для высокопроизводительных шлюзов

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

  • Проверка согласования ESN: Убедитесь, что конфигурация IKEv2 содержит спецификацию ESN для всех предложений ESP Child SA во избежание переполнения 32-битного счетчика.
  • Увеличение размера окна: Расширьте окно со стандартных 32/64 до как минимум 512 или 1024 пакетов на сетевых интерфейсах со скоростью от 1 Гбит/с.
  • Активация битовых карт RFC 6479: Проверьте, поддерживает ли ядро операционной системы циклические массивы без линейного сдвига памяти.
  • Оптимизация хеширования RSS: Настройте распределение очередей сетевой карты или задействуйте инкапсуляцию IPsec в UDP (NAT-T RFC 3948) для симметричного распределения потоков по ядрам.
  • Мониторинг счетчиков сброса: Настройте экспорт метрик XfrmInReplayError (Linux SNMP) или netstat -s -p esp в Prometheus для своевременного обнаружения ложных потерь.
  • Сохранение проверки целостности: Категорически избегайте полного отключения защиты от повторов (replay-window 0), так как это открывает систему для разрушительных атак типа отказ в обслуживании.