Im Jahr 2024 sollten selbst VPN-Verbindungen IPv6-Konnektivität bieten, zumal sich das oft mit wenigen Schritten einrichten lässt. In diesem Artikel wird die vorherige Anleitung für die Einrichtung eines Wireguard-VPNs erweitert und modernisiert, sodass zum einen Dual-Stack (gleichzeitig IPv4 und IPv6) möglich ist und zum anderen das veraltete iptables Firewall-Backend durch dessen Nachfolger nftables ersetzt wird.

Voraussetzungen

Die folgenden Schritte wurden mit einem frisch installierten Debian 12 (Bookworm) getestet. Falls ein anderes Betriebssystem als Basis verwendet wird, könnten sich manche Befehle natürlich etwas unterscheiden.

Die wichtigste Voraussetzung für die IPv6-Konnektivität ist, dass dem Server ein ganzes IPv6-Netz (z.B. /64) zugewiesen ist (“switched”) und nicht bloß eine einzige Adresse (“routed”). Denn nur so können den Client-Peers einzigartige IPv6-Adressen für die gewünschte End-to-End Konnektivität zugewiesen werden.

Lässt der Provider die IPv6-Adresse des Servers in einem gegebenen Adressbereich frei wählen, sind die Erfolgsaussichten recht hoch. Beispielsweise ist dies bei netcup der Fall. Weitere Hinweise, positiv wie negativ, nehme ich gerne per Mail entgegen.

Übersicht

Vorweg eine kurze Übersicht der beispielhaft verwendeten Adressen:

Öffentliche Adressen des Servers

  • DNS: server.example.com
    • Endpoint der Clients, zu dem die Client-Peers den Tunnel aufbauen
  • IPv6-Netz: 2001:db8::/64, IPv6-Adresse: 2001:db8::1

Private Adressen im Wireguard-Netz

  • IPv4-Netz: 10.0.1.0/24
  • IPv6-Netz: 2001:db8::cafe:0/112
    • Achtung: Kleiner Teil des öffentlichen IPv6-Netzes, der nicht die öffentliche IPv6-Adresse des Servers enthält!
  • Server: IPv4: 10.0.1.1, IPv6: 2001:db8::cafe:1
  • Client A: IPv4: 10.0.1.20, IPv6: 2001:db8::cafe:20
  • Client B: IPv4: 10.0.1.21, IPv6: 2001:db8::cafe:21

Einrichtung des Server

1. IP-Forwarding aktivieren

Zunächst muss sichergestellt werden, dass IP-Forwarding für sowohl IPv4 als auch IPv6 im Kernel aktiviert ist. Das ist nötig, damit die Pakete von der Wireguard- zu der für den Internetzugang verwendete Netzwerkschnittstelle (und umgekehrt) weitergeleitet werden können. Prüfen lässt sich das durch das Lesen der beiden entsprechenden sysfs-Dateien, die beide den Wert “1” enthalten müssen.

$ cat /proc/sys/net/ipv4/ip_forward
1
$ cat /proc/sys/net/ipv6/conf/all/forwarding
1

Falls einer oder beide Werte auf “0” stehen sollte, kann das Forwarding in /etc/sysctl.conf oder besser in einer *.conf Datei im Verzeichnis /etc/sysctl.d/ permantent aktiviert werden:

# /etc/sysctl.d/90-ip-fwd.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Zum Übernehmen kann der Befehl sysctl --system ausgeführt werden oder das System neugestartet werden. Danach sollten die beiden sysfs-Dateien den Wert “1” enthalten.

2. Wireguard konfigurieren

Die Konfiguration von Wireguard für Dual-Stack Tunnelverbindungen ist ähnlich derer eines reinen IPv4 Tunnels, wie sie im vorherigen Artikel beschrieben wurde. Die wesentlichen Unterschiede sind die hinzukommenden IPv6-Adressen und (später) die Firewallregeln. Die benötigten Schritte werden daher an dieser Stelle kurz gehalten.

2.1 Wireguard Tools installieren

