WireGuard: технический обзор протокола, настройки и ограничений

2513
WireGuard: технический обзор протокола, настройки и ограничений

WireGuard не пытается быть универсальной платформой удалённого доступа. Протокол решает более узкую задачу: берёт IP-пакет, шифрует его, упаковывает в UDP и отправляет другому узлу, который узнаётся по публичному ключу. Поэтому WireGuard выглядит проще OpenVPN и многих IPsec-конфигураций, но простота не отменяет сетевую инженерию. Маршруты, DNS, NAT, firewall, IPv6, выдача ключей и отзыв доступа остаются на администраторе.

WireGuard: технический обзор протокола

Ключевая идея WireGuard называется cryptokey routing. Каждый peer имеет публичный ключ и список AllowedIPs. При отправке пакет выбирает peer по адресу назначения, а при приёме WireGuard проверяет, разрешён ли расшифрованный исходный адрес для ключа отправителя. Так один параметр одновременно задаёт маршрут и базовый список допустимых адресов. На официальной странице WireGuard авторы прямо описывают AllowedIPs как таблицу маршрутизации для исходящих пакетов и как список контроля доступа для входящих.

Как WireGuard видит сеть

WireGuard работает на третьем сетевом уровне. В Linux появляется виртуальный интерфейс, например wg0. Приложения не знают про WireGuard напрямую: они отправляют обычные IP-пакеты, система выбирает маршрут через wg0, а WireGuard шифрует внутренний пакет и отправляет внешний UDP-пакет на endpoint другого peer-узла.

В протоколе нет строгого деления на сервер и клиент. Есть peer-узлы. В реальной схеме один узел часто имеет публичный адрес и слушает UDP-порт, а ноутбуки, телефоны и домашние роутеры выходят к нему из-за NAT. Поэтому в инструкциях такой узел называют сервером, хотя WireGuard обрабатывает участников симметрично.

Порт 51820 часто встречается в примерах, но протокол не требует именно его. В конфиге можно указать любой разрешённый UDP-порт. Если ListenPort не задан, реализация может выбрать порт сама. Поэтому фраза «стандартный порт WireGuard» годится только как практическое упрощение, а не как свойство протокола.

[Interface]
 Address = 10.8.0.1/24
 ListenPort = 51820
 PrivateKey = SERVER_PRIVATE_KEY
 
 [Peer]
 PublicKey = CLIENT_PUBLIC_KEY
 AllowedIPs = 10.8.0.2/32
 

В этом примере серверный peer разрешает клиенту только адрес 10.8.0.2 внутри туннеля. Если клиент отправит пакет с исходным адресом 10.8.0.55, WireGuard расшифрует пакет, сравнит адрес с AllowedIPs и отбросит трафик. Firewall ещё не участвовал, базовую проверку уже сделал сам WireGuard.

На клиенте AllowedIPs читаются иначе. Значение 0.0.0.0/0 означает «отправлять весь IPv4-трафик через этого peer». Значение ::/0 делает то же для IPv6. Для split tunnel указывают только нужные внутренние сети, например 10.8.0.0/24 и 192.168.50.0/24.

[Interface]
 Address = 10.8.0.2/32
 PrivateKey = CLIENT_PRIVATE_KEY
 DNS = 10.8.0.1
 
 [Peer]
 PublicKey = SERVER_PUBLIC_KEY
 Endpoint = vpn.example.com:51820
 AllowedIPs = 10.8.0.0/24, 192.168.50.0/24
 PersistentKeepalive = 25
 

Для полного туннеля конфигурация будет другой:

[Interface]
 Address = 10.8.0.2/32
 PrivateKey = CLIENT_PRIVATE_KEY
 DNS = 10.8.0.1
 
 [Peer]
 PublicKey = SERVER_PUBLIC_KEY
 Endpoint = vpn.example.com:51820
 AllowedIPs = 0.0.0.0/0, ::/0
 PersistentKeepalive = 25
 

Разница критична. В первом случае через WireGuard уйдут только выбранные сети. Во втором через WireGuard пойдёт почти весь IPv4 и IPv6-трафик. Если настроить только 0.0.0.0/0, а IPv6 оставить активным, часть трафика может пройти мимо туннеля. Для публичных сетей и коммерческих VPN такой промах часто превращается в утечку адреса.

Ключи, handshake и криптография

