WireGuard Site-to-Site: поетапне з’єднання двох офісів через інтернет

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

Сайтові VPN виходять з ладу специфічним чином: все виглядає «вгору», ніхто не може дістатися до файлового сервера, а телефон починає вібрувати, ніби намагається пробитися тунелем.
WireGuard зазвичай — протидія: чиста конфігурація, швидка криптографія, мало складних частин — але сайто-ту-сайту все ще має досить гострих питань з маршрутизації та брандмауером, щоб тримати SRE на роботі.

Цей посібник — як я фактично будую офісний WireGuard-лінк у продакшні: два шлюзи, дві локальні мережі, реальна маршрутизація, свідомі рішення щодо NAT і план діагностики, коли реальність не сходиться з діаграмою.

Топологія, припущення та що ми будуємо

Ми з’єднаємо два офіси через публічний інтернет, використовуючи два Linux-шлюзи з WireGuard.
Кожен офіс має свою приватну LAN. Шлюзи маршрутизуватимуть трафік між LAN через WireGuard-тунель.
Клієнти всередині кожного офісу повинні дістатися підмереж іншого офісу без встановлення WireGuard на себе.

Приклад адресації (змініть під вашу ситуацію)

  • LAN офісу A: 10.10.0.0/24
  • LAN офісу B: 10.20.0.0/24
  • Мережа тунелю WireGuard: 10.99.0.0/24
  • Публічна IP шлюзу A: 198.51.100.10 (приклад)
  • Публічна IP шлюзу B: 203.0.113.20 (приклад)
  • wg IP шлюзу A: 10.99.0.1
  • wg IP шлюзу B: 10.99.0.2
  • Порт прослуховування: 51820/udp

Як виглядає «готово»

  • З хоста в Офісі A (наприклад, 10.10.0.50) ви можете дістатися 10.20.0.60 в Офісі B (ping + TCP).
  • З хоста в Офісі B можна дістатися сервісів LAN Офісу A.
  • Тунель тримається вгору через NAT та періоди простою.
  • Маршрутизація явна; NAT — це усвідомлений вибір, а не «тому що так спрацювало».
  • Коли щось ламається, ви можете за кілька хвилин визначити: крипто, транспорт, маршрутизація чи політика.

Цікаві факти та коротка історія

  • WireGuard молодий за стандартами VPN. Він з’явився в середині 2010-х як простіша, сучасна альтернатива IPsec та OpenVPN.
  • Він потрапив у ядро Linux у 2020 році. Це важливо: менше зовнішніх модулів, менше сюрпризів при оновленнях, краща продуктивність.
  • Під капотом — фреймворк Noise. Хендшейк WireGuard базується на патернах Noise — компактних, придатних для аудиту й сучасної криптографії.
  • Немає переговорів набору шифрів. Це не недолік; це навмисний вибір, щоб зменшити ризики зниження й розростання конфігурацій.
  • Він навмисно «на рівні IP». WireGuard передає IP-пакети; він не прагне бути повною системою управління мережею.
  • «AllowedIPs» — це одночасно маршрутизація й контроль доступу. Це примітив політики, що одночасно виступає селектором маршруту.
  • Роумінг — це перший клас концепції. Якщо IP-адреса піра змінюється (мобільність, зсув NAT), WireGuard може продовжити після валідації хендшейку.
  • UDP робить усе простіше. Уникає проблем TCP-over-TCP і більшості головних затримок, які з’являються при тунелюванні через TCP.
  • Малий кодовий базис. WireGuard відомий компактністю в порівнянні з багатьма VPN-стеками — це полегшує аудит і зменшує площу для помилок.

Вибори проєктування, що мають значення (і ті, що ні)

Вирішіть: маршрутизація проти NAT між офісами

Для site-to-site маршрутизація — це стандартна опція, до якої слід прагнути: Офіс A бачить Офіс B як 10.20.0.0/24, і навпаки.
NAT «працює», але ховає ідентичність, ускладнює логування і викликає дивну поведінку застосунків (Kerberos, ACL за IP, все, що залежить від вихідної адреси).

Використовуйте NAT лише коли є незаперечні колізії (обидва офіси використовують 192.168.1.0/24 тому, що роутер поставлявся з такою мережею і ніхто не змінив),
або коли віддалена сторона відмовляється додати маршрути. Якщо можна маршрутувати — маршрутуйте.

Вирішіть: де живе маршрутизація

Потрібно, щоб хости LAN відправляли трафік «до віддаленого LAN» на WireGuard-шлюз. Є два розумних варіанти:

  • Правильна маршрутизація: Додайте статичний маршрут на роутері/корі офісу, щоб 10.20.0.0/24 йшов на LAN IP шлюзу A, і 10.10.0.0/24 — на LAN IP шлюзу B.
  • Маршрути на хостах: Додавайте маршрути на окремих хостах. Це підходить для невеликих лабораторій і жахливо для офісів із людьми.

Вирішіть: межі політики брандмауера

