VPS als IPv4-Portweiterleitung für DS-Lite-Anschluss

By Jürgen @ (@juergen.me)
Published:

Diese Anleitung richtet einen VPS mit öffentlicher IPv4-Adresse als "Vorposten" für einen DS-Lite-Anschluss (z. B. sim.de) ein. Ziel: Dienste im Heimnetz (Webserver, NAS, etc.) sollen über die feste IPv4 des VPS von außen erreichbar sein, obwohl die FritzBox selbst nur eine wechselnde öffentliche IPv6-Adresse hat.

Architektur: Die FritzBox arbeitet als WireGuard-Server, der VPS als WireGuard-Client. Eingehender Traffic auf dem VPS wird per DNAT durch den Tunnel ins Heimnetz weitergeleitet.


Voraussetzungen

als Fallback, falls SSH während der Einrichtung ausfällt


Teil 1: MyFRITZ! aktivieren (Adressierbarkeit der FritzBox sicherstellen)

Da DS-Lite-Anschlüsse nur eine wechselnde öffentliche IPv6-Adresse haben, braucht der VPS einen festen Hostnamen, um die FritzBox jederzeit zu finden.

Dieser Hostname bleibt stabil, auch wenn sich die IPv6-Adresse der FritzBox ändert.


Teil 2: WireGuard-Verbindung auf der FritzBox anlegen

(nicht "Site-to-Site" – die Variante für ein einzelnes Gerät lässt die FritzBox eine fertige Konfigurationsdatei erzeugen, inkl. eigenem Schlüsselpaar)

Warum diese Reihenfolge wichtig ist: Die FritzBox nutzt intern einen einzigen privaten

Schlüssel für alle WireGuard-Verbindungen. Ein Import einer selbst erstellten Config mit fremdem PrivateKey schlägt mit der Fehlermeldung "Importierte Konfigurationsdatei der WireGuard-Gegenstelle löst einen Schlüsselkonflikt aus" fehl. Lässt man stattdessen die FritzBox die Config erzeugen, entfällt dieses Problem komplett.


Teil 3: Config auf den VPS übertragen

scp vps.conf root@<VPS-IP>:/etc/wireguard/wg0.conf

Datei ansehen:

sudo cat /etc/wireguard/wg0.conf

Typischer Inhalt (Beispielwerte):

[Interface]
PrivateKey = <von der FritzBox generiert>
Address = 192.168.178.203/24, fd41:2ff5:823c::203/64
DNS = 192.168.178.1

[Peer]
PublicKey = <Public Key der FritzBox>
Endpoint = server.abcdefghijklmnop.myfritz.net:51820
AllowedIPs = 192.168.178.0/24, 0.0.0.0/0, fd41:2ff5:823c::/64, ::/0

Diese Datei muss vor dem ersten Start an zwei Stellen zwingend angepasst werden (Teil 4 und 5) – sonst drohen die zwei häufigsten Fehler dieser Einrichtung.


Teil 4: DNS-Zeile entfernen (verhindert Startfehler)

wg-quick versucht bei einer vorhandenen DNS =-Zeile, das Tool resolvconf aufzurufen, um den DNS-Server systemweit einzutragen. Das ist auf den meisten schlanken VPS-Images nicht installiert und lässt den Dienst mit status=127 fehlschlagen.

sudo nano /etc/wireguard/wg0.conf

Zeile löschen:

DNS = 192.168.178.1

Der VPS braucht diesen DNS-Server nicht – er soll nur gezielt Pakete ins Heimnetz weiterleiten, nicht seinen eigenen DNS-Verkehr umleiten.


Teil 5: AllowedIPs einschränken (verhindert SSH-Aussperrung!)

⚠️ Der wichtigste Schritt in dieser Anleitung. Die von der FritzBox generierte Config enthält standardmäßig 0.0.0.0/0 und ::/0 in AllowedIPs. Das weist den VPS an, seinen gesamten Internet-Traffic – inklusive der laufenden SSH-Verbindung – durch den Tunnel zur FritzBox zu routen. Sobald der Tunnel steht, bricht SSH ab und der VPS ist nur noch über die Provider-Webkonsole erreichbar.

