
WireGuard VPN — bezpieczny dostęp do homelabu z zewnątrz
Konfiguracja WireGuard na serwerze domowym i urządzeniach mobilnych. Bezpiecznie łącz się z domową siecią z dowolnego miejsca.
Dlaczego WireGuard?
Jeśli kiedykolwiek próbowałeś skonfigurować OpenVPN, wiesz jak to wygląda — setki linii konfiguracji, własne CA, certyfikaty, klucze, CRL. WireGuard robi to samo w 10 liniach pliku konfiguracyjnego i działa szybciej. To nie marketing — to matematyka.
WireGuard vs OpenVPN — twarda porównanie
| Cecha | WireGuard | OpenVPN |
|---|---|---|
| Rozmiar kodu | ~4 000 linii | ~70 000+ linii |
| Przepustowość | ~1 Gb/s | ~250 Mb/s |
| Latencja | bardzo niska | wyższa (TCP overhead) |
| Konfiguracja | minimalna | rozbudowana |
| Protokół | UDP (zawsze) | UDP lub TCP |
| Audytowalność | łatwa | trudna |
| Mobilność (IP roaming) | natywna | brak |
WireGuard działa w przestrzeni jądra Linuksa (od wersji 5.6 jest wbudowany), co oznacza dramatycznie niższy overhead w porównaniu do OpenVPN działającego w przestrzeni użytkownika. Na przeciętnym serwerze homelab różnica w przepustowości to 3-4x na korzyść WireGuard.
**Najważniejsza zaleta dla homelabu:** kiedy Twoje urządzenie mobilne zmienia sieć (WiFi → LTE → inny WiFi), WireGuard utrzymuje połączenie bez zrywania. OpenVPN wymaga nowego uzgodnienia. W praktyce oznacza to, że VPN po prostu działa — bez reconnectów, bez przerw w SSH.
---
Instalacja na serwerze
Zakładam, że masz serwer z Debian 12 lub Ubuntu 22.04+. WireGuard jest w standardowych repozytoriach.
Przygotowanie systemu
```bash
# Aktualizacja systemu
sudo apt update && sudo apt upgrade -y
# Instalacja WireGuard
sudo apt install wireguard wireguard-tools -y
# Weryfikacja modułu jądra
modinfo wireguard
```
Generowanie kluczy serwera
```bash
# Przejdź do katalogu WireGuard
cd /etc/wireguard
# Generuj parę kluczy serwera (prywatny + publiczny)
wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
# Zabezpiecz klucz prywatny
sudo chmod 600 server_private.key
# Wyświetl klucze (zapisz je!)
echo "Private key: $(sudo cat server_private.key)"
echo "Public key: $(sudo cat server_public.key)"
```
Generowanie kluczy klienta (na serwerze)
```bash
# Generuj klucze dla każdego klienta osobno
wg genkey | sudo tee client1_private.key | wg pubkey | sudo tee client1_public.key
sudo chmod 600 client1_private.key
# Pre-shared key dla dodatkowej warstwy bezpieczeństwa
wg genpsk | sudo tee client1_preshared.key
sudo chmod 600 client1_preshared.key
```
Ustal interfejs sieciowy serwera
```bash
# Znajdź główny interfejs sieciowy
ip route | grep default
# Przykład: default via 192.168.1.1 dev eth0
# Twój interfejs to np. eth0, ens3, enp3s0 — zapamiętaj go!
```
---
Konfiguracja serwera
Plik /etc/wireguard/wg0.conf
```ini
[Interface]
# Adres IP serwera w sieci VPN
Address = 10.0.0.1/24
# Port nasłuchu UDP (możesz użyć 51820, 443 lub dowolnego)
ListenPort = 51820
# Klucz prywatny serwera
PrivateKey = TWOJ_KLUCZ_PRYWATNY_SERWERA
# Reguły iptables — włącz routing (zamień eth0 na swój interfejs!)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# --- Klient 1: Laptop ---
[Peer]
PublicKey = KLUCZ_PUBLICZNY_KLIENTA_1
PresharedKey = PRESHARED_KEY_KLIENTA_1
# Adres IP klienta w sieci VPN
AllowedIPs = 10.0.0.2/32
# --- Klient 2: Telefon ---
[Peer]
PublicKey = KLUCZ_PUBLICZNY_KLIENTA_2
AllowedIPs = 10.0.0.3/32
```
Włącz IP forwarding
```bash
# Tymczasowo (do następnego restartu)
sudo sysctl -w net.ipv4.ip_forward=1
# Trwale — dodaj do sysctl.conf
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
Uruchom interfejs WireGuard
```bash
# Uruchom interfejs
sudo wg-quick up wg0
# Włącz autostart przy restarcie systemu
sudo systemctl enable wg-quick@wg0
# Sprawdź status i podłączonych klientów
sudo wg show
```
Port forwarding na routerze
Na routerze domowym przekieruj ruch UDP na port 51820 do IP serwera:
Każdy router ma inny interfejs — szukaj sekcji "Port Forwarding", "Virtual Server" lub "NAT".
---
Konfiguracja klienta
Linux (wersja CLI)
```bash
# Instalacja
sudo apt install wireguard -y
# Utwórz plik konfiguracyjny
sudo nano /etc/wireguard/wg0.conf
```
```ini
[Interface]
# Adres klienta w sieci VPN
Address = 10.0.0.2/24
# Klucz prywatny klienta
PrivateKey = KLUCZ_PRYWATNY_KLIENTA_1
# Serwer DNS z homelabu (np. Pi-hole) lub publiczny
DNS = 10.0.0.1
[Peer]
# Klucz publiczny serwera
PublicKey = KLUCZ_PUBLICZNY_SERWERA
# Pre-shared key (zalecane)
PresharedKey = PRESHARED_KEY_KLIENTA_1
# Publiczny IP lub domena serwera + port
Endpoint = TWOJ_PUBLICZNY_IP:51820
# Co routować przez VPN:
# 0.0.0.0/0 = cały ruch (full tunnel)
# 10.0.0.0/24, 192.168.1.0/24 = tylko homelab (split tunnel)
AllowedIPs = 0.0.0.0/0, ::/0
# Keepalive dla połączeń za NAT
PersistentKeepalive = 25
```
```bash
# Połącz
sudo wg-quick up wg0
# Rozłącz
sudo wg-quick down wg0
```
Windows i macOS
1. Pobierz oficjalną aplikację WireGuard z wireguard.com/install
2. Kliknij "Add Tunnel" i wybierz "Add empty tunnel"
3. Wklej konfigurację klienta — identyczny format jak na Linuksie
4. Kliknij "Activate"
Aplikacja na Windows i macOS ma graficzny interfejs, ale konfiguracja jest dokładnie taka sama — wklejana do GUI zamiast pliku tekstowego.
Android i iOS — kod QR
Najszybsza metoda to wygenerowanie kodu QR bezpośrednio na serwerze:
```bash
# Na serwerze — zainstaluj qrencode
sudo apt install qrencode -y
# Wygeneruj konfigurację klienta i zamień w kod QR
cat << 'WGCONF' | qrencode -t ansiutf8
[Interface]
Address = 10.0.0.3/24
PrivateKey = KLUCZ_PRYWATNY_KLIENTA_2
DNS = 10.0.0.1
[Peer]
PublicKey = KLUCZ_PUBLICZNY_SERWERA
Endpoint = TWOJ_PUBLICZNY_IP:51820
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25
WGCONF
```
W aplikacji WireGuard na telefonie wybierz "+" a następnie "Scan from QR code" i zeskanuj kod wyświetlony w terminalu. Gotowe w 30 sekund.
---
Docker: wg-easy
Dla tych, którzy wolą panel webowy zamiast konfiguracji ręcznej, **wg-easy** to kompletny serwer VPN z interfejsem graficznym zamknięty w jednym kontenerze.
docker-compose.yml
```yaml
version: '3.8'
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
environment:
# Twój publiczny IP lub domena DDNS
- WG_HOST=TWOJ_PUBLICZNY_IP
# Hasło do panelu webowego — zmień na silne!
- PASSWORD=zmien_to_haslo_na_silne
# Port UDP dla WireGuard
- WG_PORT=51820
# Port HTTP dla panelu webowego
- PORT=51821
# Domyślny DNS dla klientów
- WG_DEFAULT_DNS=1.1.1.1,8.8.8.8
# MTU — zostaw domyślne lub dostosuj
- WG_MTU=1420
# Keepalive w sekundach
- WG_PERSISTENT_KEEPALIVE=25
# Zakres IP dla klientów VPN
- WG_DEFAULT_ADDRESS=10.8.0.x
# Split tunnel — tylko homelab przez VPN
- WG_ALLOWED_IPS=10.8.0.0/24, 192.168.1.0/24
volumes:
- ./wg-easy-data:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv4.ip_forward=1
restart: unless-stopped
```
```bash
# Uruchom
docker compose up -d
# Panel webowy dostępny pod adresem:
# http://IP_SERWERA:51821
```
Panel wg-easy pozwala:
To idealne rozwiązanie dla rodziny — możesz dodać klienta dla każdego domownika bez dotykania terminala.
---
Bezpieczeństwo
Zarządzanie kluczami
Klucz prywatny WireGuard to tożsamość urządzenia. Kilka zasad których przestrzegaj bezwzględnie:
```bash
# Zawsze ustaw odpowiednie uprawnienia na klucze prywatne
chmod 600 /etc/wireguard/*.key
chown root:root /etc/wireguard/*.key
# Backup konfiguracji — zaszyfrowany archiwum
tar czf - /etc/wireguard/ | gpg --symmetric --cipher-algo AES256 -o wg-backup-$(date +%Y%m%d).tar.gz.gpg
# Generuj nowe klucze dla każdego urządzenia — nie kopiuj konfiguracji między urządzeniami
# Jeśli klucz prywatny wycieknie, wygeneruj nowy i zaktualizuj serwer
```
Firewall — UFW
```bash
# Zainstaluj UFW jeśli go nie masz
sudo apt install ufw -y
# Domyślna polityka
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH — zmień port jeśli używasz innego niż 22
sudo ufw allow 22/tcp
# WireGuard UDP
sudo ufw allow 51820/udp
# Routing przez interfejs VPN
sudo ufw allow in on wg0
sudo ufw allow out on wg0
# Włącz firewall
sudo ufw enable
# Sprawdź status
sudo ufw status verbose
```
Zapobieganie wyciekom DNS
W konfiguracji każdego klienta zawsze ustaw DNS:
```ini
[Interface]
DNS = 10.0.0.1 # Pi-hole lub inny DNS w homelabіe
```
Weryfikacja na Linuksie przy aktywnym VPN:
```bash
# Sprawdź czy zewnętrzny IP wychodzi przez serwer VPN
dig +short myip.opendns.com @resolver1.opendns.com
# Sprawdź jaki DNS jest używany
resolvectl status
```
Na telefonie użyj strony dnsleaktest.com — powinna pokazać wyłącznie IP Twojego serwera lub Pi-hole.
Split tunnel vs Full tunnel
Dla niezaufanego WiFi (kawiarnie, hotele, lotniska) używaj full tunnel. Do codziennego dostępu z telefonu do domowych zasobów — split tunnel.
---
Rozwiązywanie problemów
Problem 1: Nie mogę się połączyć z zewnątrz
```bash
# 1. Sprawdź czy WireGuard działa
sudo wg show
sudo systemctl status wg-quick@wg0
# 2. Sprawdź czy port jest otwarty na serwerze
sudo ss -tulnp | grep 51820
# 3. Test z zewnętrznej sieci (np. telefon na LTE)
# Zainstaluj nmap i sprawdź port UDP:
nmap -sU -p 51820 TWOJ_PUBLICZNY_IP
# 4. Sprawdź logi w czasie rzeczywistym
sudo journalctl -u wg-quick@wg0 -f
```
Najczęstszy powód: port forwarding na routerze skonfigurowany dla TCP zamiast UDP. WireGuard używa wyłącznie UDP.
Problem 2: Połączenie jest, ale nie ma dostępu do internetu (full tunnel)
```bash
# Sprawdź IP forwarding
sysctl net.ipv4.ip_forward
# Wynik powinien być: net.ipv4.ip_forward = 1
# Sprawdź reguły iptables NAT
sudo iptables -t nat -L POSTROUTING -v
# Sprawdź czy PostUp w wg0.conf używa właściwego interfejsu
ip route | grep default
# Interfejs w PostUp musi być identyczny z tym co tutaj widzisz
```
Problem 3: Wysoka latencja lub niska przepustowość — MTU
MTU to najczęstszy problem przy WireGuard przez PPPoE (VDSL, ADSL) lub podwójny NAT:
```bash
# Znajdź maksymalne MTU bez fragmentacji
# Zmniejszaj wartość -s aż ping przejdzie bez błędu "Frag needed"
ping -M do -s 1400 10.0.0.1
ping -M do -s 1350 10.0.0.1
ping -M do -s 1300 10.0.0.1
```
```ini
# W konfiguracji klienta i serwera dodaj w sekcji [Interface]:
MTU = 1280 # Bezpieczna wartość dla większości łączy
# PPPoE (VDSL/ADSL): spróbuj 1412
# Standardowy Ethernet: 1420
```
Problem 4: Dynamiczny IP — DDNS
Jeśli ISP zmienia Ci IP (brak statycznego adresu):
```bash
# Zainstaluj ddclient dla automatycznych aktualizacji DNS
sudo apt install ddclient -y
# Lub użyj lekkiego skryptu z cron (przykład dla DuckDNS)
cat << 'EOF' | sudo tee /usr/local/bin/update-duckdns.sh
#!/bin/bash
DOMAIN="twojadomena"
TOKEN="twoj-token-duckdns"
curl -s "https://www.duckdns.org/update?domains=${DOMAIN}&token=${TOKEN}&ip=" > /tmp/duckdns.log
EOF
sudo chmod +x /usr/local/bin/update-duckdns.sh
# Dodaj do cron — aktualizuj co 5 minut
echo "*/5 * * * * /usr/local/bin/update-duckdns.sh" | sudo crontab -
```
W konfiguracji klienta używaj nazwy domenowej zamiast IP:
```ini
Endpoint = mojhomelab.duckdns.org:51820
```
WireGuard rozwiązuje DNS przy nawiązywaniu połączenia, więc zmiana IP serwera jest obsługiwana automatycznie przy następnym połączeniu klienta.
---
Podsumowanie
WireGuard to aktualnie najlepszy wybór dla homelabowców potrzebujących bezpiecznego zdalnego dostępu. Konfiguracja zajmuje 30 minut, działa niezawodnie i wymaga minimalnego utrzymania. Kluczowe punkty:
Masz pytania albo coś nie działa? Piszcie w komentarzach — community TechTemple pomoże.