Тунель site-to-site — не магічна парасолька довіри. Трактуйте його як підключення довгого Ethernet-кабелю до чужого комутатора.
Дозволяйте лише те, що потрібно; забороняйте те, що не потрібно; логируйте те, про що потім пошкодуєте, що не логували.

MTU і MSS: оберіть щастя

Більшість загадкових проблем «ping працює, але SMB падає» — це проблеми MTU/MSS в маскуванні.
Почніть з консервативного MTU інтерфейсу WireGuard, наприклад 1420, і зафіксуйте TCP MSS на шлюзі, якщо ви проходите через PPPoE, LTE або невідомі middlebox.

Цитата, щоб не забувати: «Надія — не стратегія.» — перефразована ідея, часто цитована в операційних колах (точна фраза варіюється).

Передумови та базові перевірки

  • Два Linux-шлюзи (приклади Debian/Ubuntu). Це можуть бути VM, виділені бокси або малі пристрої.
  • Кожен шлюз має:
    • Один інтерфейс у LAN офісу (наприклад, eth1)
    • Один інтерфейс до інтернету (наприклад, eth0)
  • Ви контролюєте маршрутизацію в кожній офісній мережі або принаймні дефолтний шлюз/роутер.
  • UDP порт 51820 може бути проброшений на кожен шлюз, якщо він за NAT.
  • Неперекриваючі LAN-підмережі. Якщо вони перекриваються — ви робите NAT/трансляцію (розглядається далі як запасний варіант).

Жарт №1: Якщо ви виявили, що обидва офіси використовують 192.168.0.0/24, вітаю — ви знайшли найпоширенішу корпоративну традицію у світі.

Чек-лісти / поетапний план

Фаза 0: домовтесь про маршрутну історію

  1. Виберіть виділену підмережу тунелю WireGuard (приклад 10.99.0.0/24).
  2. Підтвердіть, що LAN офісу A і LAN офісу B не перекриваються.
  3. Виберіть пристрій у кожному офісі, який буде «шлюзом», і переконайтеся, що він має надійне живлення й стабільний інтернет.
  4. Вирішіть метод маршрутизації:
    • Переважно: додайте статичні маршрути на офісних роутерах.
    • У запасі: додайте маршрути на хостах (лише для малих розгортань).

Фаза 1: інсталюйте WireGuard і згенеруйте ключі

  1. Встановіть інструменти WireGuard на обох шлюзах.
  2. Згенеруйте пари ключів; зберігайте приватні ключі з суворими правами доступу.
  3. Створіть конфігурації wg0 з явними адресами та AllowedIPs.

Фаза 2: увімкніть форвардінг і налаштуйте брандмауер

  1. Увімкніть IPv4 forwarding на обох шлюзах.
  2. Дозвольте UDP 51820 вхідний на кожен шлюз (публічний інтерфейс).
  3. Дозвольте форвардінг між wg0 і LAN інтерфейсом для конкретних підмереж/сервісів, які вам потрібні.
  4. Опціонально — зафіксуйте MSS.

Фаза 3: підніміть тунель і перевіряйте по шарах

  1. Увімкніть WireGuard, перевірте часи хендшейку та endpoints.
  2. Пінгуйте tunnel IP-адреси (10.99.0.110.99.0.2).
  3. Пінгуйте LAN-to-LAN з тестового хоста з кожної сторони.
  4. Перевірте TCP-сервіси (SSH/HTTP/SMB) обидва напрямки.
  5. Затягніть правила брандмауера та логування, коли все працює.

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

Різниця між лабораторною VPN і продакшн VPN — в спостережуваності та дисциплінованому ухваленні рішень.
Нижче — конкретні завдання, які я виконую по порядку. Кожне містить те, що означає вивід, і що я вирішую далі.

Завдання 1: підтвердіть імена інтерфейсів і адреси

cr0x@gw-a:~$ ip -br addr
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             198.51.100.10/24
eth1             UP             10.10.0.1/24

Значення: eth0 — публічний, eth1 — LAN офісу A. Добре.
Якщо ваш «LAN» інтерфейс показує публічний IP — зупиніться. Ваше підключення кабелів (або прив’язка NIC у VM) неправильні.

Рішення: Занотуйте LAN-інтерфейс для правил форвардінгу брандмауера і LAN-шлюз для статичних маршрутів.

Завдання 2: встановіть інструменти WireGuard

cr0x@gw-a:~$ sudo apt-get update
...output...
cr0x@gw-a:~$ sudo apt-get install -y wireguard
...output...

Значення: У вас є wg, wg-quick і підтримка у ядрі (або DKMS).

Рішення: Якщо це тягне DKMS-модуль на старому ядрі — плануйте оновлення ядра. Продакшн VPN не має залежати від крихкого зовнішнього білду.

Завдання 3: згенеруйте пару ключів (зробіть це на кожному шлюзі)

cr0x@gw-a:~$ umask 077
cr0x@gw-a:~$ wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
cr0x@gw-a:~$ sudo ls -l /etc/wireguard
total 8
-rw------- 1 root root 45 privatekey
-rw-r--r-- 1 root root 45 publickey

Значення: Приватний ключ — лише для root. Публічний ключ можна передавати пірінгу.

