WireGuard Hub-and-Spoke для 3 офісів через центральний шлюз

Було корисно?

Ваші три офіси не можуть «просто VPN-ом з’єднатися». Один знаходиться за подвійним NAT, інший має «дружній» роутер від провайдера, до якого вам не дозволено торкатися, а третій — той, в якому серверна кімната ще й зберігає різдвяні прикраси. Але всі очікують спільні сервіси, стабільний VoIP і мережеве сховище, яке не здається розміщеним на тостері.

Модель hub-and-spoke на базі WireGuard дає передбачувану маршрутизацію, не перетворюючи вашу мережу на інтерпретативне мистецтво. Вона залишається передбачуваною лише якщо поважати, як WireGuard фактично працює: це захищений UDP-тунель із прикріпленою таблицею маршрутизації. Якщо ставитися до нього як до магічного «прапорця VPN», він чемно дозволить вам неправильно надсилати пакети до того дня, коли ви в чергуванні.

Виберіть топологію та чесно оцініть обмеження

Hub-and-spoke означає: кожен офіс (спок) будує тунель WireGuard лише до центрального шлюзу (хабу). Хаб маршрутизує трафік між споками. Споки ніколи не повинні стикатися безпосередньо — у цьому вся суть: менше тунелів, простіше керування ключами, менше дір у фаєрволі, менше сюрпризів.

Це не єдина модель. Існує повна mesh-мережа, але вона масштабується як груповий чат, де всі можуть відповісти всім. Для трьох офісів ви можете зробити mesh, але вам все одно знадобиться центральна точка керування політиками, логуванням і питанням «хто з ким може спілкуватися». Hub-and-spoke перемагає в корпоративній реальності: централізований контроль виходу в інтернет, централізоване спостереження і лише одне місце для застосування політик «ні, принтери не повинні зв’язуватися з фінансами».

Яким має бути хаб

  • Стабільна публічна кінцева точка (статична IP або стабільний DNS, але відносіться до збоїв DNS серйозно).
  • Роутер із Linux IP-форвардингом, фаєрволом і бажано nftables або iptables під вашим контролем.
  • Сервер з операційною гігієною: синхронізація часу, логи, бекапи, контроль змін і чіткий власник.

Якими мають бути споки

  • Пристрій, який може запускати WireGuard і маршрутизувати LAN (Linux, підтримуване роутерне дистрибутивне ПЗ або невеликий апарат).
  • Послідовність: один інтерфейс для WAN, один для LAN, один для WireGuard. Не ускладнюйте.
  • Відомі LAN-підмережі (без перекриттів). Перекриття — це спосіб, як «тимчасові фікси» стають постійними аваріями.

Визначте на початку, чи буде хаб також «виходом в інтернет» для споків (споки маршрутизують 0.0.0.0/0 через хаб), або хаб лише маршрутизує між офісами. Для трьох офісів зазвичай спочатку роблять лише міжофісну маршрутизацію; централізований вихід в інтернет можна додати пізніше, коли будете готові нести супорт.

Жарт №1: VPN hub-and-spoke — як корпоративна організаційна схема: усі звітують у центр, а центр усе життя витрачає на маршрутизацію скарг.

Цікаві факти (і чому вони важливі в експлуатації)

  • WireGuard навмисно мінімалістичний. Він не узгоджує купу алгоритмів і не підтримує зоопарк шифрів; використовує невеликий сучасний набір, щоб зменшити кількість помилок у конфігурації та поверхню атак.
  • Він використовує фреймворк Noise. Це не дрібниця; пояснює, чому рукостискання швидкі і чому стан легший у порівнянні зі старими VPN-стеками.
  • WireGuard працює в ядрі Linux. Ось чому продуктивність загалом відмінна і чому вам слід дбати про оновлення ядра та регресії, як про будь-яку іншу зміну в datapath.
  • «AllowedIPs» одночасно ACL і маршрути. Багато збоїв виникає через те, що забувають: це поле визначає, які маршрути встановлюються і який трафік приймається від піра.
  • Роумінг — це первинна поведінка. Піри можуть змінювати IP/порт відправника; WireGuard вчиться новій кінцевій точці після автентифікованого трафіку, що ідеально для офісів за NAT — аж поки немає keepalive.
  • Це UDP. Отже воно проходить через багато мереж, але це також означає, що stateful-фаєрволи і таймаути NAT — ваші проблеми.
  • Немає вбудованої «авторизації користувачів». Це ключі між машинами. Якщо потрібен доступ на рівні користувача — робіть це в іншому шарі (або окремою системою).
  • WireGuard молодший за IPsec. IPsec має десятиліття шрамів та сумісні проблеми. WireGuard має менше ручок, менше підводних каменів і менше «але постачальник сказав…» зустрічей.
  • Малі конфіги — це перевага. Коли всю конфігурацію VPN можна вмістити на одну сторінку, відладка у чергуванні раптово стає терпимою.

Одна перефразована ідея від Werner Vogels (CTO Amazon) досі працює в експлуатації: все рано чи пізно ламається; проектуйте так, щоб відновлення було рутинним і нудним. Це менталітет для VPN теж: припускайте, що NATи перезавантажуються, лінки флапають, а хтось редагує не той файл о 2:00 ночі.

План адресації та модель маршрутизації

Почніть з плану адресації. Якщо його пропустити, ви заплатите пізніше з відсотками.

Приклад мережевого плану (три офіси + хаб)

  • Office A LAN: 10.10.10.0/24
  • Office B LAN: 10.10.20.0/24
  • Office C LAN: 10.10.30.0/24
  • WireGuard transit network: 10.99.0.0/24 (лише для IP-адрес інтерфейсів тунелю)
  • Hub wg0: 10.99.0.1/24
  • Spoke A wg0: 10.99.0.11/32
  • Spoke B wg0: 10.99.0.12/32
  • Spoke C wg0: 10.99.0.13/32

