WireGuard (WG) je VPN (virtuálna privátna sieť), resp. protokol, ktorý implementuje techniky VPN na vytváranie bezpečných spojení typu P2P. WG sa zameriava na poskytovanie VPN, ktorá je jednoduchá a zároveň vysoko efektívna. WG je podporovaný väčšinou operačných systémov a je vydaný pod licenciou GPLv2. WG je možné implementovať na sieť IPv4 aj IPv6. Ja som nasadil WG do neprivilegovaného LXC Debian 11 a o tom by som chcel dnes niečo napísať.
Obsah
- Úvod
- Nastavenia NAT pre WG
- Priprava-kontajnera-LXC
- Poinštalačné nastavenia Debianu
- Inštalácia WireGuard
- Generovanie kľúčov a konfigurácia servera
- Generovanie kľúčov a konfigurácia klienta
- Pridávame klienta na server a generujeme QR kód
- Nastavujeme iptables
- Ďalšia WG sieť ?
- Záver
- Použitá literatúra
Úvod
Na internete sú stovky návodov aké je jednoduché nasadiť WG a zdá sa, že je to naozaj tak. Ako obvykle sa budem zameriavať na inštaláciu v LXC postavenom na Debian 11. Vo svete Linuxu existuje viacero možností ako implementovať WG do systému či už pomocou skriptov, Dockera a pod. Pre mňa však bola čistá inštalácia a konfigurácia prínosnejšia ako len spustiť skript a čakať na QR kód pre klienta. Kto nemá záujem sa trocha potrápiť, tak nech sa páči, tu je jeden veľmi šikovný skript na githube
wget https://git.io/wireguard -O wireguard-install.sh && bash wireguard-install.sh
Tento skript nám položí počas inštalácie niekoľko otázok a radovo do niekoľkých sekúnd môžeme WG využívať v plnej sile.
Nastavenia NAT pre WG
Aby som počas konfigurácie WG nemusel odbočovať, tak ešte pred tým než začneme riešiť WG si nastavíme NAT (Network Address Translator). Nastavovať budeme Destination-NAT (DNAT), čo je preklad WAN IP adresy na LAN IP adresu. Ja používam na sieti firewall pfSense, preto ukážem ako sa to nastavuje na pfSense. Prihlásime sa do web konfigurátora pfSense a prejdeme do
Firewall --> NAT --> Port Forward --> ↓Add
Nastavíme to podľa obrázku. Dôležité je nastaviť protokol na UDP. Port je štandardne 51820, ale môžeme si zvoliť aj iný. IP adresa je LAN adresa stroja na ktorom bude bežať WG. Pokiaľ to máme, môžeme nastavenia uložiť save