Рішення: Якщо права доступу нестрогі — виправте. Приватний ключ — це ідентичність.

Завдання 4: створіть конфіг WireGuard на Шлюзі A

cr0x@gw-a:~$ sudo tee /etc/wireguard/wg0.conf >/dev/null <<'EOF'
[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = __GW_A_PRIVATE_KEY__
MTU = 1420

# Optional: ensure routes are added by wg-quick
# (wg-quick will add routes for AllowedIPs on peers)

[Peer]
PublicKey = __GW_B_PUBLIC_KEY__
Endpoint = 203.0.113.20:51820
AllowedIPs = 10.99.0.2/32, 10.20.0.0/24
PersistentKeepalive = 25
EOF

Значення: Шлюз A буде направляти трафік, призначений для LAN B (10.20.0.0/24), у тунель, а також знає IP тунелю пірінгу.

Рішення: Тримайте AllowedIPs щільними. Не ставте 0.0.0.0/0 тут для site-to-site, хіба що ви справді хочете весь трафік хеірпінити через інший офіс.

Завдання 5: створіть конфіг WireGuard на Шлюзі B (дзеркально)

cr0x@gw-b:~$ sudo tee /etc/wireguard/wg0.conf >/dev/null <<'EOF'
[Interface]
Address = 10.99.0.2/24
ListenPort = 51820
PrivateKey = __GW_B_PRIVATE_KEY__
MTU = 1420

[Peer]
PublicKey = __GW_A_PUBLIC_KEY__
Endpoint = 198.51.100.10:51820
AllowedIPs = 10.99.0.1/32, 10.10.0.0/24
PersistentKeepalive = 25
EOF

Значення: Симетрія. Кожна сторона є авторитетною для своєї LAN-підмережі в AllowedIPs.

Рішення: Якщо якийсь шлюз за NAT і має динамічний публічний IP, потрібна стабільна стратегія кінцевої точки (статичний IP, DNS-ім’я або одна сторона як «тільки вихід»). Не вдавайте, що це стабільно.

Завдання 6: увімкніть IP forwarding (обидва шлюзи)

cr0x@gw-a:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
cr0x@gw-a:~$ echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-wireguard-forward.conf
net.ipv4.ip_forward=1

Значення: Шлюз може маршрутизувати пакети між інтерфейсами.

Рішення: Якщо забудете це — тунель виглядатиме нормально, але LAN-to-LAN трафік тихо помре. Увімкніть це постійно через sysctl drop-in.

Завдання 7: підніміть інтерфейс і підтвердіть, що він працює

cr0x@gw-a:~$ sudo systemctl enable --now wg-quick@wg0
Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@wg0.service → /lib/systemd/system/wg-quick@.service.
cr0x@gw-a:~$ sudo wg show
interface: wg0
  public key: 7wz...REDACTED...nU=
  private key: (hidden)
  listening port: 51820

peer: X1p...REDACTED...b0=
  endpoint: 203.0.113.20:51820
  allowed ips: 10.99.0.2/32, 10.20.0.0/24
  latest handshake: 18 seconds ago
  transfer: 84.12 KiB received, 90.44 KiB sent
  persistent keepalive: every 25 seconds

Значення: «Latest handshake» — ваш перший зелений сигнал. Якщо стоїть «(none)», тунелю ще немає — не витрачайте час на маршрути LAN.

Рішення: Немає хендшейку — зосередьтеся на UDP-доступності, endpoints, ключах та зсуві часу (рідко, але буває). Є хендшейк — переходьте вгору по стеку до маршрутизації й брандмауера.

Завдання 8: перевірте, що ядро створило маршрути для AllowedIPs

cr0x@gw-a:~$ ip route show table main | grep -E '10\.20\.0\.0/24|10\.99\.0\.2'
10.20.0.0/24 dev wg0 scope link
10.99.0.2 dev wg0 scope link

Значення: Пакети, призначені для LAN B, підуть у wg0. Це критично.

Рішення: Якщо маршрут відсутній — ваш конфіг не застосовується wg-quick, або ви редагували неправильний файл. Виправте перед тим, як лізти в роутери.

Завдання 9: відкрийте брандмауер для транспорту WireGuard (UDP 51820)

cr0x@gw-a:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;
    iif "lo" accept
    ct state established,related accept
    tcp dport 22 accept
  }
}

Значення: Політика input — drop; UDP 51820 не дозволений. Ось чому хендшейки часто не відбуваються.

Рішення: Додайте явне правило для дозволу UDP 51820 на публічному інтерфейсі.

cr0x@gw-a:~$ sudo nft add rule inet filter input iif "eth0" udp dport 51820 ct state new accept
cr0x@gw-a:~$ sudo nft list chain inet filter input
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;
    iif "lo" accept
    ct state established,related accept
    tcp dport 22 accept
    iif "eth0" udp dport 51820 ct state new accept
  }
}

Значення: Ми дозволили транспорт WireGuard з інтернету. Все ще мінімально піддано ризику.