WireGuard убрал выбор шифров из конфигурации. Администратор не выбирает «набор шифров» и не может случайно включить устаревший режим ради совместимости. Протокол использует Curve25519 для обмена ключами, ChaCha20-Poly1305 для аутентифицированного шифрования, BLAKE2s для хеширования, SipHash24 для ключей хеш-таблиц и HKDF для вывода ключевого материала. Подробный список приведён в документации протокола.

Каждый peer имеет постоянную пару ключей. Приватный ключ хранится локально. Публичный ключ передают другим участникам. Сертификатов, центра сертификации, CRL и OCSP в базовом WireGuard нет. Такой подход резко упрощает запуск, но переносит жизненный цикл доступа в операционные процессы. Если сотрудник ушёл из компании, публичный ключ надо удалить из всех конфигураций, где peer был разрешён.

umask 077
 wg genkey | tee private.key | wg pubkey > public.key
 

Handshake построен на схеме Noise_IK. При первом обмене стороны используют постоянные ключи и эфемерные ключи, получают симметричные ключи для передачи данных и дальше шлют короткие транспортные сообщения. WireGuard периодически обновляет ключи по таймерам и счётчикам пакетов, а не держит «вечную сессию». Поэтому отсутствие свежего handshake в выводе wg show не всегда означает поломку. Возможно, через туннель давно не шёл трафик.

wg show
 
 interface: wg0
   public key: SERVER_PUBLIC_KEY
   listening port: 51820
 
 peer: CLIENT_PUBLIC_KEY
   endpoint: 203.0.113.10:45512
   allowed ips: 10.8.0.2/32
   latest handshake: 38 seconds ago
   transfer: 12.4 MiB received, 41.8 MiB sent
   persistent keepalive: every 25 seconds
 

Поле latest handshake показывает время последнего успешного криптографического обмена. Поля transfer показывают счётчики переданных данных. Для диагностики полезно сначала отправить активный пакет, например ping 10.8.0.1 с клиента, а потом снова посмотреть wg show.

WireGuard умеет использовать опциональный PresharedKey. Такой ключ смешивается с обычной криптографией на открытых ключах и добавляет дополнительный симметричный слой. Называть WireGuard постквантовым протоколом нельзя. Без PSK WireGuard не рассчитан на постквантовую стойкость, а PSK не заменяет полноценный постквантовый handshake. Для строгой модели угроз PSK полезен, но создаёт ещё один секрет, который надо генерировать, хранить, ротировать и удалять.

wg genpsk > psk.key
 

Защита от мусорных handshake-пакетов тоже встроена не полностью магически. WireGuard не отвечает неавторизованным клиентам и под нагрузкой может использовать cookie reply, чтобы снизить стоимость обработки. Но такой механизм не заменяет rate limit, фильтрацию на периметре, защиту облачного провайдера от DDoS и мониторинг CPU.

Практическая настройка без хрупких PostUp-команд

На Linux удобнее разделить три вещи. WireGuard-конфиг описывает интерфейс и peer-узлы. Системный sysctl включает маршрутизацию. Firewall живёт в отдельном nftables или iptables-правиле. Вставлять длинные nft add table и nft add chain прямо в PostUp можно для лаборатории, но в продакшене такой конфиг часто падает при повторном запуске, потому что таблица или цепочка уже существуют.

apt update
 apt install wireguard nftables
 

Сначала включаем IPv4 forwarding постоянно:

cat > /etc/sysctl.d/99-wireguard.conf <<'EOF'
 net.ipv4.ip_forward = 1
 EOF
 
 sysctl --system
 

Если нужен IPv6 через сервер, включаем пересылку IPv6 отдельно:

cat >> /etc/sysctl.d/99-wireguard.conf <<'EOF'
 net.ipv6.conf.all.forwarding = 1
 EOF
 
 sysctl --system
 

Затем создаём WireGuard-конфиг сервера:

cat > /etc/wireguard/wg0.conf <<'EOF'
 [Interface]
 Address = 10.8.0.1/24
 ListenPort = 51820
 PrivateKey = SERVER_PRIVATE_KEY
 
 [Peer]
 PublicKey = CLIENT_PUBLIC_KEY
 AllowedIPs = 10.8.0.2/32
 EOF
 

NAT лучше вынести в nftables. Пример ниже маскирует трафик из сети 10.8.0.0/24, который выходит через eth0. Имя внешнего интерфейса надо проверить командой ip route get 1.1.1.1.

