SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-28

WireGuard-VPN auf dem eigenen VPS einrichten

Richten Sie WireGuard auf Ihrem Linux-VPS ein: Schlüsselpaar, wg0.conf, IP-Forwarding, NAT, AllowedIPs, DNS und typische Handshake-Fehler.

Was Sie einrichten

Ein WireGuard-VPN auf einem eigenen Server umfasst etwa vierzig Konfigurationszeilen: ein Schlüsselpaar, eine Schnittstellendatei, einen sysctl-Wert, eine NAT-Regel und eine Firewall-Freigabe. Die Installation ist unkompliziert. Daher behandelt dieser Leitfaden hauptsächlich Fehlerquellen, Berechtigungen für Schlüssel, AllowedIPs, Weiterleitung und DNS.

WireGuard ist ein Layer-3-Tunnel im Kernel und seit Linux 5.6 im Mainline-Kernel enthalten. Ubuntu 24.04 und Debian 13 liefern es daher ohne externes Modul aus. Es gibt keine Aushandlung von Verschlüsselungsverfahren, keine Zertifizierungsstelle und keine Anmeldung mit Benutzername und Passwort. Ein Peer besteht aus einem öffentlichen Schlüssel und den IP-Adressen, die dieser Schlüssel verwenden darf. Ein Paket, dessen MAC-Prüfung fehlschlägt, wird ohne Antwort verworfen. Daher antwortet der Port nicht auf Scans. Der Nachteil: Es gibt keinen Authentifizierungsserver. Um den Zugriff zu entziehen, müssen Sie einen Peer auf dem Server löschen.

Prüfen Sie zuerst die Virtualisierung

WireGuard benötigt einen Kernel, in den ein Modul geladen werden kann. Auf einem KVM-VPS funktioniert es direkt nach der Installation. Bei containerbasierter Virtualisierung mit gemeinsam genutztem Host-Kernel, etwa OpenVZ oder LXC, schlägt der erste Befehl mit RTNETLINK answers: Operation not supported fehl. Verwenden Sie in diesem Fall die Userspace-Implementierung wireguard-go. Prüfen Sie die Umgebung zuerst mit sudo modprobe wireguard && echo ok.

Schlüssel generieren, ohne sie offenzulegen

Ein für alle Benutzer lesbarer /etc/wireguard/server.key ist praktisch genauso unsicher wie ein VPN ohne Verschlüsselung. Die übliche Zeile umask 077 && wg genkey | sudo tee ... ist unzuverlässig, weil sudo die von tee erstellte Datei mit einer eigenen umask anlegt. Setzen Sie die Dateiberechtigungen ausdrücklich.

sudo apt update && sudo apt install -y wireguard nftables
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.key

Generieren Sie das Client-Schlüsselpaar auf dieselbe Weise. wg genpsk fügt einen optionalen Pre-Shared Key hinzu, der in jeder Konfiguration in einer eigenen Zeile steht.

Die Server-Schnittstelle: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>

[Peer]
PublicKey = <laptop public key>
PresharedKey = <psk, optional>
AllowedIPs = 10.8.0.2/32

chmod 600; eine Warnung beim Start, dass die Datei für alle Benutzer zugänglich ist, bedeutet, dass Sie diesen Schritt übersprungen haben. Address ist die Serveradresse innerhalb des Tunnels und enthält die Netzmaske des gesamten VPN-Subnetzes. Wählen Sie einen Bereich, der in realen Netzwerken möglichst nicht vorkommt. 192.168.1.0/24 überschneidet sich mit der Hälfte der Heimrouter, hinter denen Ihre Clients sitzen. Der Tunnel verliert dann unbemerkt gegen die lokale Route.

Der AllowedIPs eines Peers auf der Server-Seite ist ein /32, also die eine Tunneladresse, die diesem Client gehört. Wenn Sie zwei Peers dieselbe zulässige IP-Adresse zuweisen, wird sie dem Peer zugeordnet, der zuletzt konfiguriert wurde. Der erste Peer empfängt dann keinen Datenverkehr mehr, ohne dass irgendwo eine Fehlermeldung ausgegeben wird. Lassen Sie SaveConfig nicht gesetzt. Andernfalls überschreibt wg-quick down diese Datei anhand des aktuellen Laufzeitstatus.

Den Server als Router einrichten

Ein Linux-Server verwirft Pakete, die nicht an ihn adressiert sind. Weiterleitung und Source-NAT sind standardmäßig nicht aktiviert.

printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
  | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