Рішення: Зробіть аналогічне на Шлюзі B. Якщо одна зі сторін за NAT — переконайтеся, що проброс порту потрапляє на правильний внутрішній хост.

Завдання 10: дозволіть форвардінг між LAN і wg0 (режим маршрутизації)

cr0x@gw-a:~$ sudo nft add table inet wgsite
cr0x@gw-a:~$ sudo nft add chain inet wgsite forward '{ type filter hook forward priority 0; policy drop; }'
cr0x@gw-a:~$ sudo nft add rule inet wgsite forward ct state established,related accept
cr0x@gw-a:~$ sudo nft add rule inet wgsite forward iif "eth1" oif "wg0" ip saddr 10.10.0.0/24 ip daddr 10.20.0.0/24 accept
cr0x@gw-a:~$ sudo nft add rule inet wgsite forward iif "wg0" oif "eth1" ip saddr 10.20.0.0/24 ip daddr 10.10.0.0/24 accept
cr0x@gw-a:~$ sudo nft list chain inet wgsite forward
table inet wgsite {
  chain forward {
    type filter hook forward priority 0; policy drop;
    ct state established,related accept
    iif "eth1" oif "wg0" ip saddr 10.10.0.0/24 ip daddr 10.20.0.0/24 accept
    iif "wg0" oif "eth1" ip saddr 10.20.0.0/24 ip daddr 10.10.0.0/24 accept
  }
}

Значення: Через шлюз дозволяється лише LAN-to-LAN трафік. Все інше за замовчуванням відкидається.

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

Завдання 11: додайте статичні маршрути на офісних роутерах (переважно)

Це залежить від вендора, але логіка завжди одна: скажіть офісному роутеру, що віддалена LAN доступна через локальний LAN-next-hop — локальний IP WireGuard-шлюзу.
Якщо не можете налаштувати це на роутері, можете тимчасово додати маршрут на тестовому хості для валідації.

cr0x@host-a:~$ ip route
default via 10.10.0.254 dev eth0
10.10.0.0/24 dev eth0 proto kernel scope link src 10.10.0.50

Значення: Немає маршруту до 10.20.0.0/24. Хост відправить цей трафік дефолтним шлюзом, який, ймовірно, не знає, що робити.

Рішення: Додайте тимчасовий маршрут на хості для тестування, потім впровадьте його на роутері офісу належним чином.

cr0x@host-a:~$ sudo ip route add 10.20.0.0/24 via 10.10.0.1
cr0x@host-a:~$ ip route get 10.20.0.60
10.20.0.60 via 10.10.0.1 dev eth0 src 10.10.0.50 uid 1000
    cache

Значення: Хост тепер відправлятиме трафік до віддаленого LAN через Шлюз A (10.10.0.1).

Рішення: Якщо це усе працює, ви довели, що VPN і форвардінг шлюзу в порядку; тепер потрібно реалізувати маршрути на рівні мережі.

Завдання 12: протестуйте зв’язність тунелю (шлюз ↔ шлюз)

cr0x@gw-a:~$ ping -c 3 10.99.0.2
PING 10.99.0.2 (10.99.0.2) 56(84) bytes of data.
64 bytes from 10.99.0.2: icmp_seq=1 ttl=64 time=21.3 ms
64 bytes from 10.99.0.2: icmp_seq=2 ttl=64 time=20.9 ms
64 bytes from 10.99.0.2: icmp_seq=3 ttl=21.1 ms

--- 10.99.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 20.9/21.1/21.3/0.16 ms

Значення: Шлях шифрування працює і форвардінг для підмережі тунелю правильний.

Рішення: Якщо це не працює, але хендшейк є, ймовірно ви заблокували ICMP у правилах форвардінгу або неправильно вказали AllowedIPs для IP тунелю. Спочатку виправте політику.

Завдання 13: протестуйте LAN-to-LAN зв’язність з хоста

cr0x@host-a:~$ ping -c 3 10.20.0.60
PING 10.20.0.60 (10.20.0.60) 56(84) bytes of data.
64 bytes from 10.20.0.60: icmp_seq=1 ttl=63 time=24.7 ms
64 bytes from 10.20.0.60: icmp_seq=2 ttl=63 time=24.1 ms
64 bytes from 10.20.0.60: icmp_seq=3 ttl=63 time=23.9 ms

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

Значення: Маршрути через шлюз працюють. TTL 63 вказує на щонайменше один хоп (шлюз) у шляху. Добре.

Рішення: Якщо ping працює, а TCP — ні, ймовірно це брандмауер, MTU/MSS або асиметрична маршрутизація. Не гадати — вимірюйте.

Завдання 14: протестуйте TCP-зв’язок (бо «ping працює» — пастка)

cr0x@host-a:~$ nc -vz -w 2 10.20.0.60 445
Connection to 10.20.0.60 445 port [tcp/microsoft-ds] succeeded!

Значення: Щонайменше TCP-хендшейк до SMB відбувається. Це означає, що маршрути + stateful брандмауер дозволяють його.

Рішення: Якщо таймаут — перевірте правила форвардінгу та локальний брандмауер на цільовому хості. Якщо «refused» — сервіс не слухає або ACL блокують — інша проблема.

