Ранее на нашем сайте мы подробно рассматривали запуск и настройку сервера OpenVPN, но не так давно у него появился достойный соперник — WireGuard, который мы сегодня и разберём в данной статье.
Введение
WireGuard — это самый современный в настоящее время протокол для реализации виртуальных частных сетей (VPN).
Основные преимущества WireGuard:
- реализован посредством модуля ядра, что значительно увеличивает производительность туннеля из-за отсутствия необходимости в постоянных переключениях между режимами ядра и пользовательским;
- использует современные криптографические протоколы: Curve25519, ChaCha20, Poly1305 и т.д.;
- имеет простую реализацию, что снижает вероятность возникновения ошибок и, как следствие, уязвимостей;
- хорошо спроектирован и документирован.
Установка в Fedora
Начиная с версии ядра Linux 5.6.0, все необходимые для работы WireGuard модули ядра уже включены в его состав, поэтому установим лишь клиентскую утилиту настройки из основного репозитория Fedora:
sudo dnf install wireguard-tools
Настройка сервера
Создадим главный файл конфигурации сервера /etc/wireguard/wg0.conf:
[Interface] Address = 10.8.0.1/24 PrivateKey = SERVER_PRIVATE_KEY ListenPort = 27015
Сгенерируем секретный ключ для сервера в файл wg-srv-private и пропишем его содержимое вместо SERVER_PRIVATE_KEY:
touch wg-srv-private chmod 0600 wg-srv-private wg genkey > wg-srv-private
Вычислим на основе секретного ключа сервера публичный для передачи его клиентам:
wg pubkey < wg-srv-private > wg-srv-public
Зададим порт сервера при помощи директивы ListenPort. WireGuard работает только посредством протокола UDP. TCP не поддерживается.
Активируем сервер и настроим его автоматический запуск средствами systemd:
sudo systemctl enable --now wg-quick@wg0.service
Настройка брандмауэра
Для того, чтобы наш сервер начал принимать входящие соединения, необходимо настроить брандмауэр и правила маршрутизации.
Разрешим входящие подключения на порт сервера (в нашем примере применяется 27015):
sudo firewall-cmd --permanent --zone=public --add-port=27015/udp
Включим маскарадинг для зоны Firewalld:
sudo firewall-cmd --permanent --zone=public --add-masquerade
Разрешим перенаправление трафика между сетевыми интерфейсами:
sudo firewall-cmd --permanent --zone public --add-forward
Применим изменения в конфигурации Firewalld:
sudo firewall-cmd --reload
Разрешим перенаправление трафика как по протоколу TCP/IP версии 4, так и версии 6:
sudo sysctl -w net.ipv4.conf.all.forwarding=1 sudo sysctl -w net.ipv6.conf.all.forwarding=1
Сохраним настройки перенаправления так, чтобы они работали и после перезагрузки системы:
sudo bash -c "echo -e \"net.ipv4.conf.all.forwarding=1\nnet.ipv6.conf.all.forwarding=1\" > /etc/sysctl.d/99-wireguard.conf"
Настройка клиентов
Клиентская сторона
Теперь каждому клиенту необходимо самостоятельно сгенерировать ключевую пару. Принцип аналогичен GnuPG и SSH: секретная часть (private key) остаётся у клиента, а публичная (public key) передаётся администратору сервера.
Сгенерируем секретный ключ клиента 1:
touch wg-cli1-private chmod 0600 wg-cli1-private wg genkey > wg-cli1-private
Получим публичный ключ клиента 1:
wg pubkey < wg-cli1-private > wg-cli1-public
Создадим файл конфигурации клиента /etc/wireguard/wg0.conf (имя файла конфигурации на клиенте и сервере совпадают):
[Interface] Address = 10.8.0.2/24 PrivateKey = CLIENT_PRIVATE_KEY DNS = 1.1.1.1,8.8.8.8 [Peer] PublicKey = SERVER_PUBLIC_KEY AllowedIPs = 0.0.0.0/0 Endpoint = 1.2.3.4:27015 PersistentKeepalive = 20
Здесь вместо CLIENT_PRIVATE_KEY укажем секретный ключ клиента (содержимое файла wg-cli1-private), а SERVER_PUBLIC_KEY — публичный ключ сервера (содержимое wg-srv-public).
Директива Address содержит желаемый внутренний IP-адрес на сервере, а Endpoint — доменное имя или IP адрес сервера WireGuard, а также его порт.
Сторона сервера
Клиент любым способом передаёт администратору сервера свой публичный ключ (содержимое файла wg-cli1-public), затем администратор прописывает его в главный конфигурационный файл /etc/wireguard/wg0.conf:
[Peer] PublicKey = CLIENT1_PUBLIC_KEY AllowedIPs = 10.8.0.2/32
Здесь CLIENT1_PUBLIC_KEY — публичный ключ, переданный клиентом, а AllowedIPs — IP-адрес или подсеть, из которой клиенту будет выдан внутренний IP-адрес на сервере WireGuard.
Если клиентов несколько, то все действия следует повторить для каждого из них.
Подключение к серверу
Существует два основных способа настройки подключения к серверу. Рассмотрим каждый из них более подробно.
Современный способ
Network Manager имеет встроенную поддержку WireGuard, поэтому воспользуемся им для быстрой настройки соединения.
Импортируем созданную ранее конфигурацию:
nmcli connection import type wireguard file /etc/wireguard/wg0.conf
Запустим автоматически созданное соединение с именем wg0:
nmcli connection up wg0
При необходимости настроим автоматическое подключение к VPN-серверу при загрузке системы:
nmcli connection modify wg0 connection.autoconnect yes
Классический способ
Запустим туннель и настроим его автоматическое поднятие при помощи wg-quick:
sudo systemctl enable --now wg-quick@wg0.service
Если всё сделано верно, то подключение будет успешно установлено.
Приложение
Пример файла конфигурации сервера для двух клиентов:
# Главные настройки сервера: его внутренний IP-адрес, # секретный ключ и порт, который он будет слушать. [Interface] Address = 10.8.0.1/24 PrivateKey = SERVER_PRIVATE_KEY ListenPort = 27015 # Настройки клиентов. Каждый отдельным блоком. # Клиент №1 [Peer] PublicKey = CLIENT1_PUBLIC_KEY AllowedIPs = 10.8.0.2/32 # Клиент №2 [Peer] PublicKey = CLIENT2_PUBLIC_KEY AllowedIPs = 10.8.0.3/32
Если кто-то вместо Network Manager использует systemd-networkd, то он поддерживает WireGuard «из коробки»:
Листинг файла /etc/systemd/network/10-wg0.netdev:
Листинг файла /etc/systemd/network/10-wg0.network:
Отсутствуют совпадения для аргумента: hernel-headers
Ошибка: Совпадений не найдено
У вас опечатка. Пакет называется kernel-headers.
Опечатка была в статье. Я исправил.
Также можно добавить, что для усиления безопасности существует возможность добавить слой симметричного шифрования для рукопожатия — общий ключ между клиентом и сервером — pre-shared key (PSK).
Создание PSK:
Далее в конфиг сервера и клиента нужно добавить строку:
Здесь вместо PSK_KEY — содержимое файла wg-psk.
Разумеется, для каждого клиента в файле конфигурации сервера, в блоке Peer, должен быть указан свой общий ключ. Этот же ключ должен быть прописан и на самом клиенте.
При создании файла 99-wireguard не указано значение для второго параметра
Большое спасибо, исправили.
Статья обновлена. WireGuard теперь входит в состав ядра Linux версии 5.6.0 и выше.
Может кто-нибудь знает как защитить конфиг на стороне клиента? Если я угнал клиентский конфиг, то могу без проблем конектится к серверу. Парольная аутентификация как я понял не предусмотрена в самом протоколе. PresharedKey тоже непонятно зачем нужен — если я могу просто скопировать конфиг у клиента
Да, в случае кражи клиентского конфига, им смогут пользоваться злоумышленники до тех пор, пока публичный ключ не будет удалён на стороне сервера из разрешённых.
На Reddit и в баг-трекере WireGuard эта тема неоднократно поднималась, но разработчики отказываются добавлять поддержку парольной защиты для закрытых ключей.
Начиная с 33 версии федора использует systemd-resolved. А wg-quick, ничего об этом не знает и пытается использовать resolvconf. Это приводит к ошибкам связанным с резолвингом имён.
Инструкция как пофиксить есть в арчивики (статья про wireguard), но хорошо эту инструкцию тоже обновить бы.
Да, поэтому WireGuard подключение сейчас лучше поднимать при помощи Network Manager, который корректно интегрируется с systemd-resolved.
Обновил статью. Спасибо.
Там можно просто не указывать «DNS=х.х.х.х», тогда проблем не будет
Если не указывать DNS для соединения, может произойти утечка DNS (dns leak).
Да, поэтому в systemd-resolved надо указать свои DNS и включить DoT
Активация DNS-over-TLS не требуется ибо DNS-трафик и так будет перенаправляться целиком внутрь WireGuard интерфейса.
Там даже будет что-то типа шифрования DNS трафика?
WireGuard шифрует весь проходящий через него трафик, в т.ч. и DNS.
Как поставить wireguard на ядро 5.14.12
Начиная с Linux версии 5.6, все необходимые модули ядра WireGuard входят в комплект его поставки. Отдельно устанавливать их больше не требуется.
А что насчет IPv6 адресов?
Пропишите выделенную серверу IPv6 /128 подсеть и WireGuard будет выдавать клиентам адреса из неё.
Добрый день. Никак не могу понять взаимодействие между клиентами возможно?
Т.е между Клиент №1 — Клиент №2 через сервер.
Да. Ответ есть в нашем FAQ.
Подскажите, пожалуйста, какие настройки нужно сделать, чтобы можно было использовать почтового клиента на клиенте wireguard?
Если подключаюсь к vpn — почта не принимается / не отправляется.
Ответ на этот вопрос зависит от того, где находится WireGuard сервер.
Если почтовый сервер доступен только внутри виртуальной частной сети, то нужно явно указать маршрут до него, либо разрешить p2p роутинг внутри WireGuard сети.
Если во внешней сети и WireGuard экспортирует основной шлюз, то всё должно работать автоматически в штатном режиме.
Почтовый сервер находится во внешней сети. Если не сложно, можете кратко указать что нужно проверить в этом случае? (Может быть порты открыть и т.п.)
Если сервер находится во внешней сети, то он должен быть доступен по своему основному IP-адресу, т.к. в наших примерах соединение WireGuard становится основным шлюзом.
Проверьте, что выдаётся действительный внешний IP-адрес и он пингуется:
Открывать порты для интерфейса WireGuard необходимо только если требуется подключаться к серверу по его внутреннему IP.
Прикольно бы запихнуть wireguard в сеть yggdrasil, тут даже статика не нужна.
В таком случае потеряется весь смысл использования WireGuard — скорость и работа исключительно в режиме ядра.