Ранее на нашем сайте мы подробно рассматривали запуск и настройку сервера 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 [email protected]
Настройка брандмауэра
Для того, чтобы наш сервер начал принимать входящие соединения, необходимо настроить брандмауэр и правила маршрутизации.
Разрешим входящие подключения на порт сервера (в нашем примере применяется 27015):
sudo firewall-cmd --permanent --zone=public --add-port=27015/udp
Включим маскарадинг для зоны Firewalld:
sudo firewall-cmd --permanent --zone=public --add-masquerade
Применим изменения в конфигурации 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 [email protected]
Если всё сделано верно, то подключение будет успешно установлено.
Приложение
Пример файла конфигурации сервера для двух клиентов:
# Главные настройки сервера: его внутренний 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.
Обновил статью. Спасибо.