Eintrag

WireGuard: Modernes VPN für dein Homelab mit wg-easy

WireGuard: Modernes VPN für dein Homelab mit wg-easy

Hinweis: Dieser Post beschreibt wg-easy v14. Seit Version 15 hat sich das Setup grundlegend geändert – Environment-Variablen wurden durch ein Admin Panel und eine SQLite-Datenbank ersetzt. Für v15 siehe wg-easy v15: Migration & Neues Setup.

Du bist unterwegs und möchtest auf dein Homelab zugreifen - das Proxmox-Dashboard checken, Dateien vom NAS holen, oder die Heizung über Home Assistant regulieren. Die Lösung: ein VPN. Und wenn es um moderne VPN-Technologie geht, führt kein Weg an WireGuard vorbei. Mit wg-easy hast du das Ganze in unter 5 Minuten am Laufen - versprochen.


Was ist WireGuard?

WireGuard ist ein modernes VPN-Protokoll, das seit 2020 direkt im Linux-Kernel integriert ist (ab Version 5.6). Entwickelt von Jason Donenfeld, setzt es neue Maßstäbe in Sachen Geschwindigkeit, Sicherheit und Einfachheit.

Die Zahlen sprechen für sich: WireGuard kommt mit gerade mal rund 4.000 Zeilen Code aus - OpenVPN bringt es auf über 100.000 Zeilen. Weniger Code bedeutet weniger Angriffsfläche und einfacheres Auditing.

Technische Grundlagen:

  • Nutzt moderne, bewährte Kryptographie: Curve25519 für den Schlüsselaustausch, ChaCha20 für die Verschlüsselung, Poly1305 für die Authentifizierung und BLAKE2s für Hashing
  • Läuft im Kernel-Space, nicht im Userspace - das macht es deutlich schneller
  • Arbeitet mit statischen Public/Private-Key-Paaren (ähnlich wie SSH)
  • Unterstützt nahtloses Roaming zwischen Netzwerken (WLAN zu mobilen Daten ohne Verbindungsabbruch)
  • In jeder modernen Linux-Distribution enthalten, verfügbar für Windows, macOS, iOS, Android und mehr

Die Philosophie dahinter: Ein VPN sollte so einfach wie möglich sein, dabei aber trotzdem höchste Sicherheitsstandards erfüllen. Kein Schnickschnack, keine hundert Konfigurationsoptionen - einfach funktionieren.


Warum WireGuard statt OpenVPN?

Viele Homelab-Betreiber schwören noch auf OpenVPN. Verständlich - es funktioniert seit Jahren zuverlässig. Aber ein direkter Vergleich zeigt deutlich, warum ein Umstieg sinnvoll ist:

Aspekt WireGuard OpenVPN IPSec/IKEv2
Codebase ~4.000 Zeilen ~100.000 Zeilen Komplex
Geschwindigkeit Sehr schnell Mittel Schnell
Verbindungsaufbau ~100ms ~8s ~1s
Kryptographie Modern, fest Konfigurierbar Konfigurierbar
Kernel-Integration Ja (Linux) Nein (Userspace) Ja
Roaming Ja (IP-Wechsel) Eingeschränkt Ja
Konfiguration Einfach Komplex Komplex
Mobile Akku Sehr gut Mäßig Gut

Die Killer-Features von WireGuard:

Roaming: Du wechselst von WLAN zu mobilen Daten? Kein Problem. WireGuard merkt das und baut die Verbindung nahtlos wieder auf. Bei OpenVPN bedeutet das oft einen Verbindungsabbruch und Neuaufbau.

Akkulaufzeit: Auf mobilen Geräten ist WireGuard ein Traum. Durch die effiziente Implementierung und intelligente Keep-Alive-Mechanismen hält der Akku deutlich länger als mit OpenVPN.

Geschwindigkeit: Die Kernel-Integration und moderne Kryptographie sorgen für maximale Performance. Besonders bei Uploads merkt man den Unterschied - wichtig, wenn du von unterwegs auf dein Homelab zugreifst.

Einfachheit: Eine WireGuard-Konfiguration passt auf eine Haftnotiz. Keine Certificate Authorities, keine komplexen TLS-Handshakes, keine Dutzende von Konfigurationsparametern. Einfach zwei Schlüsselpaare, fertig.

WireGuard ist nicht nur schneller und sicherer - es macht auch einfach mehr Spaß. Keine ewig dauernden Verbindungsaufbauten, kein Gefrickel mit Zertifikaten, keine kryptischen Fehlermeldungen.


WireGuard Grundkonzepte

Bevor wir uns wg-easy anschauen, solltest du die Grundlagen verstehen. WireGuard ist konzeptionell sehr einfach, aber ein paar Kernkonzepte sind wichtig.

Schlüsselpaare

Jeder Teilnehmer in einem WireGuard-Netzwerk hat ein Schlüsselpaar - genau wie bei SSH. Ein privater Schlüssel (bleibt geheim) und ein öffentlicher Schlüssel (wird geteilt).

1
2
3
4
5
6
7
8
9
10
# Schlüsselpaar generieren
wg genkey | tee private.key | wg pubkey > public.key

# Privater Schlüssel (NIEMALS teilen!)
cat private.key
# Ausgabe: yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=

# Öffentlicher Schlüssel (wird in Peer-Configs eingetragen)
cat public.key
# Ausgabe: HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=