Використовуйте /32-адреси для пірів на інтерфейсі тунелю і тримайте транзитну мережу окремо від офісних LAN. Хочете, щоб «дріт» був окремим всесвітом. І не використовуйте RFC1918 діапазони, які вже застосовані в офісах. Перекриття приватних підмереж — корпоративний еквівалент «ми все вирішимо на ходу».

Намір маршрутизації

Ваш намір у hub-and-spoke простий:

  • Споки знають: «щоб дістатися до LAN інших офісів, відправляй трафік у wg0.»
  • Хаб знає: «щоб дістатися до LAN кожного офісу, відправляй трафік через wg0 до відповідного піра.»
  • Клієнти в LAN кожного офісу знають: «для підмереж інших офісів шлюз за замовчуванням — офісний роутер.»

Ось і все. Немає NAT між офісами, якщо тільки у вас немає перекриттів підмереж, які ви не можете виправити (і якщо не можете — заплануйте час, щоб це виправити). NAT приховує проблеми і ускладнює їх діагностику, бо стирає ідентичність джерела — саме те, що треба зберегти для аудиту й політик безпеки.

Конфігурація хаба: центральний шлюз

Припустимо, хаб — це Linux VM у датацентрі або хмарі з публічною IP. Назвемо його wg-hub-1. Він має:

  • eth0 = публічний/WAN інтерфейс
  • wg0 = WireGuard інтерфейс

Встановіть WireGuard

На сучасних дистрибутивах це пакунок і модуль ядра, який уже є. Тримайте все буденно.

Згенеруйте ключі

Робіть це на хабі та на кожному споку; ніколи не копіюйте приватні ключі через чат або коментарі в тікетах. Ставтесь до них як до root-паролів.

Хаб: /etc/wireguard/wg0.conf

Цей приклад маршрутизує три офісні підмережі. Хаб буде єдиною налаштованою кінцевою точкою; споки вкажуть на нього.

cr0x@server:~$ sudo sed -n '1,200p' /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = HUB_PRIVATE_KEY_REDACTED
SaveConfig = false

# Enable NAT only if you want spokes to reach the hub's WAN or internet via hub.
# For pure site-to-site, you typically do not NAT between offices.
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = nft add table inet wg; nft 'add chain inet wg forward { type filter hook forward priority 0; policy drop; }'
PostUp = nft add rule inet wg forward iif "wg0" oif "wg0" accept
PostUp = nft add rule inet wg forward iif "wg0" oif "eth0" accept
PostUp = nft add rule inet wg forward iif "eth0" oif "wg0" ct state established,related accept
PostDown = nft delete table inet wg

[Peer]
PublicKey = SPOKE_A_PUBLIC_KEY_REDACTED
AllowedIPs = 10.99.0.11/32, 10.10.10.0/24
PersistentKeepalive = 25

[Peer]
PublicKey = SPOKE_B_PUBLIC_KEY_REDACTED
AllowedIPs = 10.99.0.12/32, 10.10.20.0/24
PersistentKeepalive = 25

[Peer]
PublicKey = SPOKE_C_PUBLIC_KEY_REDACTED
AllowedIPs = 10.99.0.13/32, 10.10.30.0/24
PersistentKeepalive = 25

Примітки, які не варто пропускати:

  • AllowedIPs на хабі фактично є таблицею маршрутизації хаба для споків. Якщо вона неправильна, хаб або загубить трафік, або доставить неправильно.
  • PersistentKeepalive на хабі не завжди обов’язковий, але допомагає зберегти NAT-міпінги на віддаленій стороні. У реальності філій таймаути NAT завершуються, коли ви відволікаєтесь.
  • SaveConfig=false запобігає запису змін у runtime назад у файл. Це уникає ситуацій «хтось використав wg set і тепер файл бреше».
  • Правила nftables наведенні вище навмисно суворіші. Багато налаштувань «приймають весь forward», і це нормально, поки VPN не стане неконтрольованим транзитом для всього.

Увімкніть і запустіть

Використовуйте systemd-юнити для послідовності. Потрібне автоматичне відновлення при завантаженні без кастомних скриптів.

Конфігурація споків: кожен офісний роутер

Кожен офіс має роутер/фаєрвол (Linux) з:

  • eth0 = WAN-лінк до роутера/модема ISP
  • eth1 = LAN до офісного комутатора
  • wg0 = WireGuard тунель до хаба

Spoke A: /etc/wireguard/wg0.conf

cr0x@server:~$ sudo sed -n '1,200p' /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.11/32
PrivateKey = SPOKE_A_PRIVATE_KEY_REDACTED
ListenPort = 51820
SaveConfig = false

PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = nft add table inet wg; nft 'add chain inet wg forward { type filter hook forward priority 0; policy drop; }'
PostUp = nft add rule inet wg forward iif "eth1" oif "wg0" accept
PostUp = nft add rule inet wg forward iif "wg0" oif "eth1" ct state established,related accept
PostUp = nft add rule inet wg forward iif "wg0" oif "wg0" accept
PostDown = nft delete table inet wg

[Peer]
PublicKey = HUB_PUBLIC_KEY_REDACTED
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.99.0.1/32, 10.10.20.0/24, 10.10.30.0/24
PersistentKeepalive = 25

Spoke B і C ідентичні, крім Address і офісних LAN у AllowedIPs, які мають включати «інші офіси», а не власний LAN. Ви можете також включити адресу wg хаба, щоб пінгувати хаб.