Ein einzelnes sysctl -w funktioniert nur bis zum nächsten Reboot und wird danach stillschweigend deaktiviert. Für NAT ist das ausgehende Interface erforderlich, also die Netzwerkkarte mit Internetzugang, nicht wg0. Gehen Sie nicht von eth0 aus. Ermitteln Sie den Wert mit ip route show default, da aktuelle Images Namen wie enp1s0 oder ens3 verwenden.

Firewall: the port, and the forward path

One nftables file covers filter and NAT. Write /etc/nftables.conf, it flushes the existing ruleset, so skip this on a box already managed by ufw or Docker.

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    iif lo accept
    tcp dport 22 accept
    udp dport 51820 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "enp1s0" accept
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" masquerade
  }
}

Apply it with sudo systemctl enable --now nftables, keeping a second SSH session open: policy drop plus a typo in the SSH rule locks you out of your own server. Note what the forward chain does not allow, wg0 to wg0. Peers reach the internet, not each other; add iifname "wg0" oifname "wg0" accept for a peer-to-peer VPN. The same chain governs what a peer may touch on the server itself, which matters when the box doubles as a remote development box running Claude Code in tmux and you would rather not expose that side of it publicly.

On a ufw box: ufw allow 51820/udp, DEFAULT_FORWARD_POLICY="ACCEPT" in /etc/default/ufw, and a *nat POSTROUTING MASQUERADE rule at the top of /etc/ufw/before.rules.

Unter systemd starten

sudo systemctl enable --now wg-quick@wg0
sudo wg show

wg-quick erstellt das Interface, weist die Adressen zu und richtet die aus AllowedIPs abgeleiteten Routen ein. enable --now ist der entscheidende Teil: Ein manuell ausgeführtes wg-quick up wg0 ist nach dem nächsten Reboot nicht mehr vorhanden, und Kernel-Upgrades erfordern Reboots. Eine Unit, die nach einem dieser Reboots nicht erneut startet, bleibt unbemerkt, bis jemand versucht, eine Verbindung herzustellen. Ein OnFailure=-Drop-in für wg-quick@wg0 mit einem Verweis auf Ihren eigenen ntfy-Server ist daher die kostengünstigste Möglichkeit, die Meldung auf Ihrem Telefon zu erhalten, statt von einem ausgesperrten Benutzer darauf hingewiesen zu werden.

Die Client-Konfiguration und die Einstellung, die fast alle falsch setzen

[Interface]
PrivateKey = <laptop private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

AllowedIPs erfüllt gleichzeitig zwei verschiedene Aufgaben. Wenn diese Aufgaben vermischt werden, entstehen die meisten Missverständnisse bei WireGuard.

Ausgehend ist die Einstellung eine Routingtabelle. Ein Paket, dessen Ziel zu AllowedIPs eines Peers passt, wird verschlüsselt und an diesen Peer gesendet. 0.0.0.0/0, ::/0 leitet sämtlichen Datenverkehr durch den Tunnel. Das ist ein vollständiger Tunnel, bei dem der Server als Standardroute dient. Ein Split-Tunnel enthält eine engere Liste: AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 überträgt den VPN-Datenverkehr sowie ein privates Netzwerk hinter dem Server. Für alles andere bleibt die lokale Route bestehen. Diese engere Liste ermöglicht es, Dienste vollständig aus dem öffentlichen Internet herauszuhalten. So bleiben beispielsweise eine private Nextcloud-Instanz auf einem VPS, die an die Tunneladresse gebunden ist, oder die VMs des verschachtelten Virtualisierungslabors, die auf demselben System laufen, für Peers erreichbar und für alle anderen unsichtbar.

Eingehend ist die Einstellung eine Zugriffskontrollliste. Ein entschlüsseltes Paket von einem Peer wird verworfen, wenn seine Quelladresse nicht in AllowedIPs dieses Peers enthalten ist. Deshalb trägt der Server für den Laptop 10.8.0.2/32 ein: Ein Eintrag von 0.0.0.0/0 an dieser Stelle würde es dem Client ermöglichen, jede Adresse im Tunnel zu fälschen.

PersistentKeepalive ist für Clients hinter NAT vorgesehen. Der Router hält die UDP-Zuordnung nur offen, solange Datenpakete übertragen werden. Nach ihrem Ablauf kann der Server den Client nicht mehr erreichen. PersistentKeepalive = 25 hält die Zuordnung offen. Setzen Sie diese Einstellung auf dem Client, nicht auf einem Server mit öffentlicher IP-Adresse.

DNS und das Leck, das niemand bemerkt

