MHOSTMHOST

WireGuard VPN: сервер и клиенты

WireGuard — современный VPN-протокол, работающий прямо в ядре Linux: минимум кода, современная криптография и заметно более простая настройка, чем у OpenVPN или IPsec. В этой статье вы поднимете собственный WireGuard-сервер на VPS mHost и подключите к нему клиентское устройство, чтобы маршрутизировать его трафик через сервер.

Диаграмма: клиентское устройство и VPN-сервер обмениваются трафиком через зашифрованный туннель, а сервер выходит дальше в интернет

Что понадобится

  • VPS mHost на Ubuntu 22.04/24.04, Debian 11/12 или AlmaLinux/Rocky Linux 8/9.
  • Доступ по SSH под root или пользователем с правами sudo.
  • Публичный IP-адрес сервера (или домен, указывающий на него) — понадобится в конфиге клиента как Endpoint.
  • Устройство-клиент с приложением WireGuard — официальные клиенты для Windows, macOS, Linux, iOS и Android перечислены на wireguard.com/install — либо ещё один Linux-сервер.
Совет: если не принципиально настраивать всё вручную, в VMmanager 6 есть готовый рецепт Wireguard VPN — поднимает VPN-сервер в один клик и сразу кладёт готовый конфиг для подключения клиента в /etc/wireguard/client/client.conf (как войти в панель — статья «Как войти в VMmanager 6», полный каталог рецептов — «Готовые рецепты VMmanager 6»). Ниже — та же задача вручную: пригодится, если рецепт недоступен для вашей ОС, нужен контроль над подсетью, портом или числом клиентов, либо хочется разобраться, как всё устроено внутри.

Шаг 1. Установите wireguard-tools

WireGuard встроен в ядро Linux начиная с версии 5.6 — на Ubuntu 22.04/24.04, Debian 11/12 и AlmaLinux/Rocky Linux 9 отдельно собирать модуль ядра не нужно, достаточно пользовательских утилит wg и wg-quick из пакета wireguard-tools.

Ubuntu и Debian

bash
sudo apt update
sudo apt install -y wireguard-tools

AlmaLinux и Rocky Linux

bash
sudo dnf install -y epel-release
sudo dnf install -y wireguard-tools
Совет: это работает на версии 9 — там ядро уже включает поддержку WireGuard нативно. На версии 8 дополнительно понадобится модуль ядра из ELRepo:
bash
sudo dnf install -y https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
sudo dnf install -y kmod-wireguard
Проверьте: ссылка на пакет elrepo-release привязана к конкретному релизу и со временем может смениться — если команда выше не сработает, актуальную ссылку для своей версии ищите на elrepo.org.

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

bash
wg --version

Шаг 2. Сгенерируйте ключи сервера и клиента

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

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

bash
sudo mkdir -p /etc/wireguard/client
sudo chmod 700 /etc/wireguard /etc/wireguard/client

Сгенерируйте пару ключей сервера:

bash
sudo sh -c 'umask 077; wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key'

И пару ключей клиента:

bash
sudo sh -c 'umask 077; wg genkey | tee /etc/wireguard/client/client_private.key | wg pubkey > /etc/wireguard/client/client_public.key'
  • wg genkey печатает в stdout случайный приватный ключ; tee сохраняет его в файл и одновременно пропускает дальше по конвейеру; wg pubkey вычисляет из приватного ключа соответствующий публичный.
  • umask 077 перед созданием файлов гарантирует права 600 (чтение и запись только для root) — приватные ключи не должны быть доступны на чтение никому, кроме владельца.

Публичные ключи понадобятся на следующих шагах:

bash
sudo cat /etc/wireguard/server_public.key
sudo cat /etc/wireguard/client/client_public.key
Важно: приватные ключи (server_private.key, client_private.key) остаются каждый на своей стороне — сервер использует только свой, клиент — только свой. Копировать приватный ключ на другую сторону не нужно и небезопасно; публичные ключи, наоборот, секретными не являются и передаются открыто.

Шаг 3. Настройте сервер: wg0.conf