Два правила для споків:

  1. Не ставте 0.0.0.0/0 в AllowedIPs, якщо ви навмисно не примушуєте весь трафік іти через хаб (централізований вихід). Не «тестуйте» це в продакшні і не забувайте.
  2. Не робіть NAT для міжофісного трафіку. Якщо вам потрібен NAT, щоб щось «працювало», швидше за все, ви неправильно маршрутизуєте.

Маршрутизація, NAT і правила фаєрвола без сюрпризів

WireGuard не робить маршрутизацію за вас; він лише шифрує трафік, який ви маршрутизуєте в нього. Linux маршрутизує на основі:

  • адрес інтерфейсів (connected routes),
  • маршрутів, які додає wg-quick з AllowedIPs, та/або
  • ваших явних статичних маршрутів.

Віддавайте перевагу явній маршрутизації над хитрістью

Коли ви піднімаєте wg0 через wg-quick, він зазвичай додає маршрути для AllowedIPs. Це зручно, але ви маєте точно розуміти, які маршрути існують і чому. Зручність перетворюється на таємницю під час аварії.

Форвардинг: три ворота

Щоб пакети пройшли з LAN офісу A до LAN офісу B через хаб, має бути істинним три речі:

  1. Клієнти офісу A відправляють трафік на свій локальний роутер (шлюз за замовчуванням).
  2. Роутер спока A форвардить у wg0 і шифрує до хаба.
  3. Хаб форвардить з wg0 до wg0 (до іншого піра) на основі маршрутизації.

Кожен пристрій потребує:

  • увімкнений IP-форвардинг (net.ipv4.ip_forward=1)
  • правила фаєрвола, які дозволяють шлях форвардингу
  • маршрути для віддалених LAN

Коли потрібен NAT

Є лише кілька причин для NAT у цій архітектурі:

  • Централізований вихід в інтернет. Споки маршрутизують 0.0.0.0/0 через хаб, хаб робить NAT на публічний інтерфейс.
  • Перекриття підмереж, які ви не можете перенумерувати. Ви все одно маєте планувати перенумерацію, але іноді бувають злиття, апаратні рішення або системи автоматизації будівлі, які не хочуть рухатися.
  • Тимчасова міграція. Використовуйте NAT як допоміжну опору з датою закінчення, а не як архітектурне рішення.

Якщо ви NATите між офісами за замовчуванням, рано чи пізно зламаєте щось, що покладається на IP джерела (ACL, логування, правила SMB, правила VoIP SBC). Гірше: ви втратите здатність відповісти «хто отримав доступ до цієї системи?» без розслідування трансляцій пакетів.

MTU, фрагментація та чому «в мене працює» — не метрика

Проблеми з MTU — найпоширеніша причина «встановлено з’єднання, але щось висне» у site-to-site WireGuard. Тунель додає накладні байти. Якщо ви передаєте пакети, що занадто великі для якогось сегмента шляху, вони фрагментуються або відкидаються, і ви отримаєте помилки, що виглядають як баги в додатках.

WireGuard інкапсулює IP в UDP. Типовий наклад — близько 60 байт (варіюється). Якщо WAN MTU = 1500, безпечний MTU для WireGuard часто 1420. Багато дистрибутивів за замовчуванням ставлять 1420 на wg-інтерфейси з цієї причини.

Але не можна припускати 1500 на WAN. PPPoE часто має 1492. Деякі LTE/5G траси поводяться по-іншому. Деякі провайдери роблять дивні речі з ICMP, що ламає PMTU discovery і робить усе «майже працездатним».

Жарт №2: Помилки MTU — доросла версія натрапляння на LEGO: усе болить, і ви не відразу можете довести причину.

Моя продукційна позиція щодо MTU

  • Встановлюйте MTU = 1420 на wg0, якщо немає вимірюваних підстав робити інакше.
  • Якщо бачите зависання під час великих передавань або деяких сайтів/сервісів, агресивно тестуйте PMTU і налаштовуйте.
  • Не вимикайте ICMP глобально. Ви не «підвищуєте захист», ви зав’язуєте очі.

Спостереження: що логувати, що графати

VPN, що «працює», але не піддається відлагодженню, — це майбутня аварія, за яку ви вже заплатили. Для hub-and-spoke інструментуйте хаб як продакшн-маршрутизуючу інфраструктуру — бо так воно і є.

Що стежити на хабі

  • Позначки часу рукостискань по кожному пірі. Пір, який не робив handshake годинами — або просто бездіяльний (нормально), або помер (не нормально). Корелюйте з лічильниками трафіку.
  • Лічильники RX/TX байтів. Раптове падіння до нуля в робочі години означає, що хтось поламав маршрутизацію або фаєрвол.
  • CPU softirq і NIC drops. Рідко для трьох офісів, але якщо VM хаба мала або перевантажена, ви це побачите.
  • Лічильники фаєрвола. Якщо ви не рахуєте drop-и, ви будете сваритися з собою о 3 ранку.
  • Дрег часу системи. Крипто та час-залежні handshake-и не люблять подорожі в часі.

Логи: будьте вибіркові

WireGuard сам по собі тихий. Це добре. Не намагайтесь «логувати кожен пакет». Замість цього:

  • логувати події підняття/опускання інтерфейсу,
  • логувати відмови фаєрвола з вибіркою або переглядати лічильники правил,
  • зберігати історію змін конфігів і оновлень ядра.

Практичні завдання: команди, виводи й рішення

Це реальні завдання, які ви виконаєте в продакшні. Кожне містить команду, приклад виводу, що це означає і яке рішення прийняти. Використовуйте їх на хабі і на споках. Послідовність рятує від аварій.

Завдання 1: Перевірити стан інтерфейсу WireGuard

