ГлавнаяСтатьиПроект YvixSlideCraft

WireGuard: быстрый VPN между Linux-хостами

WireGuard — современный VPN, который живёт прямо в ядре Linux (с версии 5.6). Он использует протокол Noise, криптографию Curve25519, ChaCha20-Poly1305 и BLAKE2s, а его код в десятки раз меньше, чем у IPsec или OpenVPN. Отсюда главные плюсы: простота настройки, высокая скорость и «роуминг» — клиент может менять IP-адрес, и соединение восстановится само.

В отличие от IP-IP, WireGuard шифрует и аутентифицирует весь трафик, поэтому подходит не только для связки сетей, но и для удалённого доступа.

Как работает маршрутизация

У WireGuard нет понятий «клиент» и «сервер» в классическом смысле — это одноранговая сеть (peer-to-peer). Каждый узел имеет пару ключей, а маршрутизация задаётся списком AllowedIPs:

Такую схему называют cryptokey routing.

Схема сети

 Офис A: 10.0.1.0/24                      Офис B: 10.0.2.0/24
        |                                        |
   [ Router A ] ---------- WireGuard --------- [ Router B ]
   WAN: 203.0.113.10                      WAN: 198.51.100.20
   wg0: 10.77.0.1/24                      wg0: 10.77.0.2/24

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

apt install wireguard-tools   # Debian/Ubuntu
dnf install wireguard-tools   # Fedora/RHEL

Шаг 1. Генерируем ключи

На каждом маршрутизаторе создаём приватный ключ и из него — публичный. Приватный ключ никуда не передаём.

На Router A:

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

То же самое на Router B. Сохраните вывод cat .../public.key — эти ключи понадобятся в конфигах напротив.

Шаг 2. Пишем конфигурацию

Файл /etc/wireguard/wg0.conf на Router A:

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

[Peer]
PublicKey = <публичный-ключ-B>
Endpoint = 198.51.100.20:51820
AllowedIPs = 10.77.0.2/32, 10.0.2.0/24
PersistentKeepalive = 25

Файл /etc/wireguard/wg0.conf на Router B:

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

[Peer]
PublicKey = <публичный-ключ-A>
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.77.0.1/32, 10.0.1.0/24
PersistentKeepalive = 25

Разберём параметры:

Файл содержит приватный ключ, поэтому ограничьте права:

chmod 600 /etc/wireguard/wg0.conf

Шаг 3. Включаем маршрутизацию

Чтобы трафик ходил между wg0 и локальной сетью, включаем форвардинг (на обоих маршрутизаторах):

echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-ip-forward.conf
sysctl --system

Шаг 4. Поднимаем туннель

wg-quick up wg0

Проверяем:

wg show
ip addr show wg0
ping -c 3 10.77.0.2

wg show выводит ключи, endpoint и статистику, а строка latest handshake показывает, что рукопожатие прошло.

Шаг 5. Маршруты до удалённых сетей

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

ip route

На Router A должна появиться запись вида 10.0.2.0/24 dev wg0 scope link. Добавлять её вручную не нужно — wg-quick делает это из AllowedIPs.

Шаг 6. Настраиваем nftables

Разрешаем UDP-порт WireGuard на внешнем интерфейсе и форвардинг между локальной сетью и туннелем. На Router A (/etc/nftables.conf):

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;

        iif "lo" accept
        ct state established,related accept

        # WireGuard только от соседнего маршрутизатора
        iifname "wan0" ip saddr 198.51.100.20 udp dport 51820 accept

        # SSH для управления (сузьте источник под себя)
        iifname "wan0" ip saddr 203.0.113.0/24 tcp dport 22 accept

        counter drop
    }

    chain forward {
        type filter hook forward priority filter; policy drop;

        ct state established,related accept

        # Разрешаем трафик между локальной сетью и туннелем
        iifname "lan0" oifname "wg0" accept
        iifname "wg0" oifname "lan0" accept

        counter drop
    }
}

Применяем:

nft -f /etc/nftables.conf

Если одна из сетей «за NAT» и у неё нет обратного маршрута, добавьте маскарадинг:

table inet nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        iifname "lan0" oifname "wg0" masquerade
    }
}

Шаг 7. Автозапуск

wg-quick поставляется с systemd-юнитом, который поднимает интерфейс по имени:

systemctl enable --now wg-quick@wg0

Сделайте это на обоих узлах. Конфиг, sysctl и правила nftables при этом уже должны быть на месте.

Полезные команды

wg show                         # общая информация и пиры
wg show wg0 latest-handshakes   # когда был последний handshake
wg-quick down wg0               # опустить интерфейс

Безопасность

Заключение

WireGuard даёт шифрованный туннель с минимумом настроек: сгенерировал ключи, описал пиров, поднял wg-quick — и готово. Для связки сетей это сегодня, пожалуй, лучший баланс между простотой и безопасностью.