Завдання 15: підтвердіть, що трафік дійсно йде через wg0

cr0x@gw-a:~$ sudo wg show wg0 transfer
peer: X1p...REDACTED...b0=
  transfer: 2.31 MiB received, 2.88 MiB sent

Значення: Рахунки, що рухаються, підтверджують, що реальний трафік пройшов тунелем, а не тільки хендшейк.

Рішення: Якщо хендшейки є, але transfer близький до нуля під час тестів — трафік не потрапляє на шлюз (маршрутизація) або блокується перед шифруванням (брандмауер на боці LAN).

Завдання 16: використовуйте tcpdump, щоб знайти місце, де пакети гинуть

cr0x@gw-a:~$ sudo tcpdump -ni eth1 host 10.20.0.60
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:14:31.120331 IP 10.10.0.50 > 10.20.0.60: ICMP echo request, id 1923, seq 1, length 64

Значення: Шлюз отримує пакети з LAN, призначені для віддаленого LAN. Добре.

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

cr0x@gw-a:~$ sudo tcpdump -ni wg0 host 10.20.0.60
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
10:14:31.120882 IP 10.10.0.50 > 10.20.0.60: ICMP echo request, id 1923, seq 1, length 64

Значення: Пакет маршрутизується в тунель. Якщо віддалений хост не відповідає, проблема на далекій стороні (повернення маршруту, брандмауер, політика хоста).

Завдання 17: перевірте зворотний шлях на Шлюзі B

cr0x@gw-b:~$ ip route get 10.10.0.50
10.10.0.50 dev wg0 src 10.99.0.2 uid 0
    cache

Значення: Шлюз B знає, що повертати трафік до Офісу A через тунель. Якщо він каже «via eth1», ви створили асиметричну маршрутизацію і ваш брандмауер вас покарає.

Рішення: Виправте AllowedIPs і маршрути, поки обидві сторони не погодяться щодо шляху.

Завдання 18: шукайте MTU-проблеми «ping без фрагментації»

cr0x@host-a:~$ ping -M do -s 1380 -c 3 10.20.0.60
PING 10.20.0.60 (10.20.0.60) 1380(1408) bytes of data.
1388 bytes from 10.20.0.60: icmp_seq=1 ttl=63 time=25.4 ms
1388 bytes from 10.20.0.60: icmp_seq=2 ttl=63 time=24.9 ms
1388 bytes from 10.20.0.60: icmp_seq=3 ttl=63 time=25.2 ms

Значення: Великі пакети проходять без фрагментації. Добрий знак.

Рішення: Якщо отримаєте «Frag needed», зменшіть MTU wg (наприклад, 1380–1420) або зафіксуйте MSS на шлюзах. Зробіть це до того, як звинуватите «ISP».

Завдання 19: зафіксуйте TCP MSS, якщо бачите зависання при великих передачах

cr0x@gw-a:~$ sudo nft add table ip mangle
cr0x@gw-a:~$ sudo nft add chain ip mangle forward '{ type filter hook forward priority -150; policy accept; }'
cr0x@gw-a:~$ sudo nft add rule ip mangle forward oif "wg0" tcp flags syn tcp option maxseg size set 1360
cr0x@gw-a:~$ sudo nft list chain ip mangle forward
table ip mangle {
  chain forward {
    type filter hook forward priority -150; policy accept;
    oif "wg0" tcp flags syn tcp option maxseg size set 1360
  }
}

Значення: Нові TCP-з’єднання, що виходять у тунель, будуть рекламувати менший MSS, запобігаючи чорним дірам, залежним від PMTUD.

Рішення: Фіксуйте тільки якщо треба. Це прагматичне виправлення, але також визнання того, що PMTU у вашому середовищі нестабільна (часто через блокування ICMP).

Завдання 20: переконайтеся, що systemd бачить wg-quick здоровим

cr0x@gw-a:~$ systemctl status wg-quick@wg0 --no-pager
● 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 Tue 2025-12-09 10:01:12 UTC; 2h 8min ago
       Docs: man:wg-quick(8)
             man:wg(8)
    Process: 1234 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)

Значення: «active (exited)» — нормальна поведінка для oneshot-сервісів. Інтерфейс залишається в ядрі.

Рішення: Якщо він упав — читайте журнали systemd. Не перезапускайте без кінця; виправте помилку конфігу (неправильне форматування ключа, відсутня адреса інтерфейсу тощо).

Три корпоративні міні-історії з полі бою

Міні-історія 1: інцидент через невірне припущення

Середня компанія об’єдналася з меншою і потребувала «швидкого тунелю», щоб фінанси могли дістатися ERP-системи.
Новий VPN встановили за вихідні. У понеділок тунель був піднятий, хендшейки свіжі, і дашборд сяяв зеленим.
Користувачі все одно не могли увійти в ERP. Мережеві інженери одразу звинуватили додаток. Команда додатку — мережу.

