WireGuard: проверка конфигурации и AllowedIPs в изолированных netns

0
17
Обложка статьи: WireGuard: проверка конфигурации и AllowedIPs в изолированных netns

Ошибка в конфигурации VPN проявляется потерей доступа или, хуже, туннелем, который «работает», но пропускает лишнее. Проверить конфигурацию WireGuard можно заранее на одной машине: сервер и клиент запускаются в изолированных сетевых пространствах имён (netns), соединённых виртуальным кабелем. Вы получаете настоящее рукопожатие, трафик и проверку правил AllowedIPs без затрагивания рабочих интерфейсов. Ниже конфигурации, скрипт и ожидаемые результаты.

Статья опирается на логику направления «Сетевая безопасность» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена на Debian 12 (ядро 6.1, wireguard-tools 1.0.20210914) от root: после скрипта пространств имён и интерфейсов не осталось, рабочие настройки сети не менялись. Установка и развёртывание сервера: WireGuard: настройка VPN-сервера; изоляция тестов по тому же принципу: проверка правил в netns.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Сеть сегментирована, удалённый доступ идёт через VPN с контролем, правила и конфигурации проверяются

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

Конфигурации

Скрипт ниже создаёт два файла в формате wg-quick. Сервер (wgs0.conf) и клиент (wgc0.conf):

Параметр Сервер Клиент
Address 10.77.0.1/24 10.77.0.2/24
ListenPort 51820 не задаётся (случайный)
PrivateKey ключ сервера ключ клиента
[Peer] PublicKey открытый ключ клиента открытый ключ сервера
PresharedKey общий предварительный ключ тот же
AllowedIPs 10.77.0.2/32 (только адрес этого клиента) 10.77.0.1/32 (только адрес сервера)
Endpoint, PersistentKeepalive не нужны 192.0.2.1:51820, 25

Принципы: на сервере в AllowedIPs каждого клиента стоит только его адрес с маской /32, на клиенте — только то, что должно идти через туннель (здесь адрес сервера; для выхода всего трафика через VPN — 0.0.0.0/0, но осознанно). Предварительный ключ добавляет защиту на случай появления квантового взлома открытых ключей и усиливает аутентификацию.

Скрипт проверки

Запускайте от root на машине, где установлены wireguard-tools и поддержка WireGuard в ядре (современные ядра Linux её содержат). Скрипт создаёт пространства zwgsrv, zwgcli и виртуальный кабель, генерирует временные ключи, запускает туннель, проверяет связь и полностью убирает за собой.

#!/bin/bash
set -u
S=zwgsrv; C=zwgcli
cleanup() { ip netns del $S 2>/dev/null; ip netns del $C 2>/dev/null; rm -rf /tmp/zwg; }
trap cleanup EXIT; cleanup
umask 077; mkdir -p /tmp/zwg; cd /tmp/zwg
SK=$(wg genkey); SP=$(echo $SK | wg pubkey); CK=$(wg genkey); CP=$(echo $CK | wg pubkey); PSK=$(wg genpsk)
cat > wgs0.conf <<EOF
[Interface]
Address = 10.77.0.1/24
ListenPort = 51820
PrivateKey = $SK

[Peer]
# клиент laptop-anna
PublicKey = $CP
PresharedKey = $PSK
AllowedIPs = 10.77.0.2/32
EOF
cat > wgc0.conf <<EOF
[Interface]
Address = 10.77.0.2/24
PrivateKey = $CK

[Peer]
PublicKey = $SP
PresharedKey = $PSK
Endpoint = 192.0.2.1:51820
AllowedIPs = 10.77.0.1/32
PersistentKeepalive = 25
EOF
ip netns add $S; ip netns add $C
ip link add zwgv0 type veth peer name zwgv1
ip link set zwgv0 netns $S; ip link set zwgv1 netns $C
ip -n $S addr add 192.0.2.1/24 dev zwgv0; ip -n $S link set zwgv0 up; ip -n $S link set lo up
ip -n $C addr add 192.0.2.2/24 dev zwgv1; ip -n $C link set zwgv1 up; ip -n $C link set lo up
command -v wg-quick || { echo "wg-quick не установлен"; exit 3; }
echo "права файлов:"; stat -c '%a %n' wgs0.conf wgc0.conf
ip netns exec $S wg-quick up ./wgs0.conf 2>&1 | grep -vE "^\[#\] (ip link add|wg setconf|ip -4 address|ip link set mtu|ip link set up)" | head -3
ip netns exec $C wg-quick up ./wgc0.conf 2>&1 | grep -vE "^\[#\] (ip link add|wg setconf|ip -4 address|ip link set mtu|ip link set up)" | head -3
echo "=== пинг"; ip netns exec $C ping -c 2 -W 2 -q 10.77.0.1 | tail -2
echo "=== handshake"; ip netns exec $S wg show wgs0 | grep -E "latest handshake|allowed ips|endpoint"
echo "=== wg-quick предупреждение о правах"; chmod 644 wgc0.conf; ip netns exec $C wg-quick down ./wgc0.conf >/dev/null 2>&1; ip netns exec $C wg-quick up ./wgc0.conf 2>&1 | grep -i "world accessible" | head -1