Определите, через какой сетевой интерфейс сервер выходит в интернет, — он понадобится в правилах NAT ниже:

bash
ip route get 1.1.1.1

В выводе будет строка вида 1.1.1.1 via <шлюз> dev eth0 src <IP сервера> — имя после dev (часто eth0, но встречаются и ens3, enp1s0 и похожие) и есть нужный интерфейс. В примерах ниже используется eth0 — замените на своё значение, если оно другое.

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

bash
sudo nano /etc/wireguard/wg0.conf
ini
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# client
PublicKey = <CLIENT_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32
  • Address — адрес самого сервера в VPN-подсети 10.8.0.0/24.
  • ListenPort — UDP-порт, на котором WireGuard принимает подключения; стандартный для WireGuard порт — 51820, откроем его в firewall на шаге 6.
  • PrivateKey — замените <SERVER_PRIVATE_KEY> на содержимое /etc/wireguard/server_private.key.
  • PostUp/PostDown — команды bash, которые выполняются при поднятии и опускании интерфейса (%i разворачивается в имя интерфейса — wg0): разрешают перенаправление пакетов между туннелем и основным интерфейсом (iptables -A FORWARD) и подменяют исходный адрес клиента на адрес сервера при выходе в интернет (MASQUERADE в таблице nat) — без этого ответные пакеты извне не найдут дороги обратно в приватную подсеть 10.8.0.0/24.
  • [Peer] — публичный ключ клиента и его адрес в туннеле (AllowedIPs): одновременно и разрешение принимать пакеты от этого клиента, только если они пришли с 10.8.0.2, и маршрут — пакеты для 10.8.0.2 сервер направит именно этому клиенту.

Ограничьте права на файл — в нём лежит приватный ключ сервера:

bash
sudo chmod 600 /etc/wireguard/wg0.conf
Совет (AlmaLinux/Rocky): на некоторых минимальных шаблонах команды iptables в системе может не быть — если на следующем шаге появится ошибка iptables: command not found, поставьте пакет sudo dnf install -y iptables-nft.

Шаг 4. Включите интерфейс WireGuard

bash
sudo systemctl enable --now wg-quick@wg0

Команда сразу поднимает интерфейс wg0 (по сути выполняет wg-quick up wg0, включая ваши PostUp-правила) и включает автозапуск при перезагрузке сервера — имя юнита wg-quick@wg0 собирается из имени файла /etc/wireguard/wg0.conf.

Проверьте, что всё поднялось:

bash
sudo systemctl status wg-quick@wg0
sudo wg show

wg show должен показать интерфейс wg0, порт 51820 и добавленного клиента в списке peer — пока без latest handshake, оно появится, когда клиент реально подключится (шаг 7).

Важно: если правите wg0.conf уже после первого запуска, sudo systemctl restart wg-quick@wg0 пересоздаст интерфейс с нуля и на секунду разорвёт все текущие соединения. Чтобы применить изменения без разрыва, используйте sudo wg syncconf wg0 <(sudo wg-quick strip wg0) — эта команда применит только изменившиеся параметры, не пересоздавая интерфейс.

Шаг 5. Включите IP-форвардинг

Без этой настройки ядро вообще не будет перенаправлять пакеты между интерфейсом wg0 и внешним интерфейсом сервера, и PostUp-правила из шага 3 не будут иметь эффекта. Включите форвардинг постоянно — отдельным файлом в /etc/sysctl.d/:

bash
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

Проверьте значение:

bash
sysctl net.ipv4.ip_forward
Готово: команда должна вывести net.ipv4.ip_forward = 1.

Шаг 6. Откройте порт WireGuard в ufw

WireGuard слушает UDP, а не TCP, — не перепутайте протокол при открытии порта. Подробнее про сам ufw — в статье «Файрвол ufw: порты».

bash
sudo ufw allow 51820/udp
sudo ufw status
Готово: в выводе sudo ufw status — строка с портом 51820/udp и статусом ALLOW, а Status: active подтверждает, что firewall включён.
На AlmaLinux/Rocky Linux по умолчанию используется firewalld, а не ufw — команды другие (firewall-cmd); откройте порт 51820/udp соответствующим способом, эта статья firewalld не рассматривает.

