W domu stoi NAS. Albo Raspberry z Home Assistantem, albo kamerka. Chciałbyś się do tego dobić spoza domu, ale operator dał Ci CGNAT i żadnego publicznego IP, więc na routerze możesz sobie przekierowywać porty do woli, a i tak nic z tego nie wyjdzie.

Brzmi znajomo? To dość powszechna bolączka, a rozwiązanie jest zaskakująco eleganckie: VPS w roli pośrednika. VPS ma publiczny adres, więc domowa maszyna łączy się do niego jako klient WireGuarda. Ty z laptopa robisz dokładnie to samo, i przez VPS-a lądujesz w domowej sieci.

Od razu jedno sprostowanie, bo pytania o to wracają jak bumerang. To nie jest ten darmowy, współdzielony WireGuard z panelu Mikrusa (sekcja “Wireguard”). Tamten służy do wychodzenia z VPS-a w świat przez fiński węzeł, choćby po to, żeby zmienić widoczny adres IP. Do wpuszczania ruchu do domu kompletnie się nie nadaje. Tutaj stawiamy własny serwer WireGuard, na Twoim VPS-ie.

Na Mikrusie#

W NOOBS-ie jest wprawdzie skrypt chce_wireguard.sh, ale on rozwiązuje inny problem. Stawia prosty tunel serwer + jeden klient (tzw. “road warrior”) z configiem z mikr.us/generator.php, a do tego kompiluje ze źródeł Go i wireguard-go, czyli WireGuarda w wersji userspace. Ma to sens na maszynach, gdzie jądro WireGuarda nie obsługuje.

Na obecnych węzłach Mikrusa ta gimnastyka jest zbędna. Sprawdziłem to sam: WireGuard z jądra działa od strzału, wystarczy zwykły pakiet z apt. Skrypt nie radzi sobie poza tym z kilkoma peerami ani z routingiem do sieci domowej. Dlatego robimy wszystko ręcznie. Paradoksalnie wychodzi prościej i pewniej niż budowanie czegokolwiek ze źródeł.

Na dowolnym serwerze (Ubuntu/Debian)#

Na Mikrusie i na każdym innym VPS-ie z Ubuntu albo Debianem:

sudo apt update
sudo apt install wireguard

I tyle, jeśli chodzi o instalację.

Konfiguracja serwera (VPS)#

Para kluczy dla VPS-a:

umask 077
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey

umask 077 dba o to, żeby klucz prywatny mógł odczytać wyłącznie root. Bez tego plik dostałby domyślne, zdecydowanie zbyt liberalne uprawnienia.

Konfiguracja ląduje w /etc/wireguard/wg0.conf:

sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.20.0.1/24
ListenPort = 20112
PrivateKey = TUTAJ_KLUCZ_PRYWATNY_VPS

PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.20.0.0/24 -o eth0 -j MASQUERADE

Przejdźmy przez to po kolei.

ListenPort to port UDP, na którym nasłuchuje WireGuard. Standardowo 51820, tylko że na Mikrusie po IPv4 z zewnątrz dotrzesz wyłącznie do portów przekierowanych na Twój serwer, czyli 20000+ID i 30000+ID. Zamiast 20112 wpisz więc jeden z nich (dla m112 będzie to 20112 albo 30112). Na zwykłym VPS-ie z własnym publicznym IPv4 spokojnie zostaw 51820.

Address to adres VPS-a wewnątrz tunelu. Wziąłem 10.20.0.0/24, bo raczej nie pogryzie się z żadną domową siecią.

W miejsce TUTAJ_KLUCZ_PRYWATNY_VPS wklejasz zawartość /etc/wireguard/privatekey (podglądniesz ją przez sudo cat /etc/wireguard/privatekey).

PostUp i PostDown włączają przekazywanie pakietów - bez tego VPS nie puści ruchu dalej, w stronę domu - oraz maskaradę, dzięki której ruch z tunelu wyjdzie normalnym interfejsem VPS-a. Twój interfejs nie nazywa się eth0? Sprawdzisz to przez ip route | grep default.

Peery, czyli dom i laptop, dopiszemy do tego pliku za moment.

Konfiguracja peera w domu#

Na domowym komputerze albo routerze też instalujesz WireGuarda: na Linuksie apt install wireguard, na pozostałych systemach oficjalna aplikacja. Ten peer dostaje osobną parę kluczy:

umask 077
wg genkey | tee dom-privatekey | wg pubkey > dom-publickey

