Кожен пакет 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) і дозволяє досліджувати цільову систему без надсилання пакетів із власної IP-адреси.
Схема атаки вимагає участі трьох компонентів:
- Атакуючий: комп'ютер, що генерує запити та проводить обчислення.
- Вузол-зомбі (Zombie Host): неактивна машина в мережі зі спільним лічильником 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, значення виявляється більшим на 2 одиниці. - Закритий або фільтрований порт ($\Delta = 1$): Якщо порт закритий, ціль відправляє
RST(зомбі його ігнорує). Якщо порт відфільтровано брандмауером, пакет знищується без відповіді. В обох випадках зомбі не випускає нових пакетів, і лічильник зростає лише на одиницю через власний зонд атакуючого.
Журнали брандмауера та систем виявлення вторгнень (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
Сучасні платформи повністю відмовилися від глобальних спільних лічильників для ідентифікаторів пакетів.
Хеш-таблиці для окремих сокетів та криптографічні PRNG
Мережеві стеки забезпечують сувору ізоляцію:
- Архітектура ядра Linux: За замовчуванням виставляє
iph->id = 0для всіх атомарних пакетів. Якщо ж фрагментація обов'язкова, Linux застосовує хешування (siphash) IP-адрес джерела й призначення, протоколу та внутрішнього ключа ядра, закріплюючи окремий стан за кожним віддаленим піром. - Сімейства BSD та macOS: Застосовують криптографічно стійкі генератори псевдовипадкових чисел (PRNG), що унеможливлюють передбачення значень між послідовними пакетами.
- Системи Windows: Починаючи з Windows 10 та Windows Server 2016, старі лічильники замінено на незалежну випадкову генерацію для окремих вузлів.
Як тунелі L3 та протокол RiceGuard нейтралізують витоки IP ID
Віртуальні приватні мережі 3-го рівня в режимі TUN (наприклад, WireGuard) створюють фундаментальний захист проти атак через побічний канал IP ID.
Інфраструктура VPNRice побудована на засадах надійного криптографічного захисту. Завдяки протоколу RiceGuard, весь трафік клієнтських додатків інкапсулюється в автентифіковані датаграми UDP перед передачею у відкриту мережу.
+-------------------------------------------------------------------------+
| ІНКАПСУЛЯЦІЯ ТА ІЗОЛЯЦІЯ IP ID У ПРОТОКОЛІ RICEGUARD |
+-------------------------------------------------------------------------+
| Локальний мережевий стек клієнта: |
| [ Внутрішній IP-пакет: TCP-запит до цілі | Локальний IP ID системи ] |
| │ |
| ▼ |
| Модуль тунелювання RiceGuard: |
| [ Зашифроване навантаження ChaCha20-Poly1305 (Внутрішній заголовок) ] |
| │ |
| ▼ |
| Фізична зовнішня мережа: |
| [ Зовнішній заголовок IPv4: UDP 51820 | Зовнішній IP ID = 0x0000 ] |
+-------------------------------------------------------------------------+
RiceGuard повністю нівелює загрози побічних каналів завдяки трьом механізмам:
- Повна інкапсуляція заголовків: Внутрішній заголовок IPv4 та його початковий IP ID зашифровані всередині пакета Noise, тому транзитні провайдери та спостерігачі не мають до них доступу.
- Зовнішня відповідність RFC 6864: Датаграми тунелю завжди мають прапорець
DF = 1і зовнішнійIP ID = 0x0000, унеможливлюючи вимірювання дельти лічильника. - Криптографічна фільтрація підробок: Сервери перевіряють відкриті ключі перед обробкою даних; підроблені пакети розвідки відкидаються одразу, не залишаючи слідів у роботі системи.
Користувачі, які прагнуть захистити свою мережеву активність від прихованого аналізу, можуть завантажити офіційний клієнт на сторінці завантаження VPN.
Практичне тестування: виявлення вразливих зомбі за допомогою Nmap
Спеціалісти з аудиту безпеки можуть перевірити стабільність генерації ідентифікаторів хоста за допомогою скриптів 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: повне вилучення ідентифікатора з базового заголовка
Остаточне та безапеляційне вирішення проблеми IP ID було закладено в архітектурі протоколу IPv6 (RFC 8200).
Зважаючи на те, що фрагментація трапляється менш ніж у 0,1% сучасного трафіку, розробники IPv6 повністю вилучили поле Identification з фіксованого 40-байтного базового заголовка. В IPv6 проміжним маршрутизаторам суворо заборонено фрагментувати пакети; це завдання покладається виключно на джерело через опціональний заголовок розширення (Fragment Extension Header):
+-------------------------------------------------------------------------+
| БАЗОВИЙ ЗАГОЛОВОК IPV6: БЕЗ СТАТИЧНИХ ІДЕНТИФІКАТОРІВ |
+-------------------------------------------------------------------------+
| Базовий заголовок 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) на граничних маршрутизаторах для відсікання пакетів із підробленими IP. - Захищати внутрішні канали: Передавати міжсерверний трафік через тунелі RiceGuard для захисту транспортних метаданих.
- Оновлювати застарілі системи: Вивести з експлуатації старі сервери та мережеві пристрої, які все ще ведуть загальні монотонні лічильники.
Розвиток мережевих стандартів та перехід на надійні криптографічні тунелі остаточно нейтралізували побічний канал IP ID, унеможлививши приховане дослідження систем через службові поля пакетів.