Der private Schlüssel verlässt nie dein Gerät. Andere Peers bekommen nur deinen öffentlichen Schlüssel - genau wie bei SSH.

Peers und AllowedIPs

WireGuard kennt keine strikte Client-Server-Hierarchie. Es gibt nur Peers, die miteinander kommunizieren. Jeder Peer kann initiieren, jeder kann Verbindungen annehmen.

Das Herzstück ist AllowedIPs - damit definierst du, welcher Traffic durch den Tunnel soll:

1
2
3
4
5
6
7
8
# Full Tunnel: ALLER Traffic geht durchs VPN
AllowedIPs = 0.0.0.0/0, ::/0

# Split Tunnel: Nur Homelab-Traffic geht durchs VPN
AllowedIPs = 10.8.0.0/24, 192.168.60.0/24, 192.168.2.0/24

# Einzelner Host
AllowedIPs = 10.8.0.2/32

Full Tunnel bedeutet: Deine komplette Internetverbindung läuft über das VPN. Dein Homelab wird quasi dein Internet-Gateway. Gut für Sicherheit auf öffentlichen WLANs, aber langsamer.

Split Tunnel bedeutet: Nur spezifische Netzwerke gehen durchs VPN. YouTube und Netflix laufen weiterhin direkt, aber Proxmox, NAS und Home Assistant gehen durch den Tunnel. Die bessere Wahl für die meisten Homelab-Szenarien.

WireGuard-Konfiguration manuell

So würde eine manuelle Server-Konfiguration aussehen:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
Address = 10.8.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
AllowedIPs = 10.8.0.2/32

Und die entsprechende Client-Konfiguration:

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = cGaP7jJZpGJYQqDDx9x5dMl8z8p7TYB9nYnKM5wZVnE=
Address = 10.8.0.2/24
DNS = 10.8.0.1

[Peer]
PublicKey = 2S7mA0vEMethCNQrJpJKE81wykf0jAZbpHJh2T7D5Ik=
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

Die Erklärung:

  • PostUp/PostDown: iptables-Regeln für NAT und Forwarding - damit deine Clients ins Internet können
  • Endpoint: Die öffentliche IP oder Domain deines Servers
  • PersistentKeepalive: Sendet alle 25 Sekunden ein Keep-Alive-Paket - wichtig für NAT-Traversal
  • DNS: DNS-Server, der im VPN genutzt wird (z.B. dein Pi-hole)

Das funktioniert - aber für jeden neuen Client musst du ein Schlüsselpaar generieren, die Config manuell schreiben und auf beiden Seiten eintragen. Machbar für 2-3 Geräte, nervig ab 5+.

Genau hier kommt wg-easy ins Spiel.


Was ist wg-easy?

wg-easy ist die einfachste Art, WireGuard zu betreiben. Es ist ein Docker-Container, der WireGuard mit einer wunderschönen Web-UI kombiniert.

Was es kann:

  • Client-Verwaltung über eine intuitive Web-Oberfläche
  • QR-Codes für Mobile-Clients - einfach scannen, fertig
  • Automatische Schlüsselgenerierung - kein manuelles Gefummel
  • Eingebaute Traffic-Statistiken - siehst sofort, welcher Client wie viel Traffic macht
  • Ein-Klick-Download von Client-Configs
  • Revoke-Funktion - Clients lassen sich mit einem Klick deaktivieren

Das Projekt auf GitHub hat über 18.000 Stars und wird aktiv weiterentwickelt: github.com/wg-easy/wg-easy

Die Architektur:

WireGuard Topologie

So einfach ist das: Du installierst wg-easy auf einem Server in deinem Homelab, machst Port-Forwarding für UDP 51820, und schon können sich deine Geräte verbinden. Die Web-UI läuft auf Port 51821 und ist ausschließlich für die Administration gedacht - nicht für den VPN-Traffic selbst.

wg-easy macht WireGuard so einfach wie Tailscale - aber du behältst die volle Kontrolle. Keine Cloud, keine Drittanbieter, alles bei dir im Homelab.


Installation mit Docker

Die Installation ist denkbar einfach. Du brauchst nur Docker und Docker Compose.

Voraussetzungen:

  • Docker und Docker Compose installiert
  • Eine öffentliche IP oder DynDNS-Domain
  • Port-Forwarding im Router (UDP 51820)
  • Ein Server in deinem Homelab (VM, LXC, oder direkt auf dem Host)

Docker Compose Setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:latest
    container_name: wg-easy
    environment:
      - LANG=de
      - WG_HOST=vpn.example.com          # Deine öffentliche IP oder Domain
      - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuOKJxsK.eH9JZBWYf9ibRJpq7ZPPe.StLk7S/CU6  # bcrypt Hash für Web-UI
      - WG_DEFAULT_DNS=10.8.0.1           # DNS-Server im VPN (z.B. AdGuard/Pi-hole)
      - WG_ALLOWED_IPS=0.0.0.0/0          # Full Tunnel (oder spezifische Netze)
      - WG_PERSISTENT_KEEPALIVE=25        # Keep-Alive für NAT
      - WG_DEFAULT_ADDRESS=10.8.0.x       # Subnet für Clients
      - WG_MTU=1420                       # MTU-Größe (Standard)
      - UI_TRAFFIC_STATS=true             # Traffic-Statistiken aktivieren
      - UI_CHART_TYPE=2                   # Chart-Typ (0=none, 1=bar, 2=line)
    volumes:
      - ./wg-easy:/etc/wireguard
    ports:
      - "51820:51820/udp"                 # WireGuard
      - "51821:51821/tcp"                 # Web UI
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