Шаг 7. Настройте клиента и проверьте подключение

Создайте конфиг клиента — по тому же пути, куда его кладёт готовый рецепт:

bash
sudo nano /etc/wireguard/client/client.conf
ini
[Interface]
Address = 10.8.0.2/24
PrivateKey = <CLIENT_PRIVATE_KEY>
DNS = 1.1.1.1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = 203.0.113.10:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
  • PrivateKey — содержимое /etc/wireguard/client/client_private.key.
  • PublicKey в [Peer] — содержимое /etc/wireguard/server_public.key.
  • Endpoint — публичный IP-адрес (или домен) вашего сервера и порт 51820; вместо 203.0.113.10 подставьте свой.
  • AllowedIPs = 0.0.0.0/0 направляет через туннель весь трафик клиента — полноценный VPN, а не доступ только к подсети сервера. Если нужен именно доступ к внутренней подсети 10.8.0.0/24 без маршрутизации всего остального трафика — укажите её вместо 0.0.0.0/0.
  • PersistentKeepalive = 25 — клиент отправляет keep-alive каждые 25 секунд; полезно, если клиент сам находится за NAT (домашний роутер, мобильная сеть), — без этого сервер может не суметь достучаться до клиента первым.
bash
sudo chmod 600 /etc/wireguard/client/client.conf
Совет: если при поднятии интерфейса на Ubuntu/Debian появится ошибка resolvconf: command not found — это из-за поля DNS, для которого нужен пакет resolvconf или openresolv. Поставьте его: sudo apt install -y openresolv.

Перенесите файл на клиентское устройство, например через scp (команда выполняется с самого клиентского устройства, замените 203.0.113.10 на IP своего сервера):

bash
scp root@203.0.113.10:/etc/wireguard/client/client.conf .
  • Если клиент — тоже Linux: скопируйте файл в /etc/wireguard/wg0.conf и включите интерфейс так же, как на сервере — sudo systemctl enable --now wg-quick@wg0.
  • Если клиент — официальное приложение WireGuard для Windows, macOS, iOS или Android: импортируйте client.conf через «Импорт туннеля из файла». Для телефона зачастую проще отсканировать QR-код: sudo apt install -y qrencode, затем qrencode -t ansiutf8 < /etc/wireguard/client/client.conf.
Важно: после того как передали client.conf на устройство клиента, удалите приватный ключ клиента с сервера (sudo rm /etc/wireguard/client/client_private.key) — серверу он для работы не нужен, а хранить лишнюю копию чужого приватного ключа незачем.

Включите туннель на клиенте и проверьте на сервере, что рукопожатие состоялось:

bash
sudo wg show wg0
interface: wg0
  public key: <SERVER_PUBLIC_KEY>
  private key: (hidden)
  listening port: 51820

peer: <CLIENT_PUBLIC_KEY>
  endpoint: 198.51.100.20:51280
  allowed ips: 10.8.0.2/32
  latest handshake: 1 minute, 5 seconds ago
  transfer: 1.42 KiB received, 4.68 KiB sent
Готово: строка latest handshake означает, что клиент успешно подключился и туннель работает. Проверить, что трафик действительно идёт через сервер, можно командой curl ifconfig.me на клиенте — в ответ должен прийти публичный IP-адрес сервера, а не клиента.

Что дальше

Чтобы добавить ещё одного клиента: повторите шаг 2 для новой пары ключей, добавьте в wg0.conf сервера ещё один блок [Peer] со свободным адресом в подсети (например, 10.8.0.3/32) и примените изменения без разрыва туннеля — sudo wg syncconf wg0 <(sudo wg-quick strip wg0) (см. шаг 4). Конфиг для нового клиента создайте по аналогии с шагом 7, под своим именем (например, client2.conf).

Нужен более привычный вариант VPN вместо WireGuard? В VMmanager 6 есть готовый рецепт Openvpn — см. статью «OpenVPN: сервер и клиенты».