cat > /etc/nftables.d/wireguard.nft <<'EOF'
 table ip wireguard_nat {
   chain postrouting {
     type nat hook postrouting priority srcnat; policy accept;
     oifname "eth0" ip saddr 10.8.0.0/24 masquerade
   }
 }
 EOF
 
 nft -f /etc/nftables.d/wireguard.nft
 

Правило для входящего UDP-порта зависит от используемого firewall. На чистом nftables можно добавить отдельную таблицу фильтрации. В облаке надо проверить ещё и security group, потому что открытый локальный порт не поможет, если провайдерский firewall режет UDP 51820.

ss -lunp | grep 51820
 tcpdump -ni any udp port 51820
 

Запуск и диагностика базовые:

systemctl enable --now wg-quick@wg0
 wg show
 ip address show wg0
 ip route
 

wg-quick стоит отличать от самого WireGuard. Утилита wg управляет ключами, peer-узлами, endpoint, AllowedIPs и keepalive. А wg-quick дополнительно обрабатывает Address, DNS, MTU, Table, PreUp, PostUp, PreDown и PostDown. На systemd-networkd, NetworkManager, OpenWrt, MikroTik и pfSense те же идеи остаются, но синтаксис и поведение отличаются. Для проверки полезно держать рядом man-страницу wg.

Где WireGuard хорош, а где обещания надо резать

WireGuard хорошо подходит для доступа администратора к серверам, связи домашних устройств, site-to-site-туннелей, связи облачных узлов и небольшого корпоративного доступа. В этих сценариях выигрывают компактная конфигурация, быстрый handshake, маленькое число криптографических вариантов и понятная диагностика.

Сценарий WireGuard подходит Главный риск
Доступ администратора к серверам Да Потеря приватного ключа, слишком широкие AllowedIPs, отсутствие резервного доступа
Домашний VPN Да NAT, динамический адрес, DNS, IPv6, MTU
Site-to-site между офисами Да, при простой схеме Пересекающиеся сети, асимметричная маршрутизация, слабая фильтрация между сегментами
Крупный корпоративный удалённый доступ Частично Нет встроенных ролей, SSO, MFA, каталога пользователей и аудита действий
Коммерческий privacy-VPN Как транспорт, но не как вся система приватности Статические внутренние адреса, fingerprinting, доверие к оператору, журналы, DNS и утечки
Маскировка под HTTPS Нет WireGuard не занимается обфускацией и не поддерживает TCP-транспорт в базовом протоколе

Скорость WireGuard нельзя оценивать лозунгом «всегда быстрее». На Linux реализация в ядре и ChaCha20-Poly1305 часто дают хороший результат, особенно на слабых устройствах без аппаратного AES. Но реальный канал упирается в потери, задержку, MTU, качество маршрута, CPU роутера, настройки offload, облачного провайдера и блокировки UDP. Бывают тесты, где OpenVPN проигрывает WireGuard, и бывают условия с высокой задержкой, где результат уже не такой однозначный.

MTU ломает WireGuard чаще, чем кажется. Внутренний IP-пакет получает внешнюю UDP-обёртку и криптографический overhead. Если внешний путь не пропускает крупные пакеты или где-то сломан Path MTU Discovery, пользователь видит странную картину: ping проходит, SSH работает, а сайты открываются наполовину или загрузки зависают. wg-quick умеет определять MTU автоматически, но при проблемах стоит вручную попробовать 1420, 1380 или 1280.

[Interface]
 Address = 10.8.0.2/32
 PrivateKey = CLIENT_PRIVATE_KEY
 MTU = 1380
 

DNS тоже не часть криптографического протокола. Строка DNS в конфиге wg-quick меняет настройки резолвера через системные механизмы, но не гарантирует одинаковое поведение на всех платформах. Браузер может использовать DNS over HTTPS, операционная система может держать старый резолвер, а IPv6 может уйти мимо туннеля. Проверять надо не только внешний IP, но и DNS, IPv6 и маршруты.

PersistentKeepalive нужен не всем. Значение 25 обычно ставят клиенту за NAT, если сервер должен иметь возможность достучаться до клиента в любой момент. Клиент будет отправлять пустой аутентифицированный пакет раз в 25 секунд, чтобы домашний роутер, операторский NAT или stateful firewall не забыли UDP-сопоставление. На сервере с публичным адресом keepalive часто не нужен.