Passwort-Hash generieren:

Das Passwort für die Web-UI wird als bcrypt-Hash gespeichert. Generiere ihn so:

1
docker run -it ghcr.io/wg-easy/wg-easy wgpw 'DeinSicheresPasswort123!'

Kopiere den Output (beginnend mit $2y$10$...) und trage ihn bei PASSWORD_HASH ein. Wichtig: In Docker Compose musst du das $ escapen - daher $$2y$$10$$... mit doppelten Dollar-Zeichen.

Container starten:

1
docker compose up -d

Das war’s. Nach wenigen Sekunden läuft dein WireGuard-Server.

WARNUNG: Exponiere Port 51821 (Web-UI) niemals direkt ins Internet ohne zusätzliche Absicherung! Nutze einen Reverse Proxy mit SSL oder beschränke den Zugriff auf dein lokales Netz.

Erste Schritte:

  1. Öffne http://<server-ip>:51821 im Browser
  2. Logge dich mit deinem Passwort ein
  3. Klicke auf “New Client”
  4. Vergib einen Namen (z.B. “iPhone Frank”)
  5. Fertig - QR-Code scannen oder Config herunterladen

Netzwerk-Voraussetzungen

Damit deine Clients von außen auf den WireGuard-Server zugreifen können, brauchst du ein paar Netzwerk-Einstellungen.

Port-Forwarding im Router

WireGuard nutzt UDP Port 51820. Dieser muss von deinem Router auf den Server weitergeleitet werden, auf dem wg-easy läuft.

Typische Router-Einstellung:

  • Protokoll: UDP
  • Externer Port: 51820
  • Interner Port: 51820
  • Ziel-IP: Die IP deines wg-easy Servers (z.B. 192.168.60.100)

Öffentliche IP oder DynDNS

Deine Clients müssen wissen, wie sie deinen Server erreichen. Dafür brauchst du entweder:

Statische öffentliche IP: Einfach die IP als WG_HOST eintragen.

DynDNS: Wenn dein Provider dir regelmäßig neue IPs zuteilt, nutze einen DynDNS-Dienst wie DuckDNS, No-IP oder Cloudflare. Dann trägst du die Domain als WG_HOST ein (z.B. vpn.example.com).

CGNAT-Problem

Wenn du hinter Carrier-Grade NAT (CGNAT) sitzt - also keine öffentliche IP hast - wird es kompliziert. Port-Forwarding funktioniert dann nicht.

Lösungen:

  • Einen kleinen VPS mieten und darauf WireGuard laufen lassen
  • Eine Relay-Lösung wie Pangolin nutzen (siehe meinen anderen Post über Pangolin)
  • Auf Tailscale/Netbird umsteigen (beide haben NAT-Traversal eingebaut)

Netzwerk-Topologie

So sieht der Datenfluss aus:

flowchart LR
    Phone([Smartphone<br>unterwegs]) -->|WireGuard<br>UDP:51820| Router[Router<br>Port-Forward]
    Router -->|LAN| WGEasy[wg-easy<br>10.8.0.1]
    WGEasy -->|VPN Tunnel| Services[Homelab Services<br>Proxmox: 192.168.60.15<br>NAS: 192.168.2.10<br>Home Assistant: 192.168.30.85]

    style Phone fill:#e1f5ff
    style WGEasy fill:#ffe1e1
    style Services fill:#e1ffe1

Dein Smartphone verbindet sich über das Internet zum Router, der leitet den Traffic an wg-easy weiter. wg-easy entschlüsselt den Tunnel und routet die Pakete an deine Homelab-Services.


Clients einrichten

Jetzt kommt der schönste Teil: Clients hinzufügen. Mit wg-easy ist das kinderleicht.

Web-UI Walkthrough

  1. Web-UI öffnen: http://<server-ip>:51821
  2. Einloggen mit dem Passwort, das du im Docker Compose hinterlegt hast
  3. “New Client” klicken - ein Popup öffnet sich
  4. Namen vergeben - z.B. “iPhone Frank”, “Laptop Arbeit”, “iPad Wohnzimmer”
  5. QR-Code erscheint - entweder scannen oder Config-Datei herunterladen
  6. Fertig! Der Client ist aktiv und kann sich verbinden

Die Web-UI zeigt dir sofort:

  • Alle Clients mit Namen
  • Wann sie zuletzt online waren
  • Wie viel Traffic sie verbraucht haben
  • Den öffentlichen Schlüssel jedes Clients
  • Download-Button für die Config-Datei
  • Delete-Button zum Entfernen

Ein riesiger Vorteil: Du siehst auf einen Blick, welche Geräte verbunden sind und wie viel Traffic sie machen. Alte, ungenutzte Clients kannst du einfach löschen.

Mobile (iOS/Android)

Mobile Clients sind am einfachsten:

  1. WireGuard-App installieren
  2. QR-Code scannen
    • App öffnen
    • “Add a tunnel” → “Create from QR code”
    • QR-Code aus der wg-easy Web-UI scannen
    • Fertig
  3. VPN aktivieren
    • Toggle anschalten
    • Bei Bedarf: “On-Demand” aktivieren, damit das VPN automatisch startet, wenn du das Heim-WLAN verlässt

