Протокол управления передачей (TCP), стандартизированный в спецификации RFC 793 в 1981 году, остается фундаментальной основой сетевого взаимодействия. При возникновении сбоев сокета или внезапном разрыве соединения протокол использует флаг сброса (RST) для мгновенного закрытия сессии и освобождения ресурсов операционной системы. Однако из-за отсутствия криптографической аутентификации в заголовках TCP любой транзитный узел, способный наблюдать или подбирать параметры сессии, может сформировать поддельный сегмент сброса.

Этот класс угроз известен как внедрение пакетов TCP RST (TCP RST Injection). Системы глубокого анализа пакетов (DPI), промежуточные сетевые экраны и злоумышленники на маршруте используют поддельные пакеты RST для принудительного прерывания загрузок файлов, разрыва сессий защищенной оболочки (SSH), баз данных и веб-трафика.

Для понимания уязвимости стандартного TCP перед слепыми атаками в пределах окна приема (blind in-window attacks) необходимо проанализировать математику окна TCP, механизмы спецификации RFC 5961 и криптографическую инкапсуляцию сетевого уровня.

[Стандартная обработка сброса в пределах окна по RFC 793]
Диапазон окна приема: [RCV.NXT = 10 000] <──────── 1 048 576 байт ────────> [1 058 576]
                                                       ▲
                                   Поддельный RST: SEQ = 450 000
                                   (Принят! Сокет немедленно закрывается)

─────────────────────────────────────────────────────────────────────────────────────────────

[Строгая верификация сброса по RFC 5961]
Диапазон окна приема: [RCV.NXT = 10 000] <──────── 1 048 576 байт ────────> [1 058 576]
                      ▲                                ▲
Принимается только SEQ == 10 000!      RST внутри окна вызывает Challenge ACK;
                                       Соединение сохраняется активным и стабильным.

Анатомия внедрения пакетов TCP RST и архитектурный дефект окна приема

В первоначальной спецификации RFC 793 стек TCP в состоянии установленного соединения (ESTABLISHED) обрабатывает входящий пакет с установленным флагом RST на основе базовой проверки границы окна. Пакет считается валидным при соблюдении условия:

$$\text{RCV.NXT} \le \text{SEG.SEQ} < \text{RCV.NXT} + \text{RCV.WND}$$

Где $\text{RCV.NXT}$ — следующий ожидаемый порядковый номер, а $\text{RCV.WND}$ — объявленный размер окна приема.

В 1980-х годах размеры буферов и окон были невелики (обычно до 64 КБ). Однако современные высокоскоростные каналы повсеместно применяют масштабирование окна TCP Window Scale (RFC 7323), что расширяет окно приема до сотен килобайт или нескольких мегабайт (типично от 256 КБ до 4 МБ).

Такое расширение окна кардинально снижает стойкость перед атаками подбора порядковых номеров:

  1. Сужение пространства поиска: В 32-битном пространстве ($2^{32} \approx 4,29 \times 10^9$ значений) подбор точного порядкового номера требует миллионов попыток. Но для попадания в окно размером 2 МБ атакующему достаточно попасть в диапазон из $2,097,152$ последовательных номеров.
  2. Высокая вероятность успеха: Вероятность попадания одного сгенерированного номера в активное окно составляет $\frac{\text{RCV.WND}}{2^{32}}$. При окне 2 МБ отправка всего нескольких тысяч поддельных пакетов гарантирует сброс соединения.
  3. Асимметрия затрат ресурсов: Источник атаки отправляет короткие служебные пакеты размером 40–54 байта с минимальной нагрузкой на канал, в то время как целевая система немедленно уничтожает структуры сокета и уведомляет приложение об аварийном разрыве связи.

Оборудование на пути следования трафика (on-path middlebox) не нуждается в подборе. Анализируя незашифрованный 5-кортеж параметров IP и считывая открытые заголовки TCP, устройство извлекает текущие значения $\text{SEG.SEQ}$ и направляет встречные пакеты RST обоим участникам обмена.

Защитные механизмы RFC 5961 и уязвимость канала утечки Challenge ACK

В августе 2010 года комитет IETF утвердил спецификацию RFC 5961 для защиты стека TCP от слепых атак внедрения RST, SYN и поврежденных данных. Стандарт внес ключевые изменения в логику работы протокола:

1. Строгая проверка порядкового номера для пакетов RST

Согласно разделу 3.2 RFC 5961, входящий сегмент RST принимается для немедленного закрытия соединения только тогда, когда порядковый номер строго равен ожидаемому значению:

$$\text{SEG.SEQ} == \text{RCV.NXT}$$

Если порядковый номер находится в пределах активного окна, но не совпадает точно ($\text{RCV.NXT} < \text{SEG.SEQ} < \text{RCV.NXT} + \text{RCV.WND}$), стек TCP не разрывает соединение. Вместо этого он генерирует и отправляет обратно проверочный пакет Challenge ACK:

Клиент                                                       Сервер
   |                                                            |
   | ------- Поддельный RST (Внутри окна, SEQ != RCV.NXT) -----> |
   |                                                            |
   | <------ Challenge ACK (SEQ = SND.NXT, ACK = RCV.NXT) ----- |
   |                                                            |
   | (Сторонний атакующий не может ответить; передача продолжается)

Пакет Challenge ACK содержит действительное текущее значение $\text{RCV.NXT}$. Если запрос на сброс был подлинным (например, удаленный узел действительно перезагрузился), удаленный хост в ответ отправит корректный RST с точным порядковым номером из поля ACK. Если пакет был сгенерирован злоумышленником, легитимный партнер проигнорирует неожиданный Challenge ACK, и поток данных продолжится без прерывания.