cr0x@server:~$ sudo wg show
interface: wg0
  public key: 3kN9...REDACTED
  listening port: 51820

peer: zZp2...REDACTED
  endpoint: 198.51.100.24:60433
  allowed ips: 10.99.0.11/32, 10.10.10.0/24
  latest handshake: 1 minute, 12 seconds ago
  transfer: 1.42 GiB received, 1.87 GiB sent
  persistent keepalive: every 25 seconds

Значення: Тунель піднятий настільки, щоб робити handshake; endpoint показує, де зараз пір (очікується NATed порт). Лічильники transfer підтверджують реальний трафік.

Рішення: Якщо latest handshake — «never» або застарілий під час скарг користувачів, одразу переходьте до перевірки доступності firewall/NAT і маршрутів.

Завдання 2: Підняти інтерфейс і підтвердити статус systemd

cr0x@server:~$ sudo systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
     Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; preset: enabled)
     Active: active (exited) since Sat 2025-12-27 10:11:02 UTC; 7min ago
       Docs: man:wg-quick(8)
             man:wg(8)
    Process: 1724 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)

Значення: wg-quick — одноразовий; «active (exited)» — нормально. Він не зазнав помилки під час створення інтерфейсу.

Рішення: Якщо статус failed, читайте journal на предмет синтаксичних помилок або відсутнього модуля ядра перед тим, як робити інші зміни в мережі.

Завдання 3: Переглянути логи wg-quick на помилки

