VPS Public IP in das Homelab tunneln mit Wireguard und Debian 10

Eins vorweg: Das ist nichts "for productional use"! Ich grabe mir hier an meiner Firewall vorbei einen Tunnel nach aussen auf einen VPS um Dienste aus Docker Containern auf einem internen Server zu veröffentlichen. Es gibt zwar Firewallregeln auf den beteiligten Hosts, aber das ist eher so hemdsärmelig. Das hier ist die absolute low-budget Homelab Variante. Richtigerweise terminiert man den Tunnel auf seine Firewall und regelt von dort aus den Traffic weiter!

Urlaub + Gewitter + Pandemie = Blogzeit

Wireguard ist ja eher so das New Kid on the VPN Block. Wireguard VPN Verbindungen sind wirklich absolut einfach und schnell zu erstellen. Wireguard verfügt über Unterstützung für Linux Network Namespaces und kann daher prima für die Anbindung von Containern genutzt werden - dazu später vielleicht mehr.

Was ist denn nun der Anwendungsfall?

Ich betreibe seit Jahren einen Rootserver bei einem bekannten deutschen Hoster. Im Prinzip brauche ich den Server nicht mehr, mein einziges Problem ist e-Mail. Ich hoste meinen Mailserver gerne selber, so muss ich auf niemanden Rücksicht nehmen, sollte ich mal einen kompletten Netzbereich blocken oder den Spamfilter härter drehen. Auch das mitlesen meiner Mails durch einen Provider oder dessen Personal ist nicht mehr ganz so einfach und das Erstellen eines täglichen Backups ist viel einfacher.

Einen Mailserver hinter einer dynamischen IP von meinem DSL Provider zu betreiben wird schwierig. Ein sehr grosser Teil der annehmenden Mailserver wird die Annahme einer Mail von solch einer IP schlicht und einfach verweigern. Ja, dafür kann man problemlos SMTP-Relaying benutzen, dann sucht man im Fehlerfall aber wieder in zwei Mailserverlogs rum - brauche ich nicht. Die Idee ist also den Mailserver demnächst im Homelab zu betreiben und sich damit die Kosten für den etwas dickeren Root Server zu sparen. Die paar statischen Webseiten ziehen direkt in Docker Container um und werden ebenfalls aus dem Homelab betrieben. Gehostet wird das auf einem stromsparenden Intel Atom Board mit einer SSD, damit die gesparten Kosten für den Rootserver nicht vom Energieversorger aufgefressen werden.

Es braucht also eine feste IP im Homelab, diese bietet mein DSL Provider aber nicht am Privatkundenanschluss an. Also miete ich mir einfach einen kleinen VPS mit einer öffentlichen IP (gibt es inzwischen für unter 3 Euro im Monat), erstelle einen VPN Tunnel und nutze NAT um die notwendige feste IP ins Homelab zu tunneln. Ist doch easy! :-)  

Wireguard Installation auf Debian 10

Die folgenden Schritte müssen auf beiden Systemen erfolgen.

Die Installation ist auf einem aktuellen Debian schnell erledigt. Zuerst halten wir das System aktuell. (Wer direkt als root angemeldet ist, lässt das sudo einfach weg).

sudo apt update && sudo apt upgrade

Wireguard Pakete für Debian werden im Debian-Backports Repository bereitgestellt. Das muss zuerst hinzugefügt werden.

sudo sh -c "echo 'deb http://deb.debian.org/debian buster-backports main contrib non-free' > /etc/apt/sources.list.d/buster-backports.list"

Nun werden die Paketlisten aus dem neuen Repository gezogen

sudo apt update

Wireguard kann jetzt installiert werden.

sudo apt install wireguard

Und das war es dann auch mit der Installation. Auf beiden Systemen wird jetzt ein Schlüsselpaar erstellt:

sudo -i
cd /etc/wireguard/
umask 077; wg genkey | tee privatekey | wg pubkey > publickey

Auf dem beiden Servern gibt es jetzt in /etc/wireguard/ zwei Dateien: privatekey und publickey. Diese Inhalte zeigt man sich mit z.b. cat an und notiert sich diese. Mit diesen Daten kann nun die Konfiguration des Tunnels vorgenommen werden. Der UDP Port kann relativ frei gewählt werden, ich habe mich in dem Beispiel für 51820 entschieden. Der Homelabserver ruft den VPS an, so sollte nach einer Zwangstrennung der Tunnel recht schnell wieder oben sein. Zwischen den Servern richte ich mir ein virtuelles Netzwerk 192.168.197.0/24 ein und gebe jedem Server eine IP aus diesem Netzbereich. Dies ist später für das NAT und Routing hilfreich.

nano /etc/wireguard/wg0.conf
Tunnelconfig auf jedem Server erstellen

Wireguard VPS Config

Hier wird <vps private key> und <homelab public key> mit dem Inhalt aus den oben genannten Dateien ersetzt.

[Interface]
PrivateKey = <vps private key>
ListenPort = 51820
Address = 192.168.197.1

[Peer]
PublicKey = <homelab public key>
AllowedIPs = 192.168.197.2/32
/etc/wireguard/wg0.conf

Wireguard Homelab Server Config