On-Demand ist genial: Du kannst Regeln definieren, z.B. “VPN immer an, außer im Heim-WLAN”. Sobald du das Haus verlässt, aktiviert sich das VPN automatisch - ohne dass du dran denken musst.

Desktop (Windows/macOS/Linux)

Für Desktop-Geräte lädst du die Config-Datei herunter:

Windows/macOS:

  1. WireGuard-Client installieren: wireguard.com/install
  2. Config-Datei aus wg-easy Web-UI herunterladen
  3. In der WireGuard-App: “Add Tunnel” → Config-Datei auswählen
  4. Verbinden

Linux:

1
2
3
4
5
6
7
8
9
10
11
# Config-Datei herunterladen
wget http://<wg-easy-ip>:51821/api/wireguard/client/<client-id>/configuration -O ~/laptop.conf

# Tunnel aktivieren
wg-quick up ~/laptop.conf

# Status prüfen
sudo wg show

# Tunnel deaktivieren
wg-quick down ~/laptop.conf

Für dauerhaften Betrieb auf Linux:

1
2
3
4
5
6
7
8
9
# Config nach /etc/wireguard kopieren
sudo cp ~/laptop.conf /etc/wireguard/wg0.conf

# Systemd-Service aktivieren
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Status
sudo systemctl status wg-quick@wg0

Split Tunnel vs. Full Tunnel

Eine der wichtigsten Entscheidungen: Soll ALLER Traffic durchs VPN oder nur der für dein Homelab?

Full Tunnel (0.0.0.0/0)

Bedeutet:

  • ALLER Internet-Traffic läuft durchs VPN
  • Dein Homelab wird dein Internet-Gateway
  • Deine öffentliche IP ist die deines Heimnetzes

Vorteile:

  • Maximum an Sicherheit auf öffentlichen WLANs
  • Perfekt für Reisen oder unsichere Netzwerke
  • Ad-Blocking via Pi-hole/AdGuard auch unterwegs

Nachteile:

  • Höhere Latenz für alle Dienste
  • Upload-Bandbreite deines Heimanschlusses wird zum Bottleneck
  • Streaming (Netflix, YouTube) läuft über deine Heimleitung

Split Tunnel (spezifische Subnetze)

Bedeutet:

  • Nur Traffic für bestimmte Netzwerke geht durchs VPN
  • Rest geht direkt (normale Routing)

Vorteile:

  • Bessere Performance für allgemeines Surfen
  • Streaming läuft direkt, nicht über deine Heimleitung
  • Geringerer Akku-Verbrauch auf mobilen Geräten
  • Weniger Last auf deinem Heim-Upload

Nachteile:

  • Kein Ad-Blocking für normalen Internet-Traffic
  • Öffentliche WLANs bleiben unsicher für Nicht-Homelab-Traffic

Konfiguration:

1
2
3
4
5
# Full Tunnel (in docker-compose.yml)
- WG_ALLOWED_IPS=0.0.0.0/0

# Split Tunnel (nur Homelab)
- WG_ALLOWED_IPS=10.8.0.0/24,192.168.60.0/24,192.168.2.0/24

Oder nachträglich in der Client-Config ändern:

1
2
3
4
5
[Peer]
PublicKey = ...
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 192.168.60.0/24, 192.168.2.0/24  # Nur Homelab
PersistentKeepalive = 25

Meine Empfehlung:

Für die meisten Homelab-Anwendungen ist Split Tunnel die bessere Wahl. Du greifst auf deine lokalen Services zu - Proxmox, NAS, Home Assistant, GitLab - ohne dass Netflix, YouTube und Spotify durch deinen Heim-Upload gequetscht werden.

Split Tunnel ist der Sweet Spot: Zugriff aufs Homelab mit voller Performance, normaler Internet-Traffic bleibt schnell.


DNS im VPN-Tunnel

Ein oft unterschätztes Feature: DNS-Konfiguration im VPN. Damit kannst du nicht nur auf IP-Adressen zugreifen, sondern auch auf Hostnamen - und sogar Ad-Blocking mitnehmen.

DNS-Server konfigurieren

In der wg-easy docker-compose.yml:

1
- WG_DEFAULT_DNS=10.8.0.1  # DNS-Server für VPN-Clients

Optionen:

AdGuard/Pi-hole im Homelab:

1
- WG_DEFAULT_DNS=192.168.2.5  # Dein AdGuard/Pi-hole

Damit bekommen deine VPN-Clients automatisch Ad-Blocking, egal wo sie sind.

Cloudflare/Google:

1
- WG_DEFAULT_DNS=1.1.1.1,8.8.8.8  # Öffentliche DNS

Funktioniert immer, aber kein Ad-Blocking.

Lokales DNS + Fallback:

1
- WG_DEFAULT_DNS=192.168.2.5,1.1.1.1  # Erst lokales DNS, dann Cloudflare

Lokale Hostnamen nutzen

Wenn dein DNS-Server (z.B. Pi-hole) lokale Hostnamen auflöst, kannst du im VPN direkt auf proxmox.local oder nas.home zugreifen - ohne IP-Adressen zu merken.

Beispiel-Setup:

  1. Pi-hole läuft auf 192.168.2.5
  2. Pi-hole hat Local DNS Records:
    • proxmox.home192.168.60.15
    • nas.home192.168.2.10
    • hass.home192.168.30.85
  3. WG_DEFAULT_DNS=192.168.2.5 in wg-easy
  4. Im VPN: http://proxmox.home:8006 funktioniert direkt

