Это многостраничный печатный вид этого раздела. Нажмите что бы печатать.

Вернуться к обычному просмотру страницы.

WireGuard

WireGuard — быстрый, современный и безопасный VPN-туннель

Простой и удобный в использовании

WireGuard стремится быть таким же простым в настройке и развертывании, как SSH. VPN-соединение устанавливается простым обменом открытыми ключами — точно так же, как при обмене SSH-ключами — а всё остальное прозрачно обрабатывается WireGuard. Он даже способен роумить между IP-адресами, как Mosh. Нет необходимости управлять соединениями, беспокоиться о состоянии, управлять демонами или беспокоиться о том, что находится под капотом. WireGuard предоставляет чрезвычайно простой, но мощный интерфейс.

Криптографическая надёжность

WireGuard использует современную криптографию, такую как фреймворк Noise, Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24, HKDF и безопасные доверенные конструкции. Он делает консервативные и разумные выборы и был проверен криптографами.

Минимальная поверхность атаки

WireGuard разработан с учётом простоты реализации и лёгкости. Он предназначен для простой реализации в очень небольшом количестве строк кода и лёгкого аудита на наличие уязвимостей безопасности. По сравнению с гигантами вроде *Swan/IPsec или OpenVPN/OpenSSL, аудит огромных кодовых баз которых является непосильной задачей даже для больших команд экспертов по безопасности, WireGuard предназначен для всесторонней проверки отдельными специалистами.

Высокая производительность

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

Хорошо определённый и тщательно продуманный

WireGuard является результатом длительного и тщательно продуманного академического процесса, результатом которого стал технический документ — академическая исследовательская работа, которая чётко определяет протокол и тщательные соображения, лежащие в основе каждого решения.

1 - Обзор WireGuard

Концептуальный обзор WireGuard — быстрого, современного и безопасного VPN-туннеля

Концептуальный обзор

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

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

WireGuard безопасно инкапсулирует IP-пакеты через UDP. Вы добавляете интерфейс WireGuard, настраиваете его с вашим приватным ключом и открытыми ключами ваших пиров, а затем отправляете через него пакеты. Все вопросы распространения ключей и принудительной настройки находятся вне области WireGuard; эти вопросы гораздо лучше оставить другим уровням, чтобы не получить раздувание IKE или OpenVPN. Напротив, он больше имитирует модель SSH и Mosh: обе стороны имеют открытые ключи друг друга, а затем они просто могут начать обмениваться пакетами через интерфейс.

Простой сетевой интерфейс

WireGuard работает путём добавления сетевого интерфейса (или нескольких), например eth0 или wlan0, называемого wg0 (или wg1, wg2, wg3 и т.д.). Этот сетевой интерфейс затем можно настраивать обычным образом с помощью ifconfig(8) или ip-address(8), добавлять и удалять маршруты с помощью route(8) или ip-route(8) и так далее со всеми обычными сетевыми утилитами. Специфические для WireGuard аспекты интерфейса настраиваются с помощью инструмента wg(8). Этот интерфейс действует как туннельный интерфейс.

WireGuard связывает IP-адреса туннеля с открытыми ключами и удалёнными конечными точками. Когда интерфейс отправляет пакет пиру, он делает следующее:

  1. Этот пакет предназначен для 192.168.30.8. Какой это пир? Позвольте мне посмотреть… Хорошо, это для пира ABCDEFGH. (Или если он не предназначен ни для одного настроенного пира — отбросить пакет.)

  2. Зашифровать весь IP-пакет, используя открытый ключ пира ABCDEFGH.

  3. Какова удалённая конечная точка пира ABCDEFGH? Позвольте мне посмотреть… Хорошо, конечная точка — UDP-порт 53133 на хосте 216.58.211.110.

  4. Отправить зашифрованные байты из шага 2 через Интернет на 216.58.211.110:53133 через UDP.

Когда интерфейс получает пакет, происходит следующее:

  1. Я только что получил пакет с UDP-порта 7361 от хоста 98.139.183.24. Давайте расшифруем его!

  2. Он успешно расшифрован и аутентифицирован для пира LMNOPQRS. Хорошо, давайте запомним, что последняя конечная точка пира LMNOPQRS в Интернете — 98.139.183.24:7361 через UDP.

  3. После расшифровки обычный текстовый пакет пришёл с 192.168.43.89. Разрешено ли пиру LMNOPQRS отправлять нам пакеты с адреса 192.168.43.89?

  4. Если да — принять пакет на интерфейсе. Если нет — отбросить его.

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

Криптоключевая маршрутизация

В основе WireGuard лежит концепция, называемая Криптоключевой маршрутизацией, которая работает путём связывания открытых ключей со списком IP-адресов туннеля, которым разрешено находиться внутри туннеля. Каждый сетевой интерфейс имеет приватный ключ и список пиров. Каждый пир имеет открытый ключ. Открытые ключи короткие и простые и используются пирами для аутентификации друг друга. Их можно передавать для использования в конфигурационных файлах любым внешним методом, подобно тому, как можно отправить свой открытый ключ SSH другу для доступа к серверу оболочки.

Например, серверный компьютер может иметь такую конфигурацию:

[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
AllowedIPs = 10.10.10.230/32

2 - Установка WireGuard

Инструкции по установке WireGuard на различные операционные системы и устройства

Обзор

WireGuard доступен для широкого спектра операционных систем и платформ. Ниже приведены инструкции по установке для наиболее популярных систем. Если ваша система не указана в списке, вы также можете легко скомпилировать WireGuard из исходного кода.

Краткая таблица установки

Операционная системаКоманда установки
Windows 10/11/2016/2019/2022/2025Скачать MSI-установщик
macOS (App Store)Установить из App Store
Ubuntusudo apt install wireguard
Debian# apt install wireguard
Fedorasudo dnf install wireguard-tools
Arch Linuxsudo pacman -S wireguard-tools
AndroidGoogle Play или APK-файл
iOSУстановить из App Store
OpenSUSE/SLEsudo zypper install wireguard-tools
Alpine# apk add -U wireguard-tools
Gentoo# emerge wireguard-tools
FreeBSD# pkg install wireguard
OpenBSD# pkg_add wireguard-tools

Подробные инструкции

Установка на сервере Ubuntu

WireGuard включён в репозитории Ubuntu, начиная с версии 20.04 (Focal Fossa). Для более ранних версий рекомендуется использовать PPA.

Ubuntu 20.04 и новее:

sudo apt update
sudo apt install wireguard

Ubuntu 18.04 (Bionic Beaver) и более ранние:

sudo add-apt-repository ppa:wireguard/wireguard
sudo apt update
sudo apt install wireguard

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

Проверка установки:

wg --version
modinfo wireguard

Установка на сервере Fedora

В Fedora WireGuard доступен в официальных репозиториях. Для установки требуются утилиты пользовательского пространства, так как модуль ядра встроен в ядро Linux начиная с версии 5.6.

Fedora 32 и новее (с ядром 5.6+):

sudo dnf install wireguard-tools

Fedora 31 и более ранние версии:

Для старых версий Fedora, где модуль ядра не встроен, необходимо установить модуль отдельно:

sudo dnf install wireguard-tools
sudo dnf copr enable jdoss/wireguard
sudo dnf install wireguard-dkms

Настройка автоматической загрузки модуля (для ядер < 5.6):

sudo modprobe wireguard
echo "wireguard" | sudo tee /etc/modules-load.d/wireguard.conf

Установка на рабочей станции Fedora

На рабочей станции Fedora процесс установки аналогичен серверной версии. Однако для рабочей станции может потребоваться графический интерфейс для управления VPN-подключениями.

Установка базовых инструментов:

sudo dnf install wireguard-tools

Установка GUI-менеджера (опционально):

Для управления WireGuard через графический интерфейс можно установить NetworkManager:

sudo dnf install networkmanager-wireguard
sudo systemctl restart NetworkManager

После этого вы сможете настраивать WireGuard через стандартные сетевые настройки GNOME или KDE.

Настройка автозапуска (опционально):

Чтобы WireGuard автоматически поднимался при загрузке системы:

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Установка на Android

WireGuard для Android доступен двумя способами:

Способ 1: Установка из Google Play Store

  1. Откройте Google Play Store на вашем устройстве
  2. Найдите “WireGuard”
  3. Нажмите “Установить”
  4. Дождитесь завершения установки

Прямая ссылка на Google Play

Способ 2: Установка из APK-файла

Если у вас нет доступа к Google Play, вы можете установить WireGuard напрямую из APK-файла:

  1. Загрузите последнюю версию APK с официального сайта WireGuard или из репозитория релизов
  2. На устройстве перейдите в НастройкиБезопасность и включите “Неизвестные источники”
  3. Откройте загруженный APK-файл
  4. Нажмите “Установить”
  5. После установки запустите приложение

Импорт конфигурации на Android:

После установки приложения:

  1. Откройте приложение WireGuard
  2. Нажмите на кнопку “+” (плюс) в правом нижнем углу
  3. Выберите “Импортировать из файла” или “Импортировать из архива”
  4. Выберите конфигурационный файл (обычно имеет расширение .conf)
  5. Нажмите “Сохранить”
  6. Для активации VPN нажмите на переключатель рядом с именем конфигурации

Дополнительные дистрибутивы

Debian

Debian Bullseye (11) и новее:

# apt update
# apt install wireguard

Debian Buster (10) и более ранние:

Для старых версий Debian необходимо включить backports:

# echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
# apt update
# apt -t buster-backports install wireguard

Arch Linux

Установка с модулем ядра (ядро 5.6+):

sudo pacman -S wireguard-tools

Для ядер < 5.6:

sudo pacman -S wireguard-lts  # для LTS-ядра
# или
sudo pacman -S wireguard-dkms linux-headers  # для DKMS с заголовками ядра

macOS

Установка из App Store:

  1. Откройте App Store
  2. Найдите “WireGuard”
  3. Нажмите “Получить” или кнопку установки
  4. Введите пароль Apple ID или используйте Touch ID

Прямая ссылка в App Store

Установка через Homebrew (только CLI-инструменты):

brew install wireguard-tools

Установка через MacPorts:

port install wireguard-tools

iOS

WireGuard доступен в App Store для iPhone и iPad:

  1. Откройте App Store
  2. Найдите “WireGuard”
  3. Нажмите “Получить”
  4. Подтвердите установку с помощью Face ID, Touch ID или пароля Apple ID

Прямая ссылка в App Store

После установки импортируйте конфигурацию через файлы или QR-код.

FreeBSD

# pkg install wireguard

OpenBSD

# pkg_add wireguard-tools

Alpine Linux

# apk add -U wireguard-tools

Gentoo

# emerge wireguard-tools

Для совместимости со старыми ядрами также доступен ebuild wireguard-modules:

# emerge wireguard-modules

OpenSUSE и SLE

sudo zypper install wireguard-tools

Slackware

sudo slackpkg install wireguard-tools

Mageia

sudo urpmi wireguard-tools

Termux (Android CLI)

pkg install wireguard-tools

NixOS

В конфигурации NixOS добавьте:

boot.extraModulePackages = [ config.boot.kernelPackages.wireguard ];
environment.systemPackages = [ pkgs.wireguard pkgs.wireguard-tools ];

Nix на Darwin (macOS CLI)

nix-env -iA nixpkgs.wireguard-tools

OpenWRT

opkg install wireguard

Дополнительные инструкции по установке и настройке можно найти в вики OpenWRT.

Enterprise Linux (RHEL/CentOS/Oracle)

Oracle Linux 8 (UEK6)

# dnf install oraclelinux-developer-release-el8
# dnf config-manager --disable ol8_developer
# dnf config-manager --enable ol8_developer_UEKR6
# dnf config-manager --save --setopt=ol8_developer_UEKR6.includepkgs='wireguard-tools*'
# dnf install wireguard-tools

Red Hat Enterprise Linux 8

Метод 1 (предварительно собранный модуль из ELRepo):

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
sudo yum install kmod-wireguard wireguard-tools

Метод 2 (DKMS для нестандартных ядер):

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo subscription-manager repos --enable codeready-builder-for-rhel-8-$(arch)-rpms
sudo yum copr enable jdoss/wireguard
sudo yum install wireguard-dkms wireguard-tools

CentOS 8

Метод 1 (встроенный модуль в kernel-plus):

sudo yum install yum-utils epel-release
sudo yum-config-manager --setopt=centosplus.includepkgs="kernel-plus, kernel-plus-*" --setopt=centosplus.enabled=1 --save
sudo sed -e 's/^DEFAULTKERNEL=kernel-core$/DEFAULTKERNEL=kernel-plus-core/' -i /etc/sysconfig/kernel
sudo yum install kernel-plus wireguard-tools
sudo reboot

Метод 2 (предварительно собранный модуль из ELRepo):

sudo yum install elrepo-release epel-release
sudo yum install kmod-wireguard wireguard-tools

Метод 3 (DKMS):

sudo yum install epel-release
sudo yum config-manager --set-enabled PowerTools
sudo yum copr enable jdoss/wireguard
sudo yum install wireguard-dkms wireguard-tools

Oracle Linux 7 (UEK6)

# yum install oraclelinux-developer-release-el7
# yum-config-manager --disable ol7_developer
# yum-config-manager --enable ol7_developer_UEKR6
# yum-config-manager --save --setopt=ol7_developer_UEKR6.includepkgs='wireguard-tools*'
# yum install wireguard-tools

Red Hat Enterprise Linux 7

Метод 1 (предварительно собранный модуль из ELRepo):

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum install kmod-wireguard wireguard-tools

Метод 2 (DKMS):

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo curl -o /etc/yum.repos.d/jdoss-wireguard-epel-7.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo
sudo yum install wireguard-dkms wireguard-tools

CentOS 7

Метод 1 (kernel-plus):

sudo yum install yum-utils epel-release
sudo yum-config-manager --setopt=centosplus.includepkgs=kernel-plus --enablerepo=centosplus --save
sudo sed -e 's/^DEFAULTKERNEL=kernel$/DEFAULTKERNEL=kernel-plus/' -i /etc/sysconfig/kernel
sudo yum install kernel-plus wireguard-tools
sudo reboot

Метод 2 (ELRepo):

sudo yum install epel-release elrepo-release
sudo yum install yum-plugin-elrepo
sudo yum install kmod-wireguard wireguard-tools

Метод 3 (DKMS):

sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo curl -o /etc/yum.repos.d/jdoss-wireguard-epel-7.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo
sudo yum install wireguard-dkms wireguard-tools

Другие дистрибутивы

Void Linux

xbps-install -S wireguard-tools wireguard-dkms

Adélie Linux

apk add wireguard-tools wireguard-module

Source Mage

cast wireguard-tools

Buildroot

В конфигурации Buildroot добавьте:

BR2_PACKAGE_WIREGUARD_LINUX_COMPAT=y
BR2_PACKAGE_WIREGUARD_TOOLS=y

EdgeOS

Скачайте соответствующий предварительно собранный файл со страницы релизов, а затем установите его с помощью dpkg:

sudo dpkg -i wireguard-{type}-{version}.deb

AstLinux

В конфигурации AstLinux добавьте:

BR2_PACKAGE_WIREGUARD_TOOLS=y
BR2_PACKAGE_WIREGUARD=y

Milis Linux

# mps kur wireguard-tools wireguard-linux-compat

Дальнейшие шаги

После успешной установки переходите к руководству по быстрому запуску для настройки вашего первого WireGuard-подключения.

Если вашего дистрибутива нет в списке выше, вы можете легко скомпилировать WireGuard из исходного кода — это довольно простая процедура.

3 - Быстрый старт

Быстрый старт с WireGuard — настройка интерфейса, генерация ключей и базовое использование

Быстрый старт

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

Видео параллельной настройки

Прежде чем подробно объяснять команды, будет чрезвычайно полезно посмотреть видео, где два пира настраиваются одновременно:

Или по отдельности, настройка одного узла выглядит так:

Пример настройки wg(8)

Интерфейс командной строки

Новый интерфейс можно добавить с помощью ip-link(8), который должен автоматически загрузить модуль:

# ip link add dev wg0 type wireguard

IP-адрес и пир можно назначить с помощью ifconfig(8) или ip-address(8):

# ip address add dev wg0 192.168.2.1/24

Или, если всего два пира, можно использовать такой синтаксис:

# ip address add dev wg0 192.168.2.1 peer 192.168.2.2

Интерфейс можно настроить с ключами и конечными точками пиров с помощью утилиты wg(8):

# wg setconf wg0 myconfig.conf

или

# wg set wg0 listen-port 51820 private-key /path/to/private-key peer ABCDEF... allowed-ips 192.168.88.0/24 endpoint 209.202.254.14:8172

Наконец, интерфейс можно активировать с помощью ifconfig(8) или ip-link(8):

# ip link set up dev wg0

Также доступны команды wg show и wg showconf для просмотра текущей конфигурации. Вызов wg без аргументов показывает все WireGuard-интерфейсы.

Утилита wg(8)

Подробнее в man-странице wg(8).

Большую часть рутинных операций по поднятию и опусканию интерфейса можно автоматизировать с помощью инструмента wg-quick(8):

Утилита wg-quick(8)

Пример конфигурационного файла

Для использования wg-quick создайте файл конфигурации /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
Address = 10.0.0.1/24
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.0.0.2/32
Endpoint = 192.95.5.69:51820

Затем поднимите интерфейс:

# wg-quick up wg0

И остановите его:

# wg-quick down wg0

Генерация ключей

WireGuard использует ключи в формате base64. Их можно сгенерировать с помощью утилиты wg(8):

$ umask 077
$ wg genkey > privatekey

Это создаст файл privatekey с новым приватным ключом.

Затем вы можете получить публичный ключ из приватного:

$ wg pubkey < privatekey > publickey

Это прочитает privatekey из stdin и запишет соответствующий публичный ключ в publickey.

Конечно, вы можете сделать всё за один раз:

$ wg genkey | tee privatekey | wg pubkey > publickey

Постоянство при обходе NAT и файерволов

По умолчанию WireGuard старается быть максимально тихим, когда не используется; это не болтливый протокол. В основном он передаёт данные только тогда, когда пир хочет отправить пакеты. Когда его не просят отправлять пакеты, он перестаёт отправлять их до следующего запроса. В большинстве конфигураций это работает хорошо.

Однако, когда пир находится за NAT или файерволом, он может захотеть получать входящие пакеты, даже если не отправляет их. Поскольку NAT и stateful-файерволы отслеживают “соединения”, если пир за NAT или файерволом хочет получать входящие пакеты, он должен поддерживать актуальность NAT/файервола, периодически отправляя keepalive-пакеты. Это называется постоянные keepalive.

Когда эта опция включена, keepalive-пакет отправляется на конечную точку сервера каждые interval секунд. Разумный интервал, который работает с большим количеством файерволов — 25 секунд. Установка значения 0 отключает функцию (это значение по умолчанию, так как большинству пользователей она не нужна и делает WireGuard немного более болтливым).

Эта функция может быть задана добавлением поля PersistentKeepalive = в конфигурации пира или установкой persistent-keepalive в командной строке:

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.0.0.2/32
Endpoint = 192.95.5.69:51820
PersistentKeepalive = 25

Демо-сервер

После установки WireGuard, если вы хотите попробовать отправить несколько пакетов через WireGuard, вы можете использовать для тестирования скрипт из contrib/ncat-client-server/client.sh:

$ sudo contrib/examples/ncat-client-server/client.sh
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) 2015-2026 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.

