Сучасні віртуальні приватні мережі вимагають математичної надійності та стійкості до аналізу трафіку. Історичні протоколи, такі як IPsec (RFC 4301) та OpenVPN, базувалися на громіздких узгоджувальних автоматах станів, складних ланцюжках сертифікатів X.509 та динамічному виборі алгоритмів шифрування. Така архітектурна надмірність породжувала сотні тисяч рядків коду, розширювала поверхню атак та сповільнювала встановлення зв'язку через численні мережеві обміни.

Творець WireGuard Джейсон Доненфельд повністю відмовився від динамічного узгодження алгоритмів під час з'єднання. Замість створення неперевірених схем WireGuard взяв за основу фреймворк Noise Protocol Framework, розроблений Тревором Перріном. Було реалізовано конкретний фіксований шаблон Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s.

Цей протокол виконує обмін ключами за один цикл прийому-передачі (1-RTT), приховує ідентифікатори клієнтів від пасивних спостерігачів, гарантує досконалу пряму секретність (PFS), захищає сервери від атак типу «відмова в обслуговуванні» (DoS) та не виділяє системну пам'ять під неавтентифіковані пакети.

+-----------------------------------------------------------------------------+
|                  СХЕМА 1-RTT РУКОСТИСКАННЯ NOISE_IKPSK2 У WIREGUARD         |
|                                                                             |
|  Ініціатор (Клієнт)                                    Відповідач (Сервер)  |
|  Статичний ключ: s_i                                   Статичний ключ: s_r  |
|  Тимчасовий ключ: e_i                                  Тимчасовий ключ: e_r |
|                                                                             |
|  [ Повідомлення 1: Ініціація (148 байтів) ]                                 |
|  Type(0x01) + Sender Index + e_i + Enc(s_i) + Enc(Timestamp) + MAC1 + MAC2 |
|  --------------------------------------------------->                       |
|                                                     Перевірка MAC1 та часу  |
|                                                     Обчислення спільних DH  |
|                                                                             |
|  [ Повідомлення 2: Відповідь (92 байти) ]                                   |
|  Type(0x02) + Sender Index + Receiver Index + e_r + Enc(Empty) + MAC1 + MAC2|
|  <---------------------------------------------------                       |
|  Обчислення спільних ключів DH та додавання PSK                             |
|  Формування ключів передачі даних (Split)                                   |
|                                                                             |
|  ==================== ЗАХИЩЕНА ПЕРЕДАЧА ДАНИХ (1-RTT) ===================== |
|  Type(0x04) + Receiver Index + Лічильник + Enc(IP-пакет)                    |
|  <--------------------------------------------------->                      |
+-----------------------------------------------------------------------------+

Основи фреймворку Noise: чому WireGuard обрав Noise_IKpsk2

Фреймворк Noise є формальною граматикою для опису протоколів автентифікованого обміну ключами Діффі-Хеллмана. Замість довільного обміну байтами Noise визначає протоколи через декларативні шаблони. Кожен шаблон чітко регламентує, як статичні ключі ($s$), одноразові тимчасові ключі ($e$) та попередньо розподілені секрети ($psk$) комбінуються для обчислення спільних секретів.

WireGuard обирає шаблон Noise_IKpsk2:

  1. I (Передача статичного ключа ініціатора): Клієнт передає свій відкритий ключ $s_i$ уже в першому повідомленні, зашифрувавши його ключем від множення тимчасового ключа на статичний ключ сервера.
  2. K (Відомий статичний ключ відповідача): Клієнт заздалегідь знає статичний відкритий ключ $s_r$ сервера. Це відповідає криптографічній маршрутизації (Cryptokey Routing), де відкриті ключі є безпосередніми мережевими адресами.
  3. psk2 (Додавання PSK у другому повідомленні): 256-бітний симетричний ключ ($PSK$) додається до ланцюжка обчислень у другому повідомленні. Це гарантує гібридний постквантовий захист від дешифрування квантовими комп'ютерами в майбутньому.
  4. 25519: Усі асиметричні операції використовують еліптичну криву Монтгомері Curve25519 (X25519), забезпечуючи рівень стійкості 128 біт та захист від атак за часом виконання.
  5. ChaChaPoly: Автентифіковане шифрування спирається на шифр ChaCha20 та імітовставку Poly1305 (RFC 8439), обробляючи 64-байтні блоки з 128-бітною міткою автентифікації.
  6. BLAKE2s: Хешування, коди автентифікації повідомлень та деривація ключів HKDF реалізовані через алгоритм BLAKE2s-256 (RFC 7693), оптимізований для 32- та 64-бітних архітектур.

Завдяки фіксованому набору алгоритмів WireGuard унеможливлює атаки зниження версії (downgrade attacks). У системі немає прапорців стиснення та відсутня підтримка застарілих бібліотек.

Криптографічний автомат станів: HandshakeState, SymmetricState та CipherState