Datenfluss:

flowchart LR
    Phone([Smartphone<br>im VPN]) -->|DNS-Anfrage:<br>proxmox.home| WG[WireGuard Tunnel]
    WG -->|Anfrage an<br>10.8.0.1| DNS[Pi-hole/AdGuard<br>192.168.2.5]
    DNS -->|Antwort:<br>192.168.60.15| WG
    WG -->|IP zurück| Phone
    Phone -->|HTTPS zu<br>192.168.60.15| Proxmox[Proxmox<br>192.168.60.15:8006]

    style Phone fill:#e1f5ff
    style DNS fill:#ffe1e1
    style Proxmox fill:#e1ffe1

Das ist besonders praktisch, wenn du viele Services hast - keine IP-Adressen merken, einfach die Hostnamen nutzen.

DNS-Integration ist ein Game-Changer: Ad-Blocking unterwegs + bequeme Hostnamen statt IP-Adressen.


wg-easy hinter einem Reverse Proxy

Die Web-UI auf Port 51821 solltest du nicht direkt ins Internet exponieren. Besser: Hinter einem Reverse Proxy mit SSL.

WICHTIG: Nur die Web-UI (TCP 51821) kann hinter einen Proxy. Der WireGuard-Port (UDP 51820) MUSS direkt erreichbar sein - UDP funktioniert nicht durch HTTP-Proxies.

Nginx Proxy Manager

Wenn du NPM nutzt:

  1. Proxy Host erstellen
    • Domain: wg.example.com
    • Scheme: http
    • Forward Hostname: <wg-easy-ip>
    • Forward Port: 51821
  2. SSL aktivieren
    • SSL Certificate: Let’s Encrypt generieren
    • Force SSL: aktivieren
    • HTTP/2: aktivieren
    • Websockets Support: aktivieren (wichtig!)
  3. Port aus docker-compose.yml entfernen

Ändere die docker-compose.yml:

1
2
3
4
5
6
7
8
services:
  wg-easy:
    # ...
    ports:
      - "51820:51820/udp"    # WireGuard - bleibt
      # - "51821:51821/tcp"  # Web UI - entfernen
    expose:
      - "51821"              # Nur intern exponieren

Jetzt ist die Web-UI nur noch über https://wg.example.com erreichbar - mit SSL, HTTP/2 und sauberem Zertifikat.

Traefik

Falls du Traefik nutzt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy:latest
    # ...
    ports:
      - "51820:51820/udp"
    expose:
      - "51821"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wg-easy.rule=Host(`wg.example.com`)"
      - "traefik.http.routers.wg-easy.entrypoints=websecure"
      - "traefik.http.routers.wg-easy.tls.certresolver=letsencrypt"
      - "traefik.http.services.wg-easy.loadbalancer.server.port=51821"
    networks:
      - traefik-net

networks:
  traefik-net:
    external: true

Auch hier: UDP 51820 bleibt direkt exponiert, nur die Web-UI läuft über Traefik.

Reverse Proxy für die Web-UI = sauber, sicher, SSL. Aber nie den WireGuard-Port selbst hinter einen Proxy packen - das funktioniert nicht.


Sicherheit

WireGuard ist von Haus aus sehr sicher - aber ein paar Punkte solltest du beachten.

Kryptographie

WireGuard nutzt moderne, geprüfte Algorithmen:

  • Curve25519: Elliptic Curve für Schlüsselaustausch
  • ChaCha20: Verschlüsselung (schneller als AES auf mobilen Geräten ohne Hardware-Beschleunigung)
  • Poly1305: Authentifizierung
  • BLAKE2s: Hashing
  • HKDF: Key Derivation

Im Gegensatz zu OpenVPN oder IPSec gibt es keine Konfigurationsoptionen für “schwächere” oder “stärkere” Krypto. Die Algorithmen sind fest - und das ist gut so. Weniger Entscheidungen = weniger Fehlerquellen.

Private Keys

Private Keys verlassen niemals das Gerät. Selbst die wg-easy Web-UI zeigt sie nicht an - nur die öffentlichen Keys sind sichtbar.

Wenn ein Gerät verloren geht: Einfach in der Web-UI löschen. Der Client kann sich nicht mehr verbinden.

Keine offenen Ports

Ein unterschätzter Sicherheitsvorteil: WireGuard lauscht zwar auf Port 51820, aber antwortet nur auf korrekt signierte Pakete. Ohne gültiges Schlüsselpaar sieht ein Port-Scan… nichts. Der Port scheint geschlossen.

Web-UI schützen

Die Web-UI ist der einzige “angreifbare” Teil:

Best Practices:

  1. Starkes Passwort: Mindestens 20 Zeichen, Buchstaben, Zahlen, Sonderzeichen
  2. Reverse Proxy mit SSL: Verschlüsselte Verbindung zur UI
  3. Nur im lokalen Netz: Port 51821 nicht von außen erreichbar machen
  4. fail2ban: Bei wiederholten Login-Versuchen IPs sperren

AllowedIPs einschränken

Wenn du Split Tunnel nutzt, limitierst du automatisch, welche Netze über das VPN erreichbar sind. Das ist auch ein Sicherheitsfeature:

1
- WG_ALLOWED_IPS=10.8.0.0/24,192.168.60.0/24  # Nur VPN-Subnet und Homelab