set -e
[[ $UID == 0 ]] || { echo "You must be root to run this."; exit 1; }
exec 3<>/dev/tcp/demo.wireguard.com/42912
privatekey="$(wg genkey)"
wg pubkey <<<"$privatekey" >&3
IFS=: read -r status server_pubkey server_port internal_ip <&3
[[ $status == OK ]]
ip link del dev wg0 2>/dev/null || true
ip link add dev wg0 type wireguard
wg set wg0 private-key <(echo "$privatekey") peer "$server_pubkey" allowed-ips 0.0.0.0/0 endpoint "demo.wireguard.com:$server_port" persistent-keepalive 25
ip address add "$internal_ip"/24 dev wg0
ip link set up dev wg0
if [ "$1" == "default-route" ]; then
	host="$(wg show wg0 endpoints | sed -n 's/.*\t\(.*\):.*/\1/p')"
	ip route add $(ip route get $host | sed '/ via [0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/{s/^\(.* via [0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/}' | head -n 1) 2>/dev/null || true
	ip route add 0/1 dev wg0
	ip route add 128/1 dev wg0
fi

Это автоматически настроит интерфейс wg0 через очень небезопасный транспорт, который подходит только для демонстрационных целей. Затем вы можете попробовать загрузить скрытый сайт или отправить пинги:

$ chromium http://192.168.4.1
$ ping 192.168.4.1

Если вы хотите перенаправить ваш интернет-трафик, вы можете запустить его так:

$ sudo contrib/examples/ncat-client-server/client.sh default-route
$ curl zx2c4.com/ip
163.172.161.0
demo.wireguard.com
curl/7.49.1

Отладочная информация

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

# modprobe wireguard && echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control

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

export LOG_LEVEL=verbose

Пример полной настройки клиент-сервер

Серверная конфигурация (/etc/wireguard/wg0.conf)

[Interface]
PrivateKey = SERVER_PRIVATE_KEY
Address = 10.0.0.1/24
ListenPort = 51820
SaveConfig = true