Архітектура Noise структурує стан протоколу за трьома рівнями:

1. Стан шифру CipherState

Рівень CipherState керує симетричним шифруванням та розшифруванням. Він зберігає 256-бітний ключ $k$ та 64-бітний беззнаковий лічильник $n$. Під час кожного виклику EncryptWithAd() значення $n$ збільшується на 1, запобігаючи повторному використанню вектора ініціалізації. Якщо $n$ досягає $2^{64}-1$, стан блокує шифрування та вимагає оновлення ключів.

2. Симетричний стан SymmetricState

Рівень SymmetricState огортає CipherState та підтримує два внутрішні 256-бітні буфери:

  • Ключ ланцюжка ($ck$): Пул ентропії, що оновлюється через HKDF за появи нових матеріалів Діффі-Хеллмана.
  • Хеш рукостискання ($h$): Неперервний криптографічний дайджест усіх переданих і отриманих байтів (ідентифікатори протоколу, відкриті ключі та шифротексти).

Значення $h$ слугує асоційованими автентифікованими даними (AD) для Poly1305, що робить недійсною фінальну мітку в разі будь-якого втручання в передані поля.

3. Стан рукостискання HandshakeState

Рівень HandshakeState об'єднує локальні й віддалені ключі разом із SymmetricState. Він координує виконання правил шаблону Noise_IKpsk2:

$$\text{Від ініціатора до відповідача:} \quad \rightarrow e, ; es, ; s, ; ss$$ $$\text{Від відповідача до ініціатора:} \quad \leftarrow e, ; ee, ; se, ; psk$$

Анатомія рукостискання 1-RTT: структура повідомлень і побайтовий аналіз

Рукостискання WireGuard відбувається за допомогою двох UDP-пакетів: Повідомлення ініціації та Повідомлення відповіді.

ПОВІДОМЛЕННЯ 1: ІНІЦІАЦІЯ (148 БАЙТІВ)
+-------------------+--------------------+--------------------------------+
| Тип: 0x01 (4Б)    | Індекс клієнта (4Б)| Тимчасовий ключ e (32Б)        |
+-------------------+--------------------+--------------------------------+
| Шифрований статичний ключ (48Б)        | Шифрована мітка часу (28Б)     |
+----------------------------------------+--------------------------------+
| MAC1: Хеш відкритого ключа сервера(16Б)| MAC2: Cookie MAC (16Б)         |
+----------------------------------------+--------------------------------+

ПОВІДОМЛЕННЯ 2: ВІДПОВІДЬ СЕРВЕРА (92 БАЙТИ)
+-------------------+--------------------+--------------------------------+
| Тип: 0x02 (4Б)    | Індекс сервера (4Б)| Індекс отримувача (4Б)         |
+-------------------+--------------------+--------------------------------+
| Тимчасовий ключ e_r (32Б)              | Шифрований порожній блок (16Б) |
+----------------------------------------+--------------------------------+
| MAC1: Хеш відкритого ключа сервера(16Б)| MAC2: Cookie MAC (16Б)         |
+----------------------------------------+--------------------------------+

Крок 1: Ініціація рукостискання (148 байтів)

  1. Заголовок та індекс (8 байтів): Поле 0x01 ідентифікує пакет, а 32-бітний індекс сесії клієнта дозволяє швидко знаходити запис у пам'яті.
  2. Тимчасовий ключ $e_i$ (32 байти): Клієнт створює нову пару ключів Curve25519 і передає відкриту частину без шифрування.
  3. Операція Діффі-Хеллмана ($es$): Обчислюється $DH(e_i, s_r)$, що додається до $ck$ через HKDF-2 для створення проміжного ключа $k$.
  4. Шифрований статичний ключ ($s_i$, 48 байтів): Клієнт шифрує постійний ключ $s_i$ (32 байти) з міткою Poly1305 (16 байтів) та прив'язкою хешу $h$.
  5. Операція Діффі-Хеллмана ($ss$): Розраховується $DH(s_i, s_r)$ і результат додається до $ck$.
  6. Шифрована мітка часу (28 байтів): Час у форматі TAI64N (12 байтів із точністю до наносекунд) шифрується з 16-байтною міткою. Сервер відхиляє повідомлення з часом, меншим або рівним збереженому для $s_i$, нейтралізуючи атаки повторного відтворення.
  7. Поля MAC (32 байти): Додаються поля MAC1 (16 байтів BLAKE2s від тіла пакета) та MAC2 (16 байтів cookie-автентифікації).

Крок 2: Відповідь сервера (92 байти)