sudo nano /etc/wireguard/wg0.conf

Ersetze:

AllowedIPs = 192.168.178.0/24, 0.0.0.0/0, fd41:2ff5:823c::/64, ::/0

durch nur das Heimnetz-Subnetz (kein 0.0.0.0/0, kein ::/0):

AllowedIPs = 192.168.178.0/24, fd41:2ff5:823c::/64

Noch enger fassen (empfohlen): Willst du nur ein einzelnes Gerät erreichbar machen (z. B. deinen Webserver auf 192.168.178.163), trage nur dessen Adresse mit /32 ein:

AllowedIPs = 192.168.178.163/32
Damit ist ausschließlich dieses eine Gerät über den Tunnel erreichbar – alle anderen Geräte im Heimnetz (auch die FritzBox selbst) bleiben vom VPS aus unerreichbar. Mehrere einzelne Geräte lassen sich kommagetrennt ergänzen:
AllowedIPs = 192.168.178.163/32, 192.168.178.1/32


Teil 6: IP-Forwarding aktivieren

sudo nano /etc/sysctl.conf
Zeile einfügen/entkommentieren:
net.ipv4.ip_forward=1
Anwenden:
sudo sysctl -p


Teil 7: WireGuard-Tunnel starten (mit SSH-Absicherung)

Öffne dafür zwei separate Terminal-Fenster/Sessions zum VPS – falls die Verbindung durch einen Konfigurationsfehler abbricht, hast du im zweiten Fenster noch Zugriff, um zu korrigieren.

sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0

Status und Handshake prüfen:

sudo wg show

Ein erfolgreicher Aufbau zeigt eine Zeile latest handshake: X seconds ago. Fehlt diese Zeile dauerhaft, sind Keys, Endpoint oder Firewall/Cloud-Firewall-Regeln zu prüfen (siehe Fehlerbehebung am Ende).

Verbindungstest zum Heimnetz:

ping 192.168.178.163
(Hinweis: Manche FritzBox-Geräte blocken ICMP/Ping auf VPN-Schnittstellen – falls Ping nicht antwortet, aber der Handshake steht, direkt mit einem TCP-Dienst testen, z. B. nc -zv 192.168.178.163 80.)


Teil 8: Firewall auf dem VPS öffnen

WireGuard-Port und Firewall-Weiterleitung freigeben:

sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT


Teil 9: HTTP/HTTPS per DNAT ins Heimnetz weiterleiten

Eingehenden Traffic auf Port 80/443 zur Ziel-IP im Tunnel umleiten (Beispiel-Ziel 192.168.178.163):

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.178.163:80
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 192.168.178.163:443

sudo iptables -A FORWARD -p tcp -d 192.168.178.163 --dport 80 -j ACCEPT
sudo iptables -A FORWARD -p tcp -d 192.168.178.163 --dport 443 -j ACCEPT

MASQUERADE für den Rückweg sicherstellen:

sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
Prüfen:
sudo iptables -t nat -L POSTROUTING -v -n

Regeln dauerhaft speichern (sonst gehen sie beim nächsten Neustart verloren):

sudo apt install iptables-persistent -y
sudo netfilter-persistent save


Teil 10: Portfreigabe auf der FritzBox selbst

Zusätzlich zur DNAT-Regel auf dem VPS muss die FritzBox die Ports 80/443 lokal an das Zielgerät freigeben (unabhängig vom WireGuard-Tunnel, normale Portfreigabe):

Internet → Freigaben → Portfreigaben → Gerät 192.168.178.163 auswählen → Port 80 (HTTP) und 443 (HTTPS) freigeben.


Teil 11: End-to-End-Test

Von einem externen Gerät (nicht VPS, nicht Heimnetz – z. B. Smartphone im Mobilfunknetz):

curl -I http://<VPS-öffentliche-IPv4>
curl -Ik https://<VPS-öffentliche-IPv4>

Kommt eine Antwort von deinem Heimnetz-Server zurück, funktioniert die komplette Kette.

Zur Live-Kontrolle während des Tests, ob Pakete überhaupt ankommen:

