Donnerstag, 18. April 2024

Wireguard Hub and Spoke

In meinem Beitrag "Verbundene Netzwerke" hatte ich mit PiVPN begonnen. 

PiVPN wird eventuell nicht mehr weiterentwickelt -> Zeit eine eigene, möglichst zeitlose Konfiguration zu beschreiben!

Die Idee: irgendwo im Internet (oder an einem Standort in der DMZ) befindet sich ein Einwahlknoten und alle Peers verbinden sich zu diesem Knoten. Es gibt zwei Sorten Peers:

  1. Administratoren/Entwickler, 
  2. Netzwerke mit mehreren Geräten die administriert oder gewartet werden müssen. 

Der Knoten ist möglichst isoliert. Die Peers müssen keine Port öffnen, am eigenen Netzwerk nichts verändern.

Ausgangspunkt für meine Beschreibung ist ein aktualisiertes, minimales Debian (Bookworm) System, 1-2 CPUs, 1-2GB RAM, 10-20 GB Disk, eine Netzwerkkarte, Internet Zugang. Wahrscheinlich braucht man noch weniger (Container). Kein Desktop, kein Gnome, nur sshd und Standard Systemwerkzeuge.

Hier kommt noch ein Diagramm, bis dahin muss der Link hier genügen.

Einrichtung zentraler Knoten "Server"

Router 

  • DHCP feste Reservierung für den Knoten
  • Port Freigabe/Weiterleitung (udp 51820)

Computer

  • Port Weiterleitung (udp 51820) falls Container
  • DDNS Einträge setzen, vor allem für IPv6 muss dies von dieser Maschine aus geschehen, die IPv6 Adresse vom Router ist hierfür nutzlos! Ich nutze hierfür einen Cronjob mit einem wget / curl Aufruf zum Provider (ClouDNS bzw. All-Inkl). 
  • Software Installation


sudo apt install wireguard qrencode

Da wir auch Netzwerke außerhalb des Tunnels erreichen wollen, muss IP Forwarding (Routing) aktiviert werden. Das wird bequem in der Serverconfig mit erledigt.

Alle hier benötigten Keys für die wireguard Konfigurationen werden mit dem wg Utility erzeugt, siehe unten im Code Abschnitt.

Die Basis Konfiguration für den Server sieht so aus. 

[Interface]
PrivateKey = Private_Key_Server
Address = 10.0.6.1/24
ListenPort = 51820
# Routing active
PreUp = sysctl -q net.ipv4.ip_forward=1
PreUp = sysctl -q net.ipv6.conf.all.forwarding=1

Die wird aktiviert und überprüft: 

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

Hinweis: Mit wg show wird auch der Public Key vom Server angezeigt, dieser wird beim Client als Anmeldung eintragen. 

Damit ist der Serverknoten fast fertig, es fehlen noch die peers.

Einrichtung Client

Die Software Installation ist vom Client System abhängig - Download und Info.

Nach dem Setup muss eine Client Konfiguration erzeugt und dem Server bekannt gemacht werden. Dafür hat man generell zwei Möglichkeiten:

  1. Konfiguration am Server erzeugen und komplett auf den Client übertragen.
  2. Konfiguration am Client erzeugen, den Public Key zum Server übertragen und die Clientkonfiguration durch ein paar Zeilen (vom Server) ergänzen.

Variante 1 ermöglicht eine zentrale Aufbewahrung und Dokumentation der eingerichteten Clients. Die Einträge beim Server können automatisiert werden. Für mobile Clients kann man leicht einen QR Code erzeugen. 

Variante 2 bietet höchste Sicherheit, da der private Key den Client nicht verlässt. Ich finde sie für die Windows Clients ganz gut zu handhaben oder wenn man einen Zugang auf "Zuruf" einrichtet.

Der Client (Windows Client Fenster bzw. Linux wg show) zeigt den letzten Schlüsseltausch und die übertragenen Pakete. Bei einem Funktionstest muss man ihn z.B. mit einem ping 10.6.0.1 anstossen, sonst "sieht" man nichts.

Beispielkonfigurationen für unterschiedliche Anwendung

Konfiguration Client "Administrator"

Nur der Client wird mit dem Netzwerk verbunden, DNS, Internet Traffic und lokaler Traffic werden nicht umgelenkt! Der aktivierte Tunnel wird nur bei Datenverkehr geöffnet!

[Interface]
PrivateKey = Private_Key_Peer2
Address = 10.0.6.2/32

[Peer]
PublicKey = Public_Key_Server
AllowedIPs = 10.0.6.0/24, 192.168.1.0/24
Endpoint = vpn.mywg.org:51820

Hinweis: der zweite Eintrag in AllowedIPs erzeugt am Client eine Route über den Tunnel in dieses Netzwerk.

Konfiguration Client "Netzwerk"

Das Netzwerk in dem sich der Client befindet, ist über den Tunnel durch NAT erreichbar.

[Interface]
PrivateKey = Private_Key_Peer10
Address = 10.0.6.10/32

# eth0 / wlan0 - must be changed to the real Interface Name
PreUp   = sysctl -q net.ipv4.ip_forward=1
PostUp  = iptables -A FORWARD -i %i  -j ACCEPT; iptables -A FORWARD -o %i  -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -D FORWARD -i %i  -j ACCEPT; iptables -D FORWARD -o %i  -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = Public_Key_Server
AllowedIPs = 10.0.6.0/24
Endpoint = vpn.mywg.org:51820
PersistentKeepalive = 25

