WireGuard-VPN einrichten: sicherer Zugang zum eigenen Server
Ein schlankes WireGuard-VPN nativ auf dem netcup-Server: Schlüssel, Server- und Client-Konfig, Firewall, Handy-QR – plus der Docker-Fallstrick beim Full-Tunnel.
Inhaltsverzeichnis
Bisher ist alles auf deinem Server öffentlich hinter Traefik erreichbar. Manches soll aber nur für dich laufen – ein Admin-Dashboard, eine Datenbank, ein interner Dienst. Mit WireGuard baust du dir einen verschlüsselten Tunnel direkt in den Server, ohne dafür weitere Ports ins Internet zu öffnen.
Was bauen wir?
Ein WireGuard-VPN nativ auf dem Server (kein Container – WireGuard steckt im Linux-Kernel,
das ist die schlankeste und stabilste Variante). Deine Geräte – Laptop, Handy – bekommen einen
verschlüsselten Tunnel zum Server und darüber eine private IP im Netz 10.8.0.0/24. Zwei
Betriebsarten, die du über eine einzige Client-Zeile umschaltest:
- Split-Tunnel (Standard): Nur der Weg zum Server und seinen internen Diensten läuft durchs VPN. Damit erreichst du Dinge, die nicht öffentlich stehen sollen (ein Dashboard, eine Datenbank, später ein eigener DNS-Filter), ohne dafür einen Port zu veröffentlichen.
- Full-Tunnel (optional): Der gesamte Internetverkehr deines Geräts läuft über den Server – praktisch im offenen Café-WLAN, weil dann alles verschlüsselt über deine eigene IP rausgeht.
Getestet mit wireguard-tools 1.0.20210914 unter Debian 13 (Kernel 6.12, WireGuard ist dort fest eingebaut).
Warum WireGuard und nicht OpenVPN oder ein offener Port? WireGuard läuft im Kernel, ist mit wenigen tausend Zeilen Code winzig (leicht prüfbar, kleine Angriffsfläche), braucht nur einen einzigen UDP-Port und kommt mit einer Handvoll Konfigzeilen aus. Der Handshake ist so schlank, dass eine mobile Verbindung nach dem Aufwachen praktisch sofort wieder steht. Statt also jeden internen Dienst mit eigener Authentifizierung ins Netz zu stellen, legst du einen sicheren Tunnel – und alles dahinter bleibt privat.
Voraussetzungen
- Ein Server mit aktiver UFW-Firewall und root- bzw. sudo-Zugang.
- Wenn du zusätzlich die netcup-Firewall nutzt: den WireGuard-Port dort später freigeben (fertige Vorlage im Firewall-Tutorial).
- Ein Client-Gerät mit der offiziellen WireGuard-App (Windows, macOS, Linux, iOS, Android).
VPS 1000 G12
4 vCore · 8 GB RAM · 256 GB NVMe
ab 10,36 €/Monat
Ein WireGuard-VPN braucht kaum Ressourcen – der kleinste VPS reicht locker.
💶 5 € Gutschein für netcup-Neukunden:36nc17844976032
(nur Neukunden, keine Domains)
Schritt für Schritt
Schritt 1: WireGuard installieren
Der Kernel bringt WireGuard schon mit; du brauchst nur die Userspace-Werkzeuge (und qrencode
für den Handy-QR-Code):
sudo apt update
sudo apt install -y wireguard wireguard-tools qrencodePrüfe, dass das Kernel-Modul geladen werden kann:
sudo modprobe wireguard && lsmod | grep wireguardwireguard 118784 0Schritt 2: Schlüsselpaare erzeugen
WireGuard authentifiziert rein über Schlüsselpaare – kein Passwort, keine Zertifikate. Jede Seite (Server und jeder Client) hat einen privaten und einen öffentlichen Schlüssel. Der private darf niemals die Maschine verlassen. Setz zuerst eine strikte Dateimaske, damit die Schlüssel nicht für andere lesbar sind:
umask 077
wg genkey | sudo tee /etc/wireguard/server.key | wg pubkey | sudo tee /etc/wireguard/server.pubDer erste Befehl erzeugt den privaten Schlüssel (server.key), leitet ihn durch wg pubkey
und speichert den öffentlichen (server.pub). Erzeuge auf dieselbe Weise ein Paar für deinen
ersten Client:
wg genkey | tee client.key | wg pubkey > client.pubDu hast jetzt vier Schlüssel. Merke dir die Zuordnung: In die Server-Konfig kommt der private Server-Schlüssel und der öffentliche Client-Schlüssel; in die Client-Konfig umgekehrt. Das ist die häufigste Fehlerquelle – nie den privaten Schlüssel der falschen Seite eintragen.
Schritt 3: Server-Konfiguration anlegen
Lege /etc/wireguard/wg0.conf an. Trag deinen privaten Server-Schlüssel und den öffentlichen
Client-Schlüssel ein:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = DEIN_SERVER_PRIVATE_KEY
[Peer]
PublicKey = DEIN_CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32Was die Zeilen bedeuten:
Address– die VPN-interne IP des Servers (10.8.0.1); die/24spannt das VPN-Subnetz10.8.0.0/24auf.ListenPort– der UDP-Port, auf dem WireGuard lauscht.51820ist der Standard.[Peer]+AllowedIPs = 10.8.0.2/32– dieser Client darf ausschließlich unter der VPN-IP10.8.0.2auftauchen. Wichtig:AllowedIPshat auf beiden Seiten eine andere Bedeutung – auf dem Server ist es die feste Tunnel-IP des Clients, auf dem Client (Schritt 5) legt es fest, was durch den Tunnel geroutet wird.
Für jeden weiteren Client fügst du später einfach einen weiteren [Peer]-Block mit der
nächsten IP (10.8.0.3/32 …) hinzu.
Schritt 4: Firewall öffnen und den Tunnel starten
WireGuard spricht über UDP – gib den Port frei. In der UFW:
sudo ufw allow 51820/udpSitzt zusätzlich die netcup-Firewall davor, brauchst du dort eine eingehende Regel
UDP · Ziel-Port 51820 – die fertige Vorlage steht im
netcup-Firewall-Tutorial. Starte nun den Tunnel und
richte den Autostart ein:
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0Prüfe, dass die Schnittstelle läuft:
sudo wg show wg0interface: wg0
public key: nZT4kozgZjtHVzGfPRL+niI4llEQCUqGpYG0ni+fAT4=
private key: (hidden)
listening port: 51820
peer: j5h2jl87JApAbWrJikrth3H/6fNuf6X2TgBgDSJVwwE=
allowed ips: 10.8.0.2/32Der Peer ist eingetragen, aber es gibt noch keinen latest handshake – logisch, der Client
fehlt noch.
Schritt 5: Client einrichten
Die Client-Konfig ist das Spiegelbild. Erstelle eine Datei client.conf (auf dem Server zum
Erzeugen des QR-Codes, den Inhalt trägst du dann ins Client-Gerät):
[Interface]
Address = 10.8.0.2/24
PrivateKey = DEIN_CLIENT_PRIVATE_KEY
# DNS = 10.8.0.1 # nur aktivieren, wenn auf 10.8.0.1 wirklich ein DNS-Resolver läuft – sonst z. B. 1.1.1.1
[Peer]
PublicKey = DEIN_SERVER_PUBLIC_KEY
Endpoint = DEINE_SERVER_IP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25Die entscheidenden Zeilen:
Endpoint– die öffentliche IP deines Servers plus Port. Hierhin baut der Client den Tunnel auf.AllowedIPs = 10.8.0.0/24– das ist der Split-Tunnel: Nur Verkehr ins VPN-Subnetz läuft durch den Tunnel, dein normaler Internetverkehr bleibt direkt. Für den Full-Tunnel (alles über den Server) setzt du hier0.0.0.0/0– dazu Schritt 6.DNS = 10.8.0.1– bewusst auskommentiert. Diese Zeile leitet den gesamten System-DNS deines Geräts auf10.8.0.1um – dort lauscht aber standardmäßig nichts auf Port 53, sodass bei aktivem Tunnel die Namensauflösung bricht. Setz sie nur, wenn auf dem Server wirklich ein eigener DNS-Resolver/-Filter läuft; brauchst du im Tunnel einfach einen funktionierenden DNS, trag stattdessen einen echten Resolver wie1.1.1.1ein.PersistentKeepalive = 25– hält die Verbindung offen, wenn der Client hinter einem NAT/CGNAT sitzt (Handy im Mobilfunknetz).
Fürs Handy erzeugst du aus der Datei einen QR-Code direkt im Terminal – in der WireGuard-App „Tunnel hinzufügen → QR-Code scannen":
qrencode -t ansiutf8 < client.confAm Desktop importierst du die client.conf einfach in der WireGuard-App. Danach die
client.conf und client.key vom Server löschen (sie gehören aufs Endgerät, nicht auf den
Server).
Schritt 6: Verbindung prüfen (und Full-Tunnel aktivieren)
Aktiviere den Tunnel in der Client-App und sieh auf dem Server nach:
sudo wg show wg0peer: j5h2jl87JApAbWrJikrth3H/6fNuf6X2TgBgDSJVwwE=
endpoint: 203.0.113.24:34582
allowed ips: 10.8.0.2/32
latest handshake: 45 seconds ago
transfer: 1.58 KiB received, 1.39 KiB sentEin latest handshake plus wachsender transfer heißt: Der Tunnel steht. Vom Client aus
erreichst du den Server jetzt unter seiner VPN-IP:
ping 10.8.0.1Willst du den Full-Tunnel (gesamter Verkehr übers VPN), sind zwei Änderungen nötig. Auf dem
Client AllowedIPs = 0.0.0.0/0 setzen. Setz auf dem Client jetzt außerdem eine DNS =-Zeile
(z. B. DNS = 1.1.1.1 oder deinen eigenen Resolver): Sobald aller Verkehr durch den Tunnel
läuft, ist der DNS-Leak am Tunnel vorbei nämlich der Normalfall, nicht die Ausnahme – ohne
diese Zeile fragt dein Gerät weiter die DNS-Server deines lokalen Netzes ab (Details im
DNS-Leak-Eintrag im Fehlerteil). Auf dem Server das Routing
plus NAT aktivieren – zuerst IP-Forwarding dauerhaft einschalten:
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.confDann in der [Interface]-Sektion der wg0.conf die Weiterleitungs- und NAT-Regeln ergänzen
(ersetze eth0 durch dein echtes externes Interface, siehe ip route get 1.1.1.1):
PostUp = iptables -I FORWARD 1 -i wg0 -j ACCEPT; iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADEDocker auf demselben Server? Dann müssen die Regeln nach oben
FORWARD-Policy auf DROP und schiebt eigene Ketten davor. Hängst du die
WireGuard-Regeln mit -A (anhängen) an, wird der Rückweg deiner Antwortpakete von Docker
verworfen – der Handshake klappt, aber es kommt kein Internet an. Deshalb oben -I FORWARD 1
(einfügen ganz vorne) und die RELATED,ESTABLISHED-Regel für den Rückweg. Dasselbe gilt bei
aktiver UFW, denn auch die setzt eine FORWARD-Default-Policy auf DROP – das -I FORWARD 1
übersteuert sie, sodass die Regeln in beiden Fällen greifen. Genau so getestet: Danach geht der
Client mit der IP des Servers ins Netz.Nach sudo wg-quick down wg0 && sudo wg-quick up wg0 prüfst du den Full-Tunnel, indem du auf
dem Client deine öffentliche IP abfragst – sie sollte jetzt die Server-IP sein:
curl -s ifconfig.meSchritt 7: Einen Dienst nur übers VPN erreichbar machen
Jetzt der eigentliche Gewinn. Ein Dienst, den nur du brauchst, muss nicht öffentlich hinter
Traefik stehen – du bindest ihn an die VPN-IP des Servers (10.8.0.1), dann ist er
ausschließlich durch den Tunnel erreichbar, ohne einen einzigen Port im Internet.
Bei einem Docker-Dienst heißt das: den Port nicht an 0.0.0.0, sondern gezielt an die VPN-IP
veröffentlichen. Statt - "8080:80" also:
ports:
- "10.8.0.1:8080:80"Der Dienst hört damit nur auf der WireGuard-Schnittstelle – aus dem Internet ist er
unsichtbar, über das VPN erreichst du ihn unter http://10.8.0.1:8080. (Wichtig: wg0 muss
beim Start des Containers schon oben sein – der systemctl enable aus Schritt 4 sorgt dafür.)
Nach demselben Prinzip kannst du auch SSH nur noch übers VPN zulassen: In der UFW den öffentlichen SSH-Zugang entfernen und stattdessen nur aus dem VPN-Subnetz erlauben –
sudo ufw allow from 10.8.0.0/24 to any port 22 proto tcp– dann die öffentliche SSH-Regel löschen. Vorher unbedingt eine zweite Verbindung übers VPN testen, sonst sperrst du dich aus (im Notfall hilft die VNC-Konsole im netcup-SCP).
Wenn es nicht funktioniert
In wg show erscheint nie ein latest handshake. Der UDP-Port ist nicht erreichbar oder
die Schlüssel passen nicht. WireGuard ist bei falschen Schlüsseln stumm – es gibt keine
Fehlermeldung, nur keinen Handshake. Prüfe: sudo ufw status (Port 51820/udp offen?), die
netcup-Firewall (eingehend UDP 51820), den Endpoint im Client (richtige öffentliche IP?) und
dass privater und öffentlicher Schlüssel nicht vertauscht sind.
Handshake ist da, aber im Full-Tunnel kommt kein Internet an. Fast immer das Routing/NAT.
Ist net.ipv4.ip_forward=1 gesetzt (sysctl net.ipv4.ip_forward)? Läuft Docker mit – oder ist
UFW aktiv –, greift die FORWARD-DROP-Falle aus dem Warnkasten oben; beide setzen die
Forward-Policy auf DROP. Die Regeln müssen mit -I FORWARD 1 vor den bestehenden Ketten
stehen. Stimmt das externe Interface im MASQUERADE (eth0 vs. etwas anderes)?
Full-Tunnel steht, aber DNS-Anfragen laufen weiter am Tunnel vorbei (DNS-Leak). Ohne DNS =-Zeile fragt dein Gerät weiter die DNS-Server deines lokalen Netzes – im offenen WLAN sieht
der Betreiber also weiter, welche Domains du aufrufst. Prüfe unter Linux mit resolvectl status, welcher DNS-Server dem Interface wg0 zugeordnet ist, oder mach einen Leak-Test (z. B.
auf dnsleaktest.com): Tauchen dort fremde Resolver auf, trägst du in der Client-Konfig einen
echten Resolver ein (DNS = 1.1.1.1) – oder den Server selbst (10.8.0.1), falls dort ein
eigener DNS-Resolver läuft.
Der Tunnel steht, aber große Übertragungen (SSH, HTTPS, Downloads) hängen oder brechen ab.
Ein MTU-Problem. wg-quick setzt die MTU auf 1420; in manchen Netzen (DS-Lite, bestimmte
Mobilfunknetze) ist das noch zu hoch. Setz testweise MTU = 1412 oder 1280 in der
[Interface]-Sektion des Clients.
wg-quick up meldet resolvconf: command not found. Die DNS =-Zeile braucht
resolvconf. Entweder sudo apt install openresolv installieren oder die DNS-Zeile
entfernen, wenn du den VPN-DNS nicht brauchst.
Die Verbindung schläft ein, sobald das Handy kurz nichts sendet. Der Client sitzt hinter
NAT/CGNAT. PersistentKeepalive = 25 in der Client-Konfig hält die Verbindung offen.
Wartung & Backups
Weitere Geräte hinzufügen. Pro Gerät ein eigenes Schlüsselpaar und ein weiterer
[Peer]-Block in derwg0.confmit der nächsten freien IP (10.8.0.3/32…). Nie denselben Schlüssel auf zwei Geräten verwenden. Damit bestehende Tunnel dabei nicht abreißen, lädst du die geänderte Konfig im Betrieb neu, stattdown/upzu machen:Terminalsudo wg syncconf wg0 <(wg-quick strip wg0)Schlüssel sichern – sie sind das Herz des VPN. Nimm
/etc/wireguard/in dein verschlüsseltes Restic-Backup auf. Wer die privaten Schlüssel hat, kommt ins VPN – behandle sie wie Passwörter.Aktuell halten.
wireguard-toolsbekommt seine Updates über automatische Sicherheitsupdates; das Kernel-Modul kommt mit den Kernel-Updates.Interne Dienste ans VPN binden. Der eigentliche Gewinn: Dienste, die niemand aus dem Internet erreichen soll, lässt du nur auf
10.8.0.1lauschen (statt0.0.0.0) – dann sind sie ausschließlich über den Tunnel erreichbar, ganz ohne öffentlichen Port.Bei Server-Umzug die neue öffentliche IP im
Endpointjedes Clients nachziehen – sonst findet der Client den Server nicht mehr.Ehrlich zum Aufwand: Einmal eingerichtet, läuft WireGuard praktisch wartungsfrei. Der einzige wiederkehrende Handgriff ist das Anlegen eines Peers pro neuem Gerät.
Viele Geräte? Dann lohnt ein Mesh-Manager
Feedback per E-Mail: feedback@serverkueche.de
Wie geht's weiter?

AdGuard Home: netzwerkweiter Werbe- und Tracking-Blocker
AdGuard Home mit Docker aufsetzen: ein eigener DNS-Server, der Werbung, Tracker und Schadseiten für alle Geräte blockt – …
Das könnte dir auch schmecken

CrowdSec: moderne, kollaborative Angriffsabwehr
CrowdSec mit dem Traefik-Bouncer einrichten: Angriffe aus den Zugriffs-Logs erkennen, Angreifer per 403 blocken und von …

Fail2ban einrichten: Brute-Force-Angriffe automatisch blocken
Fail2ban überwacht deine Logs und sperrt IPs nach zu vielen Fehlversuchen – mit sicherer Whitelist für die eigene …

Restic-Backups einrichten: verschlüsselt und off-site
Off-Site-Backups mit Restic: verschlüsselt einrichten, Snapshots wiederherstellen, mit Retention aufräumen und per …