sudo iptables -t nat -L PREROUTING -v -n
sudo iptables -L FORWARD -v -n
Die Paketzähler (pkts) sollten bei den passenden Regeln hochzählen.


Teil 12: DNS-Einträge für eine eigene Domain

Ziel: Ein Hostname wie server.deinedomain.de soll per IPv4 über den VPS-Tunnel und per IPv6 direkt über die FritzBox erreichbar sein. Ein A-Record und ein AAAA-Record können für denselben Namen nebeneinander existieren (kein Konflikt) – ein CNAME auf myfritz.net funktioniert an dieser Stelle dagegen nicht, da an einem Namen mit A-Record kein CNAME gleichzeitig existieren darf.

| Record-Typ | Wert | Update-Art | |---|---|---| | A | öffentliche IPv4 des VPS | statisch, einmalig eintragen | | AAAA | aktuelle IPv6 der FritzBox | dynamisch, da DS-Lite die Adresse wechselt |

A-Record (einmalig, beim DNS-Anbieter der Domain):

server.deinedomain.de.   A   <VPS-öffentliche-IPv4>

AAAA-Record (dynamisch via DynDNS):

Da sich die IPv6-Adresse bei DS-Lite regelmäßig ändert, braucht es einen DynDNS-Dienst, der AAAA-Updates für die eigene Domain unterstützt (nicht nur myfritz.net-Subdomains), z. B. deSEC (kostenlos, direkt in FRITZ!OS als Anbieter wählbar) oder IPv64.net.

Einrichtung in der FritzBox: Internet → Freigaben → DynDNS → Anbieter auswählen → Zugangsdaten und Domain eintragen. Die FritzBox aktualisiert den AAAA-Record danach automatisch bei jedem Präfixwechsel.


Fehlerbehebung – häufigste Probleme dieser Einrichtung

| Symptom | Ursache | Lösung | |---|---|---| | wg-quick scheitert mit resolvconf: command not found (Exit 127) | DNS =-Zeile in der Config, resolvconf fehlt auf dem VPS | DNS-Zeile aus wg0.conf entfernen (Teil 4) | | Key is not the correct length or format | Platzhaltertext statt echtem Public Key in der Config stehen geblieben | Echten Key eintragen, exakte Base64-Zeichenkette prüfen | | FritzBox-Import: "Schlüsselkonflikt mit bestehenden Verbindungen" | FritzBox nutzt einen einzigen PrivateKey für alle WireGuard-Verbindungen; eigene Config mit fremdem PrivateKey wird abgelehnt | Nicht selbst eine Config mit eigenem PrivateKey importieren – stattdessen die FritzBox die Config generieren lassen (Teil 2) | | SSH-Verbindung zum VPS bricht ab, sobald der Tunnel startet | AllowedIPs enthält 0.0.0.0/0/::/0, kompletter VPS-Traffic wird umgeleitet | Web-Konsole des Providers nutzen, Tunnel stoppen, AllowedIPs auf das Heimnetz-Subnetz bzw. Ziel-IPs einschränken (Teil 5) | | wg show zeigt keinen latest handshake | Falscher Endpoint/Port, Cloud-Firewall blockt UDP 51820, oder falsche Keys | Cloud-Firewall-Regeln beim VPS-Provider prüfen, Endpoint (MyFRITZ!-Hostname:51820) und Keys gegenchecken | | Ping durch den Tunnel funktioniert nicht, obwohl Handshake steht | FritzBox blockt ICMP auf der VPN-Schnittstelle (normales Verhalten) | Statt Ping direkt einen TCP-Dienst testen, z. B. nc -zv <Ziel-IP> 80 |


Kurzübersicht: Zusammenspiel der Komponenten

flowchart LR
    A[Internet-Client] -->|HTTP/HTTPS Port 80/443| B[VPS<br/>öffentliche IPv4]
    B -->|DNAT + iptables| C[WireGuard-Tunnel<br/>wg0]
    C -->|verschlüsselt via IPv6| D[FritzBox<br/>WireGuard-Server]
    D -->|Portfreigabe| E[Zielgerät im Heimnetz<br/>192.168.178.163]