Príprava kontajnera LXC
Ako obvykle si pripravíme kontajner. LXC môžeme vytvoriť cez web gui Proxmox, alebo pomocou skriptu. V tomto blogu použijem na vytvorenie LXC skript. Samozrejme nepoužívajte tento skript, pretože je nastavený na moje hodnoty a pochybujem, že niekomu by to fungovalo (je to len ukážka ako by mal skript vyzerať). Inštalovať budem Debian 11 netinst.
pct create 111 \
local:vztmpl/debian-11-standard_11.0-1_amd64.tar.gz \
--ssh-public-keys ~/ssh.key \
--ostype debian \
--hostname debian-11-wg \
--unprivileged 1 \
--net0 name=eth0,bridge=vmbr1,gw=192.168.1.1,hwaddr=3A:3D:9B:B0:71:A9,ip=192.168.1.111/24,type=veth \
--cores 1 \
--arch amd64 \
--memory 1024 --swap 512 \
--rootfs local-zfs:4 \
--features nesting=1 \
--onboot 1 \
--start 0 \
Trocha si popíšeme, čo je obsahom tohto skriptu
- Riadok 1: hovorí, že sa má vytvoriť kontajner s ID 111
- Riadok 2: ukazuje cestu k šablóne, kde je uložený inštalačný balík
- Riadok 3: ak sa chceme do LXC prihlasovať ssh kúčom, tak nastavíme cestu k ssh kľúču
- Riadok 4: typ operačného systému
- Riadok 5: hostname si môžeme pomenovať podľa seba (v rámci reguly)
- Riadok 6: LXC by mal byť neprivilegovaný
- Riadok 7: si rozpíšeme
- net0: označuje prve sieťové rozhranie LXC
- eth0: pomenovanie sieťovky v LXC
- bridge: ak má server jednu NIC, tak to bude vmbr0
- gw: je IP adresa brány
- hwaddr: MAC adresa virt. NIC
- ip: je IP adresa LXC
- type: je typ sieťového rozhrania
- Riadok 8: použité bude jedno jadro CPU
- Riadok 9: architektúra CPU md64
- Riadok 10: nastavenie RAM a swapu
- Riadok 11: LXC sa vždy spustí po štarte hostiteľa
- Riadok 12: LXC sa po vytvorení nespustí
Ten posledný riadok nastavíme na 0, aby sa LXC po vytvorení nespustil, pretože pred spustením ešte musme upraviť konfiguračný súbor LXC. Budeme pridávať zariadenie /dev/net/tun.
nano /etc/pve/lxc/111.conf
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net dev/net none bind,create=dir
Konfiguračný súbor uložíme Ctrl+x y enter. Tak isto musíme premapovať UID a GID aby neprivilegovaný LXC mal prístup na /dev/net/tun z hostiteľa. Zároveň si to skontrolujeme.
chown 100000:100000 /dev/net/tun
ls -l /dev/net/tun
crw-rw-rw- 1 100000 100000 10, 200 Mar 26 05:58 /dev/net/tun
Poinštalačné nastavenia Debianu
Teraz nám nič nebráni v spustení nášho LXC. Následne sa cez SSH do LXC prihlásime (heslo nebude vyžadované pokiaľ sme použili počas inštalácie SSH key). Po prihlásení skontrolujeme či je virt. /dev/net/tun viditeľná pod root. To je veľmi dôležité, aby /dev/net/tun v LXC bola pod UID a GID root (číže ID=0), ale na hostiteľovy musí byť pod UID a GID 100000. Teraz pokračujeme základnými nastaveniami systému
ssh root@192.168.1.111
ls -l /dev/net/tun
crw-rw-rw- 1 root root 10, 200 Mar 26 05:58 /dev/net/tun
apt update && apt dist-upgrade -y
dpkg-reconfigure tzdata
Inštalácia WireGuard
Nainštalujeme balík iptables a balík na generovanie QR kódu. Následne nainštalujeme WireGuard.
apt install iptables libqrencode4 qrencode
apt install wireguard
Počas inštalácie, resp. pred koncom môžeme vidieť niečo také
update-initramfs: Generating /boot/initrd.img-5.10.0-13-rt-amd64
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8125b-2.fw for module r8169
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8125a-3.fw for module r8169
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8107e-2.fw for module r8169
W: Possible missing firmware /lib/firmware/rtl_nic/rtl8107e-1.fw for module r8169
Inštalácia sa však bez problémov dokončí bez chyby a my môžeme pokračovať v konfigurácii WG.
Generovanie kľúčov a konfigurácia servera
Filozofia WG spočíva vo výmene verejných kľúčov medzi členmi. Aj keď WG funguje v podstate ako P2P, ja to budem chcieť využiť ako server-klient (to znamená, že kľúče budem generovať na jednom stroji aj pre klientov). Najprv generujeme privátny kľúč servera
wg genkey | tee /etc/wireguard/private.key
a výsledný kľúč bude následovný
+ELPhu4OCVRQdBynJFvtbOHtRuao0il+79k+ItGTzkU=
Tento kľúč nesmie opustiť náš stroj a preto odoberieme skupine a ostatným všetky privilégia. Ďalej z privátneho kľúča vygenerujeme verejný kľúč, ktorý budeme neskôr distribuovať klientom.
chmod go= /etc/wireguard/private.key
cat /etc/wireguard/private.key | wg pubkey | tee /etc/wireguard/public.key
a výsledný kľúč bude následovný
AmMocshc1t5BIfdRFKBuOkUbwaJtA6EZQZrule/OEkU=
Teraz je čas na nastavenie konfigurácie WG. Zvykne sa používať názov súboru wg0, ale je len na nás ako sa konfiguračný súbor bude volať (pri zmene názvu konfig. súboru je potrebné zohľadniť to pri ďalších nastaveniach). Je lepšie zachovať wg0.
nano /etc/wireguard/wg0.conf
[Interface]
PrivateKey = +ELPhu4OCVRQdBynJFvtbOHtRuao0il+79k+ItGTzkU=
Address = 10.10.0.1/32
ListenPort = 51820
To je vlastne konfigurácia celého interface. Vidíme tam náš privátny kľúč. IP adresu som zvolil 10.10.0.1 (IP adresa nesmie kolidovať z inou IP adresou v našej sieti). IP adresy si volíme podľa RFC1918. Port nastavíme 51820 (môže byť aj iný, ale potom to musime zohľadniť v NAT). WG je registrovanou službou systemd, takže môžeme službu povoliť, následne môžeme systemd využiť na sputenie, zastavenie, alebo stav služby.
systemctl enable wg-quick@wg0.service
systemctl status wg-quick@wg0.service
systemctl start wg-quick@wg0.service
systemctl stop wg-quick@wg0.service
skontrolujeme
wg show
interface: wg0
public key: AmMocshc1t5BIfdRFKBuOkUbwaJtA6EZQZrule/OEkU=
private key: (hidden)
listening port: 51820
Generovanie kľúčov a konfigurácia klienta
Teraz vytvoríme prvého klienta. Postup je obdobný ako sme generovali kľúče pre server. Kľúče budeme generovať pomocou wg genkey a wg pubkey aj pre klienta, ale ako som spomínal, všetko budeme generovať na servery.
wg genkey | tee client1_private.key
iDIyg6fTsoAgo2Vm2osanB+TuPP+5IHYm8NgKB/9UE8=
chmod go= client1_private.key
cat client1_private.key | wg pubkey | tee client1_public.key
LzOBW/tFh+4hawbdKNKg/AXHD2D3KZw7myjyUEVLn2s=
Kľúče pre klienta sme vygenerovali a teraz nastavíme konfiguračný súbor. Tento súbor na servery nepotrebujeme, ale nastavíme si ho, lebo z neho budeme generovať QR kód
nano client1.conf
[Interface]
Address = 10.10.0.2/32
PrivateKey = iDIyg6fTsoAgo2Vm2osanB+TuPP+5IHYm8NgKB/9UE8=
[Peer]
PublicKey = AmMocshc1t5BIfdRFKBuOkUbwaJtA6EZQZrule/OEkU=
AllowedIPs = 0.0.0.0/0
Endpoint = host-server.net:51820
PersistentKeepalive = 25
Address je IP adresa rozhrania. Všimnime si v sekcii [Interface] PrivateKey. Toto je privátny kľúč, ktorý patri len klientovi a nesmie opustiť klientov stroj. V sekcii [Peer] vidíme PublicKey. Toto je verejný kľúč, ktorý klientovi poskytol server (resp. klient na druhej strane). AllowedIPs je rozsah IP adries na ktoré môže klient pristupovať cez WG. Avšak na servery to musí byť povolené. Endpoint musíme zadať verejnú IP adresu servera, alebo názov domény (min. jedna strana musí byť na verejnej IPv4 adrese). Nesmieme zabudnúť port na ktorom počúva WG. PersistentKeepalive nie je povinný, ale je dobre ho nastaviť na nejakú rozumnú hodnotu (napr. 25). Tento parameter odosiela na server udržiavací paket aby ostal spoj nažive. Tieto parametre neskôr presunieme do klientského zariadenia.
Pridávame klienta na server a generujeme QR kód
Teraz na servery upravíme wg0.conf a pridáme tam klienta, ktorého sme práve vytvorili aby mohlo byt vytvorene spojenie. Čiže editujeme wg0.conf a na koniec pridáme
nano /etc/wireguard/wg0.conf
[Peer]
PublicKey = LzOBW/tFh+4hawbdKNKg/AXHD2D3KZw7myjyUEVLn2s=
AllowedIPs = 10.10.0.2/32
PublicKey je verejný kľúč, ktorý nám poskytol klient. AllowedIPs je IP adresa(y), pod ktorou môže klient pristúpiť na server.
systemctl stop wg-quick@wg0.service
systemctl start wg-quick@wg0.service
Je čas na generovanie QR kodu pre klienta. QR kód bude vygenerovaný na terminály
qrencode -t ansiutf8 < client1.conf