Für die Konfiguration müssen die Wireguard Tools installiert sein, was sich mit dem folgenden Befehl erledigen lässt:

sudo apt install wireguard-tools

2.2 Schlüsselpaar für Server generieren

Das Schlüsselpaar kann bspw. in /etc/wireguard angelegt werden. Die Dateien können nach der Einrichtung gelöscht werden, da der Private-Key in der Konfigurationsdatei stehen wird und der Public-Key jederzeit mit wg show angezeigt oder aus ersterem gewonnen werden kann.

umask 077  # damit ab nun erzeugte Dateien nur für den Besitzer lesbar sind
wg genkey > privatekey.txt
wg pubkey < privatekey.txt > publickey.txt

2.3 Konfigurationsdateien erstellen

Die folgende Beispiel-Konfigurationsdatei basiert der Einfachheit halber derjenigen aus dem vorherigen Artikel. Nur enthält diese neben IPv4- nun auch IPv6-Adressen aus dem für die VPN-Clients vorgesehenen Netz 2001:db8::cafe:0/112. Außerdem sind die Befehle für das IPv4-NAT aus den PostUp und PostDown Optionen verschwunden. Diese werden durch permanente Firewallregeln abgelöst.

# Konfiguration des SERVER-Peers (/etc/wireguard/wg0.conf)
[Interface]
Address    = 10.0.1.1, 2001:db8::cafe:1
ListenPort = 54321
PrivateKey = kNSNZaYfpIFP0GOlliBnibWudKg1FroH7UB+Pp+s2HI=

# Client A
[Peer]
PublicKey  = 6FnnYgd8MgKz7kwfCVAT0EZZ3Zcz3FzctANcl1M52CE=
AllowedIPs = 10.0.1.20, 2001:db8::cafe:20

# Client B
[Peer]
PublicKey  = e4NgtjOkjViYqhDdKXC3T7KQYJcUsVV15KGrlg3N20o=
AllowedIPs = 10.0.1.21, 2001:db8::cafe:21

Anschließend kann die Netzwerkschnittstelle permanent aktiviert werden:

sudo systemctl enable --now wg-quick@wg0

Analog wird eine Client-Konfiguration angelegt, die die beiden in der Server-Konfiguration vergebenen IP-Adressen enthält:

# Konfiguration des Peers "Client A" (/etc/wireguard/wg0.conf)
[Interface]
PrivateKey = YPc+21+sXiwyiV+nvdBMXrADydX39lFdumPKkDmipEM=
Address    = 10.0.1.20, 2001:db8::cafe:20
DNS        = 8.8.8.8, 2001:4860:4860::8888

# Server-Peer
[Peer]
PublicKey  = OpQ+Usx1ZyooZWa3tIOvH6CLJwFrS3isEC28NYAaJmc=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint   = server.example.com:54321

Die Client-Schnittstelle kann mit sudo wg-quick up wg0 temporär aktiviert werden. Anschließend müsste Client A den Server-Peer sowohl an dessen IPv4- als auch dessen IPv6-Adresse pingen können. Allerdings ist an diesem Punkt noch kein Internetrouting möglich.

3. Firewallregeln

Zum Einstellen der Firewall empfiehlt Debian die Software firewalld. Diese kann auch wie gewohnt installiert werden:

sudo apt install firewalld

Die folgenden Befehle setzen die benötigten Firewallregeln:

# Schnittstelle zum Internet (hier: eth0) zur Zone "public" hinzufügen
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
# Eingehende Verbindungen auf dem eingestellten Wireguard-Port erlauben
sudo firewall-cmd --permanent --zone=public --add-port=54321/udp

# Wireguard Schnittstelle zu neuer Zone "wg-inet" hinzufügen
sudo firewall-cmd --permanent --new-zone=wg-inet
sudo firewall-cmd --permanent --zone=wg-inet --add-interface=wg0
# eingehenden Traffic aus dem Wireguard Tunnel erlauben
sudo firewall-cmd --permanent --zone=wg-inet --set-target=ACCEPT