cr0x@server:~$ sudo journalctl -u wg-quick@wg0 -n 50 --no-pager
Dec 27 10:11:02 wg-hub-1 wg-quick[1724]: [#] ip link add wg0 type wireguard
Dec 27 10:11:02 wg-hub-1 wg-quick[1724]: [#] wg setconf wg0 /dev/fd/63
Dec 27 10:11:02 wg-hub-1 wg-quick[1724]: [#] ip -4 address add 10.99.0.1/24 dev wg0
Dec 27 10:11:02 wg-hub-1 wg-quick[1724]: [#] ip link set mtu 1420 up dev wg0
Dec 27 10:11:02 wg-hub-1 wg-quick[1724]: [#] sysctl -w net.ipv4.ip_forward=1

Значення: Інтерфейс створено, MTU встановлено, форвардинг увімкнено. Якщо ви не бачите встановлення MTU, можливо, ви покладаєтесь на значення за замовчуванням — це нормально, але майте це на увазі.

Рішення: Якщо логи показують «RTNETLINK answers: File exists» або помилки nft, у вас залишився старий стан. Очистьте і перезапустіть чисто.

Завдання 4: Підтвердьте, що форвардинг дійсно увімкнено

cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Значення: Ядро буде форвардити IPv4-пакети. Без цього ваш VPN стане дорогим іграшковим ping-ом.

Рішення: Якщо значення = 0, увімкніть його постійно в /etc/sysctl.d/ і не сподівайтесь, що воно «запам’ятається».

Завдання 5: Перевірити, що на хабі існують маршрути до офісних підмереж

cr0x@server:~$ ip route show | egrep '10\.10\.(10|20|30)\.0/24|10\.99\.0\.0/24'
10.10.10.0/24 dev wg0 scope link
10.10.20.0/24 dev wg0 scope link
10.10.30.0/24 dev wg0 scope link
10.99.0.0/24 dev wg0 proto kernel scope link src 10.99.0.1

Значення: Хаб вважає, що всі офісні LAN досяжні через wg0. Це потрібно для маршрутизації хабом.

Рішення: Якщо маршрути відсутні, AllowedIPs для пірів на хабі помилкові або wg-quick не встановив маршрути (можуть втручатися політики маршрутизації).

Завдання 6: Перевірити маршрути на споку

cr0x@server:~$ ip route show | egrep '10\.10\.(20|30)\.0/24|wg0'
10.10.20.0/24 dev wg0 scope link
10.10.30.0/24 dev wg0 scope link
10.99.0.1 dev wg0 scope link

Значення: Spoke A надсилатиме трафік для офісів B і C у тунель.

Рішення: Якщо офісні підмережі маршрутизуються інакше (або не маршрутизуються), виправте AllowedIPs або додайте явні маршрути. Не «виправляйте» це NAT-ом.

Завдання 7: Підтвердити, що хаб може дістатися до кожного wg IP спока

cr0x@server:~$ ping -c 3 10.99.0.11
PING 10.99.0.11 (10.99.0.11) 56(84) bytes of data.
64 bytes from 10.99.0.11: icmp_seq=1 ttl=64 time=18.6 ms
64 bytes from 10.99.0.11: icmp_seq=2 ttl=64 time=18.4 ms
64 bytes from 10.99.0.11: icmp_seq=3 ttl=18.9 ms

--- 10.99.0.11 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms

Значення: Існує зашифрована зв’язність до роутера спока.

Рішення: Якщо це не вдається, але handshake є, перевірте фаєрвол спока (INPUT/FORWARD) на ICMP або чи спок присвоїв саме ту wg IP, яку ви очікували.

Завдання 8: Трасування маршруту з хаба до хоста в Office B

cr0x@server:~$ traceroute -n 10.10.20.50
traceroute to 10.10.20.50 (10.10.20.50), 30 hops max, 60 byte packets
 1  10.99.0.12  20.112 ms  20.098 ms  20.085 ms
 2  10.10.20.50  21.004 ms  20.992 ms  20.980 ms

Значення: Хаб маршрутизує до правильного спока (10.99.0.12), а потім до цільового хоста.

Рішення: Якщо перший хоп неправильний, у вас перекриття AllowedIPs на хабі (два піри претендують на ту ж підмережу) або відсутні маршрути.

Завдання 9: Перевірити перекриття AllowedIPs на хабі

cr0x@server:~$ sudo wg show wg0 allowed-ips
zZp2...REDACTED	10.99.0.11/32 10.10.10.0/24
aPq8...REDACTED	10.99.0.12/32 10.10.20.0/24
mK1r...REDACTED	10.99.0.13/32 10.10.30.0/24

Значення: Кожна офісна підмережа унікально приписана одному пірі. Це те, чого ви прагнете.

Рішення: Якщо два піри вказують ту ж підмережу, виправте це негайно; маршрутизація стане недетермінованою і у вас будуть «час від часу працює» тікети.

Завдання 10: Перевірити UDP доступність порту на хабі

cr0x@server:~$ sudo ss -ulnp | grep 51820
UNCONN 0      0            0.0.0.0:51820      0.0.0.0:*    users:(("wireguard",pid=1724,fd=3))

Значення: Хаб слухає UDP/51820.

Рішення: Якщо нічого не слухає, ваш інтерфейс не піднято або ви змінили порт і не перезапустили сервіс.

Завдання 11: Переглянути правила nftables і лічильники

cr0x@server:~$ sudo nft list table inet wg
table inet wg {
	chain forward {
		type filter hook forward priority filter; policy drop;
		iifname "wg0" oifname "wg0" counter packets 18392 bytes 24581231 accept
		iifname "wg0" oifname "eth0" counter packets 0 bytes 0 accept
		iifname "eth0" oifname "wg0" ct state established,related counter packets 2901 bytes 501832 accept
	}
}

Значення: Політика форвардингу — drop за замовчуванням; дозволені специфічні шляхи. Лічильники показують реальний міжофісний трафік (wg0→wg0).

Рішення: Якщо лічильники на wg0→wg0 залишаються нульовими під час скарг, хаб не форвардить — або маршрути неправильні, або трафік не доходить до хаба.

Завдання 12: Захопити трафік, щоб довести, чи пакети прибувають

cr0x@server:~$ sudo tcpdump -ni wg0 host 10.10.20.50 -c 5
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
10:22:18.114331 IP 10.10.10.25.53422 > 10.10.20.50.445: Flags [S], seq 13922311, win 64240, options [mss 1360,sackOK,TS val 2911221 ecr 0,nop,wscale 7], length 0
10:22:19.120482 IP 10.10.10.25.53422 > 10.10.20.50.445: Flags [S], seq 13922311, win 64240, options [mss 1360,sackOK,TS val 2912227 ecr 0,nop,wscale 7], length 0

Значення: Трафік прибуває на wg0 хаба з Office A в напрямку хоста Office B. Якщо немає SYN-ACK, або хост не відповідає, або трафік не пересилається далі коректно.

Рішення: Якщо ви бачите пакети на хабі, але вони не доходять до віддаленого офісу, перевірте маршрути хаба до правильного піра, потім форвардинг спока B і фаєрвол LAN B.

Завдання 13: Перевірити поведінку MTU за допомогою пінгів «не фрагментувати»

cr0x@server:~$ ping -M do -s 1372 -c 3 10.10.20.50
PING 10.10.20.50 (10.10.20.50) 1372(1400) bytes of data.
1372 bytes from 10.10.20.50: icmp_seq=1 ttl=63 time=22.1 ms
1372 bytes from 10.10.20.50: icmp_seq=2 ttl=63 time=22.0 ms
1372 bytes from 10.10.20.50: icmp_seq=3 ttl=63 time=21.8 ms

--- 10.10.20.50 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms

Значення: Пакет розміром 1400 байт доходить енд-ту-енд без фрагментації. Це добрий знак для TCP MSS.

Рішення: Якщо це дає «Frag needed», зменшіть MTU для wg (наприклад, до 1380) і повторіть тест, або дослідіть обмеження WAN MTU.

Завдання 14: Перевірити, що політика маршрутизації не підмінює трафік

cr0x@server:~$ ip rule show
0:	from all lookup local
32766:	from all lookup main
32767:	from all lookup default

Значення: Лише стандартні правила. Це добре, якщо ви свідомо не додавали складну маршрутизацію.

Рішення: Якщо бачите додаткові правила, підтвердьте, що вони потрібні. Політична маршрутизація потужна і також надійний спосіб заплутати Майбутнього Вас.

Завдання 15: Підтвердити, що reverse path filtering не відкидає асиметричний трафік

cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.wg0.rp_filter
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.wg0.rp_filter = 0

Значення: rp_filter вимкнено тут, щоб уникнути відкидання, коли шлях відповіді відрізняється від очікуваного інтерфейсу. На роутерах строгий rp_filter часто ламає VPN-форвардинг.

Рішення: Якщо значення = 1 або 2 і ви бачите односторонній трафік, встановіть 0 для wg0 (або тонко налаштуйте) і документуйте причину.

Плейбук швидкої діагностики

Це порядок дій, який швидко знаходить вузьке місце, не блукаючи в «можливо це DNS» фантазіях. Починайте з центру назовні, бо хаб — ваш вузол контролю і найкраща точка спостереження.

Перше: тунель живий?

  1. На хабі: wg show — перевірте вік handshake і лічильники трафіку по пірі.
  2. На хабі: ss -ulnp | grep 51820 — підтвердьте, що слухає.
  3. На споку: wg show — підтвердьте, що він бачить хаб, handshake оновлюється і AllowedIPs відповідають наміру.

Якщо handshake — «never»: зазвичай проблема доступності endpoint (UDP блокується), неправильні ключі, неправильний порт або спок за NAT без keepalive і мапінг NAT прострочився.

Друге: чи правильна маршрутизація?

  1. На хабі і споках: ip route show — підтвердіть, що віддалені офісні підмережі вказують на wg0.
  2. На хабі: wg show wg0 allowed-ips — підтвердіть відсутність перекриттів.
  3. Запустіть traceroute з хаба до віддаленого LAN-хоста — підтвердіть, що перший хоп — правильний спок.

Якщо маршрути є, але traceroute хопи неправильні: у вас перекриття AllowedIPs або політична маршрутизація.

Третє: чи фаєрвол/форвардинг блокує транзит?

  1. Перевірте sysctl net.ipv4.ip_forward на хабі і споках.
  2. Проінспектуйте правила nftables/iptables і лічильники на кожному вузлі.
  3. Запустіть tcpdump на хабі wg0 і на споку wg0, щоб побачити, де пакети зупиняються.

Якщо пакети доходять до хаба, але не до дальнього спока: невідповідність маршруту/AllowedIPs на хабі або drop фаєрволом хаба. Якщо пакети доходять до дальнього спока, але не в LAN — це форвардинг спока або фаєрвол LAN.

Четверте: якщо «працює для малого трафіку»

  1. Тестуйте MTU з ping -M do на кількох розмірах.
  2. Перевірте TCP MSS clamping (якщо використовуєте) і підтвердіть, що він відповідає ефективному MTU.
  3. Шукайте блокування ICMP на шляху (PMTU його потребує).

П’яте: скарги на продуктивність (повільні файлообміни, ривки в дзвінках)

  1. Перевірте CPU хаба і NIC drops: sar, ethtool -S, ss -s.
  2. Подивіться RTT і втрати (звичайні ping-и підходять; також перевірте джиттер).
  3. Підтвердьте, що випадково не ввімкнено централізований інтернет-вихід для важкого трафіку.

Поширені помилки: симптом → причина → виправлення

1) «Handshake ніколи не відбувається»

Симптоми: wg show показує latest handshake: (none). Лічильники трафіку не зростають.

Причина: UDP/51820 заблоковано на вході до хаба, неправильний endpoint/порт хаба, неправильний публічний ключ або спок за NAT без keepalive і мапінг NAT прострочився.

Виправлення: Перевірте ss -ulnp на хабі, дозвольте UDP у хмарному фаєрволі, підтвердіть публічний IP/порт хаба, перевірте ключі, встановіть PersistentKeepalive=25 на споках (і за бажанням у записах пірів хаба).

2) «Пінгується, але SMB/RDP/VoIP плаває або висне»

Симптоми: Малі пінги проходять; великі передачі зависають; деякі додатки підключаються, а потім зависають.

Причина: MTU/PMTU blackhole; ICMP блокується; MTU тунелю завеликий для шляху WAN.

Виправлення: Встановіть MTU для wg на 1420 (або нижче), тестуйте ping -M do, уникайте блокування ICMP повідомлень про необхідність фрагментації. Якщо потрібно — обмежуйте TCP MSS на межах.

3) «Офіс A досягає офісу B, але не C»

Симптоми: Одна віддалена підмережа працює; інша — ні. Handshake є.

Причина: Відсутній маршрут/AllowedIPs для непрацюючої підмережі на споку або на хабі.

Виправлення: Додайте відсутню підмережу в потрібний AllowedIPs і підтвердіть маршрути. Перевірте wg show allowed-ips на наявність перекриттів.

4) «Працює тільки в одному напрямку»

Симптоми: Хост в Office A може дістатися Office B, але відповіді не повертаються (або навпаки).

Причина: Reverse path filtering, асиметрична маршрутизація через інший VPN, або фаєрвол LAN, який не знає про віддалені підмережі.

Виправлення: Вимкніть rp_filter для wg-інтерфейсів, забезпечте наявність маршрутів повернення і оновіть правила фаєрвола LAN, щоб дозволити віддалені підмережі.

5) «Вчора працювало, тепер ніхто не може підключитися після «дрібних змін»»

