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...