Невірне припущення: «Якщо тунель WireGuard працює, маршрутизація має бути в порядку.» Не була.
Офіс A мав статичний маршрут до Офісу B на своєму шлюзі. Офіс B — ні.
Їх дефолтний шлюз був керованим фаєрволом, де нікому не давали права додавати маршрути, тому повернення трафіку йшло на інтернет-край, впиралося в правило drop і зникало.

Розв’язка була в tcpdump: пакети заходили на wg0 віддаленого шлюзу, але відповіді ніколи не поверталися тунелем.
Виправлення — нудне: додати відсутній статичний маршрут на краю Офісу B і звузити правила брандмауера так, щоб через тунель йшли лише потрібні порти ERP.
Потім вони записали правило: ніколи не оголошуйте «VPN працює», поки не перевірите зворотну маршрутизацію командою ip route get на обох шлюзах.

Урок: успішний хендшейк доводить шифрування; він не доводить доставку пакетів і точно не доводить симетричну маршрутизацію.
Діагностуйте шлях як SRE: по одному хопу, по одному інтерфейсу, з доказами.

Міні-історія 2: оптимізація, що відігралася боком

Інша організація вирішила, що тунель має бути «максимально швидким», тому вони підняли MTU, прибрали MSS-clamp і включили агресивні оффлоади на NIC.
Тести пропускної здатності виглядали чудово в контрольованому сценарії. Потім бухгалтерія почала пересилати великі PDF по SMB — і все час від часу зависало.
Не повільно. Замерзало. Класика.

Оптимізація: більші пакети і менше циклів CPU. Наслідок: реальний WAN-шлях із нижчим ефективним MTU і фільтрацією ICMP.
Path MTU discovery мовчки зазнавав невдачі. Результат — чорна діра, де великі TCP-сегменти зникали.
Маленький трафік (ping, дрібні HTTP-запити) працював. Великі передачі гинули посеред потоку, і служба підтримки отримала квитки «іноді працює».

Виправлення — перестати вгадувати інтернет.
Вони встановили wg MTU на 1420, додали консервативний MSS clamp і залишили оффлоади за замовчуванням.
Продуктивність стала стабільною — а стабільність і є та продуктивність, яку помічають користувачі.

Урок: «швидко», що провалюється, повільніше за «нудно», що працює. Бенчмарк — після того, як у вас є коректність, а не до.

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

Компанія з двома офісами і невеликим дата-центром роками працювала на WireGuard без драм.
Секрет — не магічна конфігурація; секрет — рутина.
Кожна зміна AllowedIPs, правил брандмауера або офісної маршрутизації проходила через невеликий ранбук: протестувати ping тунельних IP, ping LAN-to-LAN, TCP-порт і зберегти вивід wg show у записі зміни.

Одного дня ISP поміняв модем в Офісі B, і публічні NAT-правила змінилися.
Тунель перестав хендшейкатися. Це могло перетворитися на двогодинну сесію з пошуком винних.
Натомість інженер онколи слідував ранбуку і знайшов «немає хендшейку» за хвилину, потім перевірив, що UDP-порт ззовні недоступний.

Оскільки в них була документована стара конфігурація пробросу портів модему, вони швидко відтворили її на новому пристрої.
Без глибокої магії пакетів, без ескалацій вендору, без нічних геройських подвигів.
VPN повернувся, і більшість людей так і не дізналися, що він був недоступний — найвищий комплімент для операцій.

Урок: робіть нудну паперову роботу, поки ви спокійні. Ваш майбутній я не дуже надійний оповідач під тиском.

План швидкої діагностики

Коли site-to-site WireGuard лінк падає, треба швидко відповісти на одне питання:
у чому вузьке місце — транспорт/крипто, маршрутизація чи брандмауер/політика?
Ось порядок, що мінімізує метушню.

По-перше: чи є хендшейк?

  • Запустіть wg show на обох шлюзах.
  • Якщо «latest handshake» свіжий на обох сторонах — транспорт і ключі, ймовірно, в порядку.
  • Якщо хендшейку немає:
    • Перевірте доступність UDP 51820 та NAT/проброс портів.
    • Переконайтеся, що endpoints правильні і публічні IP не змінилися.
    • Перевірте, що ключі відповідають тому пірінгу, якого ви очікуєте.

По-друге: чи можуть шлюзи дістатися wg IP один одного?

  • Пінгуйте 10.99.0.2 з Шлюзу A і 10.99.0.1 з Шлюзу B.
  • Якщо це не працює, але хендшейк є, підозрюйте:
    • Відсутність /32 тунелю в AllowedIPs
    • Правила форвардінгу, що відкидають ICMP або весь форвард
    • Конфлікти політики маршрутизації

По-третє: чи доходить LAN-трафік до шлюзу і потрапляє в wg0?

  • На Шлюзі A:
    • tcpdump -ni eth1 host 10.20.0.60 під час пінгу з LAN-хоста
    • tcpdump -ni wg0 host 10.20.0.60 одночасно
  • Інтерпретація:
    • Побачено на eth1, не на wg0: маршрути/форвардінг брандмауера на Шлюзі A.
    • Побачено на wg0 на A, не на wg0 на B: транспорт/endpoint/NAT.
    • Побачено на wg0 на B, відповіді не повертаються: зворотна маршрутизація або брандмауер на B чи політика на цільовому хості.