Selbst wenn jemand deinen VPN-Zugang kompromittiert, kann er nur auf diese Netze zugreifen - nicht auf dein komplettes Heimnetz.

WireGuard ist sicher by design. Die einzige Schwachstelle: schwache Passwörter für die Web-UI. Also: starkes Passwort, SSL, fertig.


Vergleich: wg-easy vs. WireGuard manuell vs. Tailscale vs. Netbird

Es gibt viele Wege, ein VPN fürs Homelab zu betreiben. Hier der Überblick:

Feature wg-easy WireGuard manuell Tailscale Netbird
Web-UI Ja, lokal Nein Ja, Cloud Ja, self-hosted
QR-Codes Ja Nein Ja Ja
Auto-Config Ja Nein Ja Ja
Self-Hosted 100% 100% Nein (Cloud) Ja (optional Cloud)
Kosten Kostenlos Kostenlos Free Tier / Pro Kostenlos / Enterprise
NAT Traversal Manuell (Port-Forward) Manuell Automatisch Automatisch
Multi-User Ja Ja (manuell) Ja Ja
Mesh VPN Nein Nein Ja Ja
Komplexität Niedrig Hoch Sehr niedrig Niedrig
Client-Apps Standard WireGuard Standard WireGuard Eigene Apps Eigene Apps
Kontrolle 100% 100% Eingeschränkt Hoch
Relay-Server Nein (direkt) Nein Ja (bei CGNAT) Ja (bei CGNAT)

Wann wg-easy?

  • Du hast eine öffentliche IP oder DynDNS
  • Du willst volle Kontrolle, alles self-hosted
  • Du brauchst eine einfache Web-UI für Client-Management
  • Standard WireGuard-Apps reichen dir

Wann Tailscale/Netbird?

  • Du sitzt hinter CGNAT (keine Port-Forwards möglich)
  • Du willst Mesh VPN (jedes Gerät direkt mit jedem verbunden)
  • Du brauchst automatisches NAT-Traversal
  • Du bist okay mit Cloud-Komponenten (Tailscale) oder self-hosted Management (Netbird)

Wann manuelles WireGuard?

  • Du hast nur 2-3 Clients, die sich nie ändern
  • Du willst absolute Minimalismus, keine zusätzlichen Services
  • Du magst Konfigurationsdateien mehr als Web-UIs

Meine Empfehlung:

Für die meisten Homelab-Setups ist wg-easy die beste Wahl. Du behältst die volle Kontrolle, hast aber den Komfort einer Web-UI. Wenn du hinter CGNAT sitzt oder Mesh-VPN brauchst, schau dir Tailscale oder Netbird an.


Erweiterte Konfiguration

Für fortgeschrittene Nutzer gibt es noch mehr Möglichkeiten.

Custom PostUp/PostDown Rules

wg-easy setzt die iptables-Regeln automatisch, aber du kannst eigene Regeln hinzufügen. Dafür musst du die Container-Config anpassen:

1
2
3
4
5
6
services:
  wg-easy:
    # ...
    environment:
      - WG_POST_UP=iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT; iptables -A FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
      - WG_POST_DOWN=iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT; iptables -D FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

Das ist nützlich, wenn du spezifische Firewall-Regeln brauchst oder nur bestimmte Ports erlauben willst.

Multiple WireGuard-Netzwerke

Du kannst mehrere wg-easy Instanzen laufen lassen - z.B. eins für Familie, eins für Arbeit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
services:
  wg-easy-family:
    image: ghcr.io/wg-easy/wg-easy:latest
    container_name: wg-easy-family
    environment:
      - WG_HOST=vpn-family.example.com
      - WG_DEFAULT_ADDRESS=10.8.0.x
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    # ...

  wg-easy-work:
    image: ghcr.io/wg-easy/wg-easy:latest
    container_name: wg-easy-work
    environment:
      - WG_HOST=vpn-work.example.com
      - WG_DEFAULT_ADDRESS=10.9.0.x
    ports:
      - "51822:51820/udp"
      - "51823:51821/tcp"
    # ...

Jede Instanz hat eigene Schlüssel, eigene Clients, eigene Subnets.

Site-to-Site VPN

Du kannst auch zwei Standorte miteinander verbinden - z.B. Homelab und Elternhaus.

Standort A (Homelab):

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = <private-key-a>
Address = 10.10.0.1/24
ListenPort = 51820

[Peer]
PublicKey = <public-key-b>
Endpoint = standort-b.example.com:51820
AllowedIPs = 10.10.0.2/32, 192.168.100.0/24  # Remote-Netz
PersistentKeepalive = 25

Standort B (Elternhaus):

1
2
3
4
5
6
7
8
9
10
[Interface]
PrivateKey = <private-key-b>
Address = 10.10.0.2/24
ListenPort = 51820

[Peer]
PublicKey = <public-key-a>
Endpoint = homelab.example.com:51820
AllowedIPs = 10.10.0.1/32, 192.168.60.0/24  # Homelab-Netz
PersistentKeepalive = 25

Jetzt können Geräte im Elternhaus (192.168.100.0/24) auf dein Homelab (192.168.60.0/24) zugreifen und umgekehrt.

fail2ban für Web-UI

Schütze die Web-UI vor Brute-Force-Attacken:

1
2
3
4
5
# fail2ban installieren
sudo apt install fail2ban

