WireGuard — почему это новый стандарт
Когда Линус Торвальдс назвал WireGuard «произведением искусства» и принял в ядро Linux (5.6, март 2020) — индустрия признала: новый стандарт VPN. 4 000 строк кода против 600 000 у OpenVPN. Быстрее IPsec в 2 раза. Криптография намертво зашита, конфигурация — одна страница. Но у него есть критическая слабость для обхода блокировок.
- Почему WireGuard такой маленький и быстрый — главные дизайн-решения
- Криптография: Curve25519 + ChaCha20-Poly1305 + Poly1305 + BLAKE2s — почему именно эти
- Noise_IK handshake побайтово: 4 сообщения, 32+16 байт каждое
- Формат пакета данных побайтово
- Cookie-anti-DoS — защита сервера от лавины подделанных handshake
- Kernel module vs
wireguard-govsboringtun - Главная слабость 2026: детектится первым байтом
- AmneziaWG — российский ответ на эту слабость
1. Философия WireGuard: «opinionated» дизайн
Jason Donenfeld в 2015 сел и решил написать VPN с нуля, опираясь на современную криптографию и многолетний опыт боли OpenVPN/IPsec. Ключевые принципы:
- Один шифр, один key exchange, один MAC. Никакого согласования алгоритмов (как в TLS). Криптография зашита: Curve25519, ChaCha20-Poly1305, BLAKE2s. Не нравится — не используй WireGuard. Если завтра ChaCha20 сломают — выйдет WireGuard 2.0.
- UDP-only. Никакого TCP. TCP-over-TCP даёт «meltdown» при потерях.
- Stateless handshake. Сервер не помнит «полусоединения» — нет DoS-уязвимости.
- Crypto-routing. Адрес клиента в туннеле жёстко привязан к его публичному ключу в конфиге (AllowedIPs). Не угадаешь IP — не подменишь.
- Stealth. Сервер не отвечает на левые пакеты вообще. Без знания ключа — порт «закрыт».
- Конфигурация — текстовый файл на 10 строк. Не XML, не GUI, не базу.
2. Криптопримитивы — почему именно эти
| Задача | Алгоритм | Почему |
|---|---|---|
| Key exchange | Curve25519 (X25519) | Быстрый ECDH, без слабых параметров (привет, P-curves NSA) |
| Симметричное шифрование | ChaCha20 | Быстрее AES на ARM (мобильники), без cache-timing атак |
| Аутентификация (AEAD) | Poly1305 | Идёт в паре с ChaCha20, стандарт от Bernstein |
| Хэш / KDF / MAC | BLAKE2s | Быстрее SHA-2, безопасно использовать как PRF |
| HKDF | HKDF(BLAKE2s) | Стандартное KDF из RFC 5869 |
Почему «принцип одного шифра» — это сила, а не слабость
В TLS/IPsec клиент и сервер согласовывают шифры. Это создаёт downgrade-атаки: MITM меняет ClientHello и заставляет согласиться на слабый шифр. Все BEAST, POODLE, FREAK, Logjam — об этом.
В WireGuard согласовывать нечего. Поддерживаемый шифр один. Атаки на согласование невозможны математически. Это редкий случай в безопасности, когда жёсткое ограничение — преимущество.
3. Noise_IK handshake — 4 сообщения
WireGuard использует паттерн Noise_IK из Noise Framework (см. урок 02). 4 сообщения: Initiation, Response, далее уже data. Каждое — фиксированной длины.
Сообщение 1 — Handshake Initiation побайтово
Первый байт всегда 0x01
Длина пакета — всегда 148 байт. Первый байт — всегда 0x01. Это идеальная сигнатура для DPI. Правило ТСПУ выглядит примерно так:
match: udp.length == 148 AND udp.payload[0] == 0x01
AND udp.payload[1..4] == 0x000000
AND udp.payload[8..40] looks like X25519 point
action: drop, blacklist src_ip for 60s
Поэтому WireGuard на дефолтных настройках режут в России c 2023. И в Иране, и в Китае. Канал поднимается, через 30 секунд handshake перестаёт проходить.
4. Cookie reply — защита от DoS
Сервер делает дорогое X25519-вычисление при каждой Initiation. Атакующий мог бы засыпать сервер фальшивыми Initiation — сервер тратил бы CPU. Решение: cookie-reply.
Если сервер под нагрузкой — на следующую Initiation от данного IP он отвечает не Response, а специальным cookie-пакетом (type=3). Cookie — это hmac(secret, client_ip), валиден 2 минуты. Клиент должен включить cookie в mac2 следующей Initiation.
Атакующий с подделанным src_ip не получит cookie (ответ пойдёт на жертву, не атакующему). Без cookie сервер не делает дорогих DH-вычислений. Атака на CPU не работает.
5. Data-пакет побайтово
После handshake клиент и сервер обмениваются Transport Data packets:
Длина зашифрованного пакета = длина оригинального IP-пакета + 16 байт (auth tag) + дополнения до 16-байтового выравнивания (padding). Overhead самого WireGuard над исходным IP-пакетом: 16 (data-header) + 16 (tag) = 32 байта. С учётом внешнего IPv4 (20) и UDP (8) полный overhead туннеля — ≈ 60 байт (поэтому типичный MTU интерфейса WireGuard — 1420).
6. Реализации: kernel vs userspace
| Реализация | Где | Производительность | Зачем |
|---|---|---|---|
| kernel module | Linux 5.6+, FreeBSD 13.2+, OpenBSD | 10+ Гбит/с на ядро | Продакшн на серверах |
| wireguard-go | macOS, Windows, любой OS | 1-2 Гбит/с | Кроссплатформа референсная |
| BoringTun (Rust) | Cloudflare, embedded | 2-4 Гбит/с | Безопасность памяти (Rust) |
| kmod на роутерах | OpenWRT, Mikrotik 7.x, Asuswrt-Merlin | зависит от железа | Домашние/SOHO |
Почему kernel так быстро
В user-space реализации (OpenVPN, wireguard-go) пакет проходит: kernel → tun → userspace → шифр → userspace → udp → kernel. 4 переключения контекста на пакет.
Kernel-module делает всё в одном context: получил пакет → расшифровал → передал в стек. В разы быстрее. Плюс ChaCha20-Poly1305 в Linux 5.6+ векторизованный (AVX-512).
7. Минимальная конфигурация
Серверная сторона /etc/wireguard/wg0.conf:
[Interface] PrivateKey = SERVER_PRIV_KEY_BASE64 # ← wg genkey Address = 10.8.0.1/24 # внутренний IP туннеля ListenPort = 51820 # UDP-порт (любой) PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE [Peer] PublicKey = CLIENT_PUB_KEY_BASE64 # ← клиент сообщает свой публичный ключ AllowedIPs = 10.8.0.2/32 # какие IP пропускать «как от этого клиента»
Клиентская сторона:
[Interface] PrivateKey = CLIENT_PRIV_KEY_BASE64 Address = 10.8.0.2/24 DNS = 1.1.1.1, 1.0.0.1 # DNS внутри туннеля (необязательно) [Peer] PublicKey = SERVER_PUB_KEY_BASE64 Endpoint = vpn.example.com:51820 # IP/домен сервера AllowedIPs = 0.0.0.0/0, ::/0 # «весь трафик в туннель» PersistentKeepalive = 25 # каждые 25с пинг, чтобы NAT не закрыл маппинг
Всё. Стартуем: sudo wg-quick up wg0. Никаких XML, GUI, БД.
8. AmneziaWG — российский ответ на детект
Российская команда AmneziaVPN доработала WireGuard, чтобы обойти проблему «первый байт всегда 0x01 / длина всегда 148». Идея — добавить junk-пакеты и обфускацию.
- Jc / Jmin / Jmax: сразу после соединения клиент шлёт несколько мусорных пакетов случайной длины — DPI видит «много байт непонятно чего», не похожих на WG.
- S1 / S2: к каждому обычному пакету добавляется случайный prefix-byte и postfix-byte. Длина пакета перестаёт быть «148 байт».
- H1 / H2 / H3 / H4: магические заголовки заменяются на конфигурируемые значения. Первый байт уже НЕ 0x01.
В результате трафик AmneziaWG неотличим от случайного UDP-шума. ТСПУ перестаёт детектить «по сигнатуре». В 2024-2025 это активно работает в РФ.
ML-классификация всё ещё может зацепить
ТСПУ может смотреть не только на байты, но и на статистику пакетов (тайминги, размеры, корреляция). AmneziaWG ломает байтовый fingerprint, но не статистический. Поэтому будущее — за более радикальной маскировкой (Reality, ECH). AmneziaWG — отличное tactical решение, но не «защита навсегда».
9. Итог
- WireGuard — лучший VPN для скорости и простоты. Если задача — корпоративный remote-access, site-to-site без DPI, домашняя приватность — WG победил всех.
- В странах с активным DPI голый WireGuard не работает: 0x01 + 148 байт = жалоба ТСПУ.
- AmneziaWG закрывает байтовую сигнатуру, но не статистическую — это решение на год-два, пока DPI не нагонит.
- Для обхода продвинутых блокировок WireGuard не годится в чистом виде. Нужна обёртка (Reality, Shadowsocks-as-proxy + WG внутри) или другой протокол.
- Знать WireGuard обязательно — это базовый VPN в любой корпоративной/домашней инфре.
В следующем уроке — модель противника. Что такое DPI, как он работает, что видит: JA3/JA4, ALPN-fingerprinting, active probing. Без этой модели бессмысленно говорить об обходе блокировок — сначала нужно понять, что именно ищет ТСПУ/GFW и по каким признакам отличает VPN-трафик от обычного.