[Peer]
 PublicKey = SERVER_PUBLIC_KEY
 Endpoint = vpn.example.com:51820
 AllowedIPs = 0.0.0.0/0, ::/0
 PersistentKeepalive = 25
 

Endpoint в WireGuard может обновляться автоматически. Если peer прислал корректно аутентифицированный пакет с нового IP и порта, WireGuard запомнит свежий источник. Для мобильного клиента, который переходит с Wi-Fi на LTE, такое поведение удобно. Для строгого site-to-site с фиксированными адресами может потребоваться дополнительная фильтрация UDP-сокета firewall-правилами.

Материал предназначен для легального и ответственного применения WireGuard в своих сетях, лабораториях, инфраструктуре и корпоративном доступе. Инструкции нельзя использовать для несанкционированного доступа, слежки, взлома, нарушения правил сервисов или незаконного обхода блокировок. Законы своей страны, включая российские правила связи и доступа к ресурсам, читатель должен проверять отдельно.

Мифы, слабые места и финальный вывод

Первый миф: WireGuard сам по себе делает пользователя анонимным. Протокол шифрует трафик между peer-узлами и скрывает содержимое от промежуточной сети, но VPN-сервер видит внутренний адрес клиента, внешний сайт видит адрес VPN-выхода, а провайдер видит UDP-обмен с endpoint. Анонимность требует отдельной модели: доверия к оператору, политики журналов, изоляции приложений, защиты от fingerprinting, DNS-утечек и корреляции трафика.

Второй миф: WireGuard заменяет Zero Trust. На самом деле WireGuard даёт защищённый транспорт и привязку ключа к IP-диапазонам. Проверку устройства, SSO, MFA, роль пользователя, контекст доступа, posture checks, журнал действий и контроль приложений надо строить выше. WireGuard может быть хорошей транспортной частью такой архитектуры, но не заменяет систему управления доступом.

Третий миф: маленькая кодовая база автоматически означает безопасность. Компактность упрощает аудит и уменьшает поверхность атаки, но эксплуатационные ошибки остаются. Украденный приватный ключ, забытый peer бывшего сотрудника, широкий AllowedIPs = 0.0.0.0/0 на сервере, слабый firewall между сегментами, DNS-утечка или отсутствие резервного доступа дают реальный инцидент без единой уязвимости в протоколе.

Четвёртый миф: WireGuard сложно обнаружить. Базовый WireGuard не занимается обфускацией и не маскируется под HTTPS. Официальная страница ограничений прямо пишет, что обфускация должна находиться уровнем выше, а сам WireGuard сосредоточен на криптографии и простой реализации. В сетях, где UDP режут или анализируют, обычный WireGuard может не работать вовсе.

Пятый миф: достаточно настроить туннель, и сеть защищена. WireGuard защищает транспорт между peer-узлами, но не исправляет плохую сегментацию. Если после подключения клиент видит лишние подсети, открытые панели администрирования, metadata endpoint облака или соседние VPN-клиенты, проблема лежит в маршрутизации и firewall. Хорошая схема начинается с минимальных AllowedIPs, отдельных адресов на каждого пользователя, запрета лишнего forwarding и явных правил между сегментами.

Правильный вывод простой. WireGuard стоит выбирать, когда нужен быстрый, понятный и минималистичный IP-туннель без тяжёлой инфраструктуры сертификатов. Для домашней сети, доступа администратора, связи серверов и небольших site-to-site-схем протокол часто даёт лучший баланс простоты и надёжности. Для большого удалённого доступа одного WireGuard мало: вокруг него нужны учёт ключей, отзыв доступа, MFA или SSO на уровне приложений, журнал изменений, DNS-политики, контроль IPv6, мониторинг и резервный канал администрирования.

WireGuard VPN протокол туннель криптография AllowedIPs NAT MTU маршрутизация безопасность
Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
42 000
CVE / год
Аналитика · Уязвимости
42 000 CVE за год. Что чинить первым?
Разобрали, почему CVSS уже мало, как помогают EPSS и CISA KEV и где Security Vision NG VM сокращает путь от риска до патча.
Перейти к статье
18+. Реклама. Рекламодатель ООО «Интеллектуальная безопасность», ИНН 7719435412

Юрий Кочетов

Здесь я делюсь своими не самыми полезными, но крайне забавными мыслями о том, как устроен этот мир. Если вы устали от скучных советов и правильных решений, то вам точно сюда.