# Filter erstellen
sudo nano /etc/fail2ban/filter.d/wg-easy.conf
1
2
3
[Definition]
failregex = ^.*Failed login attempt from <HOST>.*$
ignoreregex =
1
2
# Jail konfigurieren
sudo nano /etc/fail2ban/jail.local
1
2
3
4
5
6
7
[wg-easy]
enabled = true
port = 51821
filter = wg-easy
logpath = /var/lib/docker/containers/<container-id>/<container-id>-json.log
maxretry = 5
bantime = 3600

Nach 5 fehlgeschlagenen Login-Versuchen wird die IP für 1 Stunde gesperrt.


Monitoring

Du willst wissen, wer wann verbunden ist und wie viel Traffic läuft.

Built-in Traffic Statistics

wg-easy zeigt dir direkt in der Web-UI:

  • Aktuell verbundene Clients
  • Letzter Handshake (wann war der Client zuletzt online)
  • Upload/Download-Traffic pro Client
  • Grafiken (wenn UI_CHART_TYPE gesetzt ist)

Das reicht für die meisten Fälle.

WireGuard Status via CLI

Auf dem Server:

1
docker exec wg-easy wg show

Ausgabe:

1
2
3
4
5
6
7
8
9
10
interface: wg0
  public key: 2S7mA0vEMethCNQrJpJKE81wykf0jAZbpHJh2T7D5Ik=
  private key: (hidden)
  listening port: 51820

peer: HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
  endpoint: 93.184.216.34:41234
  allowed ips: 10.8.0.2/32
  latest handshake: 1 minute, 23 seconds ago
  transfer: 15.27 MiB received, 89.12 MiB sent

Hier siehst du:

  • Wann der letzte Handshake war (zeigt, ob Client noch verbunden ist)
  • Wie viel Traffic der Client gemacht hat
  • Von welcher IP der Client kommt

Homepage Dashboard Widget

Wenn du Homepage nutzt, kannst du ein Widget einbinden:

1
2
3
4
5
6
7
8
9
10
11
12
13
- WireGuard:
    icon: wireguard.png
    href: https://wg.example.com
    description: VPN Server
    widget:
      type: customapi
      url: http://wg-easy:51821/api/wireguard/client
      method: GET
      headers:
        Cookie: "connect.sid=<session-cookie>"
      mappings:
        - field: length
          label: Connected Clients

Uptime Monitoring

Nutze Uptime Kuma oder UptimeRobot, um zu überwachen, ob der VPN-Endpoint erreichbar ist:

  • Typ: UDP Port Check
  • Host: vpn.example.com
  • Port: 51820
  • Interval: 60s

Wenn der Port nicht erreichbar ist, bekommst du eine Benachrichtigung.


Troubleshooting

Probleme? Hier die häufigsten Fehler und Lösungen.

Problem: Kann mich nicht verbinden

Symptom: Client zeigt “Handshake failed” oder keine Verbindung.

Lösungen:

  1. Port-Forwarding prüfen:
    1
    2
    
    # Von außen (über mobiles Netz) testen
    nc -vuz vpn.example.com 51820
    

    Wenn das nicht funktioniert: Router-Konfiguration prüfen.

  2. Firewall auf dem Server:
    1
    2
    
    sudo ufw allow 51820/udp
    sudo ufw status
    
  3. WireGuard läuft?
    1
    2
    
    docker ps | grep wg-easy
    docker logs wg-easy
    
  4. Endpoint korrekt? In der Client-Config muss Endpoint = vpn.example.com:51820 auf die richtige IP/Domain zeigen.

Problem: Verbunden, aber kein Traffic

Symptom: Handshake erfolgreich, aber keine Daten kommen durch.

Lösungen:

  1. AllowedIPs prüfen:
    1
    2
    3
    
    # In der Client-Config
    [Peer]
    AllowedIPs = 0.0.0.0/0  # Oder spezifische Netze
    

    Wenn AllowedIPs falsch ist, wird Traffic nicht geroutet.

  2. IP Forwarding aktiviert?
    1
    2
    
    docker exec wg-easy sysctl net.ipv4.ip_forward
    # Sollte "1" sein
    

    Falls nicht: In docker-compose.yml ist das via sysctls gesetzt.

  3. iptables-Regeln:
    1
    
    docker exec wg-easy iptables -t nat -L POSTROUTING -n -v
    

    Es sollte eine MASQUERADE-Regel für das VPN-Subnet geben.

Problem: DNS funktioniert nicht

Symptom: Kann auf IPs zugreifen, aber Hostnamen lösen nicht auf.

Lösungen:

  1. DNS-Server erreichbar?
    1
    2
    3
    4
    
    # Im VPN-Client
    ping 10.8.0.1
    # oder
    ping 192.168.2.5  # Dein Pi-hole
    
  2. DNS in Client-Config gesetzt?
    1
    2
    
    [Interface]
    DNS = 10.8.0.1
    
  3. DNS-Server lauscht auf VPN-Interface? Pi-hole/AdGuard muss auf alle Interfaces oder spezifisch auf das VPN-Subnet lauschen.

Problem: Langsame Geschwindigkeit

Symptom: VPN ist deutlich langsamer als deine normale Verbindung.