Keď napr. v mobile cez mobilnú aplikáciu WireGuard naskenujeme QR kód a zapneme tunel, tak okamžite sa spojime s druhou stranou (čiže serverom).. Skontrolovať to môžeme napr. na servery pomocou wg show
interface: wg0
public key: AmMocshc1t5BIfdRFKBuOkUbwaJtA6EZQZrule/OEkU=
private key: (hidden)
listening port: 51820
peer: LzOBW/tFh+4hawbdKNKg/AXHD2D3KZw7myjyUEVLn2s=
endpoint: 84.245.121.33:48487
allowed ips: 10.10.0.2/32
latest handshake: 15 seconds ago
transfer: 23.79 KiB received, 19.03 KiB sent
Vidíme pripojeného peera. V riadku 7 je jeho IP adresa a náhodne generovaný port. Posledný handshake (riadok 9) bol pred 15 sekundami a je tam vidieť aj nejaký transfer.
Nastavujeme iptables
IP adresy 10.10.0.1 a 10.10.0.2 medzi sebou pingaju, takže vyzerá, že všetko je v poriadku. Problém je v tom, že spojenie máme len vo WG sieti a na ďalšie PC v LAN sa nevieme dostať. Dajme tomu, že chceme povoliť klientovi aby mohol pristupovať cez WG do LAN siete na jedinú IP adresu na určitom porte. Pre tento účel musíme spraviť na servery nejaké úpravy.
- Nastavenie preposielania paketov na servery (forwarding)
- SNAT/Masquarading na servery (iptables)
- Zmena AllowedIPs na klientovi
Ukážem nastavenie v ktorom sprístupníme pre klienta jednu IP adresu 192.168.1.156 v LAN na porte 20000 . Tak poďme na to pekne od začiatku. V Linuxe je preposielanie paketov jadrom defaultne zakázané, takže to musíme zmeniť. Skontrolujeme stav
sysctl net.ipv4.ip_forward
Ak je nastavene na 0 tak je preposielenie paketov zakázané a ak je hodnota 1, tak je povolene
net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
Forwarding aktivujeme v linuxe takto
sysctl -w net.ipv4.ip_forward=1
Teraz sme nastavili forwarding na hodnotu 1 (čiže je povolený), ale toto vydrží do najbližšieho rebootu. Ak chceme nastaviť forwarding natrvalo, tak editujeme
nano /etc/sysctl.conf
Buď odkomentujeme riadok net.ipv4.ip_forward s hodnotou 1, alebo jednoducho dopíšeme na koniec súboru toto.
net.ipv4.ip_forward = 1
Ďalej si všimnime, že iptables pravidlá začínajú od riadku 5 a končia na riadku 10. V riadku 5 reťazec FORWARD hovorí, že zakáž preposielanie paketov na akúkoľvek IP adresu, okrem (riadok 7) IP adresy192.168.1.156 na porte 20000 . Riadok 9 zabezpečí maskovanie paketov pri opúšťaní eth0, resp. pakety pri opúšťaní eth0 budú mať zdrojovú IP adresu preloženú na IP adresu ako keby pochádzali z eth0 (SNAT resp. MASQUARADE).
- PreUP pravidla sa do tabuľky zavedú vtedy ak sa spustí wg rozhranie.
- PostDown pravidla sa po zničení wg rozhrania z tabuľky odstránia
[Interface]
Address = 10.10.0.1/32
ListenPort = 51820
PrivateKey = +ELPhu4OCVRQdBynJFvtbOHtRuao0il+79k+ItGTzkU=
PreUP = iptables -I FORWARD -i wg0 -d 0.0.0.0/0 -j REJECT
PostDown = iptables -D FORWARD -i wg0 -d 0.0.0.0/0 -j REJECT
PreUp = iptables -I FORWARD -i wg0 -d 192.168.1.156 -p tcp --dport 20000 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -d 192.168.1.156 -p tcp --dport 20000 -j ACCEPT
PreUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = LzOBW/tFh+4hawbdKNKg/AXHD2D3KZw7myjyUEVLn2s=
AllowedIPs = 10.10.0.2/32
U klienta bude vyzerať nastavenie takto:
[Interface]
Address = 10.10.0.2/32
PrivateKey = iDIyg6fTsoAgo2Vm2osanB+TuPP+5IHYm8NgKB/9UE8=
[Peer]
PublicKey = AmMocshc1t5BIfdRFKBuOkUbwaJtA6EZQZrule/OEkU=
AllowedIPs = 192.168.1.0/24, 10.10.0.0/24
Endpoint = host-server.net:51820
PersistentKeepalive = 25
Teraz klient dosiahne wg0 sieť a v LAN môže komunikovať len s IP adresou 192.168.1.156 na porte 20000. Ak by sme chceli povoliť celú LAN klientovi, tak nastavíme pravidlo v riadku 7 (resp 8) takto:
PreUp = iptables -I FORWARD -i wg0 -d 192.168.1.0/24 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -d 192.168.1.0/24 -j ACCEPT
Ak by sme chceli vytvárať ďalších klientov, tak postupujeme rovnakým spôsobom. To znamená vygenerujeme pre klienta privátny kľuč a z neho následne verejný. Klient však môže tieto kľúče generovať aj u seba. Potom si verejne kľúče (server a klient) medzi sebou vymenia. Na servery do wg0.conf pridáme peera a klient si u seba vytvorí taktiež wg0 (viď vyššie).
Ďalšia WG sieť ?
Žiadny problém. WG je nainštalovaný. Vygenerujeme nový privátny a verejný kľúč pre ďalší server. Vytvoríme nový interface (pochopiteľne s novým IP rozsahom (napr. 10.11.0.0/24)), použijeme iný port (napr. 52821). Konfiguračný súbor pomenujeme napr. wg1.conf. Na firewalle/routery pridáme ďalší NAT pre nový port a máme hotovo. Je to naozaj veľmi jednoduché.
Záver
WireGuard sa zdá byť oproti robustnému OpenVPN dobrou alternatívou. Podľa rôznych štatistík je vďaka efektívnejším metódam šifrovania 3x rýchlejší ako OpenVPN. Konfigurácia WG je oveľa jednoduchšia ako konfigurácia OpenVPN. Ďalšou výhodou je roaming pri prechode medzi IP adresami. Samozrejme WG má aj nejaké nevýhody, funguje len na UDP, zatiaľčo OpenVPN pozná aj TCP. Ak používate tunelovanie OpenVPN, tak rozhodne odporúčam skúsiť aj WG.
V tomto blogu sú všetky kľúče a domény, vymyslené (vrátane QR kódu) ktoré reálne neexistujú.