По-четверте: ганяйте MTU лише після базових перевірок

  • Якщо ping працює, TCP-hеndшейк працює, але великі передачі зависають: тестуйте DF-ping і зафіксуйте MSS.
  • Не «тюнінгуйте MTU» як перший крок. Так ви витратите день і нічого не дізнаєтеся.

Жарт №2: MTU-помилки як вампіри — пустіть їх у мережу, заблокувавши ICMP, і вони житимуть там вічно.

Типові помилки: симптоми → корінь → виправлення

1) Симптом: «Latest handshake: (none)» на одному або обох шлюзах

  • Корінь: UDP-порт заблоковано, неправильний endpoint IP/порт, відсутній NAT-проброс або невірний публічний ключ пірінга.
  • Виправлення: Дозвольте UDP 51820 вхідний на публічний інтерфейс, підтвердіть проброс порту до шлюзу, перевірте публічні ключі пірінга та endpoints, і встановіть PersistentKeepalive=25 якщо за NAT.

2) Симптом: хендшейк працює, але шлюзи не пінгують wg IP один одного

  • Корінь: Відсутній /32 тунелю в AllowedIPs або політика форвардінгу блокує ICMP/форвард.
  • Виправлення: Переконайтеся, що AllowedIPs кожного пірінга включає IP тунелю іншого (10.99.0.2/32) і дозвольте форвардінг між wg0 і LAN.

3) Симптом: хости офісу не дістають віддалений LAN, але шлюзи можуть

  • Корінь: Офісний роутер не має статичного маршруту до віддаленої підмережі через WireGuard-шлюз.
  • Виправлення: Додайте статичні маршрути на офісних роутерах, а не на довільних хостах, і перевірте командою ip route get з клієнта.

4) Симптом: однонаправлена зв’язність (A→B працює, B→A ні)

  • Корінь: Асиметрична маршрутизація або stateful брандмауер відкидає повернення.
  • Виправлення: Перевірте маршрути на обох шлюзах і на обох офісних роутерах. Підтвердіть правила форвардінгу в обох напрямках. Використовуйте tcpdump на обох кінцях, щоб довести, де зупиняється повернення.

5) Симптом: ping працює, дрібний TCP працює, великі передачі зависають

  • Корінь: Несумісний MTU і зламаний PMTUD, часто через блокування ICMP на шляху.
  • Виправлення: Зменшіть wg MTU (почніть з 1420) і зафіксуйте MSS на SYN-пакетах, що виходять у wg0. Підтвердіть DF-ping.

6) Симптом: випадкові обриви кожні кілька хвилин, особливо за NAT

  • Корінь: Таймаут простору NAT, який закінчує UDP-мапінги.
  • Виправлення: Встановіть PersistentKeepalive=25 на боці за NAT (або на обох сторонах, якщо невпевнені). Перевірте час хендшейку, щоб залишався свіжим.

7) Симптом: віддалена LAN стала доступною, але DNS або AD поводяться дивно

  • Корінь: Ви зробили NAT між сайтами і порушили очікування ідентичності, або забули спрямувати DNS-запити до правильних резолверів.
  • Виправлення: Віддавайте перевагу маршрутизованому режиму. Якщо NAT неминучий — документуйте схему трансляції і налаштуйте очікування додатка (ACL, логи). Переконайтеся, що DNS-форвардинг і умовні зони відповідають новій топології.

8) Симптом: wireguard працює до перезавантаження, після — ні

  • Корінь: Конфіг не ввімкнено як сервіс, правила брандмауера не збережено, або sysctl forwarding не збережено.
  • Виправлення: Увімкніть wg-quick@wg0 і зробіть збереження nftables/sysctl конфігурацій. Перезавантажте у вікні обслуговування й перевірте.

Зміцнення, операції та кроки для надійності

Тримайте AllowedIPs мінімальними і свідомими

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

  • IP тунелю пірінга (/32)
  • LAN-підмережа(-и) пірінга (наприклад, 10.20.0.0/24)

Надавайте перевагу маршрутизованому режиму; NAT — контрольований компроміс

Якщо мусите робити NAT через перекриття підмереж, робіть це явно і документуйте схему трансляції.
Типовий підхід: Офіс B виглядає для Офісу A як 10.120.0.0/24, хоч насправді це 192.168.1.0/24.
Це вимагає NAT-правил і уважного налаштування DNS/сервісів. Це можливо, але це борг.

Логування: фіксуйте правильні докази

WireGuard сам по собі не спамить логи, що добре для дисків і погано для припущень.
Логуйте на межі брандмауера, де приймаються політичні рішення. Коли приходить інцидент, ви хочете знати:
чи пакет зайшов у шлюз, чи він увійшов у тунель, чи він вийшов з тунелю?

Моніторинг: вимірюйте те, що важливо

  • Вік хендшейку (wg show)
  • Рух лічильників (sent/received)
  • Втрати пакетів/латентність між wg IP
  • Перевірки рівня сервісів через тунель (TCP-перевірки для ваших реальних додатків)

