VPN mit WireGuard ################# .. highlight:: shell-session Die neue VPN-Technologie `WireGuard `_ ist eine völlig neue Softwarelösung, die effizient und von Altlasten befreit ist. Linus Torvalds lobte das Projekt, es sei gegegenüber dem Horror von OpenVPN und IPSec ein Kunstwerk. Im einfachsten Falle kann als Testsszenario das eigene LAN ohne Routing oder Subnetting herhalten. Dabei haben wir dann insgesamt folgende IP-Konfiguration vorliegen: 1. VPN-Server (Debian 10) - Reale NIC *enp0s3*: 10.21.21.233 (manuell hinterlegt, muss der Client später angeben!) - Virtuelles Interface *wg0*: 10.20.40.1 (wird beim VPN-Start automatisch zugewiesen) 2. VPN-Client (Artix Linux) - Reale NIC *enp0s3*: 10.21.21.201 (eher unwichtig) - Virtuelles Interface *wg0*: 10.20.40.2 (wird beim VPN-Start automatisch zugewiesen) Das folgende Tutorial basiert auf https://www.ericlight.com/wireguard-part-one-installation.html Installation ============ Für Debian 10 gibt es noch keine fertigen Pakete, es ist aber gut möglich, die Sid-Quellen anzuzapfen, wobei 'buster' die höhere Priorität behalten soll: :: root@d10:~# echo 'deb http://ftp.tu-chemnitz.de/debian/ sid main' >> /etc/apt/sources.list root@d10:~# PS2="" cat > /etc/apt/preferences.d/mypinnings <<\EOF Package: * Pin: release n=buster Pin-Priority: 700 Package: * Pin: release n=sid Pin-Priority: 600 EOF root@d10:~# root@d10:~# apt-get update ... root@d10:~# apt-get install wireguard ... Bei Ubuntu 20.04 LTS sind die betreffenden Pakete schon vorhanden, also einfach ``apt-get install wireguard`` ausführen, genauso sieht es bei Artix/Arch Linux aus, dort reicht ``pacman -Sy wireguard-tools`` aus. Auch bei SuSE Leap 15.2 gibt es ein Paket, das mit ``zypper insgesamt wireguard-tools`` auf die Platte gelangt. Konfiguration ============= Die Konfiguration geht recht einfach von statten. Es muss im Prinzip auf beiden Seiten dasselbe getan werden, nur dass der Client zusätzlich noch die reale IP-Adresse des VPN-Servers mitttels ``Endpoint`` spezifizieren muss. VPN-Server (-Gateway) --------------------- Zuerst nehmen wir uns den Server vor, hier ist das speziell Debian 10: :: root@d10:~# cd /etc/wireguard/ root@d10:/etc/wireguard# umask 077 root@d10:/etc/wireguard# root@d10:/etc/wireguard# # Dateiheader erzeugen: root@d10:/etc/wireguard# printf "[Interface]\nPrivateKey = " > wg0.conf root@d10:/etc/wireguard# root@d10:/etc/wireguard# # Privaten Schlüssel erzeugen, an die Config anhängen sowie den öffentlichen extrahieren: root@d10:/etc/wireguard# wg genkey | tee -a wg0.conf | wg pubkey > publickey root@d10:/etc/wireguard# Damit steht in der Datei *wg0.conf* erst einmal dies drin: .. highlight:: ini :: [Interface] PrivateKey = MJG6qhHVtLfWNe45Okmnr95SZKQQpuExA+5D9FgM71g= Wir kontrollieren nun das Bisherige und geben schon mal den *publickey* aus, den wir später auf der anderen Seite beim Peer einfügen müssen: .. highlight:: shell-session :: root@d10:/etc/wireguard# ls -l insgesamt 8 -rw------- 1 root root 45 Okt 20 11:52 publickey -rw------- 1 root root 70 Okt 20 11:52 wg0.conf root@d10:/etc/wireguard# root@d10:/etc/wireguard# cat publickey XBhqgxfvLdnMQy9333zAVqofi1OamozZIUz6ueyuXAo= root@d10:/etc/wireguard# Schließlich editieren wir die Datei */etc/wireguard/wg0.conf* und ergänzen sie, dass sie wie folgt aussieht (``PublicKey`` bleibt vorerst leer): .. highlight:: ini :: [Interface] PrivateKey = MJG6qhHVtLfWNe45Okmnr95SZKQQpuExA+5D9FgM71g= ListenPort = 12345 Address = 10.20.40.1/24 [Peer] PublicKey = AllowedIPs = 10.20.40.0/24 Dabei geben wir mit ``Address = ...`` an, welche IP-Adresse die virtuelle VPN-Schnittstelle erhalten soll, mit ``ListenPort = ...`` legen wir die Portnummer fest, die für den Socket benutzt werden soll und konfigurieren bei ``[Peer]`` die Eigenschaften des Gegenübers, also unseres Clients, dessen öffentlicher Schlüssel uns noch nicht vorliegt. Und mit ``AllowedIPs = ...`` definieren wir das Netzwerk, aus dem die Anfragen akzeptiert und geroutet werden sollen. VPN-Client ---------- Nun ist Artix mit der Konfiguration dran. Vorher müssen wir natürlich die Software mittels ``pacman -Sy wireguard-tools`` installiert haben: .. highlight:: shell-session :: [artix-wks ~]# cd /etc/wireguard/ [artix-wks wireguard]# umask 077 [artix-wks wireguard]# [artix-wks wireguard]# # Dateiheader erzeugen: [artix-wks wireguard]# printf "[Interface]\nPrivateKey = " > wg0.conf [artix-wks wireguard]# [artix-wks wireguard]# # Privaten Schlüssel erzeugen, an die Config anhängen sowie den öffentlichen extrahieren: [artix-wks wireguard]# wg genkey | tee -a wg0.conf | wg pubkey > publickey [artix-wks wireguard]# [artix-wks wireguard]# # Öffentlichen Schlüssel ausgeben (für späteres Einbinden weiter unten beim Peer): [artix-wks wireguard]# cat publickey +IgQQFYdJi5e467bp1c6Tv9Uvp+I2e+Gn62u2v6oDEY= [artix-wks wireguard]# Wir editieren wieder die Datei */etc/wireguard/wg0.conf*, so dass sie schließlich folgenden Inhalt aufweist (den öffentlichen Schlüssel des Servers haben wir ja weiter oben extrahiert und können ihn gleich bei ``[Peer]`` -> ``PublicKey`` eintragen): .. highlight:: ini :: [Interface] PrivateKey = gK4Zsam/sKiHlMuK7/8N3+1TEGH5t6ocPO9aVNnhO0s= ListenPort = 12345 Address = 10.20.40.2/24 [Peer] PublicKey = XBhqgxfvLdnMQy9333zAVqofi1OamozZIUz6ueyuXAo= Endpoint = 10.21.21.233:12345 AllowedIPs = 10.20.40.0/24 In diesem letzten Abschnitt ist neben den oben beschriebenden Dingen der wichtige Eintrag ``Endpoint = ...`` hinzugekommen. Damit wird dem Client mitgeteilt, unter welcher realen (öffentlichen) IP-Adresse der VPN-Server zu erreichen ist (Zum Vergleich: OpenVPN verwendet hierfür ``remote ...``). Server-Konfiguration vervollständigen ------------------------------------- Was auf dem Debian-System noch fehlt, ist der soeben erzeugte, clientseitige *publickey* von Artix, der in der Datei */etc/wireguard/wg0.conf* unter ``[Peer]`` eingetragen werden muss. Diese Datei sieht schlussendlich so aus: :: [Interface] PrivateKey = MJG6qhHVtLfWNe45Okmnr95SZKQQpuExA+5D9FgM71g= ListenPort = 12345 Address = 10.20.40.1/24 [Peer] PublicKey = +IgQQFYdJi5e467bp1c6Tv9Uvp+I2e+Gn62u2v6oDEY= AllowedIPs = 10.20.40.0/24 Damit haben wir nun die PublicKeys des jeweils anderen an der passenden Stelle hinterlegt. Inbetriebnahme ============== Zuerst bringen wir den Server an den Start: .. highlight:: shell-session :: root@d10:~# wg-quick up wg0 [#] ip link add wg0 type wireguard [#] wg setconf wg0 /dev/fd/63 [#] ip -4 address add 10.20.40.1/24 dev wg0 [#] ip link set mtu 1420 up dev wg0 root@d10:~# root@d10:~# ip -4 addr 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: enp0s3: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 10.21.21.233/24 brd 10.21.21.255 scope global enp0s3 valid_lft forever preferred_lft forever 3: wg0: mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 inet 10.20.40.1/24 scope global wg0 valid_lft forever preferred_lft forever root@d10:~# Und jetzt ist der Client dran: :: [artix-wks wireguard]# wg-quick up wg0 [#] ip link add wg0 type wireguard [#] wg setconf wg0 /dev/fd/63 [#] ip -4 address add 10.20.40.2/24 dev wg0 [#] ip link set mtu 1420 up dev wg0 [artix-wks wireguard]# [artix-wks wireguard]# ip -4 addr 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 brd 127.255.255.255 scope host lo valid_lft forever preferred_lft forever 2: enp0s3: mtu 1500 qdisc noqueue state UP group default qlen 1000 inet 10.21.21.201/24 brd 10.21.21.255 scope global enp0s3 valid_lft forever preferred_lft forever 3: wg0: mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 inet 10.20.40.2/24 scope global wg0 valid_lft forever preferred_lft forever [artix-wks wireguard]# [artix-wks wireguard]# Der Aufbau des verschlüsselten Kanals muss von Client initiiert werden; wenn der Server den Tunnelaufbau anschieben möchte, kommt es zum Fehler: :: root@d10:~# ping -c2 10.20.40.2 PING 10.20.40.2 (10.20.40.2) 56(84) bytes of data. From 10.20.40.1 icmp_seq=1 Destination Host Unreachable ping: sendmsg: Es ist eine Zieladresse notwendig From 10.20.40.1 icmp_seq=2 Destination Host Unreachable ping: sendmsg: Es ist eine Zieladresse notwendig --- 10.20.40.2 ping statistics --- 2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 23ms root@d10:~# Wenn aber wie üblich der Client als Initiator auftritt, funktioniert es: :: [artix-wks wireguard]# ping -c2 10.20.40.1 PING 10.20.40.1 (10.20.40.1) 56(84) bytes of data. 64 Bytes von 10.20.40.1: icmp_seq=1 ttl=64 Zeit=2.45 ms 64 Bytes von 10.20.40.1: icmp_seq=2 ttl=64 Zeit=0.503 ms --- 10.20.40.1 ping statistics --- 2 Pakete übertragen, 2 empfangen, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.503/1.478/2.454/0.975 ms [artix-wks wireguard]# Und nun klappt der Ping auch vom Server aus: :: root@d10:~# ping -c2 10.20.40.2 PING 10.20.40.2 (10.20.40.2) 56(84) bytes of data. 64 bytes from 10.20.40.2: icmp_seq=1 ttl=64 time=0.613 ms 64 bytes from 10.20.40.2: icmp_seq=2 ttl=64 time=0.476 ms --- 10.20.40.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 3ms rtt min/avg/max/mdev = 0.476/0.544/0.613/0.072 ms root@d10:~# Fehlersuche =========== Wenn eine Analyse der Verschlüsselung im physischen Netzwerk erfolgen soll, es also keinen Router als "Man-In-The-Middle" gibt, ist das Mitlesen schwieriger. Das Hauptproblem: Switche schalten 2 Teilnehmer direkt durch, ein 3. sieht nichts! Siehe dazu: - https://www.erg.abdn.ac.uk/users/gorry/course/lan-pages/nic.html (Promiscous Mode) - http://www.nwlab.net/guide2na/netzwerkanalyse-sniffern.html (ein Hub anstelle eines Switches benutzen) - https://www.hackers-arise.com/post/2017/07/25/man-the-middle-mitm-attack-with-arpspoofing (ARP-Poisoning, um den Switch zu überlisten) - https://www.linux-magazin.de/ausgaben/2004/06/interner-zugriff/2/ (MAC-Flooding, um den Switch als Hub arbeiten zu lassen) Ein weiteres Problem taucht auf, wenn Logging erforderlich wird. Unter https://serverfault.com/questions/1020279/how-to-see-authentication-logs-for-wireguard wird als Lösung für Kernel > 5.6 mit Unterstützung von Dynamic Debugging folgendes empfohlen (ungetestet): .. highlight:: bash :: modprobe wireguard echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control Danach sollte ``dmesg`` oder ``journalctl`` Aufschluss über die Vorgänge geben. Have \'a lot of fun...