Zwölf Builds

Ein abgehärteter WireGuard-Server mit IPv6, der tatsächlich routet

Erstellen Sie einen WireGuard-Endpunkt, der Clients eine private v4-Adresse und ein echt geroutetes IPv6-Präfix bereitstellt, hinter einer nftables-Richtlinie, die alles Ungefragte verwirft.

Was damit gebaut wird

Eine Instanz, auf der WireGuard läuft, die jedem Client eine private IPv4-Adresse, eine geroutete IPv6-Adresse aus dem eigenen /48 und einen Resolver, der im Tunnel lebt, zuweist – DNS-Anfragen nehmen also nie einen anderen Weg als der restliche Datenverkehr. Die Firewall ist in beiden Richtungen standardmäßig auf 'Drop'. Weiterleitung ist nur für das Tunnel-Interface und nur ausgehend aktiviert.

Getestet auf einer R-4 in AMS-01 mit Debian 13. WireGuard ist Single-Flow und läuft im Kernel, daher bringen mehr Kerne nichts, bis man mehrere Gigabits durchschleust. Viel wichtiger ist der Standort: Wähle den, der dir am nächsten ist, denn jede hier hinzugefügte Millisekunde kommt zu jedem Paket hinzu.

Vorbereitung

  • Eine bereitgestellte Instanz und Root-Zugang per SSH.
  • Das IPv6-/48-Add-on ist im Panel aktiviert. Das enthaltene /64 funktioniert für einen einzelnen Client, aber Subnetze pro Client aus einem einzelnen /64 bedeutet Neighbour Discovery zu proxen – und das ist ein Hobby und keine Konfiguration.
  • Ein Hostname, der auf die Instanz zeigt. Alles unten verwendet vpn.example.com.
  • Jede 2001:db8:-Adresse hier ist Dokumentationsplatz. Ersetze das Präfix mit dem auf deiner Instanzseite angezeigten.

1. Pakete und Kernel-Einstellungen

apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br link

Der letzte Befehl gibt den Namen des ausgehenden Interfaces aus. Auf unseren KVM-Images ist er ens3; falls er abweicht, ersetze ihn unten überall. Nun der Kernel:

cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --system

Die accept_ra = 2-Zeile ist die, die man vergisst. Durch Aktivieren der IPv6-Weiterleitung stoppt der Kernel die Annahme von Router Advertisements, die Standardroute verschwindet innerhalb von zehn Minuten, und die Maschine wird über v6 dunkel, antwortet aber weiter über v4. Diese Einstellung auf Zwei belässt das Annehmen von Advertisements auf einem weiterleitenden Host.

2. Schlüssel

install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.psk

Der Pre-Shared Key ist in diesem Aufbau nicht optional. Er kostet nichts, ist eine Zeile in jeder Konfiguration und macht den Unterschied zwischen einem Tunnel, der heute nur sicher ist, und einem, der gegen einen Angreifer, der jetzt Verkehr aufzeichnet, um ihn später zu entschlüsseln, sicher bleibt.

3. Das Server-Interface

Schreibe /etc/wireguard/wg0.conf und füge die Schlüssel-Inhalte an den markierten Stellen ein:

[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420

[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128

Auf der Serverseite ist AllowedIPs eine Routing-Tabelle, keine Berechtigungsliste. Gib jedem Peer genau die Adressen, die er besitzt, und nichts Breiteres, sonst streiten sich zwei Clients um dieselbe Route, und der Verlierer bekommt schlicht keine Pakete mehr.

chmod 600 /etc/wireguard/wg0.conf

4. Ein Resolver im Tunnel

Clients auf einen öffentlichen Resolver zu zeigen, macht einen guten Teil des Sinns zunichte. Unbound ist bereits installiert; gib ihm /etc/unbound/unbound.conf.d/tunnel.conf:

server:
  interface: 10.7.0.1
  interface: 2001:db8:1a2b:7::1
  access-control: 10.7.0.0/24 allow
  access-control: 2001:db8:1a2b:7::/64 allow
  do-ip6: yes
  prefetch: yes
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes

Unbound startet nicht, bevor der Tunnel existiert, weil diese Adressen noch nicht aktiv sind. Sequenziere es richtig, statt dagegen anzukämpfen:

systemctl edit unbound
[Unit]
[email protected]
[email protected]

5. Die Firewall

Ersetze /etc/nftables.conf vollständig:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
    tcp dport 22 accept
    udp dport 51820 accept
    iifname "wg0" udp dport 53 accept
    iifname "wg0" tcp dport 53 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "ens3" accept
    iifname "wg0" oifname "wg0" drop
  }
  chain output {
    type filter hook output priority filter; policy accept;
  }
}

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