Mit AllowedIPs = 0.0.0.0/0 und ohne eine Zeile mit DNS = verwendet der Client weiterhin den Resolver, den er aus dem lokalen Netzwerk gelernt hat, also den Router des Cafés unter 192.168.1.1. Diese Route ist spezifischer als die Standardroute. Daher verlassen DNS-Abfragen die Verbindung über den lokalen Link im Klartext, während der gesamte übrige Datenverkehr durch den Tunnel geleitet wird. Der Datenverkehr ist privat. Die Liste der abgefragten Namen ist es nicht.

Es gibt zwei praktikable Optionen. Verweisen Sie DNS auf einen öffentlichen Resolver (DNS = 9.9.9.9). Dann laufen die Abfragen durch den Tunnel und verlassen ihn über Ihren Server. Dieser Resolver kann die Abfragen jedoch weiterhin sehen. Oder führen Sie unbound oder dnsmasq aus, gebunden an 10.8.0.1, setzen Sie DNS = 10.8.0.1 und fügen Sie udp dport 53 iifname "wg0" accept zur Input-Kette hinzu. Setzen Sie diese Zeile und ignorieren Sie den Resolver. Dann wird überhaupt nichts aufgelöst.

Auf Linux-Clients gilt wg-quick für DNS bis resolvconf. Fehlt es, erhalten Sie resolvconf: command not found. Installieren Sie openresolv oder setzen Sie PostUp = resolvectl dns %i 10.8.0.1 auf einem Client mit systemd-resolved.

Peers hinzufügen und entfernen, ohne den Tunnel zu unterbrechen

Wenn Sie zum Hinzufügen eines Benutzers das Interface neu starten, werden alle bestehenden Verbindungen getrennt. Hängen Sie den Block [Peer] an wg0.conf an und laden Sie anschließend die Peer-Konfiguration direkt neu.

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg-quick strip gibt die Konfiguration ohne die nur von wg-quick verwendeten Schlüssel (Address, DNS, PostUp) aus, und syncconf übernimmt die Änderungen, ohne bestehende Sitzungen zu unterbrechen. Der Befehl aktualisiert nur die Peers: Ein geändertes Address erfordert weiterhin ein vollständiges Down/Up. Widerrufen Sie den Peer mit sudo wg set wg0 peer <public key> remove und löschen Sie anschließend den Block aus der Datei. Andernfalls wird er beim nächsten Neuladen erneut übernommen.

Fehlerbilder und die angezeigten Meldungen

Der Handshake wird nie abgeschlossen. wg show führt den Peer ohne latest handshake auf, und das Client-Log enthält:

Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)

Es kommt nichts an, oder nichts wird akzeptiert. Prüfen Sie in dieser Reihenfolge: Ist UDP 51820 in der Firewall des VPS und in der Netzwerk-Firewall Ihres Providers geöffnet? Bei den meisten Control Panels ist dies eine separate Einstellung. Stimmen die Endpoint-Adresse und der Port? Sind die Schlüssel vertauscht? Der Schlüssel im [Peer]-Block des Clients muss der öffentliche Schlüssel des Servers sein. Ein eingefügter privater Schlüssel oder der eigene öffentliche Schlüssel des Clients führt genau zu diesem Fehlerbild. sudo tcpdump -ni any udp port 51820 auf dem Server zeigt, ob überhaupt Pakete eintreffen. Das Kernelmodul protokolliert standardmäßig nichts. WireGuard-Meldungen erscheinen erst nach dem Aktivieren des dynamischen Debuggings (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control) in dmesg. Dann wird ein nicht passender Schlüssel als verworfenes Paket mit ungültigem MAC angezeigt.

Der Handshake funktioniert, aber es gibt kein Internet. ping 10.8.0.1 ist erfolgreich, aber ping 1.1.1.1 läuft in einen Timeout: Weiterleitung oder NAT fehlt. Prüfen Sie, ob sysctl net.ipv4.ip_forward den Wert 1 enthält. Überwachen Sie anschließend die Zähler, während der Client pingt, mit sudo nft list ruleset oder sudo iptables -t nat -L POSTROUTING -n -v. Keine Pakete an der Masquerade-Regel bedeuten, dass der Name der ausgehenden Schnittstelle falsch ist. Ein steigender Zähler ohne Antworten weist auf die Forward-Chain-Policy hin.

Das Internet funktioniert, aber Namen werden nicht aufgelöst. ping 1.1.1.1 ist erfolgreich und curl https://example.com gibt Could not resolve host zurück. Die DNS-Zeile fehlt, oder sie verweist auf einen Resolver, der aus dem Tunnel nicht erreichbar ist.