# Traffic zwischen beiden Zonen durch Policy explizit erlauben
sudo firewall-cmd --permanent --new-policy=wg-inet-to-public
sudo firewall-cmd --reload
sudo firewall-cmd --permanent --policy=wg-inet-to-public --add-ingress-zone=wg-inet
sudo firewall-cmd --permanent --policy=wg-inet-to-public --add-egress-zone=public
sudo firewall-cmd --permanent --policy=wg-inet-to-public --set-target=ACCEPT

# NAT für IPv4 aktivieren (implizit auch IP-Forwarding generell)
# Dieser Teil ersetzt die PostUp / PostDown Befehle!
sudo firewall-cmd --permanent --zone=public --add-masquerade

# alle Regeln übernehmen
sudo firewall-cmd --reload

Durch diese Befehle werden permanente Firewallregeln definiert, die als Dateien in /etc/firewalld gespeichert sind. Der Inhalt sollte nun wie folgt aussehen:

/etc/firewalld/zones/public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
  <port port="54321" protocol="udp"/>
  <masquerade/>
  <interface name="eth0"/>
  <forward/>
</zone>

/etc/firewalld/zones/wg-inet.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <interface name="wg-inet"/>
  <forward/>
</zone>

/etc/firewalld/policies/wg-inet-to-public.xml

<?xml version="1.0" encoding="utf-8"?>
<policy target="ACCEPT">
  <ingress-zone name="wg-inet"/>
  <egress-zone name="public"/>
</policy>

4. ndppd (Neighbor Discovery Protocol Proxy Daemon)

Damit nun die Wireguard Client Peers die (öffentlichen) IPv6-Adressen für den Internetzugriff nutzen können, ist als “Geheimzutat” die Software ndppd notwendig. Diese kann mit sudo apt install ndppd einfach installiert werden.

Die sogenannten “Neighbor Solicitation” Pakete des Neighbor Discovery Protocol (NDP), sind das IPv6-Äquivalent zu ARP in IPv4-Netzen. Das Internet-Gateway des Servers sendet diese Nachrichten an alle Hosts im Netz, um die MAC-Adresse zu einer Adresse im Netz herauszufinden. Da diese Adressen allerdings nicht auf der Internet-Schnittstelle des Servers liegen, sondern ein einem Ende des Wireguard-Tunnels, werden diese Pakete vom Netzwerkstack des Servers ignoriert, sodass das Gateways die Pakete nicht zustellen kann.

Mit dem ndppd kann das Problem gelöst werden. Dieses prüft für alle eingehenden Neighbor Solicitation Nachrichten, ob die angefragte IPv6-Adresse in einen konfigurierten Bereich fällt und leitet diese an eine definierte Schnittstelle weiter, also in diesem Fall die Wireguard-Schnittstelle.

Dazu muss entsprechend der Dokumentation (man 5 ndppd.conf) die Konfigurationsdatei /etc/ndppd.conf erstellt und wie folgt mit Inhalt gefüllt werden:

proxy eth0 {
    rule 2001:db8::cafe:0/112 {
        iface wg0
    }
}

Dem Beispiel anzupassen sind die Internet-Schnittstelle (hier eth0) und vor allem der (möglichst kleine!) Teil des IPv6-Netzes (hinter rule), das den Wireguard Client Peers zur Verfügung gestellt werden soll. Der Teil iface wg0 teilt ndppd mit, an welche Schnittstelle die entsprechenden Neighbor Solicitations weitergeleitet werden sollen. Diese werden dann von den Client Peers beantwortet. Alternativ kann stattdessen das Keyword static angegeben werden, sodass die entsprechenden Neighbor Solicitations sofort beantwortet werden sollen und nicht an die Peers über die Wireguard-Schnittstelle weitergeleitet werden. Dadurch erscheinen diese Adressen immer erreichbar zu sein. Diese Einstellung ist gegenenfalls zuverlässiger, versorgt aber das Gateway mit potentiell falschen Informationen.