WireGuard — поглиблений гайд¶
WireGuard — сучасний VPN протокол, що поєднує простоту, швидкість та безпеку. Цей гайд розглядає просунуті аспекти: криптографію, mesh топології, оптимізацію та troubleshooting.
Чому WireGuard?¶
Порівняння з іншими VPN¶
| Аспект | WireGuard | OpenVPN | IPsec |
|---|---|---|---|
| Код | ~4000 рядків | ~100000 | ~400000 |
| Швидкість | Найвища | Середня | Висока |
| Криптографія | Сучасна, фіксована | Налаштовується | Налаштовується |
| Аудит | Простий | Складний | Дуже складний |
| Handshake | 1 RTT | 2+ RTT | Багато RTT |
| Statefulness | Stateless | Stateful | Stateful |
Переваги WireGuard¶
mindmap
root((WireGuard))
Простота
Мінімальна конфігурація
Легкий troubleshooting
4000 рядків коду
Швидкість
Kernel module
ChaCha20 на ARM
~1 Gbps на RPi4
Безпека
Сучасна криптографія
Криптографічна маршрутизація
Немає legacy алгоритмів
Roaming
Auto reconnect
WiFi ↔ LTE
Stateless designКриптографія¶
Noise Protocol Framework¶
WireGuard використовує Noise_IK handshake — лише 1 RTT (порівняно з 2+ RTT для TLS):
sequenceDiagram
participant I as 🔑 Initiator
participant R as 🔑 Responder
I->>R: Handshake Initiation
Note over I,R: ephemeral_pub, encrypted_static,<br/>encrypted_timestamp, MAC
R->>I: Handshake Response
Note over I,R: ephemeral_pub, encrypted_nothing, MAC
Note over I,R: 🔐 Symmetric keys derived<br/>(ChaCha20-Poly1305)
I->>R: Encrypted Data
R->>I: Encrypted Data
Note over I,R: Захищений двосторонній каналКриптографічні примітиви¶
| Примітив | Використання |
|---|---|
| Curve25519 | ECDH для обміну ключами |
| ChaCha20 | Симетричне шифрування |
| Poly1305 | Автентифікація (MAC) |
| BLAKE2s | Хешування |
| HKDF | Деривація ключів |
# Всі примітиви — сучасні та швидкі
# Особливо ChaCha20-Poly1305 на ARM без AES-NI
# Benchmark на MikroTik hAP ax3:
# AES-GCM: ~300 Mbps
# ChaCha20: ~500 Mbps
Ключі¶
# Генерація ключів
wg genkey > private.key
wg pubkey < private.key > public.key
# Або одним рядком
wg genkey | tee private.key | wg pubkey > public.key
# Pre-shared key (додатковий захист)
wg genpsk > psk.key
Private key — 32 байти Curve25519 scalar
Public key — 32 байти Curve25519 point
Pre-shared key — 32 байти симетричний ключ (опціонально)
Криптографічна маршрутизація (Cryptokey Routing)¶
Унікальна особливість WireGuard — AllowedIPs працює одночасно як таблиця маршрутизації (для вихідних) та ACL (для вхідних):
flowchart TB
subgraph outgoing["Вихідний пакет до 192.168.2.100"]
OUT1["1️⃣ Шукаємо peer<br/>AllowedIPs містить 192.168.2.100"]
OUT2["2️⃣ Шифруємо<br/>public key peer"]
OUT3["3️⃣ Відправляємо<br/>на endpoint peer"]
OUT1 --> OUT2 --> OUT3
end
subgraph incoming["Вхідний пакет"]
IN1["1️⃣ Дешифруємо<br/>визначаємо peer"]
IN2["2️⃣ Перевіряємо<br/>source IP в AllowedIPs?"]
IN3{"✅ Так"}
IN4{"❌ Ні"}
IN5["ACCEPT"]
IN6["DROP"]
IN1 --> IN2
IN2 --> IN3 --> IN5
IN2 --> IN4 --> IN6
end
style outgoing fill:#dbeafe
style incoming fill:#fef3c7Приклад конфігурації¶
[Peer]
PublicKey = ABC123...
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Mesh топологія¶
Full Mesh¶
flowchart TB
A["🖥️ Node A<br/>10.0.0.1"]
B["🖥️ Node B<br/>10.0.0.2"]
C["🖥️ Node C<br/>10.0.0.3"]
A <-->|"WireGuard"| B
B <-->|"WireGuard"| C
A <-->|"WireGuard"| C
style A fill:#dbeafe
style B fill:#d1fae5
style C fill:#fef3c7| Metric | Full Mesh |
|---|---|
| З'єднання | N(N-1)/2 |
| 3 nodes | 3 з'єднання |
| 10 nodes | 45 з'єднань |
Hub and Spoke¶
flowchart TB
HUB["🏢 Hub<br/>10.0.0.1"]
A["📱 Spoke A<br/>10.0.0.2"]
B["📱 Spoke B<br/>10.0.0.3"]
C["📱 Spoke C<br/>10.0.0.4"]
HUB <--> A
HUB <--> B
HUB <--> C
style HUB fill:#ef4444,color:#fff
style A fill:#dbeafe
style B fill:#d1fae5
style C fill:#fef3c7| Metric | Hub and Spoke |
|---|---|
| З'єднання | N-1 |
| Масштабування | Легке |
| SPOF | Hub |
Приклад mesh на MikroTik¶
# Node A (Hub): 10.0.0.1, public IP 203.0.113.1
/interface wireguard add listen-port=51820 name=wg0 private-key="<A_PRIVATE>"
/interface wireguard peers
add allowed-address=10.0.0.2/32,192.168.2.0/24 interface=wg0 \
public-key="<B_PUBLIC>" endpoint-address=203.0.113.2 endpoint-port=51820
add allowed-address=10.0.0.3/32,192.168.3.0/24 interface=wg0 \
public-key="<C_PUBLIC>" endpoint-address=203.0.113.3 endpoint-port=51820
/ip address add address=10.0.0.1/24 interface=wg0
# Маршрути до мереж за nodes
/ip route add dst-address=192.168.2.0/24 gateway=wg0
/ip route add dst-address=192.168.3.0/24 gateway=wg0
AllowedIPs детально¶
Як працює¶
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Означає:
1. ВИХІДНІ пакети на 10.0.0.2 або 192.168.2.0/24
→ шифруються цим peer
2. ВХІДНІ пакети від цього peer
→ можуть мати source IP тільки з цих діапазонів
Типові значення¶
# Тільки peer IP (point-to-point)
AllowedIPs = 10.0.0.2/32
# Peer + мережа за ним
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
# Весь трафік через peer (VPN gateway)
AllowedIPs = 0.0.0.0/0, ::/0
# Декілька мереж
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24, 172.16.0.0/16
Split Tunnel vs Full Tunnel¶
flowchart LR
subgraph split["Split Tunnel"]
C1["👤 Client"]
VPN1["🔒 WireGuard<br/>10.0.0.0/24"]
INET1["🌐 Internet<br/>напряму"]
C1 -->|"internal"| VPN1
C1 -->|"youtube, google"| INET1
end
subgraph full["Full Tunnel"]
C2["👤 Client"]
VPN2["🔒 WireGuard<br/>0.0.0.0/0"]
INET2["🌐 Internet"]
C2 --> VPN2 --> INET2
end
style split fill:#d1fae5
style full fill:#dbeafe| Аспект | Split Tunnel | Full Tunnel |
|---|---|---|
| AllowedIPs | 10.0.0.0/24, ... |
0.0.0.0/0 |
| Інтернет | Напряму | Через VPN |
| Навантаження | Менше | Більше |
| Приватність | Часткова | Повна |
| UMTC рекомендація | ✅ | Для спец. випадків |
PersistentKeepalive¶
Навіщо потрібен?¶
sequenceDiagram
participant A as 📱 Peer A<br/>(за NAT)
participant NAT as 🔀 NAT Router
participant B as 🖥️ Peer B<br/>(public IP)
A->>NAT: Пакет до B
Note over NAT: Створює запис<br/>в NAT table
NAT->>B: Forward
B->>NAT: Відповідь
NAT->>A: Forward (є запис)
Note over NAT: ⏰ 60-300 сек без трафіку
Note over NAT: ❌ Запис видалено!
B--xNAT: Не може достукатись
Note over B: Зв'язок втраченоРішення: PersistentKeepalive = 25 — кожні 25 секунд відправляється keepalive пакет, NAT запис оновлюється.
Коли використовувати?¶
# Потрібен якщо:
# - Peer за NAT
# - Peer ініціює з'єднання ззовні (сервер хоче достукатись до клієнта)
# - Нестабільна мережа
# НЕ потрібен якщо:
# - Обидва peer з public IP
# - Клієнт завжди ініціює з'єднання сам
# - Постійний трафік в обидва боки
# MikroTik
/interface wireguard peers set [find] persistent-keepalive=25
# Linux
[Peer]
PersistentKeepalive = 25
MTU оптимізація¶
Проблема фрагментації¶
flowchart LR
subgraph overhead["WireGuard Overhead"]
IP["IPv4: 20 bytes"]
UDP["UDP: 8 bytes"]
WG["WireGuard: 32 bytes"]
TOTAL["Total: 60 bytes"]
end
ETH["Ethernet MTU<br/>1500 bytes"] --> WG_MTU["WireGuard MTU<br/>1500 - 60 = 1440"]
WG_MTU --> PPPOE["З PPPoE<br/>1440 - 8 = 1432"]
style overhead fill:#fee2e2| Сценарій | MTU |
|---|---|
| Ethernet | 1500 |
| WireGuard | 1440 |
| WireGuard + PPPoE | 1432 |
| Safe default | 1420 |
flowchart LR
PKT["📦 1500 byte packet"]
WG["🔒 WireGuard<br/>+60 bytes"]
BIG["📦 1560 bytes"]
FRAG["⚠️ Fragmentation"]
DROP["❌ DROP (DF=1)"]
PKT --> WG --> BIG
BIG --> FRAG
BIG --> DROPРішення¶
# MikroTik — встановити MTU на WireGuard інтерфейсі
/interface wireguard set wg0 mtu=1420
# Linux
ip link set wg0 mtu 1420
# Або в конфізі
[Interface]
MTU = 1420
# Визначити оптимальний MTU
ping -M do -s 1400 10.0.0.1 # Збільшувати поки не буде fragmented
MSS Clamping (альтернатива)¶
# MikroTik — змінювати MSS в TCP пакетах
/ip firewall mangle add chain=forward protocol=tcp \
tcp-flags=syn in-interface=wg0 \
action=change-mss new-mss=clamp-to-pmtu
# Або фіксоване значення
action=change-mss new-mss=1380
NAT Traversal¶
Проблема подвійного NAT¶
flowchart TB
A["📱 Peer A<br/>192.168.1.x"]
NAT_A["🔀 NAT A"]
INET["🌐 Internet"]
NAT_B["🔀 NAT B"]
B["📱 Peer B<br/>192.168.2.x"]
A --- NAT_A
NAT_A --- INET
INET --- NAT_B
NAT_B --- B
A -.->|"❓"| B
style A fill:#fee2e2
style B fill:#fee2e2Проблема: Жоден не має public IP — як з'єднатись?
Рішення¶
-
Один peer з public IP (рекомендовано)
Peer A (NAT) → Peer B (public) — працює -
UDP Hole Punching (складно)
Потрібен STUN сервер для координації Не завжди працює (symmetric NAT) -
Relay сервер
Peer A → Relay (public) → Peer B Завжди працює, але затримка
Моніторинг та дебаг¶
Linux¶
# Статус інтерфейсу
wg show
# Детальніше
wg show wg0
# interface: wg0
# public key: ABC...
# private key: (hidden)
# listening port: 51820
#
# peer: XYZ...
# endpoint: 203.0.113.1:51820
# allowed ips: 10.0.0.2/32
# latest handshake: 15 seconds ago
# transfer: 1.5 MiB received, 2.3 MiB sent
# Перевірити handshake
# "latest handshake" має бути < 2 хвилини
# Якщо "never" — peer недоступний
MikroTik¶
# Статус peers
/interface wireguard peers print detail
# Rx/Tx лічильники
/interface wireguard peers print stats
# Моніторинг в реальному часі
/interface wireguard peers monitor [find]
# Логи
/system logging add topics=wireguard action=memory
/log print where topics~"wireguard"
Типові проблеми¶
Проблема: "latest handshake: never"
Причина:
- Неправильний endpoint
- Firewall блокує UDP
- Неправильні ключі
Рішення:
- Перевірити ping до endpoint
- Відкрити UDP port
- Перегенерувати ключі
Проблема: Handshake є, але немає трафіку
Причина:
- AllowedIPs не включає потрібні мережі
- Немає маршрутів
- Firewall на peer
Рішення:
- Перевірити AllowedIPs
- Додати маршрути
- Перевірити firewall
Проблема: Періодичні обриви
Причина:
- NAT timeout
- Нестабільний endpoint
Рішення:
- Додати PersistentKeepalive=25
- Перевірити мережу
MikroTik особливості¶
Firewall для WireGuard¶
# Дозволити WireGuard (UDP 51820)
/ip firewall filter add chain=input protocol=udp dst-port=51820 action=accept \
comment="WireGuard"
# Дозволити трафік з wg інтерфейсу (якщо потрібно)
/ip firewall filter add chain=input in-interface=wg0 action=accept \
comment="WireGuard tunnel traffic"
# Forward між WireGuard та LAN
/ip firewall filter add chain=forward in-interface=wg0 out-interface=bridge-lan action=accept
/ip firewall filter add chain=forward in-interface=bridge-lan out-interface=wg0 action=accept
DDNS (динамічний endpoint)¶
# Якщо peer не має статичного IP
# Використовувати доменне ім'я в endpoint
# MikroTik Cloud DDNS
/ip cloud set ddns-enabled=yes
# Отримати ім'я
/ip cloud print
# dns-name: abc123.sn.mynetname.net
# На іншому peer:
endpoint-address=abc123.sn.mynetname.net
Резервування (failover)¶
# Створити два WireGuard інтерфейси
/interface wireguard add name=wg-primary ...
/interface wireguard add name=wg-backup ...
# Налаштувати routing з distance
/ip route add dst-address=10.0.0.0/24 gateway=wg-primary distance=1
/ip route add dst-address=10.0.0.0/24 gateway=wg-backup distance=2
# Netwatch для перевірки
/tool netwatch add host=10.0.0.1 interval=10s \
down-script="/ip route disable [find gateway=wg-primary]" \
up-script="/ip route enable [find gateway=wg-primary]"
Безпека та hardening¶
# 1. Використовувати PSK для постквантової безпеки
wg genpsk > psk.key
# Додати до обох peers
# 2. Обмежити AllowedIPs
# НЕ використовувати 0.0.0.0/0 якщо не потрібно
# 3. Firewall — дозволяти тільки потрібний трафік
/ip firewall filter add chain=forward in-interface=wg0 \
dst-address=192.168.1.0/24 dst-port=22,80,443 protocol=tcp action=accept
# 4. Приховати private key
# Ніколи не показувати в логах
# Зберігати в захищеному місці
# 5. Регулярно оновлювати RouterOS
/system package update check-for-updates
Пов'язані теми¶
- WireGuard mesh — базове налаштування
- GNS3 — тестування в лабораторії
- SSH ключі — аналогічний підхід до ключів
- MikroTik — налаштування роутерів
- Криптографія — основи шифрування
- WireGuard node setup — покрокова інструкція
Шлях: networking/vpn/wireguard-advanced.md