Lösungen:

  1. MTU anpassen: ```yaml
    • WG_MTU=1280 # Statt 1420 ``` Manchmal hilft ein kleinerer MTU-Wert, besonders bei mobilem Internet.
  2. Server-Performance prüfen:
    1
    
    docker stats wg-easy
    

    Wenn CPU/RAM ausgelastet ist: mehr Ressourcen geben.

  3. Netzwerk-Engpass? Dein Heim-Upload ist der Bottleneck. Ein 16 Mbit/s Upload limitiert alle Downloads übers VPN auf 16 Mbit/s.

Problem: Handshake, aber keine Daten

Symptom: Handshake alle 1-2 Minuten erfolgreich, aber keine Daten.

Lösungen:

  1. PostUp/PostDown-Regeln prüfen:
    1
    2
    
    docker exec wg-easy iptables -L -n -v
    docker exec wg-easy iptables -t nat -L -n -v
    

    FORWARD- und MASQUERADE-Regeln müssen vorhanden sein.

  2. Interface-Name: wg-easy nutzt wg0 - wenn du das Interface umbenannt hast, passen die Regeln nicht mehr.

Tipps für die Praxis

Ein paar Best Practices aus der echten Welt:

Client-Namen sinnvoll vergeben

Statt “Client 1”, “Client 2” nutze:

  • “iPhone Frank”
  • “Laptop Arbeit”
  • “iPad Wohnzimmer”
  • “Android Maria”

So siehst du in der Web-UI sofort, welches Gerät wie viel Traffic macht.

Alte Clients revoken

Gerät verkauft? Smartphone verloren? In der wg-easy Web-UI: Client löschen. Sofort. Der Client kann sich dann nicht mehr verbinden.

DynDNS für dynamische IPs

Wenn dein Provider dir regelmäßig neue IPs gibt:

  • DuckDNS: Kostenlos, einfach, zuverlässig
  • Cloudflare: Wenn du eh schon eine Domain dort hast
  • No-IP: Klassiker, Free Tier verfügbar

Update-Script als Cronjob:

1
2
# DuckDNS
*/5 * * * * curl "https://www.duckdns.org/update?domains=DEINE-DOMAIN&token=DEIN-TOKEN"

Test von außen

Teste IMMER über mobiles Internet, nicht über dein Heim-WLAN. Sonst merkst du nicht, ob Port-Forwarding funktioniert.

1
2
# Mobilen Hotspot am Laptop aktivieren
# Dann VPN-Verbindung testen

AdGuard/Pi-hole Integration

DNS auf deinen Ad-Blocker setzen:

1
- WG_DEFAULT_DNS=192.168.2.5  # Pi-hole/AdGuard

Jetzt hast du unterwegs Ad-Blocking, ohne Apps oder Browser-Extensions.

Split Tunnel für bessere Performance

Für die meisten Fälle reicht Split Tunnel:

1
- WG_ALLOWED_IPS=10.8.0.0/24,192.168.60.0/24,192.168.2.0/24

Nur Homelab-Traffic geht durchs VPN, Rest direkt.

Backup der Config

wg-easy speichert alle Keys und Configs in ./wg-easy:/etc/wireguard.

Regelmäßiges Backup:

1
2
3
4
5
# Backup erstellen
tar -czf wg-easy-backup-$(date +%F).tar.gz ./wg-easy

# Auf NAS kopieren
scp wg-easy-backup-*.tar.gz admin@nas:/backups/

Ohne Backup: Alle Clients müssen neu konfiguriert werden, wenn der Server stirbt.

On-Demand auf Mobile

Aktiviere “On-Demand” in der WireGuard-App:

  • iOS: VPN-Config → Edit → On-Demand
  • Android: VPN-Config → Settings → Allowed Apps / Always-on VPN

Regel: “VPN immer an, außer im Heim-WLAN (SSID: Dein-WLAN)”.

So verbindest du automatisch, sobald du das Haus verlässt.


Fazit

WireGuard ist die Zukunft von VPN - schnell, sicher, einfach. Mit wg-easy fällt auch die letzte Hürde: Die Verwaltung wird zum Kinderspiel.

Was du bekommst:

  • Sicherer Zugriff auf dein Homelab von überall
  • Schnellere Verbindungen als mit OpenVPN
  • Bessere Akkulaufzeit auf mobilen Geräten
  • Nahtloses Roaming zwischen WLAN und Mobilfunk
  • Eine schicke Web-UI für Client-Management
  • QR-Codes für Mobile-Clients - scannen und fertig
  • Optional: Ad-Blocking unterwegs via Pi-hole/AdGuard

Was du brauchst:

  • 5 Minuten Zeit
  • Docker und Docker Compose
  • Eine öffentliche IP oder DynDNS
  • Port-Forwarding im Router (UDP 51820)

wg-easy macht WireGuard so einfach wie Tailscale - aber du behältst die volle Kontrolle. Keine Cloud, keine Drittanbieter, alles bei dir im Homelab.

Kombiniert mit AdGuard oder Pi-hole für DNS bekommst du eine sichere, werbefreie Verbindung zu deinem Homelab - egal wo du bist. Ob im Café, am Flughafen oder im Hotelzimmer: Ein Klick, und du bist drin.

Und das Beste: Es funktioniert einfach. Kein Gefrickel, keine ewig langen Handshakes, keine Verbindungsabbrüche beim Wechsel zwischen WLAN und Mobilfunk. WireGuard ist VPN, wie es sein sollte.


Ressourcen

Dieser Eintrag ist vom Autor unter CC BY 4.0 lizensiert.