Симптоми: Після перезавантаження або оновлення тунелі не піднімаються або маршрути змінені.

Причина: Зміни в runtime випадково записалися назад, конфлікти імен таблиць nftables або форвардинг не збережений у sysctl.

Виправлення: Використовуйте SaveConfig=false, визначайте правила фаєрвола в призначеній, идемпотентній системі (systemd/CM), встановлюйте sysctl у /etc/sysctl.d/.

6) «Випадково перемикає, який офіс отримує трафік для підмережі»

Симптоми: Сесії йдуть не до тієї цілі; перший хоп у traceroute змінюється; періодична доступність.

Причина: Перекриття AllowedIPs на хабі. Два піри претендують на ту ж підмережу — бо приймають «бій за маршрутизацію».

Виправлення: Зробіть AllowedIPs взаємовиключними і контролюйте це при рев’ю. Ставтеся до них як до таблиці маршрутизації: унікальність — обов’язкова.

7) «VPN піднятий, але клієнти в офісі не можуть дістатися віддалених мереж»

Симптоми: Роутер спока може пінгувати віддалені хости; десктопи офісу — ні.

Причина: Клієнти офісу не мають маршруту до віддалених підмереж (неправильний шлюз за замовчуванням), або фаєрвол спока не форвардить LAN→wg0.

Виправлення: Переконайтеся, що клієнти використовують офісний роутер як шлюз (DHCP), або додайте статичні маршрути на ядровому комутаторі, якщо ви використовуєте L3 всередині; виправте правила форвардингу і перевірте лічильники.

Контрольні списки / покроковий план