Einige HTTPS-Websites hängen. SSH und Ping funktionieren, aber große Seiten bleiben stehen. Die Ursache ist die Pfad-MTU: Der Tunnel fügt zusätzlichen Overhead hinzu, und ein Link auf dem Übertragungsweg verwirft möglicherweise zu große Pakete, ohne eine ICMP-Meldung zurückzusenden. Verringern Sie MTU in der Client-[Interface], probieren Sie 1420 und anschließend 1380 und 1280. Wenn eine niedrigere MTU die Verzögerungen beseitigt, der Durchsatz aber weiterhin unzureichend ist, raten Sie nicht weiter mit groben Werten. Arbeiten Sie stattdessen den Abschnitt echte Pfad-MTU durch Halbierung ermitteln und TCP MSS begrenzen durch. Dadurch lassen sich auch Ursachen ausschließen, die überhaupt nicht am Tunnel liegen.

Die Schnittstelle lässt sich nicht starten. Address already in use bedeutet, dass ein anderer Prozess UDP 51820 verwendet. Cannot find device wg0 nach einem fehlgeschlagenen up bedeutet normalerweise, dass die Konfiguration abgelehnt wurde. Lesen Sie journalctl -u wg-quick@wg0 -n 50.

Migration von Streisand oder OpenVPN

Streisand wird nicht mehr gewartet, und sein Repository wurde archiviert. Ein VPN auf nicht mehr gepflegter Automatisierung zu betreiben, ist ein schleichendes Sicherheitsproblem. Es gibt kein Upgrade am bestehenden System, und die PKI von OpenVPN lässt sich nicht konvertieren: WireGuard verwendet keine Zertifikate, keine CA und keine Ablaufdaten. Daher erhält jeder Client ein neues Schlüsselpaar.

Führen Sie die Migration parallel durch. WireGuard auf UDP 51820 kann auf demselben System neben OpenVPN auf 1194 betrieben werden. Richten Sie wg0 ein, migrieren Sie die Clients einzeln und beenden Sie anschließend den alten Dienst. Das Benutzername-/Passwortmodell und das Sperrmodell von OpenVPN lassen sich nicht übernehmen. Wenn Sie Benutzerkonten oder eine Prüfspur benötigen, setzen Sie diese oberhalb von WireGuard um.

Backups, Upgrades und Belastungsgrenzen bei steigender Größe

/etc/wireguard ist der Server. Sichern Sie ihn (sudo tar czf wg-backup.tgz -C /etc wireguard, Modus 600, außerhalb des Servers aufbewahrt). Dann können Sie ihn innerhalb weniger Minuten auf einem frischen VPS neu aufbauen. Geht der private Schlüssel des Servers verloren, müssen Sie jede Client-Konfiguration neu ausstellen, weil die Clients den öffentlichen Schlüssel des Servers fest hinterlegen. Upgrades bestehen normalerweise aus einem apt upgrade und einem Neustart für Kernel-Updates. Wenn Sie wg-quick@wg0 aktiviert haben, wird es automatisch wiederhergestellt.

Der Zustand pro Peer ist klein, und die Kryptografie läuft im Kernel. Die Grenze liegt daher bei CPU und Bandbreite Ihres VPS und nicht bei diesem Konfigurationsumfang. Messen Sie sie mit iperf3 über den Tunnel, statt einer veröffentlichten Zahl zu vertrauen. Bei steigender Größe wird der Betrieb zum Engpass. Jeder Peer benötigt eine eindeutige Tunnel-IP. Sechzig [Peer]-Blöcke von Hand zu bearbeiten, führt leicht zu doppelten AllowedIPs. Erzeugen Sie die Konfigurationen daher mit einem Skript. Ein Server ist ein UDP-Endpunkt und ein Single Point of Failure. WireGuard bietet kein Clustering. Redundanz bedeutet einen zweiten Server mit eigenen Schlüsseln. Der Schlüsselaustausch bleibt manuell. Dokumentieren Sie daher, wer welchen Schlüssel besitzt und wie Sie ihn widerrufen. Wenn diese Verwaltung eine Textdatei übersteigt, ist eine Control Plane auf derselben Kernel-Dataplane die übliche Lösung. Ein selbst gehosteter NetBird-Server übernimmt die Adressvergabe, die Verteilung der Peers und die Setup Keys, die Sie andernfalls manuell verwalten würden. Wenn der Eigenbetrieb dieser Control Plane einen Server zu viel bedeutet, hostet Tailscale sie für Sie. Der kostenlose Tarif umfasst sechs Benutzer mit unbegrenzt vielen Geräten, was für die meisten persönlichen Umgebungen ausreicht, ohne dass Kosten entstehen. Darüber hinaus richtet sich die Abrechnung nach den Personen und nicht nach den Systemen. Was ein Haushalt oder ein kleines Team tatsächlich bezahlt, hängt davon ab, wie viele Personen Anmeldedaten besitzen, und nicht davon, wie viele Peers Sie manuell in wg0.conf eingetragen hätten. In diesem Modell wird die AllowedIPs-Verwaltung für Split-Tunneling durch die Ankündigung Ihrer privaten Bereiche über einen Subnet Router ersetzt. Diese Ankündigung erfolgt einmalig von einem VPS und wird zentral genehmigt, statt in jede Client-Datei kopiert zu werden. Ob sich dieser Tausch lohnt, hängt davon ab, worauf eine gehostete Control Plane tatsächlich zugreifen kann. Sie besitzt niemals die Schlüssel, die Ihren Datenverkehr verschlüsseln, entscheidet aber, welche Peers voneinander erfahren.

