Fritz!Box WireGuard und systemd-networkd
Vor Jahren schon habe ich einfache WireGuard-Verbindungen zwischen meinem Heimserver und meinem virtuellen Server, damals bei Contabo, eingerichtet. Ich erinnere mich düster, dass ich den WireGuard-Schnittstellen eigene IP-Adressen zuweisen musste, über die dann das Routing eingerichtet wurde.
In diesem Eintrag werde ich Verbindungsschlüssel entfernen und IP-Adressen austauschen bzw. durch Labels ersetzen, die ihre Funktion beschreiben, damit das ggf. auf vergleichbare, aber nicht identische Situationen angewendet werden kann.
Die Situation
Bei mir liegen zwei Spezialfälle vor: Ich habe auf meinem Server ein paar Systemcontainer mit systemd-nspawn am Laufen. Diese hängen dort an einer Network Zone, die von systemd-nspawn gemanagt wird. Für vorhersagbare IP-Adressen läuft auf der Bridge-Schnittstelle der DHCP-Server von systemd-networkd. Der wird einfach mittels einer Drop-in-Datei aktiviert und konfiguriert.
# /etc/systemd/network/80-container-vz.network.d/00-dhcp.conf [Network] Address=192.168.1.1/24 Address=fd00:1::1/64 DHCPServer=yes IPMasquerade=both [DHCPServer] ServerAddress=192.168.1.1/24 EmitDNS=yes DNS=9.9.9.9 EmitRouter=yes EmitTimezone=yes Timezone=Europe/Berlin PoolOffset=99 PoolSize=150 [DHCPServerStaticLease] # nspawn 1 MACAddress=12:34:56:00:00:01 Address=192.168.1.101 [DHCPServerStaticLease] # nspawn 2 MACAddress=12:34:56:00:00:02 Address=192.168.1.102 [DHCPServerStaticLease] # qemu 1 MACAddress=12:34:56:00:01:01 Address=192.168.1.201
Die einzelnen statischen Leases könnten jeweils auch in eigenen Dateien stecken.
Die andere Besonderheit ist, dass die Fritzbox bei mir nicht für das DHCP zuständig ist. Das macht ein dnsmasq auf meinem Heimserver in einem systemd-nspawn-Container.
Wichtig ist, dass am Ende aus dem lokalen Netz hinter der Fritzbox via WireGuard auf die einzelnen Container zugegriffen werden kann.
## Konfiguration auf der Fritzbox Der wichtige Teil findet statt auf der Seite "Internet > Freigaben > VPN (Wireguard)" (Fritz-OS 8.21). Der Assistent wird mit der Schaltfläche "WireGuard®-Verbindung hinzufügen" aufgerufen.
Effektiv musste ich in dem Assistenten immer die rechte Option wählen:
Welche Art Verbindung möchten Sie erstellen? → Netzwerke koppeln.
Ist diese WireGuard®-Verbindung auf der Gegenstelle bereits eingerichtet? → Nein.
Soll die Verbindung gleichzeitig zu einer bestehenden WireGuard®-Verbindung der Gegenstelle genutzt werden? → Nein. Ich habe nicht geschaut, was "ja" an der Stelle bewirkt. Ich nehme an, davon hängt ab, ob ich eine vollständige Konfiguration kriege oder nur einen Schnipsel zur Ergänzung.
Was für ein Gerät befindet sich auf der Gegenstelle? → WireGuard®-fähiger Router. Keine Ahnung, warum das abgefragt wird, wenn ich am Anfang "Netzwerke koppeln" ausgewählt habe. Ja natürlich muss da ein WireGuard®-fähiger Router sein.
Der Assistent warnt mich dann:
Das manuelle Hinzufügen der neuen Verbindungseinstellungen wird nur erfahrenen Benutzern empfohlen.
Naja, wir sind ja erfahren, nicht wahr?
Als nächstes vergeben wir einen Namen, unter dem die Verbindung geführt wird.
Der nächste Schritt ist ein wenig unklar. Der Assistent möchte eine Angabe der "DNS-Domains der WireGuard®-Gegenstelle". Nirgends scheint die Angabe eine Auswirkung zu haben. Ich kann nur mutmaßen, dass dieser Wert via DHCP als search domain verteilt wird. Wie eingangs erwähnt, kümmert sich ein anderes System hier um DHCP.
Im vorletzten Schritt fragt der Assistent nach den "IP-Einstellungen der Verbindung". Hier musste ich ein wenig experimentieren, um herauszufinden, was der Assistent damit meint. Letzten Endes funktionierte es mit der IP-Adresse der systemd-nspawn-Zone, deren Netzmaske (CIDR zu Netzmaske) und der ULA-IPv6-Adresse ebendieser Schnittstelle. Bis zu dieser Konfiguration hatte ich der Zonen-Schnittstelle überhaupt keine IPv6-Adresse vergeben, was zu ein bisschen Recherche-Arbeit geführt hat.
Im letzten Schritt gibt es ein paar Kästchen anzukreuzen oder auch nicht. In diesem Fall wird nichts davon gebraucht.
Wenn man zu lange brauchte seit der letzten Bestätigung, dass man berechtigt sei, Änderungen an der Konfiguration vorzunehmen, muss das jetzt nochmal bestätigt werden. Im Anschluss arbeitet die Fritzbox ein wenig und bietet dann den Download der erstellten Konfiguration an, was wir auch annehmen. Nach dem Download muss noch auf "Ok" geklickt werden. Der Assistent weist ein letztes Mal darauf hin, dass die geheimen Verbindungsdaten aus der Datei nicht wieder eingesehen werden können.
[Interface] PrivateKey = <privater Schlüssel des Servers> Address = 192.168.1.1/24,fd12:3456:7891::/64 DNS = <private IPv4 und IPv6 der Fritzbox> DNS = fritz.box [Peer] PublicKey = <öffentlicher Schlüssel der Fritzbox> PresharedKey = <geteilter Schlüssel der Verbindung> AllowedIPs = <private IPv4- und IPv6-Netze der Fritzbox> Endpoint = foobar.myfritz.net:52008 PersistentKeepalive = 25
Eigentlich brauchen wir die Datei gar nicht, aber sie beinhaltet die Werte, die wir für die Konfiguration mit systemd-networkd brauchen.
## Konfiguration von systemd-networkd auf dem Server
Die Konfigurationsdateien von systemd-networkd liegen üblicherweise in /etc/systedm/network/.
Die Verbindung wird auf drei Dateien aufgeteilt:
wg0.netdev-
Die Datei legt das Netzwerkgerät an. Sie beinhaltet die Verbindung zur Gegenstelle sowie alle für die Verbindung notwendigen Geheimnisse bzw. verweist auf entsprechende Dateien (vgl. man-Page systemd.netdev, Abschnitt Wireguard).
wg0.key-
Die Datei beinhaltet den base64-kodierten privaten Schlüssel des Servers für diese Verbindung.
wg0.network-
Hier wird ganz normal das Netzwerk auf der Schnittstelle
wg0konfiguriert – IP-Adressen, Routen und was sonst noch so anfällt (vgl. man-Page systemd.network).
Die Namen der Dateien sind beliebig wählbar. Allein bei dem privaten Schlüssel muss drauf geachtet werden, dass die Datei in der .netdev-Datei korrekt referenziert wird.
# wg0.netdev [NetDev] Name=wg0 Kind=wireguard Description=WireGuard tunnel wg0 [WireGuard] # Vermutlich unnötig, ist einfach auf den gleichen Port gesetzt, den die Fritzbox auch nutzt. ListenPort=52008 PrivateKeyFile=/etc/systemd/network/wg0.key [WireGuardPeer] AllowedIPs=192.168.178.1/24,fd12:3456:7890::/64 PublicKey=<öffentlicher Schlüssel der Fritzbox> PresharedKey=<geteilter Schlüssel der Verbindung> Endpoint=foobar.myfritz.net:52008 PersistentKeepalive=25
Die Werte für PublicKey und PresharedKey können einfach aus der heruntergeladenen Konfigurationsdatei kopiert werden. Tatsächlich benutzen WireGuard und systemd-networkd die gleichen Namen für die Werte, so dass sogar die Zeilen komplett kopiert werden können.
systemd-networkd möchte nicht, dass diese Datei weltlesbar ist, weswegen wir die Berechtigungen und Eigentümerschaft anpassen:
chmod 640 /etc/systemd/network/wg0.netdev chown root:systemd-network /etc/systemd/network/wg0.netdev
Das PrivateKeyFile beinhaltet einfach nur den Wert <privater Schlüssel des Servers> aus der Konfigurationsdatei ohne PrivateKey= oder ähnlichem. Netterweise ist der Wert bereits base64-kodiert, so dass dahingehend nichts weiter getan werden muss. Für die Datei verlangt systemd-networkd aber sogar, dass sie nicht weltlesbar ist:
chmod 640 /etc/systemd/network/wg0.key chown root:systemd-network /etc/systemd/network/wg0.key
Bei der letzten Datei, der wg0.network, ist systemd-networkd entspannter. Sie kann ruhig von allen gelesen werden.
# wg0.network [Match] Name=wg0 [Network] Address=192.168.1.1/24 Address=fd00:1::1/64 IPMasquerade=both [Route] Destination=<IPv4-Netzwerk der Fritzbox> [Route] Destination=<IPv6-Netzwerk der Fritzbox>
Aufmerksamen Leser*innen ist es sicher aufgefallen, und mir bereitet es auch Bauchschmerzen, aber es funktioniert tatsächlich: Die Schnittstelle wg0 erhält die gleichen Adressen und Netzmasken wie die Schnittstelle der systemd-nspawn-Zone.
Mit einem finalen networkctl reload wird die Schnittstelle aktiviert und der WireGuard-Tunnel aufgebaut.
Da die systemd-nspawn-Container als Default-Route die Adresse der Zonen-Schnittstelle konfiguriert haben, funktionieren Verbindungen von Seiten der Container sofort. Auch die Geräte hinter der Fritzbox können die Container ohne Probleme erreichen, da die Fritzbox –wie in den meisten Fällen– als Gateway konfiguriert ist.
Dieser Blog-Eintrag wurde ohne Unterstützung generativer KI erstellt.
Kommentare
With an account on the Fediverse or Mastodon, you can respond to this post. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.