Покроковий план розгортання (робіть це в такому порядку)

  1. Інвентар обмежень. Для кожного офісу: тип WAN, наявність NAT, хто контролює роутер та чи можливий вхідний UDP. Припускайте «ні», поки не доведено.
  2. Фіксуйте план адресації. Виберіть неперекривні офісні підмережі та виділений діапазон транзиту для WireGuard.
  3. Побудуйте хаб першим. Закрийте базові ОС: оновлення, NTP, базовий фаєрвол, бекапи /etc/wireguard.
  4. Згенеруйте ключі для кожного піра. Ведіть публічні ключі в контрольованому місці. Не крутіть ключі без координації.
  5. Налаштуйте hub wg0. Додайте піри з унікальними AllowedIPs (їх wg /32 та офісні підмережі).
  6. Налаштуйте один спок (пілот). Увімкніть форвардинг, маршрути і правила фаєрвола. Підніміть тунель.
  7. Протестуйте з хаба до spoka wg IP. Пінг, потім traceroute до пілотного хоста в офісі.
  8. Протестуйте з клієнта офісу до іншого офісу. Підтвердьте обидва напрямки і перевірте принаймні один «реальний» протокол (SMB або HTTPS), а не лише ping.
  9. Підтвердіть MTU. Виконайте DF-пінги біля 1400. Якщо не проходить — відрегулюйте MTU зараз, а не після скарг.
  10. Додайте інші споки. Повторіть ту саму перевірку для кожного офісу.
  11. Інструментуйте. Щонайменше — cron/systemd таймер, що знімає знімки wg show, плюс лічильники фаєрвола.
  12. Контроль змін. Обробляйте зміни конфігурації WireGuard як зміни фаєрвола: рев’ю, стаджинг і відкат.

Операційний чекліст (щотижня, нудно, ефективно)

  • Перевіряйте свіжість handshake-ів і лічильники трафіку у робочі години.
  • Переконайтеся в дисковому просторі хаба (логи й дампи не питають ваших відчуттів).
  • Переглядайте оновлення ядра/мережевого ПЗ, застосовані до хаба або споків.
  • Переконайтеся, що бекапи включають ключі та конфіги WireGuard, зашифровані й з контролем доступу.
  • Випадкова перевірка лічильників nftables на предмет несподіваних drop-ів.

Чекліст безпеки (практичний, а не показний)

  • Обмежте доступ до хаба — вхід лише на UDP/51820 і адміністративний доступ (SSH) з відомих IP керування.
  • На хабі — default-drop у форвардингу і явно дозволяйте лише те, що потрібно між споками.
  • Тримайте ключі по сайтах; не використовуйте однакові ключі між офісами.
  • Документуйте, які офісні підмережі можуть доступатися до яких сервісів; застосовуйте це на хабі.
  • Сплануйте ротацію ключів (щоквартально/піврічно) і потренуйте її. Репетиція виявляє приховані залежності.

Три корпоративні міні-історії з реального життя

Міні-історія 1: Аварія через хибне припущення

Вони «уніфікували» три філії, купивши однаковий пакет від провайдера скрізь. Та сама модель модему/роутера. Такий же план. Припущення було, що поведінка NAT теж буде «однакова», тому вони пропустили persistent keepalive. Адже WireGuard сучасний і обробляє роумінг. Що може піти не так?

Через два тижні Office C почав скаржитися: «VPN випадково відпадає». Це не було випадковістю. Пристрій ISP мав агресивний UDP-таймаут і очищував мапінг NAT після короткого простою. Коли офіс був тихим (перерви на обід, ранні ранки), мапінг прострочувався. Наступний пакет з Office C виходив, але вхідна відповідь з хаба поверталася на мертву портову мапу.

На хабі endpoint піра виглядав застарілим. Handshake оновлювався лише після того, як хтось в Office C пробував багато разів, даючи NAT-у достатньо вихідного трафіку, щоб відновити мапу. Команда шукала проблеми з DNS, потім — чи CPU хаба, потім сперечалася, чи повинен UDP бути «більш надійним».

Виправлення було соромно простим: PersistentKeepalive = 25 на споку. Висновок більший: не припускайте, що поведінка NAT однакова лише тому, що пластмасова коробка виглядає однаково. Таймаути NAT залежать від прошивки, конфігурації й настрою.

Міні-історія 2: Оптимізація, що обернулась проти

Інженер мереж вирішив, що правила фаєрвола хаба «занадто строгі». Логіка: якщо тунель зашифрований, навіщо не приймати весь forwarded трафік від wg0? Він замінив явні правила на широке accept, і потім — бо йому подобалась симетрія — дозволив форвардинг wg0→eth0 теж. «Майбутнє на увазі», — так він назвав це.

Працювало місяць. Потім пішла SaaS-міграція. Один офіс мав помилковий маршрут на тестовому VLAN, який спрямував велику частину інтернет-трафіку в VPN. Хаб радо форвардив його в інтернет. Вихід хаба став перевантаженим у робочі години.

Симптоми класичні: джиттер VoIP, повільні файлообміни і розпливчасті тікети «мережа повільна». Оскільки хаб став ненавмисним інтернет-транзитом, проблема виглядала як «продуктивність WireGuard», коли насправді ви перетворили хаб на транзитного провайдера.

Відкат був простим: повернути строгі правила форвардингу і явно блокувати wg0→eth0 для всього, крім відомих управлінських підмереж. Оптимізація — «менше правил» — не заощадила вам часу і створила важко помітний режим відмови. Тримайте хаб чесним: маршрутуйте лише те, що намірено.

Міні-історія 3: Нудна практика, що врятувала день

Інша компанія мала звичку, яка здавалась моторошно нудною: кожна мережева зміна вимагала невеликого «before/after» знімка wg show, ip route і правил фаєрвола. Вони зберігали це поруч з тікетом зміни. Ніяких героїчних вчинків, ніякої таємниці.