Dafür benötigen Sie ein Linux-System, das Sie kontrollieren, eine öffentliche IP, einen Kernel, in den Sie ein Modul laden können, und eine Firewall, deren vollständige Kontrolle bei Ihnen liegt.

FAQ

Warum wird der WireGuard-Handshake nie abgeschlossen?

Eine wg show-Auflistung eines Peers ohne latest handshake bedeutet, dass keine Pakete eintreffen oder akzeptiert werden. Prüfen Sie UDP 51820 sowohl in der VPS-Firewall als auch in der separaten Netzwerk-Firewall Ihres Providers. Bestätigen Sie den Endpoint-Host und den Port. Prüfen Sie anschließend, ob die Schlüssel vertauscht wurden. Der [Peer]-Block des Clients muss den öffentlichen Schlüssel des Servers enthalten. sudo tcpdump -ni any udp port 51820 auf dem Server zeigt, ob überhaupt Pakete eintreffen. dmesg meldet die Handshake-Fehler von WireGuard erst, nachdem Sie das dynamische Debugging (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control) aktiviert haben. Ein nicht übereinstimmender Schlüssel erscheint dann als verworfener Datensatz mit ungültigem MAC.

Der Tunnel wird hergestellt, aber ich habe kein Internet. Was fehlt?

Wenn ping 10.8.0.1 funktioniert, während ping 1.1.1.1 mit einem Timeout endet, deutet das auf Weiterleitung oder NAT hin. Bestätigen Sie, dass sysctl net.ipv4.ip_forward den Wert 1 enthält und dieser in /etc/sysctl.d/ gesetzt ist, nicht nur mit einem sysctl -w, das beim Reboot verloren geht. Prüfen Sie anschließend, ob die Masquerade-Regel anhand von ip route show default, enp1s0 oder selten ens3 die tatsächliche Ausgangsschnittstelle benennt: eth0.

Benötige ich die Zeile DNS = in meiner Client-Konfiguration?

Bei einem Full Tunnel verwendet der Client ohne eine DNS =-Zeile weiterhin den Resolver, den er aus dem lokalen Netzwerk übernommen hat. Diese Abfragen verlassen den Client dann unverschlüsselt über die lokale Verbindung, während der übrige Datenverkehr durch den Tunnel geleitet wird. Verweisen Sie DNS auf einen öffentlichen Resolver. Alternativ können Sie unbound/dnsmasq an 10.8.0.1 binden und udp dport 53 iifname "wg0" in der Input-Chain öffnen.

Was steuert AllowedIPs tatsächlich?

Die Einstellung erfüllt zwei Aufgaben. Für ausgehenden Datenverkehr ist sie eine Routing-Tabelle: Datenverkehr, der mit dem AllowedIPs eines Peers übereinstimmt, wird verschlüsselt und an diesen Peer gesendet. Für eingehenden Datenverkehr ist sie eine Zugriffskontrollliste: Ein entschlüsseltes Paket, dessen Quelle außerhalb des AllowedIPs dieses Peers liegt, wird verworfen. Deshalb enthält die Serverseite pro Client ein /32, während die Clientseite 0.0.0.0/0 enthalten kann.

Läuft WireGuard auf jedem VPS?

Auf einem KVM-VPS funktioniert WireGuard mit dem Kernelmodul ohne zusätzliche Einrichtung. Bei einer Container-Virtualisierung, die den Host-Kernel gemeinsam verwendet, beispielsweise OpenVZ oder LXC, schlägt modprobe wireguard mit Operation not supported fehl. Als Ausweichlösung dient die wireguard-go-Implementierung im Userspace. Führen Sie zuerst sudo modprobe wireguard && echo ok aus.