[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

[Peer]
PublicKey = CLIENT2_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32

Клиентская конфигурация (/etc/wireguard/wg0.conf)

[Interface]
PrivateKey = CLIENT_PRIVATE_KEY
Address = 10.0.0.2/24
DNS = 8.8.8.8

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

Запуск

На сервере:

# wg-quick up wg0
# systemctl enable wg-quick@wg0

На клиенте:

# wg-quick up wg0
# systemctl enable wg-quick@wg0

Проверка статуса

Проверьте статус соединения:

# wg show

Вы должны увидеть информацию о рукопожатии и передаче данных:

interface: wg0
  public key: SERVER_PUBLIC_KEY
  private key: (hidden)
  listening port: 51820

peer: CLIENT1_PUBLIC_KEY
  endpoint: 192.168.1.100:51820
  allowed ips: 10.0.0.2/32
  latest handshake: 1 minute, 23 seconds ago
  transfer: 1.23 MiB received, 4.56 MiB sent

Дальнейшие шаги

Теперь, когда у вас есть работающий WireGuard, вы можете:

  • Настроить маршрутизацию для пропуска всего трафика через VPN
  • Настроить несколько пиров для создания полной mesh-сети
  • Изучить продвинутые темы
  • Настроить автоматическое переподключение и мониторинг

Если у вас возникли проблемы, обратитесь к разделу известных ограничений или посетите IRC-канал #wireguard на Libera.Chat для получения помощи.

4 - wg-quick — руководство

Руководство по wg-quick — утилита для простой настройки интерфейсов WireGuard

ИМЯ

wg-quick — простая настройка интерфейса WireGuard

СИНТАКСИС

wg-quick [ up | down | save | strip ] [ CONFIG_FILE | INTERFACE ]

ОПИСАНИЕ

Это чрезвычайно простой скрипт для быстрого поднятия интерфейса WireGuard, подходящий для нескольких распространённых сценариев использования.

Используйте up для добавления и настройки интерфейса, и down для его отключения и удаления. Команда up добавляет интерфейс WireGuard, поднимает его с указанными IP-адресами, настраивает MTU и маршруты, и при необходимости выполняет предварительные/последующие скрипты. Команда down при необходимости сохраняет текущую конфигурацию, удаляет интерфейс WireGuard и при необходимости выполняет предварительные/последующие скрипты. Команда save сохраняет конфигурацию существующего интерфейса без его отключения. Используйте strip для вывода конфигурационного файла без специфичных для wg-quick опций, подходящего для использования с wg(8).

CONFIG_FILE — это конфигурационный файл, имя которого соответствует имени интерфейса с расширением .conf. В противном случае INTERFACE — это имя интерфейса, конфигурация для которого ищется сначала в /etc/wireguard/INTERFACE.conf, а затем в путях поиска, специфичных для дистрибутива.

Вообще говоря, эта утилита представляет собой простой скрипт-обёртку для вызовов wg(8) и ip(8) для настройки интерфейса WireGuard. Она предназначена для пользователей с простыми потребностями. Пользователям с более сложными требованиями настоятельно рекомендуется использовать более специализированные инструменты, более полноценные сетевые менеджеры или просто использовать wg(8) и ip(8) как обычно.

КОНФИГУРАЦИЯ

Конфигурационный файл добавляет несколько дополнительных параметров к формату, используемому wg(8), для настройки дополнительных атрибутов интерфейса. Он обрабатывает значения, которые понимает, а остальные передаёт напрямую wg(8) для дальнейшей обработки.

Инструмент определяет все маршруты из списка разрешённых IP-адресов пиров и автоматически добавляет их в системную таблицу маршрутизации. Если один из этих маршрутов является маршрутом по умолчанию (0.0.0.0/0 или ::/0), он использует ip-rule(8) для обработки переопределения шлюза по умолчанию.

Конфигурационный файл будет передан напрямую подкоманде setconf wg(8), за исключением следующих дополнений в секции [Interface], которые обрабатываются этим инструментом:

Параметры секции Interface

  • Address — разделённый запятыми список IP-адресов (v4 или v6) (опционально с масками CIDR), которые будут назначены интерфейсу. Может быть указан несколько раз.

  • DNS — разделённый запятыми список IP-адресов (v4 или v6), которые будут установлены как DNS-серверы интерфейса, или не-IP-имя хоста для установки в качестве доменов поиска DNS. Может быть указан несколько раз. При поднятии интерфейса выполняется resolvconf -a tun.INTERFACE -m 0 -x, а при отключении — resolvconf -d tun.INTERFACE. Если эти вызовы resolvconf(8) нежелательны, вместо них можно использовать ключи PostUp и PostDown ниже.

  • MTU — если не указано, MTU автоматически определяется из адресов конечных точек или системного маршрута по умолчанию, что обычно является разумным выбором. Однако для ручного указания MTU это значение может быть задано явно.

  • Table — управляет таблицей маршрутизации, в которую добавляются маршруты. Есть два специальных значения: off полностью отключает создание маршрутов, а auto (по умолчанию) добавляет маршруты в таблицу по умолчанию и включает специальную обработку маршрутов по умолчанию.

  • PreUp, PostUp, PreDown, PostDown — фрагменты скриптов, которые будут выполнены bash(1) до/после настройки/отключения интерфейса, чаще всего используются для настройки пользовательских DNS-опций или правил файервола. Специальная строка %i заменяется на имя интерфейса. Каждый из них может быть указан несколько раз, в этом случае команды выполняются по порядку.

  • SaveConfig — если установлено в true, конфигурация сохраняется из текущего состояния интерфейса при его отключении. Любые изменения, внесённые в конфигурационный файл до удаления интерфейса, будут перезаписаны.

Имена интерфейсов

Рекомендуемые имена интерфейсов включают wg0, wgvpn0 или даже wgmgmtlan0. Однако число в конце необязательно, и действительно любое имя в формате [a-zA-Z0-9_=+.-]{1,15} будет работать. Так что даже имена интерфейсов, соответствующие географическим местоположениям, например cincinnati, nyc или paris, подойдут, если это по какой-то причине желательно.

ПРИМЕРЫ

Эти примеры используют тот же синтаксис, что и для wg(8), более полное описание можно найти там. Жирные строки ниже обозначают опции, расширяющие wg(8).

Пример 1: Клиент для VPN-шлюза

Следующий пример может использоваться для подключения в качестве клиента к VPN-шлюзу для туннелирования всего трафика:

[Interface]
Address = 10.200.100.8/24
DNS = 10.200.100.1
PrivateKey = oK56DE9Ue9zK76rAc8pBl6opph+1v36lm7cXXsQKrQM=

[Peer]
PublicKey = GtL7fZc/bLnqZldpVofMCD6hDjrK28SsdLxevJ+qtKU=
PresharedKey = /UwcSPg38hW/D9Y3tcS1FOV0K1wuURMbS0sesJEP5ak=
AllowedIPs = 0.0.0.0/0
Endpoint = demo.wireguard.com:51820

Поле Address добавлено для настройки адреса интерфейса. Поле DNS указывает, что DNS-сервер для интерфейса должен быть настроен через resolvconf(8). Запись разрешённых IP-адресов пира подразумевает, что этот интерфейс должен быть настроен как шлюз по умолчанию, что этот скрипт и делает.

Пример 2: “Выключатель” (kill-switch)

Развивая предыдущий пример, можно реализовать так называемый “выключатель” для предотвращения потока незашифрованных пакетов через интерфейсы, отличные от WireGuard, добавив следующие строки PostUp и PreDown в секцию [Interface]:

PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

Поля PostUp и PreDown добавлены для указания команды iptables(8), которая при использовании с интерфейсами, имеющими пир с 0.0.0.0/0 в AllowedIPs, работает вместе с использованием fwmark в wg-quick для отбрасывания всех пакетов, которые либо не выходят из туннеля зашифрованными, либо не проходят через сам туннель. (Обратите внимание, что это продолжает пропускать большую часть DHCP-трафика, поскольку большинство DHCP-клиентов используют сокеты PF_PACKET, которые обходят Netfilter.) При использовании IPv6 могут быть добавлены дополнительные аналогичные строки с использованием ip6tables(8).

Пример 3: Хранение ключей в зашифрованном виде

Или, возможно, желательно хранить приватные ключи в зашифрованном виде, например, с использованием pass(1):

PreUp = wg set %i private-key <(pass WireGuard/private-keys/%i)

Пример 4: Сервер с несколькими пирами

Для использования на сервере следующий более сложный пример включает несколько пиров:

[Interface]
Address = 10.192.122.1/24
Address = 10.10.0.1/16
SaveConfig = true
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
AllowedIPs = 10.10.10.230/32

Обратите внимание на две строки Address вверху и что SaveConfig установлен в true, указывая, что конфигурационный файл должен быть сохранён при отключении, используя текущее состояние интерфейса.

Пример 5: Политика маршрутизации

Комбинация полей Table, PostUp и PreDown может использоваться для политики маршрутизации. Например, следующее может использоваться для отправки SSH-трафика (TCP-порт 22) через туннель:

[Interface]
Address = 10.192.122.1/24
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
Table = 1234
PostUp = ip rule add ipproto tcp dport 22 table 1234
PreDown = ip rule delete ipproto tcp dport 22 table 1234

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 0.0.0.0/0

ИСПОЛЬЗОВАНИЕ

Эти конфигурационные файлы могут быть размещены в любой директории, указав желаемое имя интерфейса в имени файла:

# wg-quick up /path/to/wgnet0.conf

Для удобства, если указано только имя интерфейса, автоматически выбирается путь в /etc/wireguard/:

# wg-quick up wgnet0

Это загрузит конфигурационный файл /etc/wireguard/wgnet0.conf.

Команда strip полезна для перезагрузки конфигурационных файлов без прерывания активных сессий:

# wg syncconf wgnet0 <(wg-quick strip wgnet0)

СМОТРИТЕ ТАКЖЕ

  • wg(8) — настройка интерфейсов WireGuard
  • ip(8) — утилита управления сетевыми устройствами
  • ip-link(8) — управление сетевыми интерфейсами
  • ip-address(8) — управление IP-адресами
  • ip-route(8) — управление таблицами маршрутизации
  • ip-rule(8) — управление правилами политической маршрутизации
  • resolvconf(8) — управление настройками DNS

АВТОР

wg-quick был написан Джейсоном А. Доненфельдом (Jason A. Donenfeld). Для обновлений и дополнительной информации доступна проектная страница во Всемирной паутине.

КРАТКИЙ СПРАВОЧНИК

Основные команды

КомандаОписание
wg-quick up INTERFACEПоднять интерфейс
wg-quick down INTERFACEОстановить интерфейс
wg-quick save INTERFACEСохранить конфигурацию
wg-quick strip INTERFACEВывести конфигурацию без wg-quick опций

Параметры конфигурации

ПараметрОписаниеПример
AddressIP-адреса интерфейса10.0.0.1/24
DNSDNS-серверы8.8.8.8
MTUМаксимальный размер пакета1420
TableТаблица маршрутизацииauto, off, 1234
PreUpКоманда перед поднятиемiptables ...
PostUpКоманда после поднятияiptables ...
PreDownКоманда перед остановкойiptables ...
PostDownКоманда после остановкиiptables ...
SaveConfigСохранять конфигурациюtrue / false

5 - wg — руководство

Руководство по wg — утилита для настройки и получения конфигурации интерфейсов WireGuard

ИМЯ

wg — установка и получение конфигурации интерфейсов WireGuard

СИНТАКСИС

wg [ КОМАНДА ] [ ОПЦИИ ]... [ АРГУМЕНТЫ ]...

ОПИСАНИЕ

wg — это утилита конфигурации для получения и установки параметров туннельных интерфейсов WireGuard. Сами интерфейсы могут быть добавлены и удалены с помощью ip-link(8), а их IP-адреса и таблицы маршрутизации могут быть настроены с помощью ip-address(8) и ip-route(8). Утилита wg предоставляет серию подкоманд для изменения специфичных для WireGuard аспектов интерфейсов.

Если КОМАНДА не указана, по умолчанию используется show. Подкоманды, принимающие ИНТЕРФЕЙС, должны получать интерфейс WireGuard.

КОМАНДЫ

show

wg show { <interface> | all | interfaces } [public-key | private-key | listen-port | fwmark | peers | preshared-keys | endpoints | allowed-ips | latest-handshakes | persistent-keepalive | transfer | dump]

Показывает текущую конфигурацию WireGuard и информацию о состоянии указанного интерфейса. Если интерфейс не указан, по умолчанию используется all. Если указано interfaces, выводит список всех интерфейсов WireGuard, по одному на строку, и завершает работу. Если после указания интерфейса не указаны опции, выводит список всех атрибутов в удобном для терминала формате. В противном случае выводит указанную информацию, сгруппированную переносами строк и табуляцией, предназначенную для использования в скриптах. При таком выводе, если указано all, первым полем для всех категорий информации является имя интерфейса. Если указано dump, выводится несколько строк; первая содержит в порядке, разделённом табуляцией: private-key, public-key, listen-port, fwmark. Последующие строки выводятся для каждого пира и содержат в порядке, разделённом табуляцией: public-key, preshared-key, endpoint, allowed-ips, latest-handshake, transfer-rx, transfer-tx, persistent-keepalive.

Примеры:

# Показать всю информацию об интерфейсе wg0
wg show wg0

# Показать только публичный ключ
wg show wg0 public-key

# Показать все интерфейсы в формате для скриптов
wg show all dump

# Список всех интерфейсов
wg show interfaces

showconf

wg showconf <interface>

Показывает текущую конфигурацию интерфейса в формате, описанном ниже в разделе ФОРМАТ КОНФИГУРАЦИОННОГО ФАЙЛА.

Пример:

wg showconf wg0

set

wg set <interface> [listen-port <port>] [fwmark <fwmark>] [private-key <file-path>] [peer <base64-public-key> [remove] [preshared-key <file-path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips [+|-]<ip1>/<cidr1>[,[+|-]<ip2>/<cidr2>]...] ]...

Устанавливает значения конфигурации для указанного интерфейса. Может быть указано несколько пиров, и если для пира указан аргумент remove, этот пир удаляется, а не настраивается.

Если listen-port не указан или установлен в 0, порт будет выбран случайно при поднятии интерфейса. И private-key, и preshared-key должны быть файлами, поскольку аргументы командной строки не считаются приватными в большинстве систем, но если вы используете bash(1), вы можете безопасно передать строку, указав в качестве private-key или preshared-key выражение: < (echo PRIVATEKEYSTRING). Если указан /dev/null или другой пустой файл в качестве имени файла для private-key или preshared-key, ключ удаляется из устройства.

Использование preshared-key необязательно и может быть опущено; оно добавляет дополнительный уровень симметричной криптографии к уже существующей криптографии с открытым ключом для устойчивости к квантовым атакам.

Если allowed-ips указан, но значение является пустой строкой, все разрешённые IP-адреса удаляются у пира. По умолчанию allowed-ips заменяет разрешённые IP-адреса пира. Если перед любым из IP-адресов указан + или -, обновление является инкрементальным; IP-адреса с префиксом + или без префикса добавляются к разрешённым IP-адресам пира, если их нет, а IP-адреса с префиксом - удаляются, если присутствуют.

Использование persistent-keepalive необязательно и по умолчанию отключено; установка в 0 или “off” отключает его. В противном случае он представляет собой интервал в секундах от 1 до 65535 включительно, как часто отправлять аутентифицированный пустой пакет пиру для поддержания актуальности stateful-файервола или NAT-маппинга. Например, если интерфейс очень редко отправляет трафик, но может в любое время получать трафик от пира и находится за NAT, интерфейс может выиграть от постоянного интервала keepalive в 25 секунд; однако большинству пользователей это не понадобится.

Использование fwmark необязательно и по умолчанию отключено; установка в 0 или “off” отключает его. В противном случае это 32-битная fwmark для исходящих пакетов, которая может быть указана в шестнадцатеричном формате с префиксом “0x”.

Примеры:

# Установить порт и приватный ключ
wg set wg0 listen-port 51820 private-key /etc/wireguard/private.key

# Добавить пира
wg set wg0 peer xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= \
    endpoint 192.95.5.67:1234 \
    allowed-ips 10.192.122.3/32

# Удалить пира
wg set wg0 peer xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= remove

# Инкрементальное добавление IP-адресов
wg set wg0 peer xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= \
    allowed-ips +192.168.1.0/24

setconf

wg setconf <interface> <configuration-filename>

Устанавливает текущую конфигурацию интерфейса в содержимое configuration-filename, которое должно быть в формате, описанном в разделе ФОРМАТ КОНФИГУРАЦИОННОГО ФАЙЛА.

Пример:

wg setconf wg0 /etc/wireguard/wg0.conf

addconf

wg addconf <interface> <configuration-filename>

Добавляет содержимое configuration-filename, которое должно быть в формате, описанном в разделе ФОРМАТ КОНФИГУРАЦИОННОГО ФАЙЛА, к текущей конфигурации интерфейса.

Пример:

wg addconf wg0 /etc/wireguard/peer.conf

syncconf

wg syncconf <interface> <configuration-filename>

Как setconf, но сначала считывает существующую конфигурацию и вносит только те изменения, которые явно отличаются между конфигурационным файлом и интерфейсом. Это гораздо менее эффективно, чем setconf, но имеет преимущество, не нарушая текущие сессии пиров. Содержимое configuration-filename должно быть в формате, описанном в разделе ФОРМАТ КОНФИГУРАЦИОННОГО ФАЙЛА.

Пример:

wg syncconf wg0 /etc/wireguard/wg0.conf

genkey

wg genkey

Генерирует случайный приватный ключ в формате base64 и выводит его в стандартный вывод.

Пример:

wg genkey > private.key

genpsk

wg genpsk

Генерирует случайный предварительный общий ключ в формате base64 и выводит его в стандартный вывод.

Пример:

wg genpsk > preshared.key

pubkey

wg pubkey

Вычисляет публичный ключ и выводит его в формате base64 в стандартный вывод из соответствующего приватного ключа (сгенерированного с помощью genkey), переданного в формате base64 в стандартный ввод.

Пример:

wg pubkey < private.key > public.key

Приватный ключ и соответствующий публичный ключ могут быть сгенерированы одновременно:

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

help

wg help

Показывает сообщение об использовании.

ФОРМАТ КОНФИГУРАЦИОННОГО ФАЙЛА

Формат конфигурационного файла основан на INI. Есть два раздела верхнего уровня — Interface и Peer. Может быть указано несколько разделов Peer, но только один раздел Interface.

Секция Interface

Секция Interface может содержать следующие поля:

ПолеОписаниеОбязательность
PrivateKeyПриватный ключ в формате base64, сгенерированный wg genkeyОбязательно
ListenPort16-битный порт для прослушивания. Необязательно; если не указан, выбирается случайноОпционально
FwMark32-битная fwmark для исходящих пакетов. Если установлено в 0 или “off”, опция отключена. Может быть указана в шестнадцатеричном формате с префиксом “0x”Опционально

Секция Peer

Секции Peer могут содержать следующие поля:

ПолеОписаниеОбязательность
PublicKeyПубличный ключ в формате base64, вычисленный wg pubkey из приватного ключа и обычно передаваемый вне полосы автору конфигурационного файлаОбязательно
PresharedKeyПредварительный общий ключ в формате base64, сгенерированный wg genpsk. Необязательно, может быть опущено. Добавляет дополнительный уровень симметричной криптографии для устойчивости к квантовым атакамОпционально
AllowedIPsРазделённый запятыми список IP-адресов (v4 или v6) с масками CIDR, с которых разрешён входящий трафик для этого пира и на который направляется исходящий трафик. Может быть указан несколько разОбязательно
EndpointКонечная точка — IP-адрес или имя хоста, за которым следует двоеточие и номер порта. Эта конечная точка будет автоматически обновляться до последнего IP-адреса и порта источника правильно аутентифицированных пакетов от пираОпционально
PersistentKeepaliveИнтервал в секундах от 1 до 65535 включительно, как часто отправлять аутентифицированный пустой пакет пиру для поддержания stateful-файервола или NAT-маппинга. Если установлено в 0 или “off”, опция отключенаОпционально

Пример конфигурационного файла

Этот пример может использоваться как модель для написания конфигурационных файлов, следуя INI-подобному синтаксису. Символы после и включая # считаются комментариями и игнорируются.

# Комментарий
[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
FwMark = 0x1234

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
Endpoint = 192.95.5.67:1234
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24
PersistentKeepalive = 25

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
Endpoint = [2607:5300:60:6b0::c05f:543]:2468
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
Endpoint = test.wireguard.com:18981
AllowedIPs = 10.10.10.230/32

ОТЛАДОЧНАЯ ИНФОРМАЦИЯ

Иногда полезно иметь информацию о текущем состоянии туннеля.

Linux (модуль ядра)

При использовании модуля ядра Linux на ядре, поддерживающем динамическую отладку, отладочная информация может быть записана в dmesg(1) запуском от root:

# modprobe wireguard && echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control

OpenBSD и FreeBSD

На OpenBSD и FreeBSD отладочная информация может быть записана в dmesg(1) для конкретного интерфейса с помощью ifconfig(1):

# ifconfig wg0 debug

Пользовательские реализации

В пользовательских реализациях принято устанавливать переменную окружения LOG_LEVEL в verbose:

export LOG_LEVEL=verbose

ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ

WG_COLOR_MODE

Управляет цветным выводом:

  • always — всегда выводить ANSI-цвета
  • never — никогда не выводить ANSI-цвета
  • auto (или не установлено) — выводить цвета только при записи в TTY

Пример:

export WG_COLOR_MODE=never

WG_HIDE_KEYS

Управляет отображением ключей:

  • never — показывать приватные и предварительные общие ключи
  • always (или не установлено) — показывать ключи как “(hidden)”

Пример:

export WG_HIDE_KEYS=never

WG_ENDPOINT_RESOLUTION_RETRIES

Управляет повторными попытками разрешения DNS:

  • Если установлено целое число или infinity, разрешение DNS для конечной точки каждого пира будет повторяться указанное количество раз для непостоянных ошибок с увеличивающейся задержкой между попытками
  • По умолчанию: 15 попыток

Пример:

export WG_ENDPOINT_RESOLUTION_RETRIES=5

КРАТКИЙ СПРАВОЧНИК

Основные команды

КомандаОписание
wg show [interface]Показать конфигурацию
wg showconf interfaceПоказать конфигурацию в формате файла
wg set interface ...Установить параметры интерфейса
wg setconf interface fileУстановить конфигурацию из файла
wg addconf interface fileДобавить конфигурацию из файла
wg syncconf interface fileСинхронизировать конфигурацию
wg genkeyСгенерировать приватный ключ
wg genpskСгенерировать предварительный общий ключ
wg pubkeyВычислить публичный ключ

Параметры секции Interface

ПараметрОписаниеПример
PrivateKeyПриватный ключ (base64)yAnz5TF+lXX...
ListenPortПорт для прослушивания51820
FwMarkМетка для исходящих пакетов0x1234

Параметры секции Peer

ПараметрОписаниеПример
PublicKeyПубличный ключ пира (base64)xTIBA5rboUvn...
PresharedKeyПредварительный общий ключ (base64)/UwcSPg38hW...
AllowedIPsРазрешённые IP-адреса10.0.0.0/24, 192.168.1.0/24
EndpointКонечная точка192.95.5.67:1234
PersistentKeepaliveИнтервал keepalive (сек)25

СМОТРИТЕ ТАКЖЕ

  • wg-quick(8) — простая настройка интерфейсов WireGuard
  • ip(8) — утилита управления сетевыми устройствами
  • ip-link(8) — управление сетевыми интерфейсами
  • ip-address(8) — управление IP-адресами
  • ip-route(8) — управление таблицами маршрутизации

АВТОР

wg был написан Джейсоном А. Доненфельдом (Jason A. Donenfeld). Для обновлений и дополнительной информации доступна проектная страница во Всемирной паутине.

6 - Компиляция из исходного кода

Пошаговое руководство по компиляции WireGuard из исходного кода для Ubuntu и Fedora

Компиляция модуля ядра из исходного кода

В этом руководстве вы узнаете, как скомпилировать WireGuard из исходного кода для Ubuntu и Fedora. Это может быть полезно, если вы используете нестандартное ядро, хотите получить самую свежую версию или если ваш дистрибутив не предоставляет готовые пакеты.

Шаг 1: Установка инструментов сборки

Ubuntu и Debian

sudo apt-get install libelf-dev linux-headers-$(uname -r) build-essential pkg-config

Fedora

sudo dnf install elfutils-libelf-devel kernel-devel pkg-config @development-tools

Red Hat Enterprise Linux / CentOS

sudo yum install elfutils-libelf-devel kernel-devel pkgconfig "@Development Tools"

Arch Linux

sudo pacman -S linux-headers base-devel pkg-config

OpenSUSE

sudo zypper install kernel-default-devel pkg-config

Alpine

apk add build-base linux-hardened-dev  # или linux-vanilla-dev для ядра vanilla

Шаг 2: Получение исходного кода

Клонируйте репозитории WireGuard:

git clone https://git.zx2c4.com/wireguard-linux-compat
git clone https://git.zx2c4.com/wireguard-tools

Шаг 3: Компиляция и установка модуля ядра

make -C wireguard-linux-compat/src -j$(nproc)
sudo make -C wireguard-linux-compat/src install

Проверка загрузки модуля

После установки проверьте, что модуль загружается:

sudo modprobe wireguard
lsmod | grep wireguard

Вы должны увидеть вывод, содержащий wireguard.

Шаг 4: Компиляция и установка утилиты wg(8)

Утилита wg(8) необходима для управления интерфейсами WireGuard:

make -C wireguard-tools/src -j$(nproc)
sudo make -C wireguard-tools/src install

Проверка установки

Проверьте, что утилита установлена корректно:

wg --version

Вы должны увидеть информацию о версии утилиты.

Шаг 5: Дополнительная настройка (опционально)

Автоматическая загрузка модуля

Чтобы модуль WireGuard загружался автоматически при старте системы:

echo "wireguard" | sudo tee /etc/modules-load.d/wireguard.conf

Настройка прав доступа к конфигурационным файлам

Создайте директорию для конфигураций с правильными правами:

sudo mkdir -p /etc/wireguard
sudo chmod 600 /etc/wireguard

Шаг 6: Создание и настройка интерфейса

Генерация ключей

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

Создание конфигурационного файла

Создайте файл /etc/wireguard/wg0.conf:

[Interface]
PrivateKey = <ваш_приватный_ключ>
Address = 10.0.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <публичный_ключ_пира>
AllowedIPs = 10.0.0.2/32
Endpoint = example.com:51820

Запуск интерфейса

sudo wg-quick up wg0

Проверка статуса

sudo wg show

Требования к ядру

WireGuard требует Linux ≥ 3.10 со следующими опциями конфигурации, которые, вероятно, уже настроены в вашем ядре:

ОпцияОписание
CONFIG_NETБазовая поддержка сети
CONFIG_INETБазовая поддержка IP
CONFIG_NET_UDP_TUNNELОтправка и получение UDP-пакетов
CONFIG_CRYPTO_ALGAPIКриптографический API для crypto_xor
CONFIG_CRYPTO_MANAGERМенеджер криптографических алгоритмов

Некоторые, но не все, из этих опций напрямую соответствуют записям в menuconfig. Для включения этих опций выберите следующие пункты в menuconfig:

[*] Networking support (NET) -->
    Networking options -->
        [*] TCP/IP networking (INET)
        [*]   IP: Foo (IP protocols) over UDP (NET_FOU)
[*] Cryptographic API (CRYPTO) -->
    [*] Cryptographic algorithm manager (CRYPTO_MANAGER)

Сборка напрямую в дереве ядра

Если вы хотите собрать WireGuard как модуль или встроенный напрямую из дерева ядра, вы можете использовать скрипт create-patch.sh, который создаёт патч для добавления WireGuard непосредственно в дерево, или скрипт jury-rig.sh, который связывает исходный каталог WireGuard с деревом ядра:

Метод 1: Использование патча

cd /usr/src/linux
~/wireguard-linux-compat/kernel-tree-scripts/create-patch.sh | patch -p1

Метод 2: Использование jury-rig

~/wireguard-linux-compat/kernel-tree-scripts/jury-rig.sh /usr/src/linux

После этого вы сможете настроить следующие опции напрямую:

ОпцияОписание
CONFIG_WIREGUARDУправляет тем, будет ли WireGuard собран как модуль, встроенный или не собран вообще
CONFIG_WIREGUARD_DEBUGВключает подробные отладочные сообщения

Эти опции легко выбираются через menuconfig, если также выбраны CONFIG_NET и CONFIG_INET:

[*] Networking support -->
    Networking options -->
        [*] TCP/IP networking
        [*]   IP: WireGuard secure network tunnel
        [ ]     Debugging checks and verbose messages

Устранение неполадок

Ошибка: “wireguard module not found”

Если модуль не загружается, проверьте:

# Проверка установки модуля
ls /lib/modules/$(uname -r)/kernel/net/wireguard/

# Проверка зависимостей
modinfo wireguard

# Проверка логов ядра
dmesg | grep -i wireguard

Ошибка: “kernel headers not found”

Убедитесь, что заголовки ядра установлены:

# Ubuntu/Debian
sudo apt install linux-headers-$(uname -r)

# Fedora
sudo dnf install kernel-devel-$(uname -r)

Проблемы с компиляцией

Если компиляция завершается с ошибками:

  1. Проверьте версию gcc:
gcc --version
  1. Убедитесь, что у вас установлены все зависимости:
# Ubuntu/Debian
sudo apt-get build-dep wireguard

# Fedora
sudo dnf builddep wireguard-tools
  1. Очистите предыдущие сборки:
make -C wireguard-linux-compat/src clean
make -C wireguard-tools/src clean

Дальнейшие шаги

После успешной компиляции и установки вы можете перейти к руководству по быстрому старту для настройки вашего первого WireGuard-подключения.

Связанные руководства

7 - Протокол и криптография

Подробное описание протокола WireGuard, криптографических примитивов и обмена ключами

Криптографические примитивы

В WireGuard используются следующие протоколы и примитивы:

  • ChaCha20 для симметричного шифрования, аутентифицированного с помощью Poly1305, с использованием AEAD-конструкции из RFC7539
  • Curve25519 для ECDH (обмена ключами по эллиптическим кривым)
  • BLAKE2s для хеширования и ключевого хеширования, описанный в RFC7693
  • SipHash24 для ключей хеш-таблиц
  • HKDF для производной ключей, как описано в RFC5869

Эти примитивы выбраны за их высокую производительность и криптографическую стойкость. Например, ChaCha20-Poly1305 обеспечивает скорость шифрования, сравнимую с AES, но без аппаратного ускорения, что делает его идеальным для встраиваемых устройств. Curve25519 считается одним из самых безопасных и быстрых алгоритмов для обмена ключами.

Протокол без установки соединения

Любой безопасный протокол требует сохранения некоторого состояния, поэтому существует начальное очень простое рукопожатие, которое устанавливает симметричные ключи для передачи данных. Это рукопожатие происходит каждые несколько минут для обеспечения вращения ключей и совершенной прямой секретности (Perfect Forward Secrecy — PFS). PFS означает, что даже если долговременный приватный ключ будет скомпрометирован, это не позволит расшифровать ранее перехваченные сессии.

Рукопожатие выполняется на основе времени, а не содержимого предыдущих пакетов, поскольку спроектировано для корректной обработки потери пакетов. Это важно, потому что в сетях с высокой загрузкой или нестабильным соединением пакеты могут теряться, и протокол должен продолжать работать без сбоев.

Используется умный механизм пульса (pulse mechanism), чтобы гарантировать, что последние ключи и рукопожатия актуальны, с повторным согласованием при необходимости. Этот механизм автоматически обнаруживает, когда рукопожатия устарели, и инициирует новые. Используется отдельная очередь пакетов на хост, чтобы минимизировать потерю пакетов во время рукопожатий, обеспечивая стабильную производительность для всех клиентов.

Другими словами, вы поднимаете устройство, и всё остальное обрабатывается автоматически. Вам не нужно беспокоиться о переподключении, отключении или переинициализации. WireGuard сам управляет всем жизненным циклом соединения.

Таймеры протокола

В протоколе используются следующие таймеры:

  • REKEY_TIMEOUT — повторная попытка рукопожатия выполняется через REKEY_TIMEOUT + jitter мс, если ответ не был получен, где jitter — случайное значение от 0 до 333 мс. Случайная задержка предотвращает синхронизацию попыток от множества клиентов.

  • KEEPALIVE — если пакет был получен от данного пира, но мы не отправили ему пакет в течение KEEPALIVE мс, мы отправляем пустой пакет. Это поддерживает NAT-маппинг активным.

  • Если мы отправили пакет данному пиру, но не получили пакет от него в течение KEEPALIVE + REKEY_TIMEOUT мс, мы инициируем новое рукопожатие.

  • Все эфемерные приватные ключи и симметричные сессионные ключи обнуляются после REJECT_AFTER_TIME * 3 мс, если новые ключи не были обменены. Это гарантирует, что старые ключи не будут случайно сохранены в памяти.

  • После отправки пакета, если количество отправленных пакетов с использованием этого ключа превышает REKEY_AFTER_MESSAGES, мы инициируем новое рукопожатие. Это ограничивает количество данных, зашифрованных одним ключом.

  • После отправки пакета, если отправитель был первоначальным инициатором рукопожатия и текущий сессионный ключ старше REKEY_AFTER_TIME мс, мы инициируем новое рукопожатие. Если отправитель был первоначальным ответчиком, мы не инициируем новое рукопожатие после REKEY_AFTER_TIME мс, как это делает инициатор.

  • После получения пакета, если получатель был первоначальным инициатором рукопожатия и текущий сессионный ключ старше REKEY_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT мс, мы инициируем новое рукопожатие.

  • Рукопожатия инициируются только один раз в REKEY_TIMEOUT мс, с применением строгого ограничения скорости.

  • Пакеты отбрасываются, если счётчик сессии больше REJECT_AFTER_MESSAGES или если его ключ старше REJECT_AFTER_TIME мс.

  • После REKEY_ATTEMPT_TIME мс попыток инициировать новое рукопожатие, попытки прекращаются, и очищаются все существующие пакеты, поставленные в очередь для отправки. Если пакет явно поставлен в очередь для отправки, этот таймер сбрасывается.

В будущем планируется настроить REKEY_TIMEOUT для использования экспоненциальной задержки (exponential back-off), что повысит эффективность при больших нагрузках.

Ключевое подтверждение

После завершения рукопожатия, с сообщением от инициатора к ответчику и затем обратно от ответчика к инициатору, инициатор может отправлять зашифрованные пакеты сессии, но ответчик не может. Ответчик обязан дождаться получения зашифрованного пакета сессии от инициатора для подтверждения ключа. Это требование обеспечивает подтверждение того, что инициатор действительно получил ключи и может использовать их.

До получения первого пакета с новым ключом ответчик должен либо поставить пакеты в очередь для отправки позже, либо использовать предыдущую сессию, если она существует и действительна. Поэтому после получения ответа от ответчика, если у инициатора нет немедленно готовых к отправке пакетов данных, он должен отправить пустой пакет для подтверждения ключа.

Пример: Представьте, что клиент устанавливает VPN-соединение с сервером. Клиент отправляет рукопожатие, сервер отвечает, и после этого клиент отправляет первый зашифрованный пакет данных. Только после получения этого пакета сервер начинает использовать новый ключ для ответов. Если клиенту нечего отправлять сразу, он отправляет пустой пакет, чтобы сервер знал, что ключ подтверждён.

Обмен ключами и пакеты данных

WireGuard использует рукопожатие Noise_IK из Noise Protocol Framework, основанное на работах CurveCP, NaCL, KEA+, SIGMA, FHMQV и HOMQV. Все эти протоколы внесли вклад в создание надёжного и безопасного механизма обмена ключами. Все пакеты передаются через UDP, что обеспечивает низкую задержку и высокую производительность.

Свойства обмена ключами

Обмен ключами обладает следующими свойствами:

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

  2. Избегает атак повторного воспроизведения — каждый пакет содержит уникальные данные, предотвращающие его повторное использование.

  3. Обеспечивает совершенную прямую секретность (PFS) — компрометация долговременных ключей не раскрывает содержимое прошлых сессий.

  4. Достигает “AKE Security” — обеспечивает безопасность аутентифицированного обмена ключами в соответствии с современными криптографическими стандартами.

  5. Обеспечивает скрытие идентичности — информация о сторонах, участвующих в обмене, защищена от пассивного наблюдения.

Предварительный общий ключ (PSK)

Если требуется дополнительный уровень симметричной криптографии (например, для устойчивости к квантовым атакам), WireGuard поддерживает опциональный предварительный общий ключ (Pre-Shared Key), который смешивается с криптографией с открытым ключом. Это обеспечивает дополнительный уровень защиты: даже если кто-то сможет взломать асимметричную криптографию с помощью квантового компьютера, PSK останется барьером.

Когда режим PSK не используется, значение предварительного общего ключа считается строкой из 32 нулевых байт. Таким образом, протокол всегда работает одинаково, независимо от использования PSK.

Используемые функции

В протоколе используются следующие криптографические функции:

  • DH(private key, public key) — умножение точек Curve25519, возвращает 32 байта общего секрета. Это основной механизм обмена ключами.

  • DH_GENERATE() — генерация случайного приватного ключа Curve25519 (32 байта). Каждый раз генерируется новый ключ для обеспечения PFS.

  • RAND(len) — возвращает len случайных байт. Используется для генерации nonce и других случайных значений.

  • DH_PUBKEY(private key) — вычисление публичного ключа Curve25519 из приватного ключа (32 байта).

  • AEAD(key, counter, plain text, auth text) — ChaCha20Poly1305 AEAD, как указано в RFC7539, с nonce, состоящим из 32 бит нулей, за которыми следует 64-битное значение counter в little-endian. Обеспечивает одновременно шифрование и аутентификацию.

  • XAEAD(key, nonce, plain text, auth text) — XChaCha20Poly1305 AEAD со случайным 24-байтовым nonce. Используется для cookie-пакетов.

  • AEAD_LEN(plain len)plain len + 16, где 16 байт — размер тега аутентификации.

  • HMAC(key, input) — HMAC-Blake2s(key, input, 32), возвращает 32 байта. Используется для создания ключей.

  • MAC(key, input) — Keyed-Blake2s(key, input, 16), возвращает 16 байт. Используется для создания MAC (Message Authentication Code).

  • HASH(input) — Blake2s(input, 32), возвращает 32 байта. Используется для хеширования.

  • TAI64N() — TAI64N-метка текущего времени (12 байт). Используется для защиты от атак повторного воспроизведения.

  • CONSTRUCTION — UTF-8 значение Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s (37 байт). Идентифицирует используемую конструкцию Noise.

  • IDENTIFIER — UTF-8 значение WireGuard v1 zx2c4 Jason@zx2c4.com (34 байта). Идентифицирует реализацию WireGuard.

  • LABEL_MAC1 — UTF-8 значение mac1---- (8 байт). Используется для маркировки MAC1.

  • LABEL_COOKIE — UTF-8 значение cookie-- (8 байт). Используется для маркировки cookie.

Структура пакетов

Первое сообщение: Инициатор → Ответчик

Инициатор отправляет это сообщение:

msg = handshake_initiation {
    u8 message_type          // Всегда 1
    u8 reserved_zero[3]      // Зарезервировано для будущего использования
    u32 sender_index         // Индекс отправителя
    u8 unencrypted_ephemeral[32]  // Эфемерный публичный ключ (не зашифрован)
    u8 encrypted_static[AEAD_LEN(32)]  // Зашифрованный статический публичный ключ
    u8 encrypted_timestamp[AEAD_LEN(12)]  // Зашифрованная метка времени
    u8 mac1[16]              // Первый MAC
    u8 mac2[16]              // Второй MAC (cookie)
}

Пример: Клиент (инициатор) отправляет это сообщение серверу (ответчику), чтобы начать установку VPN-соединения. Поле unencrypted_ephemeral содержит эфемерный публичный ключ, который не шифруется, чтобы сервер мог его использовать для вычисления общего секрета. Поля encrypted_static и encrypted_timestamp зашифрованы и содержат долговременный публичный ключ клиента и текущее время для защиты от повторных атак.

Второе сообщение: Ответчик → Инициатор

Ответчик отправляет это сообщение после обработки первого сообщения:

msg = handshake_response {
    u8 message_type          // Всегда 2
    u8 reserved_zero[3]      // Зарезервировано
    u32 sender_index         // Индекс отправителя
    u32 receiver_index       // Индекс получателя (из первого сообщения)
    u8 unencrypted_ephemeral[32]  // Эфемерный публичный ключ
    u8 encrypted_nothing[AEAD_LEN(0)]  // Зашифрованное пустое сообщение
    u8 mac1[16]              // Первый MAC
    u8 mac2[16]              // Второй MAC (cookie)
}

Пример: Сервер (ответчик) отвечает клиенту своим эфемерным публичным ключом. Поле receiver_index содержит индекс, полученный от клиента, что позволяет клиенту сопоставить ответ с правильной сессией. Зашифрованное пустое сообщение (encrypted_nothing) служит для подтверждения того, что сервер правильно вычислил ключи.

Пакеты данных

После завершения рукопожатия инициатор и ответчик обмениваются пакетами данных:

msg = packet_data {
    u8 message_type          // Всегда 4
    u8 reserved_zero[3]      // Зарезервировано
    u32 receiver_index       // Индекс получателя
    u64 counter              // Счётчик пакетов (nonce)
    u8 encrypted_encapsulated_packet[]  // Зашифрованный инкапсулированный пакет
}

Пример: После установления ключей клиент отправляет серверу зашифрованный IP-пакет. Поле counter увеличивается с каждым пакетом, предотвращая повторное использование nonce. Сами данные (encrypted_encapsulated_packet) содержат зашифрованный IP-пакет, который сервер расшифровывает и передаёт в сеть.

Производные ключей данных

После обмена двумя сообщениями ключи вычисляются инициатором и ответчиком для отправки и получения данных:

temp1 = HMAC(initiator.chaining_key, [empty])
temp2 = HMAC(temp1, 0x1)
temp3 = HMAC(temp1, temp2 || 0x2)
initiator.sending_key = temp2
initiator.receiving_key = temp3
initiator.sending_key_counter = 0
initiator.receiving_key_counter = 0

temp1 = HMAC(responder.chaining_key, [empty])
temp2 = HMAC(temp1, 0x1)
temp3 = HMAC(temp1, temp2 || 0x2)
responder.receiving_key = temp2
responder.sending_key = temp3
responder.receiving_key_counter = 0
responder.sending_key_counter = 0

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

Объяснение: Процесс использует HKDF (HMAC-based Key Derivation Function) для создания независимых ключей для каждого направления. temp1 — это начальный ключевой материал, из которого через серию HMAC-операций создаются sending_key (ключ для отправки) и receiving_key (ключ для приёма). Счётчики инициализируются нулём и увеличиваются с каждым пакетом.

Защита от DoS-атак

WireGuard требует аутентификации в первом сообщении рукопожатия, что не требует выделения состояния на сервере для потенциально неаутентифицированных сообщений. Это критически важно для защиты от DoS-атак: злоумышленник не может заставить сервер выделять ресурсы для каждого поддельного пакета.

Сервер вообще не отвечает неавторизованному клиенту; он молчит и невидим. Это делает WireGuard устойчивым к сканированию портов и DoS-атакам.

Защита от атак повторного воспроизведения

Однако это создаёт проблему: аутентификация в первом пакете всегда уязвима для атак повторного воспроизведения. Злоумышленник может воспроизвести начальные сообщения рукопожатия, чтобы заставить сервер перегенерировать свой эфемерный ключ, тем самым разорвав соединение легитимного клиента (хотя это не влияет на безопасность сообщений).

Для защиты используется TAI64N-метка времени в первом сообщении. Сервер отслеживает наибольшую полученную метку времени для каждого клиента и отбрасывает пакеты с метками, меньшими или равными предыдущей.

Пример: Клиент отправляет рукопожатие с меткой времени 2024-01-01 12:00:00.000. Сервер запоминает эту метку. Если злоумышленник попытается воспроизвести это же рукопожатие через час, сервер отбросит его, так как метка времени меньше или равна уже полученной.

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

Вычисление функции DH() требует значительных вычислительных ресурсов. Для защиты от атак на исчерпание CPU сервер может не обрабатывать сообщения рукопожатия, а вместо этого отвечать cookie-пакетом, если он находится под нагрузкой.

Чтобы сервер оставался молчаливым, если не получает действительный пакет, все сообщения должны содержать MAC, который комбинирует публичный ключ получателя и опционально PSK в качестве ключа MAC. Когда сервер находится под нагрузкой, он принимает только пакеты, которые дополнительно имеют второй MAC предыдущих байтов сообщения, использующий cookie в качестве ключа MAC.

Cookie истекают через две минуты и представляют собой MAC IP-адреса отправителя с использованием меняющегося (каждые две минуты) секрета сервера в качестве ключа MAC. Это позволяет доказать владение IP-адресом, который затем может быть правильно ограничен по скорости.

Сервер, вычислив эти MAC и сравнив их с полученными в сообщении, должен отклонять сообщения с недействительным msg.mac1 и при нагрузке — сообщения с недействительным msg.mac2.

Как упоминалось выше, когда получено сообщение с действительным msg.mac1, но msg.mac2 равен нулю или недействителен, и сервер находится под нагрузкой, сервер может отправить cookie-пакет:

msg = packet_cookie_reply {
    u8 message_type          // Всегда 3
    u8 reserved_zero[3]      // Зарезервировано
    u32 receiver_index       // Индекс получателя
    u8 nonce[24]             // Случайный nonce для XChaCha20
    u8 encrypted_cookie[AEAD_LEN(16)]  // Зашифрованный cookie
}

Пример: Злоумышленник пытается инициировать множество рукопожатий с сервера под нагрузкой. Сервер не выполняет дорогостоящие вычисления DH для каждого, а вместо этого отправляет cookie-пакет. Клиент должен расшифровать cookie и отправить его обратно в следующем рукопожатии, доказывая, что он может получить пакеты по указанному IP-адресу.

Защита от повторного использования nonce

Nonce никогда не повторяются. Используется 64-битный счётчик, который не может быть уменьшен. Это означает, что каждый пакет имеет уникальный nonce, что критически важно для безопасности ChaCha20-Poly1305.

UDP иногда доставляет сообщения в неправильном порядке. Для этого используется скользящее окно, в котором отслеживается наибольший полученный счётчик и окно примерно из 2000 предыдущих значений, проверяемых после верификации тега аутентификации. Это позволяет принимать пакеты, пришедшие не по порядку, но не позволяет повторно использовать уже принятые nonce.

Пример: Клиент отправляет пакеты с счётчиками 1, 2, 3, 4, 5. Пакет 4 приходит первым, затем пакет 2, затем пакет 5. Скользящее окно позволяет принять все эти пакеты, так как их счётчики находятся в допустимом диапазоне. Если злоумышленник попытается повторно отправить пакет с счётчиком 2, он будет отброшен, так как этот счётчик уже был принят.

DiffServ

При работе с IP-пакетами WireGuard учитывает следующие аспекты DiffServ:

  • DSCP рукопожатий: 0x88 (AF41) — эти пакеты имеют наивысший приоритет и наименьшую вероятность отбрасывания, так как они необходимы для управления туннелем. Это гарантирует, что даже при перегрузке сети рукопожатия будут доставлены.

  • DSCP данных: 0 — значение DSCP из внутреннего пакета никогда не копируется во внешний пакет. Это предотвращает утечку информации о типе трафика, проходящего через зашифрованный туннель.

  • ECN (Explicit Congestion Notification): Бит ECN копируется между внутренним и внешним пакетами в соответствии с логикой, описанной в RFC6040. Это позволяет сохранять информацию о перегрузке сети внутри туннеля.

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

Схема протокола

sequenceDiagram
    participant I as Инициатор
    participant R as Ответчик
    
    Note over I,R: 1. Инициация рукопожатия
    I->>R: message_type=1, ephemeral, encrypted_static, timestamp
    
    Note over R: Проверка MAC, дешифрование<br/>Генерация ephemeral ключа
    
    Note over I,R: 2. Ответ
    R->>I: message_type=2, ephemeral, encrypted_nothing
    
    Note over I: Проверка, дешифрование<br/>Производная ключей
    
    Note over I,R: 3. Передача данных
    I->>R: message_type=4, encrypted_data
    
    Note over R: Дешифрование данными ключами

Ссылки

8 - Формальная верификация

Формальная верификация протокола WireGuard, криптографии и реализации

Формальная верификация

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

Символическая верификация протокола с использованием Tamarin

Протокол WireGuard, описанный в техническом документе и основанный на Noise, был формально верифицирован в символической модели с использованием Tamarin. Это означает, что существует математическое доказательство безопасности протокола WireGuard.

Что такое символическая верификация? Символическая верификация рассматривает криптографические примитивы как “чёрные ящики” с идеальными свойствами. Она проверяет, что протокол логически корректен, при условии, что используемые криптографические примитивы безопасны. Это позволяет обнаруживать логические ошибки в протоколе, такие как неправильная последовательность сообщений или утечка информации.

Протокол был верифицирован на наличие следующих свойств безопасности:

СвойствоОписаниеЗначение
КорректностьПротокол всегда завершается успешно при правильном выполненииГарантирует, что при отсутствии атак протокол работает как ожидается
Надёжное согласование ключей и аутентичностьСтороны уверены, что обмениваются ключами именно с той стороной, с которой намеревалисьПредотвращает атаки “человек посередине” (MITM)
Устойчивость к компрометации ключей с подменой личностиДаже если долговременный ключ скомпрометирован, атакующий не может выдать себя за другую сторонуЗащищает от ситуаций, когда злоумышленник получает доступ к приватному ключу
Устойчивость к атакам неизвестного общего ключаСторона не может быть обманута, чтобы использовать ключ, которого она не ожидаетПредотвращает ситуации, когда атакующий заставляет две стороны использовать разные ключи
Секретность ключаКлюч остаётся известным только участвующим сторонамБазовая гарантия конфиденциальности
Совершенная прямая секретностьКомпрометация долговременных ключей не раскрывает содержимое прошлых сессийЗащищает прошлый трафик даже при компрометации ключей в будущем
Уникальность сессииКаждая сессия уникальна и не может быть спутана с другойПредотвращает смешивание сессий
Скрытие идентичностиЛичности сторон защищены от пассивного наблюденияЗлоумышленник не может узнать, кто общается с кем

Это совместная работа Джейсона Доненфельда (Jason Donenfeld) и Кевина Милнера (Kevin Milner).

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

Прочитать документ по верификации WireGuard в Tamarin

Модель Tamarin

Модель Tamarin является открытым исходным кодом и может быть запущена повторно для независимой верификации:

git clone https://git.zx2c4.com/wireguard-tamarin/
cd wireguard-tamarin
make

Для работы требуются:

  • Tamarin — инструмент для символической верификации протоколов
  • m4 — макропроцессор
  • GraphViz — визуализация графов
  • Maude — система для написания и выполнения спецификаций

Пример использования: Исследователь может запустить модель Tamarin для проверки нового свойства безопасности или для подтверждения существующих результатов. Модель генерирует доказательства, которые могут быть проверены математически.

Вычислительное доказательство протокола в модели eCK

При попытке построить вычислительное доказательство WireGuard в модели eCK (extended Canetti-Krawczyk) оказалось, что протокол WireGuard не вписывается аккуратно в традиционную модель eCK, потому что сообщение подтверждения ключа является частью транспортного уровня. Это техническая деталь, связанная с тем, как моделируются этапы протокола.

Что такое модель eCK? Это одна из самых сильных моделей безопасности для протоколов согласования ключей. Она учитывает широкий спектр атак, включая компрометацию эфемерных и долговременных ключей в различных комбинациях.

Поэтому в этом документе доказывается вариант протокола WireGuard, который морально эквивалентен реальному протоколу, давая очень сильный результат.

Что такое “морально эквивалентный”? Это означает, что вариант протокола имеет ту же логическую структуру и свойства безопасности, но адаптирован для соответствия формальным требованиям модели eCK. Доказательство для варианта применимо и к реальному протоколу.

Это совместная работа Бенджамина Даулинга (Benjamin Dowling) и Кеннета Г. Патерсона (Kenneth G. Paterson).

Прочитать документ по вычислительному доказательству в модели eCK

Вычислительное доказательство протокола в модели ACCE

Эта диссертация строит механизированное криптографическое доказательство всего протокола WireGuard, включая сообщения транспортных данных, в вычислительной модели, подобной ACCE (Authenticated and Confidential Channel Establishment), с использованием CryptoVerif.

Что такое модель ACCE? Это модель для протоколов, которые устанавливают аутентифицированные и конфиденциальные каналы. Она учитывает как установление ключей, так и последующую передачу данных, что делает её особенно подходящей для WireGuard.

Что такое CryptoVerif? Это инструмент для автоматического доказательства безопасности криптографических протоколов в вычислительной модели. В отличие от символической верификации, он учитывает реальные криптографические примитивы и их математические свойства.

Доказанные свойства:

СвойствоОписание
КорректностьПротокол работает как ожидается
Секретность сообщенийСообщения не могут быть прочитаны атакующим
Совершенная прямая секретностьПрошлые сообщения защищены при компрометации ключей
Взаимная аутентификацияОбе стороны уверены в личности друг друга
Устойчивость к компрометации ключей с подменой личностиЗащита при компрометации ключей
Устойчивость к атакам неизвестного общего ключаЗащита от смешивания ключей
Устойчивость к повторному воспроизведению первого сообщения протоколаПервое сообщение не может быть повторно использовано

Модель доступна для скачивания и может быть использована в CryptoVerif 2.00.

Это работа Бенджамина Липпа (Benjamin Lipp).

Прочитать документ по вычислительному доказательству в модели ACCE

Символическая верификация протокола с использованием ProVerif

Проект Noise Explorer стремится формально верифицировать все шаблоны протокола Noise путём генерации моделей ProVerif.

Что такое ProVerif? Это популярный инструмент для автоматической верификации криптографических протоколов в символической модели. Он может автоматически находить атаки или доказывать свойства безопасности.

Модель, относящаяся к WireGuard, — это модель IK от Noise Explorer, которая может быть подключена к ProVerif для генерации доказательств различных свойств.

Что такое шаблон IK в Noise? Это конкретный шаблон рукопожатия, используемый WireGuard. Он определяет, в каком порядке отправляются ключи и как вычисляются общие секреты.

Это работа Надима Кобейсси (Nadim Kobeissi) и Картикеяна Баргавана (Karthikeyan Bhargavan).

Прочитать документ Noise Explorer

Верифицированная C-реализация Curve25519

HACL*

WireGuard использует 64-битную реализацию умножения скаляра Curve25519 из HACL*. Кривая специфицирована в F*, что позволяет доказывать свойства стратегий реализации. KreMLin преобразует её в верифицированный C-код.

Что такое HACL?* Это библиотека криптографических примитивов, написанных на F* и верифицированных по безопасности и корректности. Она обеспечивает математические гарантии того, что реализация Curve25519 свободна от ошибок и уязвимостей.

Что такое F?* Это функциональный язык программирования с зависимыми типами, который позволяет выражать и доказывать свойства программ. Он используется для написания спецификаций криптографических примитивов.

Что такое KreMLin? Это компилятор, который преобразует код F* в верифицированный C-код, сохраняя все доказательства свойств.

HACL* — совместная работа Жана Карима Зинзиндууэ (Jean Karim Zinzindohoué), Картикеяна Баргавана (Karthikeyan Bhargavan), Джонатана Протценко (Jonathan Protzenko) и Бенджамина Беурдуше (Benjamin Beurdouche).

Прочитать документ HACL*

Fiat-Crypto

WireGuard также использует 32-битную реализацию умножения скаляра Curve25519 из Fiat-Crypto. Кривая специфицирована в Coq, что позволяет доказывать свойства стратегий реализации и генерировать верифицированный C-код.

Что такое Fiat-Crypto? Это проект по генерации верифицированного криптографического кода из формальных спецификаций в Coq. Он автоматически генерирует реализации, которые математически доказано корректны.

Что такое Coq? Это интерактивная система доказательства теорем, которая позволяет писать математические спецификации и доказывать их свойства. Она широко используется для формальной верификации программного обеспечения.

Преимущество 32-битной реализации: Она оптимизирована для устройств с 32-битными процессорами, таких как старые смартфоны или встраиваемые системы, что делает WireGuard доступным для более широкого спектра устройств.

Fiat-Crypto — совместная работа Андреса Эрбсена (Andres Erbsen), Джейд Филипум (Jade Philipoom), Джейсона Гросса (Jason Gross), Роберта Слоана (Robert Sloan) и Адама Члипала (Adam Chlipala).

Прочитать документ Fiat-Crypto

Почему формальная верификация важна?

Формальная верификация обеспечивает уровень уверенности, который невозможно достичь только тестированием или экспертной оценкой. Вот почему это критически важно для WireGuard:

  1. Математические гарантии — Верификация даёт математическое доказательство того, что протокол безопасен против определённых классов атак. Это не просто “вероятно безопасно” — это “доказано безопасно”.

  2. Обнаружение тонких ошибок — Некоторые уязвимости могут быть обнаружены только формальными методами. Например, атаки на протоколы, которые полагаются на тонкие логические ошибки.

  3. Независимая проверка — Модели с открытым исходным кодом позволяют любому исследователю независимо проверить результаты, что повышает доверие к протоколу.

  4. Документирование предположений — Верификация явно документирует предположения безопасности, на которых основан протокол, что помогает при его использовании и анализе.

  5. Устойчивость к будущим атакам — Доказательства безопасности в различных моделях (символической, вычислительной) дают уверенность, что протокол устойчив к широкому спектру атакующих стратегий.

Обзор уровней верификации

graph TD
    A[Формальная верификация WireGuard] --> B[Символическая верификация]
    A --> C[Вычислительная верификация]
    A --> D[Верификация реализации]
    
    B --> B1[Tamarin]
    B --> B2[ProVerif]
    
    C --> C1[eCK модель]
    C --> C2[ACCE модель]
    
    D --> D1[HACL* 64-bit]
    D --> D2[Fiat-Crypto 32-bit]
    
    style A fill:#88171a,color:#fff
    style B fill:#2c3e50,color:#fff
    style C fill:#2c3e50,color:#fff
    style D fill:#2c3e50,color:#fff

Ссылки

9 - Кроссплатформенная реализация

Описание пользовательской реализации WireGuard для кросс-платформенной работы и интерфейса конфигурации

Кроссплатформенная пользовательская реализация

Хотя WireGuard изначально был разработан для ядра Linux для максимальной производительности, он может работать в пользовательском пространстве с использованием отдельной реализации. В настоящее время wireguard-go вполне функционален, а wireguard-rs находится в разработке.

Что такое пользовательская реализация? В отличие от реализации в ядре, которая работает на уровне операционной системы, пользовательская реализация работает как обычное приложение. Это позволяет запускать WireGuard на платформах, где нет доступа к ядру, или когда требуется более простая интеграция с приложениями.

В любой момент документации, когда вы видите ip link add wg0 type wireguard, вы можете вместо этого написать wireguard-go wg0. Всё остальное должно быть идентичным.

Чтобы предотвратить фрагментацию и обеспечить совместимость, все пользовательские реализации должны соответствовать одному и тому же протоколу и спецификации, имея точно такое же поведение, как и оригинальная реализация для ядра Linux. Кроме того, они должны соответствовать следующему интерфейсу конфигурации.

Интерфейс командной строки

Пользовательская реализация должна иметь следующий очень ограниченный интерфейс командной строки:

# userspace-wg [-f/--foreground] INTERFACE-NAME

Объяснение параметров:

  • -f или --foreground — опциональный флаг, который заставляет процесс оставаться на переднем плане (не демонизироваться). Это полезно для отладки и при запуске из системных менеджеров.
  • INTERFACE-NAME — имя создаваемого интерфейса (например, wg0).

Например, реализация на Go будет вызываться следующим образом для создания интерфейса wg0:

# wireguard-go wg0

Что происходит при запуске? Выполнение этой команды создаёт виртуальное TUN-устройство с именем wg0 и затем демонизируется (переходит в фоновый режим). После успешной демонизации и поднятия интерфейса создаётся /var/run/wireguard/wg0.sock (или /run/wireguard/wg0.sock в зависимости от платформы) — это UNIX-сокет домена, работающий в потоковом режиме.

Что такое TUN-устройство? Это виртуальный сетевой интерфейс, который работает на уровне IP. Приложения могут читать и писать в него IP-пакеты, как если бы они работали с обычным сетевым интерфейсом. WireGuard использует TUN для получения и отправки зашифрованных пакетов.

Что такое UNIX-сокет? Это механизм межпроцессного взаимодействия (IPC), который позволяет процессам обмениваться данными. В данном случае он используется для того, чтобы утилита wg(8) могла управлять процессом WireGuard.

На Windows используются те же семантики с двунаправленным именованным каналом (named pipe) в \\.\pipe\WireGuard\wg0. Именованные каналы — это аналог UNIX-сокетов в Windows.

Использование wg(8) для конфигурации

Инструмент wg(8) используется для настройки интерфейса, что обеспечивает полное единообразие интерфейсов конфигурации во всех реализациях.

Почему это важно? Пользователи и скрипты могут использовать одни и те же команды для управления WireGuard независимо от того, работает ли он в ядре или в пользовательском пространстве. Это значительно упрощает автоматизацию и написание документации.

Инструмент wg(8) ищет интерфейсы в /var/run/wireguard/*.sock (или /run/wireguard/*.sock). Пользовательские реализации должны корректно завершать работу в ответ на SIGINT/SIGTERM, удаление TUN-интерфейса или удаление файла UNIX-сокета.

Как это работает:

  1. Вы запускаете wireguard-go wg0 — создаётся процесс и сокет
  2. Вы запускаете wg setconf wg0 config.conf — утилита wg(8) находит сокет и отправляет команду
  3. Процесс WireGuard получает команду через сокет и применяет конфигурацию
  4. Всё прозрачно работает как с ядерной версией

Инструмент wg(8) подключается к этим сокетам и отправляет и получает следующий текстовый протокол.

Протокол конфигурации

Реализация WireGuard должна отвечать на две команды: get и set, обе версии 1 на момент написания.

Что такое версия протокола? Это позволяет в будущем добавлять новые функции без нарушения совместимости. Номер версии указывает, какой формат команд и ответов используется.

Команда get

wg(8) отправляет команду get, которая выглядит так:

get=1
{empty line}

Объяснение: Команда get запрашивает текущую конфигурацию и статус интерфейса. Пустая строка в конце указывает на завершение команды.

Пользовательская реализация отвечает на команду get так:

key1=value1
key2=value2
key3=value3
key4=value4
key5=value5
...
errno=0
{empty line}

Объяснение ответа: После всех ключей и значений добавляется errno=0 (означает “успех”) и пустая строка. Если произошла ошибка, errno будет содержать код ошибки.

Команда set

wg(8) отправляет команду set, которая выглядит так:

set=1
key1=value1
key2=value2
key3=value3
key4=value4
key5=value5
...
{empty line}

Объяснение: Команда set отправляет новую конфигурацию. В отличие от get, она содержит ключи и значения для применения.

Пользовательская реализация отвечает на команду set так:

errno=0
{empty line}

Объяснение: Ответ на set проще — только код ошибки и пустая строка.

Если произошла ошибка, errno — соответствующее целое число из errno.h (стандартные коды ошибок POSIX).

Ключи и значения

Уровень интерфейса

Эти ключи применяются ко всему интерфейсу:

КлючОписаниеФормат значенияПримечания
private_keyПриватный ключ интерфейсаШестнадцатеричная строка (в нижнем регистре)Все нули = удалить ключ
listen_portПорт для прослушиванияДесятичное целое число
fwmarkМетка для исходящих пакетовДесятичное целое число0 = удалить fwmark
replace_peers=trueЗаменить всех пировТолько ключПоследующие пиры заменяют существующих

Пример использования replace_peers: Если у вас уже есть 5 пиров, и вы отправляете set с replace_peers=true и 3 новыми пирами, старые 5 пиров будут удалены, а останутся только 3 новых.

Уровень пира

Эти ключи применяются к конкретному пиру и следуют после ключа public_key:

КлючОписаниеФормат значенияПримечания
public_keyПубличный ключ пираШестнадцатеричная строка (в нижнем регистре)Начинает блок пира
remove=trueУдалить пираТолько ключПрименяется к предыдущему пиру
update_only=trueОбновить только существующегоТолько ключОшибка, если пир не существует
preshared_keyПредварительный общий ключШестнадцатеричная строкаВсе нули = удалить ключ
endpointКонечная точкаIP:port или [IP]:portДля IPv6 используются квадратные скобки
persistent_keepalive_intervalИнтервал keepaliveДесятичное целое число0 = отключить
replace_allowed_ips=trueЗаменить все разрешённые IPТолько ключЗаменяет список, а не добавляет
allowed_ipРазрешённый IP-адресIP/cidrМожет быть указан несколько раз
rx_bytesПолучено байтДесятичное целое числоТолько для get
tx_bytesОтправлено байтДесятичное целое числоТолько для get
last_handshake_time_secВремя рукопожатия (сек)Десятичное целое числоТолько для get, время Unix
last_handshake_time_nsecВремя рукопожатия (нс)Десятичное целое числоТолько для get, время Unix
protocol_versionВерсия протокола1Обычно не используется

Важные замечания о ключах

  1. Порядок важен: Все ключи уровня интерфейса должны идти до ключей уровня пира. Это логично, так как сначала определяются общие параметры интерфейса, а затем параметры отдельных пиров.

  2. Обработка allowed_ip: Если одинаковое значение allowed_ip уже существует у другого пира, запись IP будет удалена у того пира и добавлена к текущему. Это обеспечивает уникальность разрешённых IP-адресов.

  3. Формат ключей: Все ключи в шестнадцатеричном формате должны быть в нижнем регистре. Это стандарт для криптографических ключей в WireGuard.

Пример диалога

Команда get

wg(8) отправляет:

get=1
{empty line}

Пользовательская реализация WireGuard отвечает:

private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a
listen_port=12912
public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33
preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52
allowed_ip=192.168.4.4/32
endpoint=[abcd:23::33%2]:51820
public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376
tx_bytes=38333
rx_bytes=2224
allowed_ip=192.168.4.6/32
persistent_keepalive_interval=111
endpoint=182.122.22.19:3233
public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58
endpoint=5.152.198.39:51820
allowed_ip=192.168.4.10/32
allowed_ip=192.168.4.11/32
tx_bytes=1212111
rx_bytes=1929999999
protocol_version=1
errno=0
{empty line}

Разбор примера:

  • Интерфейс имеет приватный ключ, слушает на порту 12912
  • Пир 1: публичный ключ b859..., preshared_key, разрешённый IP 192.168.4.4/32, конечная точка IPv6
  • Пир 2: публичный ключ 5840..., передано 38333 байт, получено 2224 байт, разрешённый IP 192.168.4.6/32, keepalive 111 секунд
  • Пир 3: публичный ключ 662e..., два разрешённых IP, большая передача данных

Команда set

wg(8) отправляет:

set=1
private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a
fwmark=0
listen_port=12912
replace_peers=true
public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33
preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52
replace_allowed_ips=true
allowed_ip=192.168.4.4/32
endpoint=[abcd:23::33%2]:51820
public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376
replace_allowed_ips=true
allowed_ip=192.168.4.6/32
persistent_keepalive_interval=111
endpoint=182.122.22.19:3233
public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58
endpoint=5.152.198.39:51820
replace_allowed_ips=true
allowed_ip=192.168.4.10/32
allowed_ip=192.168.4.11/32
public_key=e818b58db5274087fcc1be5dc728cf53d3b5726b4cef6b9bab8f8f8c2452c25c
remove=true
{empty line}

Разбор примера:

  • replace_peers=true — все старые пиры будут удалены
  • fwmark=0 — fwmark отключён
  • Добавляются 3 пира, последний (e818...) помечен remove=true для удаления
  • У каждого пира используется replace_allowed_ips=true для замены списков разрешённых IP

Пользовательская реализация WireGuard отвечает:

errno=0
{empty line}

Практические примеры использования

Настройка интерфейса через командную строку

# Запуск пользовательской реализации
# wireguard-go wg0

# Настройка с использованием wg(8)
# wg set wg0 private-key /etc/wireguard/private.key listen-port 51820
# wg set wg0 peer xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= allowed-ips 10.0.0.2/32 endpoint 192.95.5.69:51820
# ip address add dev wg0 10.0.0.1/24
# ip link set up dev wg0

Использование с конфигурационным файлом

# Создаём конфигурационный файл /etc/wireguard/wg0.conf
# wg setconf wg0 /etc/wireguard/wg0.conf
# wg-quick up wg0

Получение статуса

# wg show wg0

Преимущества пользовательской реализации

  1. Кроссплатформенность — работает на Windows, macOS, BSD и других системах без поддержки в ядре
  2. Простота отладки — ошибки легче отслеживать в пользовательском пространстве
  3. Гибкость — можно интегрировать в приложения как библиотеку
  4. Безопасность — изоляция от ядра может быть преимуществом в некоторых сценариях

Недостатки пользовательской реализации

  1. Производительность — обычно медленнее, чем реализация в ядре
  2. Дополнительные накладные расходы — копирование данных между ядром и пользовательским пространством
  3. Потребление памяти — больше использования памяти для хранения состояния

Ссылки

10 - Маршрутизация и сетевые пространства имён

Интеграция WireGuard с сетевыми пространствами имён Linux для контейнеризации и маршрутизации трафика

Интеграция с маршрутизацией и сетевыми пространствами имён

Как и все сетевые интерфейсы Linux, WireGuard интегрируется в инфраструктуру сетевых пространств имён (network namespaces). Это означает, что администратор может иметь несколько полностью разных сетевых подсистем и выбирать, какие интерфейсы находятся в каждом из них.

Что такое сетевые пространства имён? Это механизм ядра Linux, который позволяет изолировать сетевые стеки. Каждое пространство имён имеет свои собственные сетевые интерфейсы, таблицы маршрутизации, правила файервола и сокеты. Это основа для контейнеризации (Docker, LXC и другие).

WireGuard делает кое-что довольно интересное. Когда интерфейс WireGuard создаётся (с помощью ip link add wg0 type wireguard), он запоминает пространство имён, в котором был создан: «Я был создан в пространстве имён A». Позже WireGuard может быть перемещён в новые пространства имён («Я перемещаюсь в пространство имён B»), но он всё равно будет помнить, что произошёл из пространства имён A.

Почему это важно? WireGuard использует UDP-сокет для фактической отправки и получения зашифрованных пакетов. Этот сокет всегда живёт в пространстве имён A — исходном пространстве имён рождения. Это обеспечивает очень интересные возможности. А именно, вы можете создать интерфейс WireGuard в одном пространстве имён (A), переместить его в другое (B) и отправлять незашифрованные пакеты из пространства имён B, которые будут отправляться зашифрованными через UDP-сокет в пространстве имён A.

Это открывает очень интересные возможности.

Обычная контейнеризация

Наиболее очевидное использование этого — предоставить контейнерам (например, Docker-контейнерам) интерфейс WireGuard в качестве единственного интерфейса.

Схема контейнерной организации

Пример: Внутри контейнера видно только loopback-интерфейс и интерфейс WireGuard:

container # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
17: wg0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1423 qdisc noqueue state UNKNOWN group default qlen 1
    link/none 
    inet 192.168.4.33/32 scope global wg0
       valid_lft forever preferred_lft forever

Что это значит? Единственный способ доступа к сети — через wg0, интерфейс WireGuard. Весь трафик из контейнера автоматически шифруется и отправляется через VPN. Контейнер даже не знает о существовании физических сетевых интерфейсов хоста.

Настройка контейнера с WireGuard

Шаг 1: Создание сетевого пространства имён

Сначала создаём сетевое пространство имён с именем «container»:

# ip netns add container

Шаг 2: Создание интерфейса WireGuard

Создаём интерфейс WireGuard в исходном пространстве имён (init):

# ip link add wg0 type wireguard

Шаг 3: Перемещение интерфейса

Перемещаем интерфейс в новое пространство имён:

# ip link set wg0 netns container

Шаг 4: Настройка интерфейса

Теперь настраиваем wg0 как обычно, но указываем его новое пространство имён:

# ip -n container addr add 192.168.4.33/32 dev wg0
# ip netns exec container wg setconf wg0 /etc/wireguard/wg0.conf
# ip -n container link set wg0 up
# ip -n container route add default dev wg0

Результат: Теперь единственный способ доступа к сетевым ресурсам для «container» — через интерфейс WireGuard.

Маршрутизация всего трафика

Менее очевидное, но чрезвычайно мощное использование — применение этой характеристики WireGuard для перенаправления всего вашего обычного интернет-трафика через WireGuard.

Проблема: Как заставить весь трафик идти через VPN, но при этом позволить самому VPN-соединению использовать обычный интернет?

Классические решения

Классические решения основаны на различных конфигурациях таблиц маршрутизации. Для всех них нам нужно установить явный маршрут для фактической конечной точки WireGuard.

Пример: Предположим, конечная точка WireGuard — demo.wireguard.com, которая на момент написания резолвится в 163.172.161.0. Предположим также, что мы обычно подключаемся к интернету через eth0 со шлюзом 192.168.1.1.

Замена маршрута по умолчанию

Самая простая техника — просто заменить маршрут по умолчанию, но добавить явное правило для конечной точки WireGuard:

# ip route del default
# ip route add default dev wg0
# ip route add 163.172.161.0/32 via 192.168.1.1 dev eth0

Преимущества: Просто и понятно.

Недостатки: DHCP-демоны и другие программы любят отменять то, что мы только что сделали.

Переопределение маршрута по умолчанию

Вместо замены маршрута по умолчанию мы можем переопределить его двумя более специфичными правилами, которые в сумме дают маршрут по умолчанию, но совпадают раньше:

# ip route add 0.0.0.0/1 dev wg0
# ip route add 128.0.0.0/1 dev wg0
# ip route add 163.172.161.0/32 via 192.168.1.1 dev eth0

Объяснение: 0.0.0.0/1 + 128.0.0.0/1 = 0.0.0.0/0 (весь IPv4-диапазон). Эти маршруты имеют более высокий приоритет, чем маршрут по умолчанию, поэтому они используются для всего трафика, кроме явно исключённого.

Недостатки: Когда eth0 поднимается и опускается, явный маршрут для demo.wireguard.com забывается.

Маршрутизация на основе правил

Некоторые предпочитают использовать маршрутизацию на основе правил и несколько таблиц маршрутизации:

# ip rule add to 163.172.161.0 lookup main pref 30
# ip rule add to all lookup 80 pref 40
# ip route add default dev wg0 table 80

Объяснение: Правила определяют, какую таблицу маршрутизации использовать для каждого пакета. Для IP-адреса конечной точки используется основная таблица, для всего остального — таблица 80.

Недостатки: Нужно добавлять явные правила для конечных точек, нет очистки при удалении интерфейса, более сложные правила маршрутизации нужно дублировать.

Улучшенная маршрутизация на основе правил

Предыдущее решение требует знания явного IP-адреса конечной точки, который должен быть исключён из туннеля. Но конечные точки WireGuard могут роумить, что означает, что это правило может устареть.

Решение: Устанавливаем fwmark на все пакеты, выходящие из UDP-сокета WireGuard, которые затем будут исключены из туннеля:

# wg set wg0 fwmark 1234
# ip route add default dev wg0 table 2468
# ip rule add not fwmark 1234 table 2468
# ip rule add table main suppress_prefixlength 0

Объяснение:

  1. Устанавливаем fwmark на интерфейсе
  2. Добавляем маршрут по умолчанию в альтернативную таблицу маршрутизации
  3. Указываем, что пакеты без fwmark должны использовать эту альтернативную таблицу
  4. Добавляем удобство для доступа к локальной сети

Это техника, используемая инструментом wg-quick(8).

Новое решение с пространствами имён

Оказывается, мы можем маршрутизировать весь интернет-трафик через WireGuard, используя сетевые пространства имён, а не классические хаки с таблицами маршрутизации.

Основная идея: Перемещаем интерфейсы, подключающиеся к интернету (например, eth0 или wlan0), в пространство имён «physical», а интерфейс WireGuard делаем единственным интерфейсом в пространстве имён «init».

Схема физического сетевого пространства имён

Пошаговая настройка

Шаг 1: Создание физического пространства имён

# ip netns add physical

Шаг 2: Перемещение физических интерфейсов

Перемещаем eth0 и wlan0 в пространство имён «physical»:

# ip link set eth0 netns physical
# iw phy phy0 set netns name physical

Теперь эти интерфейсы находятся в пространстве имён «physical», а в пространстве имён «init» интерфейсов нет:

# ip -n physical link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether ab:cd:ef:g1:23:45 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 01:23:45:67:89:ab brd ff:ff:ff:ff:ff:ff

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Шаг 3: Создание интерфейса WireGuard в физическом пространстве

# ip -n physical link add wg0 type wireguard

Пространство имён рождения wg0 теперь — «physical», что означает, что UDP-сокеты с зашифрованными данными будут привязаны к устройствам eth0 и wlan0.

Шаг 4: Перемещение интерфейса в init

Перемещаем wg0 в пространство имён «init». Он всё равно будет помнить своё место рождения для сокетов:

# ip -n physical link set wg0 netns 1

Теперь в пространстве имён «init» есть устройство wg0:

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
17: wg0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1423 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
    link/none

Шаг 5: Настройка физических устройств

Настраиваем физические устройства с помощью обычных инструментов, но запускаем их внутри пространства имён «physical»:

# ip netns exec physical dhcpcd wlan0
# ip netns exec physical wpa_supplicant -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
# ip -n physical addr add 192.168.12.52/24 dev eth0

Шаг 6: Настройка WireGuard

Настраиваем интерфейс wg0 как обычно и устанавливаем его как маршрут по умолчанию:

# wg setconf wg0 /etc/wireguard/wg0.conf
# ip addr add 10.2.4.5/32 dev wg0
# ip link set wg0 up
# ip route add default dev wg0

Результат: Все обычные процессы в системе маршрутизируют свои пакеты через пространство имён «init», которое содержит только интерфейс wg0 и его маршруты. Однако wg0 имеет UDP-сокет, живущий в пространстве имён «physical», что означает, что он будет отправлять трафик через eth0 или wlan0. Обычные процессы даже не знают о существовании eth0 или wlan0, за исключением dhcpcd и wpa_supplicant, которые были запущены внутри пространства имён «physical».

Выполнение команд в физическом пространстве

Иногда вам может понадобиться открыть веб-страницу или быстро сделать что-то, используя пространство имён «physical». Например, вы можете планировать маршрутизировать весь трафик через WireGuard, но кофейня, в которой вы сидите, требует аутентификации через веб-сайт перед предоставлением реального интернет-соединения.

Выполнение процесса в физическом пространстве:

$ sudo -E ip netns exec physical sudo -E -u \#$(id -u) -g \#$(id -g) chromium

Создание удобной функции для .bashrc:

physexec() { sudo -E ip netns exec physical sudo -E -u \#$(id -u) -g \#$(id -g) "$@"; }

Использование:

$ physexec chromium  # Открыть Chromium в физическом пространстве для аутентификации

После входа в сеть кофейни запускайте браузер как обычно:

$ chromium  # Весь трафик защищён WireGuard

Пример скрипта

Следующий пример скрипта можно сохранить как /usr/local/bin/wgphys и использовать для команд wgphys up, wgphys down и wgphys exec:

#!/bin/bash
set -ex

[[ $UID != 0 ]] && exec sudo -E "$(readlink -f "$0")" "$@"

up() {
    killall wpa_supplicant dhcpcd || true
    ip netns add physical
    ip -n physical link add wgvpn0 type wireguard
    ip -n physical link set wgvpn0 netns 1
    wg setconf wgvpn0 /etc/wireguard/wgvpn0.conf
    ip addr add 192.168.4.33/32 dev wgvpn0
    ip link set eth0 down
    ip link set wlan0 down
    ip link set eth0 netns physical
    iw phy phy0 set netns name physical
    ip netns exec physical dhcpcd -b eth0
    ip netns exec physical dhcpcd -b wlan0
    ip netns exec physical wpa_supplicant -B -c/etc/wpa_supplicant/wpa_supplicant-wlan0.conf -iwlan0
    ip link set wgvpn0 up
    ip route add default dev wgvpn0
}

down() {
    killall wpa_supplicant dhcpcd || true
    ip -n physical link set eth0 down
    ip -n physical link set wlan0 down
    ip -n physical link set eth0 netns 1
    ip netns exec physical iw phy phy0 set netns 1
    ip link del wgvpn0
    ip netns del physical
    dhcpcd -b eth0
    dhcpcd -b wlan0
    wpa_supplicant -B -c/etc/wpa_supplicant/wpa_supplicant-wlan0.conf -iwlan0
}

execi() {
    exec ip netns exec physical sudo -E -u \#${SUDO_UID:-$(id -u)} -g \#${SUDO_GID:-$(id -g)} -- "$@"
}

command="$1"
shift

case "$command" in
    up) up "$@" ;;
    down) down "$@" ;;
    exec) execi "$@" ;;
    *) echo "Usage: $0 up|down|exec" >&2; exit 1 ;;
esac

Демонстрация работы скрипта:

Демонстрация команды wgphys

Сравнение решений

РешениеПреимуществаНедостатки
Замена defaultПростотаDHCP отменяет изменения
Переопределение defaultНе заменяет defaultМаршрут забывается при переподключении
Правила (rule-based)Разделение таблицНужно знать IP конечной точки
Улучшенные правила (fwmark)Устойчив к роумингуСложнее для понимания
Пространства имёнПолная изоляция, чистотаТребует настройки пространств имён

Преимущества решения с пространствами имён

  1. Полная изоляция — обычные процессы не видят физические интерфейсы
  2. Автоматическая маршрутизация — весь трафик идёт через WireGuard без сложных правил
  3. Прозрачность — не нужно добавлять явные маршруты для конечных точек
  4. Чистота — нет хаков с таблицами маршрутизации
  5. Гибкость — можно запускать отдельные процессы в физическом пространстве

Ссылки

11 - Встраивание в приложения

Как встроить WireGuard в пользовательские приложения на различных платформах

Встраивание WireGuard в пользовательские приложения

Клиентские приложения проекта WireGuard были спроектированы с максимальной возможностью повторного использования, что позволяет создавать пользовательские приложения, использующие WireGuard. Ситуация несколько отличается на разных платформах, и эта страница пытается обобщить то, что доступно в проекте.

Зачем встраивать WireGuard?

Встраивание WireGuard в приложения может быть полезно для:

  • VPN-клиентов — создание собственного VPN-приложения с брендированным интерфейсом
  • Систем управления — интеграция VPN в панели управления и оркестраторы
  • Сетевых утилит — добавление безопасного туннелирования в существующие инструменты
  • IoT-устройств — встраивание безопасного канала связи в嵌入式 системы
  • Корпоративных решений — создание проприетарных решений поверх WireGuard

Платформо-специфичные решения

Windows: embeddable-dll-service

Что это? Библиотека, которая позволяет создавать полноценные автономные Windows-сервисы, встраивающие WireGuard.

Где найти: embeddable-dll-service код и документация

Для кого: Для разработчиков Windows-приложений, которые хотят добавить VPN-функциональность без написания низкоуровневого кода.

Как это работает: Библиотека предоставляет простой API для создания и управления WireGuard-туннелями из любого Windows-приложения. Она управляет всем циклом жизни VPN-соединения.

Пример использования:

// Псевдокод для понимания концепции
var wgService = new WireGuardService();
wgService.SetConfig(configFile);
wgService.Start();
// ... работа с VPN
wgService.Stop();

Преимущества:

  • Полноценная интеграция с Windows Service Manager
  • Автоматическое управление жизненным циклом
  • Встроенная обработка ошибок и восстановление
  • Простой API

Windows: WireGuardNT

Что это? Более низкоуровневая реализация WireGuard для Windows, чем embeddable-dll-service.

Где найти: Проект WireGuardNT

Для кого: Для разработчиков, которым нужен максимальный контроль над WireGuard на Windows, или для создания альтернативных реализаций.

Важное предупреждение: Настоятельно рекомендуется использовать embeddable-dll-service, а не WireGuardNT напрямую, так как первый использует второй внутри себя. WireGuardNT предоставляет более низкоуровневый API.

Что делает WireGuardNT:

  • Реализует драйвер ядра для WireGuard в Windows
  • Обеспечивает высокую производительность
  • Предоставляет низкоуровневый интерфейс управления

Когда использовать WireGuardNT:

  • Создание альтернативных менеджеров WireGuard
  • Исследовательские проекты
  • Интеграция с нестандартными системами управления

macOS и iOS: WireGuardKit

Что это? Библиотека для интеграции WireGuard в приложения для macOS и iOS.

Где найти: WireGuardKit из репозитория wireguard-apple

Для кого: Для разработчиков приложений для экосистемы Apple.

Как это работает: WireGuardKit предоставляет Swift-интерфейс для управления WireGuard-туннелями. Он интегрируется с сетевыми расширениями (Network Extensions) Apple для создания полноценных VPN-приложений.

Пример использования (Swift):

import WireGuardKit

// Создание туннеля
let tunnel = WireGuardTunnel()
tunnel.configuration = config
tunnel.start { error in
    if let error = error {
        print("Ошибка запуска: \(error)")
    } else {
        print("Туннель запущен")
    }
}

Поддерживаемые платформы:

  • macOS
  • iOS
  • iPadOS

Преимущества:

  • Интеграция с Apple Network Extension API
  • Поддержка Swift Package Manager (SPM)
  • Нативная производительность
  • Полная поддержка мобильных функций

Android: com.wireguard.android:tunnel

Что это? Библиотека для встраивания WireGuard в Android-приложения.

Где найти: Библиотека на Maven Central с обширной документацией классов и инструкцией для Gradle

Для кого: Для разработчиков Android-приложений, желающих добавить VPN-функциональность.

Подключение через Gradle:

dependencies {
    implementation 'com.wireguard.android:tunnel:1.0.20201212'
}

Пример использования (Kotlin):

import com.wireguard.android.backend.Backend
import com.wireguard.config.Config

// Создание бэкенда
val backend = Backend()

// Настройка и запуск туннеля
val config = Config.Builder()
    .setPrivateKey(privateKey)
    .addPeer(peerConfig)
    .build()

backend.setState(tunnelName, config, State.UP)

Возможности:

  • Интеграция с Android VPN Service API
  • Поддержка всех версий Android
  • Оптимизация для мобильных устройств
  • Обработка изменений сети

Linux: embeddable-wg-library

Что это? Однобиблиотечная C-библиотека для взаимодействия с WireGuard через ядро Linux.

Где найти: embeddable-wg-library в репозитории wireguard-tools

Для кого: Для разработчиков на C/C++ в среде Linux, которым нужен программный контроль над WireGuard.

Особенности:

  • Один C-файл для включения в проект
  • Простой API для управления WireGuard
  • Использует системные вызовы ядра напрямую
  • Минимальные зависимости

Пример использования (C):

// Псевдокод для понимания
#include "wg.h"

// Создание интерфейса
wg_interface_t *wg = wg_create("wg0");
wg_set_private_key(wg, private_key);
wg_add_peer(wg, public_key, allowed_ips, endpoint);
wg_set_up(wg);

Linux/BSD/Darwin: wgctrl-go

Что это? Проект для создания WireGuard-конфигураций и управления ими из Go.

Где найти: wgctrl-go на GitHub

Для кого: Для разработчиков на Go, создающих приложения для Linux, BSD и macOS.

Пример использования (Go):

import "github.com/WireGuard/wgctrl"

// Создание клиента
client, err := wgctrl.New()
if err != nil {
    log.Fatal(err)
}
defer client.Close()

// Создание конфигурации
cfg := wgtypes.Config{
    PrivateKey:   privateKey,
    ListenPort:   &port,
    Peers:        []wgtypes.PeerConfig{...},
}

// Применение конфигурации
err = client.ConfigureDevice("wg0", cfg)

Поддерживаемые платформы:

  • Linux (через netlink)
  • BSD (через ioctl)
  • macOS (через userspace)

Преимущества:

  • Единый API для нескольких платформ
  • Поддержка всех функций WireGuard
  • Хорошая документация и примеры
  • Активная поддержка

Linux: NetworkManager, Systemd, connman

Что это? Полноценная поддержка WireGuard в популярных сетевых менеджерах Linux.

Для кого: Для разработчиков, предпочитающих использовать существующие инфраструктуры, а не создавать собственные.

NetworkManager

NetworkManager имеет встроенную поддержку WireGuard. Управление осуществляется через DBus API.

Пример (через nmcli, для скриптов):

nmcli connection add type wireguard ifname wg0 con-name wg0
nmcli connection modify wg0 wireguard.private-key /path/to/key
nmcli connection up wg0

Systemd

Systemd также поддерживает WireGuard через сетевые конфигурации.

Конфигурация (в systemd-networkd):

[NetDev]
Name=wg0
Kind=wireguard

[WireGuard]
PrivateKey=...

Connman

Connman поддерживает WireGuard через свои конфигурационные файлы.

Сравнение решений по платформам

ПлатформаРешениеУровеньЯзыкСложность
Windowsembeddable-dll-serviceВысокийC#/C++/любойНизкая
WindowsWireGuardNTНизкийC/C++Высокая
macOS/iOSWireGuardKitВысокийSwiftНизкая
Androidcom.wireguard.android:tunnelВысокийKotlin/JavaНизкая
Linuxembeddable-wg-libraryСреднийC/C++Средняя
Linux/BSD/Darwinwgctrl-goСреднийGoСредняя
LinuxNetworkManager/Systemd/ConnmanВысокийЛюбойНизкая

Руководство по выбору решения

Для Windows:

  • В большинстве случаев: Используйте embeddable-dll-service
  • Для экспериментов: Можно использовать WireGuardNT

Для Apple (macOS/iOS):

  • Всегда используйте: WireGuardKit

Для Android:

  • Всегда используйте: com.wireguard.android:tunnel

Для Linux:

  • Если вы используете Go: wgctrl-go
  • Если вы используете C/C++: embeddable-wg-library
  • Если вы используете существующие сетевые менеджеры: NetworkManager/Systemd/Connman
  • Для скриптов: Используйте wg(8) и wg-quick(8)

Для кроссплатформенных приложений:

  • Используйте соответствующее решение для каждой платформы
  • Или используйте wgctrl-go (для Linux, BSD, macOS) и отдельные решения для Windows/Android

Примеры интеграции

Создание простого VPN-клиента на Windows

# Использование embeddable-dll-service
$wgService = New-Object -ComObject WireGuard.Service
$wgService.Install("MyVPN")
$wgService.SetConfig("C:\Configs\myvpn.conf")
$wgService.Start()

Интеграция в мобильное приложение (iOS)

// Использование WireGuardKit
import WireGuardKit

class VPNManager {
    let tunnel = WireGuardTunnel()
    
    func startVPN() {
        let config = try! Config(fromFile: "config.conf")
        tunnel.configuration = config
        tunnel.start()
    }
}

Интеграция в веб-приложение (Linux)

// Использование wgctrl-go
package main

import (
    "github.com/WireGuard/wgctrl"
    "github.com/WireGuard/wgctrl/wgtypes"
)

func setupVPN() error {
    client, _ := wgctrl.New()
    defer client.Close()
    
    key, _ := wgtypes.GeneratePrivateKey()
    config := wgtypes.Config{
        PrivateKey: &key,
        ListenPort: ptr(51820),
    }
    
    return client.ConfigureDevice("wg0", config)
}

func ptr[T any](v T) *T { return &v }

Рекомендации по безопасности при встраивании

  1. Хранение ключей: Всегда храните приватные ключи в защищённом месте (Keychain, Secure Storage, TPM)
  2. Проверка конфигураций: Валидируйте все входящие конфигурации перед применением
  3. Логирование: Ведите журнал действий для аудита
  4. Обновления: Следите за обновлениями WireGuard и включайте их в свои приложения
  5. Тестирование: Тщательно тестируйте интеграцию на всех целевых платформах

Ссылки