Одної п’ятниці офіс втратив доступ до двох внутрішніх сервісів, розміщених в іншій філії. Тунелі були підняті. Пінги проходили до роутерів. Але трафік додатків падав. Інженер на виклику витягнув останній «відомо добрий» знімок і порівняв його з поточним станом.

Різниця була очевидна: підмережа офісу була змінена з 10.10.30.0/24 на 10.10.30.0/23 під час «дрібного розширення», але AllowedIPs хаба все ще вказував тільки /24. Половина хостів офісу опинилась за межами маршрутизованого діапазону. Частина хостів могла ініціювати сесії (залежно від джерела IP), інші — були в чорній діри. Це виглядало випадковим, бо залежало від того, які IP роздавав DHCP.

Виправлення зайняло хвилини: оновити AllowedIPs на записі піра хаба і перезапустити інтерфейс. Порятунок не був геніальним; ним стала історія змін. Нудні практики не отримують оплесків, але вони рятують ваші вихідні.

FAQ

1) Чи потрібна мені повна mesh для трьох офісів?

Ні. Можете, але hub-and-spoke легше в експлуатації. Один хаб для захисту, моніторингу і відлагодження. Mesh перетворюється на «кожен відповідає за доступність кожного».

2) Чи повинен хаб NAT-ити між офісами?

Не за замовчуванням. Маршрутуйте реальні підмережі енд-ту-енд, щоб логи й ACL мали сенс. NAT прийнятний для централізованого виходу в інтернет або тимчасової обробки перекриттів, але не як стандартний шлях.

3) Де ставити PersistentKeepalive?

На споках майже завжди, особливо за NAT. 25 секунд — типове значення. Якщо лінк лімітований чи платний, можна збільшити, але не прибирайте це без вагомих причин.

4) Чи можна використовувати DNS-імена замість статичної IP для endpoint хаба?

Так, але не вірте, що DNS — безпомилковий. Якщо використовуєте DNS-ім’я, забезпечте надійне резолвінг на споках і продумайте, як обробляти зміну IP хаба без людського втручання.

5) Чому використовуються /32-адреси на споках для wg0?

Тому що це зменшує невизначеність. Інтерфейс тунелю не потребує відчуття спільного L2-сегмента; йому потрібен стабільний ідентифікатор для кожного піра. /32 — чисто, а маршрутизація базується на AllowedIPs.

6) Який найкращий MTU для WireGuard site-to-site?

Почніть з 1420. Якщо у вас PPPoE або дивні WAN-шляхи, можливо знадобиться менше. Виміряйте DF-пінгами і перевірте реальним файлообміном (SMB/HTTPS) перед тим, як вважати все в порядку.

7) Чи можу я обмежити, які офіси можуть спілкуватися між собою?

Так, і вам варто це зробити. Застосовуйте це на хабі правилами у forward chain (wg0→wg0), що матчать джерело/цільові підмережі. Не розраховуйте на «вони, мабуть, не будуть».

8) Як впоратися з перекриттям офісних підмереж без перенумерації?

Можна NAT-ити одну сторону або використовувати 1:1-мепінг, але це операційний борг. Ви будете витрачати час на діагностику ідентичності і ACL. Якщо це постійно, заплануйте проект перенумерації.

9) Чи надає WireGuard контроль доступу на рівні користувача?

Ні. Це ключі пірів і AllowedIPs. Для VPN на рівні користувача зазвичай термінують на окремій системі і інтегрують ідентичність, MFA і перевірку стану пристрою.

10) Чи потрібна висока доступність для хаба?

Якщо офіси залежать від нього для ключових операцій — так. Щонайменше: бекапи, автоматизований rebuild і протестований план відновлення (резервний хаб або плаваюча IP в середовищах, що підтримують це). «Ми просто відновимо» — не план, поки ви не поміряєте час відновлення.

Наступні кроки, що реально зменшують тривогу на пейджері

WireGuard hub-and-spoke — надійна архітектура, але лише якщо ви ставитеся до хаба як до інфраструктури, а не як до побочного проєкту. Ось що робити далі, у практичному порядку:

  1. Запишіть намір. Які підмережі існують, які з них мають маршрутизуватися через WireGuard і які офіси можуть доступатися до яких сервісів.
  2. Зробіть AllowedIPs підлягаючими рев’ю. Тримайте конфіги у версійній системі, вимагайте рев’ю і забезпечте правило «жодних перекриттів» як пункт чеклісту.
  3. Кодіфікуйте політику фаєрвола. Default-drop у форвардингу на хабі, потім дозволяйте лише міжофісні потоки, які ви хочете. Рахуйте drop-и.
  4. Виміряйте MTU один раз, правильно. DF-пінги та реальний тест файлообміну. Потім встановіть MTU і не торкайтеся його, якщо WAN не зміниться.
  5. Побудуйте повторювану рутину діагностики. Плейбук вище — ваш перший респондент. Роздрукуйте його, прикріпіть і використовуйте.
  6. Вирішіть, чи потрібен централізований вихід у інтернет. Якщо так — робіть це навмисно з явними маршрутами і NAT, і плануйте пропускну здатність та політики.

Якщо ви зробите ці речі, ваші три офіси перестануть поводитися як три окремі планети. І коли щось ламається — а це трапиться — у вас буде достатньо сигналу, щоб виправити все без ритуальних жертв мережевим богам.

← Попередня
MySQL vs PostgreSQL: «Раптово стало повільно» — 15‑хвилинний план діагностики для обох
Наступна →
Антивірус, який ламає ПК: іронія, що повторюється

Залишити коментар