Teraz wg0.conf na domowej maszynie. X.X.X.X to publiczny adres Twojego VPS-a. Na Mikrusie będzie to adres serwera fizycznego, na którym stoi Twój VPS (zadziała też nazwa w rodzaju srv07.mikr.us), a port to ten sam, który wpisałeś w ListenPort:

[Interface]
Address = 10.20.0.2/24
PrivateKey = TUTAJ_KLUCZ_PRYWATNY_DOMOWY

[Peer]
PublicKey = TUTAJ_KLUCZ_PUBLICZNY_VPS
Endpoint = X.X.X.X:20112
AllowedIPs = 10.20.0.0/24
PersistentKeepalive = 25

Masz w domu IPv6? To jeszcze lepiej, bo możesz połączyć się po nim. Każdy Mikrus ma własny publiczny adres IPv6 i żadne przekierowania nie są tam potrzebne. Adres wpisujesz w nawiasach kwadratowych, np. Endpoint = [2a01:4f9:xxxx::112]:20112. Swój adres IPv6 wyświetlisz na VPS-ie przez ip -6 addr show scope global. Gdyby jednak operator albo część domowego sprzętu z IPv6 się nie lubiła, zostań przy IPv4 i przekierowanym porcie.

PersistentKeepalive = 25 po stronie domowej jest istotne. Dom siedzi za NAT-em, więc po chwili ciszy tunel zwyczajnie przysypia, a VPS nie jest w stanie go dobudzić. To przecież dom łączy się do VPS-a, a nie odwrotnie.

Wracamy na VPS-a i dopisujemy peera domowego, żeby VPS wiedział, którędy kierować ruch do Twojej sieci. W miejsce 192.168.1.0/24 wpisz faktyczną podsieć domowego LAN-u:

[Peer]
# dom
PublicKey = TUTAJ_KLUCZ_PUBLICZNY_DOMOWY
AllowedIPs = 10.20.0.2/32, 192.168.1.0/24

Samo 192.168.1.0/24 w AllowedIPs nie załatwia jednak sprawy, jeśli chcesz sięgać dalej niż do tej jednej maszyny. Na domowym komputerze trzeba jeszcze włączyć przekazywanie pakietów (sysctl -w net.ipv4.ip_forward=1), a domowy router musi wiedzieć, że odpowiedzi do 10.20.0.0/24 ma odsyłać właśnie przez ten komputer.

Konfiguracja peera do zdalnego dostępu (np. laptop)#

Laptop to w zasadzie powtórka z domu. Nowa para kluczy, a w AllowedIPs na laptopie wpisujesz 10.20.0.0/24, 192.168.1.0/24 - tunel plus domową podsieć, do której chcesz się dostać.

Na VPS-ie dochodzi kolejny [Peer] z kluczem publicznym laptopa i AllowedIPs = 10.20.0.3/32. Tym razem bez domowej podsieci. O tym, że laptop kieruje tam ruch, decyduje jego własny routing, a VPS-owi wystarczy wiedza, że pakiety z 10.20.0.3 są w porządku.

Uruchomienie na stałe#

Na VPS-ie:

sudo systemctl enable --now wg-quick@wg0

Czy tunel żyje i widzi peery?

sudo wg show

Gdy peer domowy się podłączy, przy nim zamiast (none) pojawi się latest handshake z konkretnym czasem. Ten moment zawsze cieszy.

Najczęstsze błędy#

Brak latest handshake. Zwykle zawinił zły klucz publiczny w którymś configu (klucz VPS-a i domowy łatwo zamienić miejscami) albo firewall VPS-a blokuje port UDP z ListenPort. WireGuard chodzi po UDP, nie po TCP. Na Mikrusie upewnij się też, że używasz przekierowanego portu, 20000+ID albo 30000+ID. Na 51820 po IPv4 nikt z zewnątrz się nie dobije.

Handshake jest, ale domowej sieci z laptopa nie widać. Sprawdź ip_forward na domowej maszynie i to, czy w AllowedIPs peera domowego na VPS-ie rzeczywiście jest domowa podsieć, a nie sam adres z tunelu.

Tunel chwilę działa, po czym się rwie. Brakuje PersistentKeepalive u peera schowanego za NAT-em. Zazwyczaj chodzi o dom.

Address already in use przy starcie. Albo coś już zajęło port z ListenPort, albo interfejs wg0 został po poprzedniej, nieudanej próbie. Zanim ponownie odpalisz wg-quick up, zajrzyj do sudo wg show i sudo ip link show wg0.