Отримавши перше повідомлення, сервер перевіряє MAC1, витягує $e_i$, обчислює $DH(e_i, s_r)$, розшифровує $s_i$, рахує $DH(s_i, s_r)$, перевіряє час і надсилає відповідь:

  1. Заголовок та індекси (12 байтів): Значення 0x02, локальний індекс сервера та повернений індекс клієнта.
  2. Тимчасовий ключ сервера $e_r$ (32 байти): Створений відкритий ключ Curve25519.
  3. Операції Діффі-Хеллмана ($ee$ та $se$): Сервер рахує $DH(e_r, e_i)$ та $DH(e_r, s_i)$, підмішуючи результати до $ck$.
  4. Підмішування попереднього ключа ($psk2$): До ланцюжка $ck$ вводиться секрет $PSK$ через HKDF-3:

$$(ck, \tau, k) \leftarrow \text{HKDF-3}(ck, PSK)$$

  1. Шифрований порожній блок (16 байтів): Порожній буфер шифрується ключем $k$ з міткою Poly1305. Успішна дешифрація підтверджує наявність у сервера ключа $s_r$ та секрету $PSK$.
  2. Поля MAC (32 байти): Включають MAC1 та MAC2.

Деривація сесійних ключів через Split()

Після завершення обміну обидві сторони викликають функцію Noise Split():

$$(T_{\text{send}}, T_{\text{recv}}) \leftarrow \text{HKDF-2}(ck, \emptyset)$$

Утворюються два незалежні 256-бітні симетричні ключі: окремо для передачі та прийому даних. Усі проміжні значення та тимчасові ключі негайно стираються з пам'яті процедурами безпечного очищення.

Захист мережевої ідентичності, досконала пряма секретність та стирання ключів

Моніторинг каналів зв'язку часто аналізує відкриті метадані в заголовках пакетів для ідентифікації пристроїв. Шаблон Noise_IKpsk2 унеможливлює це:

  • Захист від пасивного перехоплення: Статичний ключ клієнта $s_i$ ніколи не передається відкрито. Він надійно захищений шифруванням на базі $DH(e_i, s_r)$. Спостерігач на рівні провайдера бачить лише потік випадкових байтів високої ентропії.
  • Стійкість до активних атак: Активний зловмисник (MITM) не зможе розшифрувати $s_i$, не знаючи приватного ключа сервера. У разі надсилання невалідного пакета сервер не відповідає взагалі.
  • Досконала пряма секретність (PFS): Оскільки тимчасові ключі генеруються заново для кожного сеансу та знищуються після виконання Split(), майбутня компрометація довгострокових ключів не дозволить розшифрувати збережений трафік.
  • Оновлення ключів за розкладом: Ключі автоматично змінюються кожні 120 секунд (REKEY_AFTER_TIME) або після передачі $2^{64}-2^{16}$ пакетів (REKEY_AFTER_MESSAGES). Якщо канал не використовується понад 180 секунд, ключі остаточно видаляються.

Відкриті мережеві порти часто стають цілями атак вичерпання ресурсів через високу вартість обчислень на еліптичних кривих порівняно зі звичайною маршрутизацією.

WireGuard нейтралізує цю проблему дворівневим механізмом MAC:

  1. Режим повної мовчанки (Silent Dropping): Якщо поле MAC1 не відповідає хешу ключа сервера або розшифрування зазнало невдачі, пакет просто відкидається без надсилання помилок ICMP. Для сканерів мережі порт здається неактивним або фільтрованим.
  2. Механізм stateless-cookie: У разі перевантаження процесора сервер припиняє виконання операцій Діффі-Хеллмана для пакетів лише з MAC1. Натомість надсилається компактне 64-байтне повідомлення Cookie (тип 0x03). Cookie розраховується без збереження стану на основі IP-адреси клієнта, секретного ключа сервера та випадкової солі. Клієнт формує поле MAC2 і надсилає повторний запит, підтверджуючи володіння своєю IP-адресою перед виділенням ресурсів сервера.

Архітектура RiceGuard: криптографічна оптимізація та мінімізація ризиків

Мережева інфраструктура VPNRice втілює принципи Noise Protocol Framework у швидкісному протоколі RiceGuard. Замість тривалих узгоджень, що виснажують акумулятори портативних пристроїв, RiceGuard забезпечує легкі та стабільні з'єднання.

Завдяки маршрутизації Anycast запити на підключення спрямовуються на найближчі географічні вузли, завершуючи рукостискання менш ніж за 20 мілісекунд. Ядро RiceGuard ізолює сесійні ключі в захищених структурах ядра, запобігаючи витокам даних через системну пам'ять.

Крім того, RiceGuard розширює стандарти WireGuard автоматичним розподілом постквантових симетричних ключів ($PSK$) через незалежні захищені канали. Це гарантує надійність шифрування перед обчислювальними можливостями квантових систем майбутнього, зберігаючи високу пропускну здатність та мінімальний пінг.

Фреймворк Noise демонструє, що надійна безпека не потребує складних конфігурацій. Поєднання перевірених автоматів станів, швидкості 1-RTT та приховування мережевих ідентифікаторів робить WireGuard та RiceGuard стандартом сучасного зв'язку. Оцініть надійний криптографічний захист та швидкісну роботу разом із Завантажити VPNRice.