Что проверяется и ожидаемый результат

Проверка Результат на проверке
Права файлов с ключами 600 у обоих файлов (скрипт создаёт их с umask 077)
Пинг клиента до сервера через туннель (10.77.0.1) 2 из 2, потерь 0%
Рукопожатие У сервера в wg show видны endpoint клиента, allowed ips: 10.77.0.2/32 и latest handshake: 1 second ago

Дополнительные проверки, выполненные отдельным запуском на том же стенде (команды wg set вместо wg-quick, с теми же параметрами):

Проверка Результат
wg show на клиенте latest handshake: 1 second ago, transfer: 348 B received, 436 B sent, persistent keepalive: every 25 seconds; приватный и предварительный ключи показываются как (hidden) (в выводе их нужно скрывать при копировании в отчёты)
Защита AllowedIPs: клиент отправляет пакеты с другим адресом источника (10.77.0.50), которого нет в AllowedIPs сервера 100% потерь: сервер отбрасывает пакет, потому что адрес источника не соответствует ключу клиента
Порт сервера UDP 51820 слушается на 0.0.0.0 и [::] в пространстве сервера: на рабочем сервере ограничьте его правилом firewall
Клиент подменили ключом без регистрации на сервере Рукопожатия нет, пинг даёт 100% потерь; на сервере остаётся только старое время последнего рукопожатия

Последние две строки показывают главное свойство WireGuard: сервер отвечает только на пакеты от зарегистрированных ключей, а AllowedIPs работает как фильтр источника и как таблица маршрутов.

Типовые ошибки в конфигурации

Ошибка Последствия и как исправить
На сервере у клиента AllowedIPs = 10.77.0.0/24 или 0.0.0.0/0 Клиент может представляться любым адресом из подсети (подмена другого клиента). Используйте только его адрес /32
Два клиента с одинаковым адресом в AllowedIPs Работает только последний; связь нестабильна. Назначайте уникальные адреса
Файл конфигурации доступен всем Закрытый ключ читают другие пользователи. Права 600, владелец root; проверяйте командой stat -c '%a %n' файл
Нет PersistentKeepalive у клиента за NAT Туннель «засыпает», и сервер не может отправить пакеты первым. Задайте 25 секунд
Порт UDP закрыт на firewall Нет рукопожатия, пинга нет. Откройте порт: firewall в Linux
Клиент должен выходить в интернет через сервер, но маршрутизация не включена Нужны net.ipv4.ip_forward=1 и правила трансляции адресов на сервере; проверка этой части выходит за рамки статьи

Эксплуатация ключей

  • Закрытые ключи создаются на устройстве клиента и не передаются; на сервер передаётся только открытый ключ.
  • Для каждого устройства свой ключ: потеря устройства закрывается удалением одного клиента (wg set wg0 peer ОТКРЫТЫЙ_КЛЮЧ remove и удаление из файла).
  • Список клиентов ведите в реестре с владельцем и датой выдачи; при увольнении отзывайте доступ: отзыв прав при увольнении.
  • Для критичного доступа добавьте второй фактор на уровне приложений или шлюза: MFA для SSH и WireGuard.
  • Журналы подключений: WireGuard не пишет события входа сам; используйте время последнего рукопожатия из wg show и собирайте его в мониторинг.

Диагностика

Симптом Причина и что делать
Скрипт сообщает, что wg-quick не установлен Установите пакет wireguard-tools (wireguard)
Ошибка создания интерфейса типа wireguard В ядре нет модуля или нет прав. Проверьте версию ядра и modprobe wireguard
Нет рукопожатия Неверные ключи, неверный Endpoint или порт закрыт. Проверьте ключи (открытый ключ одной стороны в конфигурации другой), доступность UDP-порта
Рукопожатие есть, пинга нет Не те адреса в AllowedIPs или на интерфейсе. Сверьте с таблицей: у каждой стороны в AllowedIPs адрес противоположной стороны
После скрипта остались интерфейсы Прерывание на середине. Удалите пространства ip netns del zwgsrv, ip netns del zwgcli

Где это в модели зрелости

Материал относится к направлению «Сетевая безопасность» (материалы направления, карта зрелости). Уровень 2 требует удалённого доступа через VPN с контролем: воспроизводимая проверка конфигурации и учёт ключей делают этот доступ управляемым.

Как проверить

  1. Скрипт проверки выполняется без ошибок: рукопожатие есть, пинг проходит, подмена адреса и неверный ключ блокируются.
  2. На сервере у каждого клиента в AllowedIPs только его адрес /32, файлы с ключами имеют права 600.
  3. Порт UDP открыт только нужным адресам или защищён ограничениями; клиенты за NAT имеют keepalive.
  4. Список клиентов и их ключей ведётся, отзыв проверен на тестовом клиенте.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация и описание протокола WireGuard: wireguard.com; руководства man wg, man wg-quick.
  • NIST SP 800-77 Rev. 1, Guide to IPsec VPNs (общие принципы защищённого удалённого доступа): csrc.nist.gov. Международная практика, не российский норматив.

Оставьте свой ответ