Публичный IP каждого VPS виден всему интернету, и порты баз данных, Redis и внутренних API приходится закрывать firewall-правилами вручную на каждом сервере. WireGuard mesh решает это иначе: серверы получают приватные адреса в отдельной подсети 10.x.x.x, трафик между ними шифруется на лету, а порты внутренних сервисов можно вообще не открывать наружу.
Зачем нужна приватная сеть между VPS
Когда приложение и база данных живут на разных серверах, соединение между ними по умолчанию идёт через публичный интернет. Даже с паролем и TLS это лишняя поверхность атаки: сканеры находят открытый порт 5432 или 6379 за минуты. Приватная сеть убирает эту проблему — сервис слушает только адрес 10.10.0.x, а публичный интерфейс порт вообще не открывает.
Второй повод — объединить серверы в разных дата-центрах и даже у разных провайдеров в одну логическую сеть. WireGuard работает поверх обычного UDP, поэтому ему всё равно, находятся узлы в одном дата-центре Hetzner или в разных странах: важна только доступность порта 51820 между ними.
Mesh или hub-and-spoke: какую топологию выбрать
Полносвязная mesh-сеть
Каждый узел хранит публичные ключи всех остальных и держит с ними прямой туннель. Трафик между любыми двумя серверами идёт кратчайшим путём, без промежуточных узлов. Цена — конфигурация растёт квадратично: для 5 серверов нужно настроить 10 пар ключей, для 10 — уже 45.
Топология hub-and-spoke через один узел
Все серверы подключаются только к одному центральному узлу, а он маршрутизирует трафик между ними. Конфигурация каждого peer одинаковая и не меняется при добавлении новых узлов, но центральный сервер становится точкой отказа и узким местом по пропускной способности.
| Критерий | Mesh | Hub-and-spoke |
|---|---|---|
| Задержка между узлами | Минимальная, напрямую | Через центральный узел |
| Точка отказа | Нет единой точки | Центральный узел — SPOF |
| Сложность конфигурации | Растёт квадратично | Постоянная для любого числа узлов |
| Подходит для числа серверов | До 10-15 | Больше 15 |
Установка WireGuard на серверах
Модуль WireGuard входит в ядро Linux начиная с версии 5.6, а пакет wireguard-tools ставится одной командой на всех современных дистрибутивах.
apt update && apt install -y wireguard
umask 077
wg genkey | tee privatekey | wg pubkey > publickey
cat privatekey
Пару ключей нужно сгенерировать на каждом узле отдельно — приватный ключ никогда не покидает свой сервер, между узлами передаются только публичные ключи.
Конфигурация mesh на трёх узлах
Файл /etc/wireguard/wg0.conf на первом узле описывает собственный адрес в приватной подсети и по одной секции [Peer] на каждый другой узел сети.
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = <приватный ключ узла 1>
[Peer]
PublicKey = <публичный ключ узла 2>
Endpoint = 203.0.113.2:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25
PersistentKeepalive обязателен, если хотя бы один из узлов сидит за NAT — без него туннель разрывается через несколько минут простоя. После правки конфигурации на всех трёх узлах интерфейс поднимается одной командой.
systemctl enable --now wg-quick@wg0
wg show wg0
Маршрутизация и firewall для приватной подсети
Как только интерфейс wg0 поднят на всех узлах, сервисы можно перевести на прослушивание приватного адреса вместо 0.0.0.0. Postgres, Redis и внутренние API конфигурируются на bind-адрес 10.10.0.x, а правило firewall открывает порт только для подсети 10.10.0.0/24, а не для всего интернета.
Серверы для mesh-сети удобно поднимать сразу с нужным набором сетевых интерфейсов — например, через API Hetzner Cloud, где приватная сеть между VPS настраивается на этапе создания. Поверх готового mesh-туннеля уже можно ставить Consul для service discovery — агенты будут общаться по адресам 10.10.0.x, не завися от смены публичных IP.
Диагностика: проверка соединения между узлами
Если пинг между приватными адресами не проходит, порядок диагностики почти всегда один и тот же.
- wg show wg0 — проверить, что у обоих узлов ненулевой latest handshake, а не только настроен peer.
- Открыт ли порт 51820/udp в firewall провайдера и в iptables/nftables на самом сервере.
- Совпадают ли публичные ключи в конфигурации peer с реальными ключами соседнего узла — опечатка не даёт никакой ошибки, просто handshake не проходит.
- AllowedIPs указывает именно на нужную подсеть, а не перекрывает 0.0.0.0/0 и не уводит через себя весь трафик узла.