Die Verbindung wird später automatisch gestartet und gehalten (PersistentKeepalive und reresolve-dns).

Aktivierung der Clients am Server

Aus der Client Konfiguration abgeleitet muss die Serverkonfiguration für jeden Client ergänzt werden.

[Peer]
# peer 2 Admin Client
PublicKey = Public_Key_Peer2
AllowedIPs = 10.0.6.2/32
[Peer]
# peer 10 Netzwerk Client
PublicKey = Public_Key_Peer10
AllowedIPs = 10.0.6.10/32, 192.168.1.0/24

Hinweis: der zweite Eintrag in AllowedIPs erzeugt am Server eine Route in dieses Netzwerk.

Jede Änderung wird aktiviert und überprüft, ein reload erhält den existierenden Tunnel:

sudo systemctl reload wg-quick@wg0
sudo wg show

Werden Clients mit Routing Einträgen ergänzt muss der Serverdienst neu gestartete werden! Damit wird allerdings der Tunnel unterbrochen:

sudo systemctl restart wq-quick@wg0

Die Client Konfiguration kann auf das Ziel übertragen werden (Copy Paste, scp, QR Code) und getestet werden.

Code

Noch nicht perfekt und derzeit nur Schnipsel und ein Gerüst! Ziel ist ein Script mit Parametern welches die einzelnen Aufgaben erledigt. 

Mit diesem Code kann die grundlegende Konfiguration für den Server erzeugt werden. Für die spätere Verwendung definiere ich ein paar Variablen  

port=51820
IP4_network=10.0.6
peer=2
url=vpn.mywg.org

Das Here Doc zur Erzeugung der Serverkonfiguration

sudo tee /etc/wireguard/wg0.conf << EOI
[Interface]
PrivateKey = $(wg genkey)
Address = ${IP4_network}.1/24
ListenPort = ${port}
EOI

Überprüfen ob es läuft: 

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

Erzeugung eines Clients zur Administration / Entwicklung. 

tee peer${peer}.conf <<EOI
[Interface]
PrivateKey = $(wg genkey)
Address = ${IP4_network}.${peer}/32

[Peer]
PublicKey = $(sudo wg show | awk '/public key/ {printf($3)}')
AllowedIPs = ${IP4_network}.0/24
Endpoint = ${url}:$(sudo wg show | awk '/listening port/ {printf($3)}')
EOI

Erzeugung eines Clients mit Netzwerkumgebung

Der Interface Name des Netzwerkes vom Client muss vorher ermittelt werden!

peer=10
interface=wlan0 # eth0 / wlan0 - must be changed to the real Interface Name

tee peer${peer}.conf <<EOI
[Interface]
PrivateKey = $(wg genkey)
Address = ${IP4_network}.${peer}/32

PreUp= sysctl -q net.ipv4.ip_forward=1
PostUp  = iptables -A FORWARD -i %i  -j ACCEPT 
PostUp  = iptables -A FORWARD -o %i  -j ACCEPT 
PostUp  = iptables -t nat -A POSTROUTING -o $interface -j MASQUERADE
PreDown = iptables -D FORWARD -i %i  -j ACCEPT 
PreDown = iptables -D FORWARD -o %i  -j ACCEPT
PreDown = iptables -t nat -D POSTROUTING -o $interface -j MASQUERADE
[Peer]
PublicKey = $(sudo wg show | awk '/public key/ {printf($3)}')
AllowedIPs = ${IP4_network}.0/24
Endpoint = ${url}:$(sudo wg show | awk '/listening port/ {printf($3)}')
PersistentKeepalive = 25
EOI

Nach jedem Client der erzeugt wird, muss auch der Server Eintrag ergänzt werden. Die notwendigen Werte werden dabei aus der letzten erzeugten Client Konfiguration geladen.

sudo tee -a /etc/wireguard/wg0.conf <<EOI

[Peer]
# peer $peer Kommentar 
PublicKey = $(cat peer${peer}.conf|awk '/PrivateKey/ {printf($3)}'|wg pubkey)
AllowedIPs = $(cat peer${peer}.conf|awk '/Address/ {printf($3)}')
EOI

peer=$(($peer+1))

Die Clientkonfiguration kann auch als QR Code ausgegeben werden. 

qrencode -t ansiutf8 < peer2.conf

Server Eintrag mit externen Informationen erzeugen 

PublicKey=''
AllowedIPs=''
sudo tee -a /etc/wireguard/wg0.conf <<EOI

[Peer]
# peer extern erzeugt 
PublicKey = ${PublicKey}
AllowedIPs = ${AllowedIPs}
EOI

Ergänzungstext für externe Konfigurationen ausgeben 

cat <<EOI
#############################################
# diese Zeilen ab hier im Tunnel einfügen
Address = ${AllowedIPs}

[Peer]
PublicKey = $(sudo wg show | awk '/public key/ {printf($3)}')
AllowedIPs = ${IP4_network}.0/24
Endpoint = ${url}:$(sudo wg show | awk '/listening port/ {printf($3)}')
EOI


ToDo? 

Script bauen?

Code

Ende 

Keine Kommentare:

Kommentar veröffentlichen