Каждый пакет IPv4, передаваемый в глобальной сети Интернет, содержит 16-битное поле идентификации (IP ID) в своем двоичном заголовке. Определенное еще в 1981 году спецификацией RFC 791, это поле предназначалось для того, чтобы операционная система получателя могла собрать воедино фрагментированные датаграммы, превышающие MTU промежуточных каналов. На протяжении десятилетий разработчики ядер ОС реализовывали это поле простым глобальным счетчиком: при каждой отправке IP-пакета внутреннее значение увеличивалось на единицу.
Простая утилитарная функция привела к появлению одной из самых известных уязвимостей по побочным каналам в истории компьютерных сетей. Отслеживая последовательные изменения счетчика IP ID на стороннем сервере, атакующий получает возможность составлять карту защищенных брандмауэром портов на удаленной целевой системе, не отправляя при этом ни единого пакета с собственного IP-адреса, а также выявлять скрытые сетевые взаимодействия и подсчитывать активность чужих хостов.
Современные стандарты, в первую очередь RFC 6864 и криптографические протоколы туннелирования WireGuard, принципиально изменили обработку идентификаторов в сетевых стеках. Анализ побочного канала IP ID раскрывает фундаментальные принципы транспортной безопасности, изоляции состояния в ядре ОС и архитектуры защищенных туннелей.
+-------------------------------------------------------------------------+
| КЛАССИЧЕСКИЙ ТРЕУГОЛЬНИК АТАКИ IDLE SCAN |
+-------------------------------------------------------------------------+
| |
| 1. Запрос IP ID (SYN/ACK) 2. Поддельный SYN (Источник=Зомби)
| IP ID зомби = 31337 Целевой порт 443 |
| ┌─────────────────────────┐ ┌─────────────────────────┐ |
| │ ▼ │ ▼ |
| [Атакующий] [Узел-зомби] [Целевой сервер]|
| ▲ │ ▲ │ |
| │ └───────┼─────────────────────────┘ |
| 3. Повторный запрос (SYN/ACK) │ Цель отвечает SYN/ACK на зомби |
| IP ID зомби = 31339 │ Зомби шлет RST (IP ID + 1!) |
| Разница Delta = 2 -> ПОРТ ОТКРЫТ! └─────────────────────────┘ |
+-------------------------------------------------------------------------+
Происхождение поля Identification в протоколе IPv4 (RFC 791)
Согласно базовому стандарту RFC 791, если транзитный маршрутизатор встречает пакет, размер которого превышает MTU следующего сетевого сегмента, он обязан разделить датаграмму на фрагменты. Чтобы принимающая сторона могла отличить фрагменты одного пакета от фрагментов другого, передающий узел присваивает каждому исходному пакету 16-битный номер.
Приемник выполняет сборку фрагментов на основе кортежа из четырех элементов:
- IP-адрес источника (Source IP)
- IP-адрес назначения (Destination IP)
- Идентификатор протокола (Protocol ID) (например, TCP, UDP, ICMP)
- Значение идентификатора (
IP ID)
Поскольку 16 бит дают лишь 65 536 уникальных значений, ранние операционные системы (ранние версии Windows, BSD и классические ядра Linux) использовали общую глобальную переменную:
// Историческая реализация в ядре: глобальный монотонный инкремент
static unsigned short global_ip_id = 0;
void build_ip_header(struct iphdr *iph) {
iph->id = htons(++global_ip_id);
}
Такая архитектура непреднамеренно создавала открытый телеметрический маяк: любой внешний наблюдатель мог точно вычислить, сколько пакетов отправил хост за определенный временной интервал.
Анатомия Idle Scan: слепое сканирование портов через узлы-зомби
В 1998 году специалист по безопасности Сальваторе Санфилиппо (antirez) продемонстрировал, что предсказуемые счетчики IP ID позволяют проводить скрытное слепое зондирование портов. Метод получил название Idle Scan (реализован в сканере Nmap с ключом -sI) и дает возможность исследовать сеть без отправки трафика с реального сетевого адреса сканирующего.
В атаке участвуют три стороны:
- Атакующий: система, генерирующая запросы и анализирующая телеметрию.
- Узел-зомби (Zombie Host): бездействующая машина в сети с глобальным инкрементом IP ID и минимальным фоновым трафиком.
- Целевой сервер: система, чьи правила фильтрации брандмауэра и состояние портов исследуются.
Разведка строится на провоцировании целевого узла отправить сетевой ответ узлу-зомби, после чего замеряется дельта счетчика IP ID на зомби.
Пошаговое техническое выполнение атаки Idle Scan
Исследование каждого порта цели проходит через три скоординированных шага:
- Шаг 1 - Базовый зонд зомби: Атакующий отправляет внезапный пакет
SYN/ACKна узел-зомби. Так как активного соединения не существует, стек зомби возвращает пакетRST, содержащий текущий идентификатор ($IPID_1 = 1000$). - Шаг 2 - Поддельный зонд цели: Атакующий отправляет сырой пакет
SYNна исследуемый порт цели (например, порт 443), подменяя IP-адрес источника на адрес узла-зомби. - Шаг 3 - Контрольный зонд зомби: Атакующий отправляет второй пакет
SYN/ACKна зомби, чтобы вызвать очереднойRSTи зафиксировать новое значение ($IPID_2$).
Анализ переходов состояний: открытые, закрытые и фильтруемые порты
Разница между двумя замерами ($\Delta = IPID_2 - IPID_1$) раскрывает физическое состояние порта:
+-------------------------------------------------------------------------+
| ТАБЛИЦА ОПРЕДЕЛЕНИЯ СОСТОЯНИЯ ПОРТОВ ПО ДЕЛЬТЕ |
+-------------------------------------------------------------------------+
| Состояние порта | Реакция цели на поддельный SYN | Дельта зомби (Δ) |
| :--- | :--- | :--- |
| ОТКРЫТ (OPEN) | Отправляет SYN/ACK узлу-зомби | Δ = 2 (Открыт) |
| | Зомби отвечает RST (тратит ID) | |
| ЗАКРЫТ (CLOSED) | Отправляет RST узлу-зомби | Δ = 1 (Закрыт) |
| | Зомби отбрасывает RST без ответа | |
| ФИЛЬТРУЕТСЯ | Сбрасывает пакет без ответа | Δ = 1 (Нет ответа|
| | Зомби ничего не получает | от цели) |
+-------------------------------------------------------------------------+
- Открытый порт ($\Delta = 2$): Цель принимает соединение и отсылает
SYN/ACKузлу-зомби. Зомби, не ожидавший этого пакета, отвечает отправкойRST, что увеличивает его собственный IP ID на единицу. Когда атакующий опрашивает зомби на Шаге 3, значение оказывается увеличенным на две единицы. - Закрытый или фильтруемый порт ($\Delta = 1$): Если порт закрыт, цель отправляет
RSTзомби (зомби игнорирует его). Если пакет отфильтрован брандмауэром, цель его молча уничтожает. В обоих случаях зомби ничего не генерирует, и его счетчик увеличивается лишь на 1 за счет собственного запроса атакующего.
В журналах систем предотвращения вторжений (IDS) и брандмауэров цели фиксируется только IP-адрес зомби, полностью скрывая координаты источника зондирования.
Оценка объемов трафика и межсетевое отслеживание узлов
Возможности побочного канала IP ID выходят далеко за рамки исследования портов:
- Анализ сетевой активности: Периодический опрос IP ID сервера позволяет отслеживать скорость генерации пакетов во времени, выявляя расписание резервного копирования или активность сеансов администрирования.
- Обнаружение скрытых взаимодействий: Если два внутренних сервера передают данные по незашифрованным каналам, синхронный рост счетчиков подтверждает наличие сетевого диалога между ними.
- Отслеживание оборудования при смене сетей: Ранее рабочие станции использовали фиксированные сиды генерации счетчиков, что позволяло сопоставлять устройство при переподключении между различными Wi-Fi сетями.
Стандартизация RFC 6864: исключение IP ID в атомарных датаграммах
Окончательное решение проблемы на уровне стандартов IETF сформулировано в документе RFC 6864: Updated Specification of the IPv4 ID Field в 2013 году.
В современных сетях практически повсеместно действует механизм Path MTU Discovery (PMTUD, RFC 1191), выставляющий флаг Don't Fragment (DF = 1) для абсолютного большинства TCP и UDP пакетов. Пакеты с установленным флагом DF = 1, не являющиеся фрагментами, получили статус атомарных датаграмм (atomic datagrams).
RFC 6864 установил следующие обязательные правила:
- Обнуление идентификатора: Отправляющим узлам разрешено и рекомендовано устанавливать значение
IP ID = 0x0000для всех атомарных датаграмм. - Освобождение принимающей стороны: Принимающие ОС не должны требовать уникальности IP ID для пакетов с флагом
DF = 1. - Запрет глобальных счетчиков: Ядрам запрещено использовать монотонно нарастающие разделяемые переменные для независимых направлений связи.
+-------------------------------------------------------------------------+
| ФОРМАТ АТОМАРНОЙ ДАТАГРАММЫ ПО СТАНДАРТУ RFC 6864 |
+-------------------------------------------------------------------------+
| Заголовок IPv4: |
| [ Version: 4 ] [ IHL: 5 ] [ DSCP/ECN ] [ Total Length: 1500 ] |
| [ Identification: 0x0000 ] <--- RFC 6864: Обнуление для атомарных |
| [ Flags: DF=1, MF=0 ] [ Fragment Offset: 0 ] |
| [ TTL: 64 ] [ Protocol: 6 (TCP) ] [ Header Checksum ] |
| [ Source IP ] [ Destination IP ] |
+-------------------------------------------------------------------------+
Защитные механизмы в современных ОС: реализации в Linux и BSD
Современные операционные системы полностью устранили зависимость поля IP ID от глобальных разделяемых переменных.
Хеш-таблицы для каждого соединения и криптографические PRNG
Сетевые стеки перешли к строгой изоляции состояний:
- Архитектура ядра Linux: По умолчанию для всех атомарных пакетов устанавливается
iph->id = 0. Если фрагментация необходима, ядро использует хеширование (siphash) от адресов источника и назначения, протокола и секретной соли ядра, выбирая отдельную ячейку в таблице. Счетчики инкрементируются строго индивидуально для каждого удаленного узла. - Системы BSD и macOS: Используют криптографически стойкие генераторы псевдослучайных чисел (PRNG), исключающие предсказуемость дельты между последовательными пакетами.
- Стек Windows: Начиная с Windows 10 и Windows Server 2016, глобальный счетчик заменен изолированными псевдослучайными последовательностями.
Нейтрализация утечек IP ID с помощью туннелей L3 и протокола RiceGuard
Виртуальные частные сети сетевого уровня L3 в режиме TUN (WireGuard и OpenVPN) обеспечивают полную невосприимчивость к атакам через побочный канал IP ID.
Инфраструктура VPNRice построена на принципах строгой криптографической инкапсуляции. На базе протокола RiceGuard пользовательские пакеты упаковываются в аутентифицированные UDP-датаграммы перед выходом во внешнюю сеть.
+-------------------------------------------------------------------------+
| ИНКАПСУЛЯЦИЯ И ИЗОЛЯЦИЯ IP ID В ПРОТОКОЛЕ RICEGUARD |
+-------------------------------------------------------------------------+
| Стек операционной системы клиента: |
| [ Внутренний IP-пакет: TCP SYN к цели | Внутренний IP ID от ОС ] |
| │ |
| ▼ |
| Модуль туннелирования RiceGuard: |
| [ Шифрованная полезная нагрузка ChaCha20-Poly1305 (Заголовок скрыт) ] |
| │ |
| ▼ |
| Внешняя физическая сеть: |
| [ Внешний заголовок IPv4: UDP 51820 | Внешний IP ID = 0x0000 (RFC 6864)|
+-------------------------------------------------------------------------+
RiceGuard исключает утечки побочного канала благодаря трем механизмам:
- Шифрование исходного заголовка: Исходный IPv4-заголовок со своим значением IP ID полностью скрыт внутри полезной нагрузки Noise. Внешние транзитные узлы не могут наблюдать внутренний идентификатор.
- Обнуление внешнего заголовка по RFC 6864: Внешние датаграммы туннеля передаются с флагом
DF = 1и нулевым значениемIP ID = 0x0000, исключая возможность вычисления дельты счетчика. - Криптографическая проверка подлинности: Серверные шлюзы отбрасывают неподписанные зондирующие пакеты до обработки стеком, предотвращая использование узла в качестве зомби.
Пользователи, нуждающиеся в защите от скрытого сетевого анализа, могут установить клиентское приложение со странице загрузки VPN.
Практическое тестирование: обнаружение уязвимых зомби с помощью Nmap
Специалисты по сетевому аудиту проверяют пригодность хостов для использования в атаках типа Idle Scan с помощью штатных скриптов Nmap:
# Проверка формирования последовательности IP ID на узле
nmap -p 80,443 --script ipidseq 198.51.100.25
# Пример уязвимого вывода (инкрементный счетчик):
# Host script results:
# |_ipidseq: Incremental! (Уязвим к использованию в качестве Zombie)
# Пример защищенного вывода по RFC 6864:
# Host script results:
# |_ipidseq: All zeros! (Безопасно: соответствует RFC 6864)
При обнаружении статуса Incremental аудиторы могут смоделировать проверку в изолированной тестовой лаборатории:
# Выполнение Idle Scan с использованием выбранного узла-зомби
nmap -Pn -sI 198.51.100.25:80 203.0.113.50
Если узел использует обнуление или рандомизацию идентификаторов, Nmap завершает работу с ошибкой: Cannot use zombie host: IP ID sequence is not incremental.
Архитектурное сравнение: глобальный счетчик против рандомизации
| Параметр безопасности | Глобальный монотонный счетчик | Рандомизация по узлам (Linux/BSD) | Обнуление по RFC 6864 (RiceGuard) |
|---|---|---|---|
| Уязвимость к Idle Scan | Критическая | Исключена (Изоляция пиров) | Исключена (Нулевой идентификатор) |
| Оценка объема трафика | Доступна сторонним узлам | Невозможна для третьих лиц | Невозможна для третьих лиц |
| Отслеживание устройства | Высокая вероятность | Практически исключена | Нулевая (Статическое поле) |
| Поддержка фрагментации | Полная | Полная (Через хеш-таблицы) | Полная через PMTUD |
| Расход памяти ядра | 2 байта (Переменная) | Средний (Таблица сессий) | Нулевой (Константа) |
| Нагрузка на процессор | Минимальная (++counter) |
Низкая (Расчет SipHash) | Минимальная (Фиксированное 0x0000) |
Переход на IPv6: полное удаление идентификатора из базового заголовка
Радикальным архитектурным решением проблемы стало проектирование стека IPv6 (RFC 8200).
Поскольку фрагментация затрагивает менее десятой доли процента современного интернет-трафика, архитекторы IPv6 полностью удалили поле Identification из фиксированного 40-байтного базового заголовка. В протоколе IPv6 промежуточные маршрутизаторы лишены права фрагментировать пакеты; фрагментация выполняется исключительно узлом-отправителем с использованием опционального заголовка расширения (Fragment Extension Header):
+-------------------------------------------------------------------------+
| ЧИСТОТА ЗАГОЛОВКА IPV6: НЕТ СТАТИЧЕСКИХ ID |
+-------------------------------------------------------------------------+
| Базовый заголовок IPv6 (Фиксированные 40 байт): |
| [ Version: 6 ] [ Traffic Class ] [ Flow Label: 20 bits ] |
| [ Payload Length: 16 bits ] [ Next Header: 6 (TCP) ] [ Hop Limit: 64 ] |
| [ Source IPv6 Address: 128 bits ] |
| [ Destination IPv6 Address: 128 bits ] |
| |
| * В БАЗОВОМ ЗАГОЛОВКЕ ПОЛЕ IDENTIFICATION ОТСУТСТВУЕТ! * |
+-------------------------------------------------------------------------+
Для атомарных датаграмм заголовок фрагментации не создается, поэтому в пакете физически отсутствует поле для измерения счетчика. Атака Idle Scan технически невозможна в чистых сетях IPv6.
Контрольный список мер защиты от утечек IP ID для системных администраторов
Для защиты инфраструктуры рекомендуется выполнить следующие шаги:
- Контроль соответствия RFC 6864: Использовать ядра Linux версии 4.0 и выше для автоматического обнуления поля IP ID в атомарных пакетах.
- Обеспечение работы PMTUD: Разрешить прохождение сообщений ICMP Type 3 Code 4 (Fragmentation Needed) на периметре сети.
- Фильтрация поддельных адресов (BCP 38): Настроить Unicast Reverse Path Forwarding (
uRPF) на пограничных маршрутизаторах для блокировки поддельных адресов источников. - Защита межсерверных каналов: Передавать административный трафик между центрами обработки данных через туннели RiceGuard.
- Вывод устаревших ОС из эксплуатации: Отказаться от устаревших версий операционных систем, продолжающих использовать глобальный инкремент счетчиков.
Внедрение современных спецификаций сетевых протоколов и криптографических туннелей полностью устранило уязвимость побочного канала IP ID, гарантируя защиту сетевого стека от скрытого зондирования.



