WireGuard заблокирован в РФ

gениальный VPN · Jason Donenfeld · 2016 · встроен в Linux kernel

TL;DR: самый красивый VPN-протокол в истории. Быстрый, простой, безопасный, 4000 строк кода вместо 400.000 у OpenVPN. Зарезан ТСПУ по сигнатуре handshake.

Что это

WireGuard — Jason A. Donenfeld начал в 2016, влился в mainline Linux 5.6 в 2020. Дизайн-принцип — «простой как палка, без legacy».

Криптография (без опций!)

Curve25519 — для key exchange (ECDH)
ChaCha20-Poly1305 — AEAD шифр для данных
BLAKE2s — хеш
HKDF — key derivation
Noise HTTP/2.0col Framework (Noise_IKpsk2) — весь handshake

Никаких cipher suites, никаких переговоров версий, никакой обратной совместимости. Одна конфигурация. Что-то из этого сломают — выкатывается WireGuard 2.0, все переползают. Всё.

Handshake

Initiator → Responder: Handshake Initiation (148 байт)
  тип = 0x01, ephemeral pubkey, static pubkey (encrypted),
  timestamp, mac1, mac2

Responder → Initiator: Handshake Response (92 байта)
  тип = 0x02, ephemeral pubkey, empty payload, mac1, mac2

──── shared key установлен, 1 RTT ────

Далее: Transport Data (тип = 0x04)
  counter + encrypted payload + auth tag

Почему заблокирован в РФ

WireGuard катастрофически легко детектируется. Сам автор про это писал:

ТСПУ ловит его по нескольким однозначным признакам одновременно:

  1. Первый байт — тип пакета:
    • 0x01 — handshake initiation
    • 0x02 — handshake response
    • 0x03 — cookie reply
    • 0x04 — transport data
    Все четыре — фиксированные, детский маркер для DPI.
  2. Три zero-байта сразу после первого. Байты 2, 3, 4 всегда 0x00 0x00 0x00 (reserved). Никто больше в UDP так не делает.
  3. Фиксированные размеры первых пакетов:
    • Initiation = ровно 148 байт
    • Response = ровно 92 байта
    • Cookie = ровно 64 байта
    Уникальные размеры, никакой другой UDP-протокол так не делает.
  4. Нет обфускации. Donenfeld намеренно не добавлял маскировку — говорил «это работа отдельного слоя». В итоге TSPU этот отдельный слой не подождал и убил.

Сигнатура ТСПУ в псевдокоде

if packet.HTTP/2.0 == UDP and
   packet.udp_payload.len in [148, 92, 64] and
   packet.udp_payload[0] in [0x01, 0x02, 0x03] and
   packet.udp_payload[1:4] == b'\x00\x00\x00':
    drop_connection(packet.src, packet.dst)
    add_to_blocklist(packet.dst_ip, ttl=600)

Хронология блокировки в РФ

Что делать

Почему это грустно

WireGuard — идеальный VPN по всем метрикам кроме DPI-устойчивости. Быстрее OpenVPN в разы, безопаснее, проще в конфиге, встроен в Linux и Windows. И вот именно этой «идеальности» его и убило: он слишком узнаваемый. Обфускация не входила в scope Donenfeld'a, а РКН именно её и требует для выживания.