Управління змінами: ставтеся до змін VPN як до продакшн-змін

Тунель — частина вашої продакшн-мережі. Зміни можуть відключити зарплатню, інвентар чи аутентифікацію.
Використовуйте поетапні розгортання: тестуйте зі шлюзів спочатку, потім з одного клієнта, потім поширюйте статичні маршрути на весь офіс.

Висока доступність (опціонально, але варто думати)

WireGuard сам по собі не робить кластеризацію. Ви все одно можете побудувати резервування:

  • Два шлюзи на офіс з VRRP/keepalived для LAN next-hop
  • Кілька пірінгів і селективна маршрутизація (складніше)
  • Швидка заміна: іммутабельні конфіги і швидке розгортання

Якщо ви малі — не перевантажуйтеся. Один добре керований шлюз зі запасними пристроями і протестованою процедурою відновлення кращий за напівзроблену HA-схему.

Поширені питання

1) Чи потрібна виділена підмережа тунелю, як 10.99.0.0/24?

Так. Дайте інтерфейсам WireGuard їхні власні адреси. Це спрощує маршрутизацію, моніторинг і політики брандмауера.
/30 або /31 теж підходять, але /24 — зручно і читабельно.

2) Що саме робить AllowedIPs?

Двоє речей: визначає, які IP-адреси призначення маршрутизуються до пірінга, і які вихідні IP-адреси приймаються від того пірінга.
Трактуйте це як комбінований список префіксів для маршрутизації й ACL.

3) Чи ставити PersistentKeepalive на обох сторонах?

Ставте його на стороні за NAT (або там, де ви підозрюєте, що UDP-мапінги вичерпуються). Якщо не знаєте, — поставити на обох сторонах допустимо.
Це невеликий періодичний пакет; витрати мізерні у порівнянні з часом простою.

4) Чи можна запускати WireGuard прямо на офісному роутері?

Якщо роутер добре підтримує це і ви можете ним безпечно керувати — так. Багато команд віддають перевагу Linux-шлюзу, бо його легше дебажити і автоматизувати.
Оберіть платформу, якою ви можете оперувати о 3:00 ранку, а не ту, що гарно виглядає на діаграмі.

5) Чому «хендшейк успішний» не гарантує працездатності трафіку?

Тому що хендшейк лише доводить, що пірінги можуть обмінюватися автентифікованими повідомленнями.
Трафік LAN все ще може падати через відсутні маршрути, вимкнений IP forwarding, політику форвардінгу брандмауера або MTU-чорні діри.

6) Чи потрібен NAT для site-to-site WireGuard VPN?

Ні, якщо ви контролюєте маршрути на обох сторонах і LAN-підмережі не перекриваються.
NAT — це обхід для обмежень (перекриття, відсутність контролю маршрутів), а не стандарт.

7) Як обробляти перекривання підмереж між офісами?

Найкраще рішення: перенумерація однієї з мереж. Так, болісно; але це чисте рішення.
Якщо не можете перенумерувати — використовуйте NAT з виділеним трансльованим префіксом, оновіть DNS-очікування і будьте готові до дивної поведінки додатків.

8) Який MTU слід використовувати?

Почніть з 1420. Якщо у вас PPPoE, LTE або ви бачите симптоми чорних дір — знижуйте й/або фіксуйте MSS.
Перевіряйте DF-ping і реальні передачі додатків.

9) Чи може WireGuard запускати динамічну маршрутизацію (OSPF/BGP) по тунелю?

WireGuard не надає протоколів маршрутизації сам по собі, але ви можете запускати OSPF/BGP через нього як через будь-яке інше IP-посилання.
Для двох офісів з кількома підмережами статичні маршрути зазвичай простіші і передбачуваніші.

10) Який найнадійніший спосіб ротації ключів?

Додайте новий публічний ключ паралельно (де можливо), перевірте хендшейк і трафік, потім видаліть старий ключ.
Уникайте одночасної заміни ключів на обох сторонах, якщо ви не любите координовані простими збої.

Висновок: практичні наступні кроки

Якщо ви хочете, щоб це спрацювало з першого разу, будуйте по шарам: транспорт, IP тунелю, маршрути, брандмауер, потім тести додатків.
Не звинувачуйте одразу «DNS», доки не довели, що пакети проходять через wg0 в обох напрямках.

  1. Розгорніть конфіги і підтвердіть хендшейки на обох шлюзах.
  2. Підтвердіть наявність маршрутів для віддалених LAN на обох шлюзах.
  3. Додайте статичні маршрути на офісних роутерах, щоб клієнти фактично використовували тунель.
  4. Затягніть правила форвардінгу до мінімально необхідних і додайте мінімальне логування.
  5. Програйте план швидкої діагностики один раз, поки все здорово, і зафіксуйте очікувані виводи.
← Попередня
Від монолітів до чіплетів: чому сучасні процесори нагадують LEGO
Наступна →
Електронна пошта не надсилається з WordPress/додатку: налаштування SMTP-ретранслятора, яке реально доставляє

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