Beachte, was fehlt: Es gibt keine NAT-Tabelle für IPv6. Clients gehen mit ihrer eigenen Adresse aus deinem /48 raus, was der ganze Grund für das /48 ist. Die iifname "wg0" oifname "wg0" drop-Zeile verhindert, dass Peers sich gegenseitig erreichen, was du willst, es sei denn, du baust absichtlich ein Mesh.

systemctl enable --now nftables
nft list ruleset | head -20

6. Starten

systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg0

7. Der Client

[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420

[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Für ein Telefon mach daraus auf dem Server einen QR-Code und fotografiere das Terminal:

qrencode -t ansiutf8 < /root/laptop.conf

Auf einem Debian- oder Ubuntu-Client benötigt die DNS =-Zeile ein installiertes openresolv, sonst druckt wg-quick eine Warnung und lässt still deinen alten Resolver stehen. Das ist die häufigste Ursache für einen Tunnel, der einwandfrei funktioniert und jede Anfrage durchsickern lässt.

Verifizieren

Vier Prüfungen, in dieser Reihenfolge. Wenn etwas fehlschlägt, weißt du, zu welchem Schritt du zurückkehren musst.

# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transfer

Ein Handshake-Zeitstempel innerhalb der letzten zwei Minuten und Zähler ungleich Null in beiden Richtungen bedeuten, dass Kryptografie und Routing in Ordnung sind.

# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +short

Der dritte Befehl beweist, dass der Tunnel-Resolver antwortet. Wenn er eine Zeitüberschreitung hat, startete Unbound vor der Existenz von wg0; starte ihn neu.

Die letzte Prüfung ist die einzige, die beweist, dass dein Verkehr dort rausgeht, wo du denkst, und sie benötigt eine zweite Maschine. Jede andere Instanz der Flotte tut es, in jeder Stadt:

# on the second instance
nc -lv 9101

# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/

Der Listener druckt die Quelladresse jeder Verbindung. Dein v4-Versuch sollte vom WireGuard-Server kommen, da er maskiert wurde. Der v6-Versuch sollte von der eigenen Tunneladresse des Clients in deinem /48 kommen, unverändert – das bedeutet geroutet und nicht geproxt.

Wenn es schiefgeht

SymptomUrsacheBehebung
Handshake gelingt, kein VerkehrWeiterleitung aus, oder die Forward-Kette verwirftsysctl net.ipv4.ip_forward, dann lies die Forward-Kette erneut
Kleine Anfragen ok, große Downloads hängenMTU und PfadfindungSenke beide Konfigurationen auf MTU = 1380 und versuche erneut
IPv6 stirbt etwa zehn Minuten nach dem BootenWeiterleitung tötete Router Advertisementsaccept_ra = 2 auf dem ausgehenden Interface
DNS löst außerhalb des Tunnels aufClient ignorierte DNS =Installiere openresolv auf dem Client
Alles nach einem Neustart wegUnits nie aktiviertsystemctl enable wg-quick@wg0 nftables unbound

Von hier aus sind die sinnvollen nächsten Schritte ein zweiter Endpunkt in einer anderen Region und ein Monitoring-Stack, der dir sagt, wann einer von ihnen nicht mehr antwortet. Beides ist anderswo in den Guides behandelt; die Netzwerkseite erklärt, was der Edge mit deinem Datenverkehr macht, bevor er dich erreicht.

Bereit, wenn Sie es sind

Wählen Sie eine Stadt. Wählen Sie eine Größe. Bezahlen Sie in Coins.

Keine Formulare darüber, wer Sie sind, kein Warten auf einen Menschen, der Sie genehmigt, kein Anruf zur Verifizierung. Die Rechnung wird beglichen, und die Zugangsdaten landen in Ihrem Posteingang.