2. Ограничение частоты Challenge ACK и уязвимость CVE-2016-5696

Генерация ответов на каждый мусорный пакет создает риск атак типа "отказ в обслуживании" (DoS). Поэтому RFC 5961 предписывает ограничение частоты генерации Challenge ACK.

В ядре Linux этот параметр задается через sysctl-переменную net.ipv4.tcp_challenge_ack_limit, изначально имевшую значение 100 или 250 пакетов в секунду на всю систему.

В 2016 году группа исследователей под руководством Чжиюня Цяня (Zhiyun Qian) выявила критическую уязвимость в этом механизме (CVE-2016-5696). Так как счетчик лимита был глобальным для всей операционной системы, сторонний атакующий вне сетевого маршрута мог открыть собственное легитимное TCP-соединение с сервером. Отправляя проверочные пакеты в свой сокет и замеряя количество полученных Challenge ACK, злоумышленник определял, был ли исчерпан глобальный лимит тестовым пакетом, направленным в сессию жертвы.

Этот побочный канал позволял:

  • За секунды определить точный эфемерный порт клиента.
  • Восстановить рабочий диапазон порядковых номеров активного соединения.
  • Внедрить вредоносные данные или принудительно разорвать соединение вопреки защите RFC 5961.

Уязвимость была устранена в ядре Linux путем внедрения рандомизированных лимитов и разделения таймеров между отдельными сокетами.

Обнаружение внедренных пакетов RST в сетевом трафике

Сетевые инженеры могут диагностировать факты внедрения пакетов сброса с помощью утилит tcpdump и Wireshark. Поддельные пакеты от промежуточных устройств почти всегда содержат характерные физические аномалии:

# Перехват подозрительных пакетов RST на внешнем интерфейсе eth0
sudo tcpdump -ni eth0 'tcp[tcpflags] & tcp-rst != 0' -vvv -c 20

Четыре основных признака внедрения:

Параметр заголовка Подлинный удаленный узел Внедренный пакет middlebox
Время жизни IP (TTL) Естественное затухание по числу хопов (например, 53) Аномальный TTL (например, 64 от соседнего маршрутизатора)
Размер окна TCP Соответствует состоянию буфера Жестко заданные константы (0, 512 или 16384)
Опции TCP Options Присутствуют SACK-Permitted, Timestamps Полное отсутствие опций (базовый 20-байтный заголовок)
Идентификатор IPID Монотонный рост или рандомизация Фиксированный ноль или сбитая последовательность

Резкий скачок TTL с 52 до 62 в потоке пакетов RST служит доказательством генерации пакета промежуточным узлом связи.

Настройка параметров ядра операционной системы

Для усиления устойчивости к слепому подбору параметров администраторы могут скорректировать параметры ядра:

# Проверка текущего лимита Challenge ACK в Linux
sysctl net.ipv4.tcp_challenge_ack_limit

# Увеличение лимита и включение рандомизации
sudo sysctl -w net.ipv4.tcp_challenge_ack_limit=2000

# Проверка активности масштабирования окон и SACK
sudo sysctl -w net.ipv4.tcp_window_scaling=1
sudo sysctl -w net.ipv4.tcp_sack=1

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

Криптографическая изоляция сетевого уровня в VPNRice RiceGuard

Коренная причина уязвимости к инъекциям RST заключается в отсутствии криптографической аутентификации заголовков IPv4 и IPv6. Пока управляющие флаги транспортного уровня передаются в открытом виде, промежуточные системы сохраняют возможность манипуляции потоками.

Шифрование прикладного уровня (TLS 1.3 или SSH) защищает полезную нагрузку, но оставляет внешние заголовки IP и TCP открытыми. Система глубокого анализа, обнаружив индикатор имени сервера (SNI) или целевой адрес, способна немедленно инжектировать RST и разорвать транспортный сокет, даже не имея доступа к содержимому TLS.

[Передача без криптографической защиты L3: риск внедрения RST]
Заголовок IP | Заголовок TCP (Флаг RST, SEQ) | Данные TLS
                    ▲
                    Промежуточный узел внедряет RST -> Соединение сброшено!

─────────────────────────────────────────────────────────────────────────────────────────────

[Инкапсуляция в VPNRice RiceGuard: криптографический барьер]
Внешний IP | Внешний UDP (WireGuard) | Код ChaCha20-Poly1305 | [Внутренний IP | Внутренний TCP | Данные]
                                                  ▲
                                Все заголовки зашифрованы и подписаны!
             Пакеты без валидной криптографической подписи отбрасываются.

VPNRice устраняет эту уязвимость за счет инкапсуляции всего трафика в криптографически изолированный туннель 3-го уровня на базе протокола RiceGuard:

  • Аутентифицированное шифрование (AEAD): Каждый передаваемый пакет шифруется алгоритмом ChaCha20 и защищается 128-битным имитовставочным кодом Poly1305.
  • Сокрытие служебных заголовков: Порядковые номера TCP, флаги, размеры окон и квитанции помещаются внутрь зашифрованного тела внешних UDP-дейтаграмм. Для внешнего наблюдателя трафик неотличим от случайного криптографического шума.
  • Мгновенная отбраковка фальсификаций: При попытке инъекции поддельного пакета RST в поток данных пакет не проходит проверку целостности Poly1305 и отбрасывается на уровне ядра на полной скорости сетевого интерфейса, не достигая внутреннего стека TCP.
  • Защита структуры DNS: Разрешение доменных имен направляется через защищенные Anycast-узлы, функционирующие в оперативной памяти (RAM-only), исключая утечки метаданных.

Перенос криптографической аутентификации на уровень сетевого интерфейса гарантирует стабильность и устойчивость сессий TCP к попыткам принудительного разрыва на ненадежных участках сети.