Hier wird <homelab private key> und <vps public key> mit dem Inhalt aus den oben genannten Dateien ersetzt. Die feste öffentliche IP des VPS wird anstatt <public ip eingetragen, der Port :51820> muss mit dem Wert von ListenPort = aus der Tunnelconfig des VPS identisch sein. AllowedIPs = 0.0.0.0/0 verdreht die Defaultroute auf dem Homelabserver sobald der Tunnel up ist. Seht zu das ihr euch für die Einrichtung im gleichen Netz befindet, oder setzt euch statische Routen auf euer Gateway in /etc/network/interfaces.

[Interface]
PrivateKey = <homelab private key>
ListenPort = 51820
Address = 192.168.197.2

[Peer]
PublicKey = <vps public key>
AllowedIPs = 0.0.0.0/0
Endpoint = <public ip:51820>
PersistentKeepalive = 25
/etc/wireguard/wg0.conf

Sollte auf dem VPS bereits eine Firewall aktiv sein, so bitte zuerst den Port freigeben. Eine Firewall im Homelab muss ausgehende Verbindungen auf diesen Port ebenfalls zulassen.

sudo ufw allow 51820/udp
Port in Firewall auf VPS erlauben

Der Tunnel ist jetzt eingerichtet und kann auf beiden Systemen (erst auf dem VPS, dann im Homelab) gestartet werden.

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
Aktivieren und starten des Tunnels

Der Tunnel sollte jetzt verbunden sein. Auf beiden Servern kann das Interface wg0 überprüft werden, der Status sollte nun "up" sein.

sudo ip a show wg0
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 192.168.197.2/32 scope global wg0
       valid_lft forever preferred_lft forever

Und Ping auf die Wireguard interne IP des VPS sollte antworten

# ping 192.168.197.1
PING 192.168.197.1 (192.168.197.1) 56(84) bytes of data.
64 bytes from 192.168.197.1: icmp_seq=1 ttl=64 time=10.6 ms
64 bytes from 192.168.197.1: icmp_seq=2 ttl=64 time=10.1 ms

Nach einem Reboot sollte der Tunnel auch direkt automatisch wieder verfügbar sein.

IP Forwarding (VPS)

Damit der Linuxkernel auf dem VPS routet, muss IP Forwarding angeschaltet werden.

sudo nano /etc/sysctl.conf
sysctl.conf editieren
net.ipv4.ip_forward=1
ipv4 forwarding (routing) einschalten
sudo sysctl -p
sysctl Einstellungen neu laden/aktivieren

IPtables (VPS)

Ja, ich weiß das geht wohl auch inzwischen mit ufw....

Wir stellen die DefaultPolicy der Forward Chain auf DROP. Dann nehmen neue Verbindungen die auf dem Netzwerkinterface (ens3) ankommen, TCP sind und auf Zielport 25(smtp),80(http) oder 443(https) wollen und werfen die auf das Tunnelinterface (wg0). Bei damit zusammenhängenden oder bereits hergestellten Verbindungen machen wir das ebenfalls. Verbindungen aus der Gegenrichtung werden genommen und auf das Netzwerkinterface (ens3) weitergeleitet. Am Ende maskiere ich mir noch die Verbindungen die vom Homeserver aus abgehen auf das Netzwerkinterface (ens3), also das was euer DSL Router zuhause mit euren Geräten im Netz auch macht. Damit bekommen die ausgehenden Verbindungen vom Homelabserver durch den Tunnel ins Internet die öffentliche IP des VPS verpasst.

sudo iptables -P FORWARD DROP
sudo iptables -A FORWARD -i ens3 -o wg0 -p tcp --syn --dport 25 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 -p tcp --syn --dport 443 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 -p tcp --syn --dport 587 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 -p tcp --syn --dport 993 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens3 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o ens3 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
IPTables Forwarding auf VPS

NAT (VPS)

Die folgenden NAT Regeln sorgen dafür, dass der Homelabserver unter den angegebenen Ports erreichbar ist.

Wer es im Detail wissen will, findet hier eine sehr gute Erklärung.

sudo iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 25 -j DNAT --to-destination 192.168.197.2
sudo iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 80 -j DNAT --to-destination 192.168.197.2
sudo iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 443 -j DNAT --to-destination 192.168.197.2
sudo iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 587 -j DNAT --to-destination 192.168.197.2
sudo iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 993 -j DNAT --to-destination 192.168.197.2
IPTables NAT auf VPS

Test auf dem Homelabserver

Wenn ihr alles richtig gemacht habt, dann ist euer Homelabserver jetzt unter der öffentlichen IP eures VPS erreichbar und kommuniziert auch mit dieser IP nach aussen.

# curl ifconfig.me
2.56.96.xxx

Speichern des Regelwerks (VPS)

Damit auch diese Einstellungen einen Reboot überleben, nutze ich netfilter-persistent.

sudo apt install netfilter-persistent
sudo netfilter-persistent save
sudo systemctl enable netfilter-persistent

Und nächstes Mal schreibe ich etwas mehr über den Homeserver, Docker, Traefik und wie lange es gedauert hat bis mein Netz durch diesen Weg, an der Firewall vorbei, infiltriert wurde. ;-)