VPN-Bridge

Was das ist und warum

TL;DR: Mit der VPN Bridge verbinde ich Geräte aus dem Heimnetz mit dem Internet.

Internet <> nginx <> OpenVPN Sever <> ISP-Netzwerk <> Heimrouter <> OpenVPN-CLient <> Heimnetzwerkgeräte
                                   <----------- VPN Tunnel ------->

Aber warum der Aufwand?

Einige ISP verwenden sogenanntes "DualStack mit CGNATv4" aka "DS-Lite", wie z.B. die Deutsche Glasfaser GmbH. Damit hat man keine öffentlich erreichbare IP Adresse mehr und dyndns-Dienste greifen hier nicht.

Durch den VPN-Tunnel manage ich quasi meine eigene Portfreigabe - vorbei am Router - und kann damit Kundenprojekte, die auf meinen lokalen Servern laufen, öffentlich zugänglich machen.

Als VPN-Client (das Gerät, was von Zusause mit dem VPN-Server kommuniziert) setze ich aktuell einen NEO3 ein (siehe dazu Hausautomation / FriendlyElec Nanopi NEO3 ) mit Ubuntu-Image, es kann aber auch ein Raspberry Pi oder ein anderes Debian-fähiges System gewählt werden.

Quellen:

1. VPN-Client Zertifikat erstellen

Auf dem gemieteten Server ("Public Server") folgendes eingeben als root:

cd /etc/openvpn/easy-rsa
./build-key nanopi-neo3-001

Die Abfrage nach einem challenge passwort kann mit ENTER übersprungen werden.

Die Schlüssel und Zertifikate auf den NEO3 übertragen.

Dann wie gehabt auf dem Client (NEO3):

  • OpenVPN Config erstellen
  • OpenVPN Autostart einrichten
  • Verbindung prüfen

Als Client VPN-IP nehmen wir beispielhaft die 10.8.1.30.

2. Reverse-Proxy Server <-> NEO3

Public Server <-> Open VPN-Client:8080

Sobald der Client mit dem Server per VPN verbunden ist, wollen wir einen Server-Port mit dem Client-Port verbinden.

Auf dem Public Server können wir nun folgende nginx-Konfiguration setzen:

server {
    charset utf-8;
    server_name piaware.karrie.software;
    proxy_connect_timeout  60;
    proxy_send_timeout    60;
    proxy_read_timeout    60;
    send_timeout      60;
    listen 80;
    location / {
         proxy_pass http://10.8.1.30:8080; # IP UND PORT VOM VPN-CLIENT
   }
}

Auf dem Client läuft unter 0.0.0.0:8000 ein Webserver. Dieser ist nun public über piaware.karrie.software erreichbar.

3. Port-Forwarding NEO3 <-> Lokale Server

Public Server <-> OpenVPN Client @:3001 <-> Lokales Gerät @:8080

Auf dem OpenVPN Client NEO3 (als root):

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -p tcp --dport 3001 -j DNAT --to-destination 192.168.178.55:8080
iptables -t nat -A POSTROUTING -j MASQUERADE

Dies routet: NEO3:3001 <-> 192.168.178.55:8080.

Der Command im Detail:

  • -t / --table nat Die Table
  • -A / --append Fügt die Zeile hinzu
  • PREROUTING sobald Pakete eintreffen
  • -p / --protocol TCP/UDP Protokolltyp
  • -d Ziel-IP (optional, per Default wird 0.0.0.0 genutzt)
  • --dport / --destination-port Ziel-Port oder Portrange auf dem Host
  • -j DNAT Sprung (jump) zum DNAT-Regelwerk
  • --to-destination Routing zur Zieladresse:Port

Public Server nginx-Konfiguration für den Eintrag:

server {
    charset utf-8;
    server_name piaware.karrie.software;
    proxy_connect_timeout  60;
    proxy_send_timeout    60;
    proxy_read_timeout    60;
    send_timeout      60;
    listen 80;
    location / {
         proxy_pass http://10.8.1.30:3001; # FORWARDED IP UND PORT VOM VPN-CLIENT
   }
}
4. IPTables und sysconfig persistent machen
IPv4 forward
sudo nano /etc/sysctl.conf

Uncomment line:

net.ipv4.ip_forward=1
IPTables
sudo apt-get install iptables-persistent

Daten prüfen:

sudo cat /etc/iptables/rules.v4

Änderungen speichern mit:

sudo netfilter-persistent save
IPTable-Einträge anzeigen und löschen

NAT-Rules listen

sudo iptables -t nat -L -n -v

Zum Löschen brauchen wir die NAT-Rules mit Zeilennummern:

root@openvpn-server # sudo iptables -t nat -v -L PREROUTING -n --line-number
Chain PREROUTING (policy ACCEPT 3842 packets, 336K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       24  1440 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3124 to:10.8.1.30:8000
2     2555  153K DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3125 to:10.8.1.30:3001
3     1149 68944 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3126 to:10.8.1.30:3002
4        0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3127 to:10.8.1.30:3003

Um die gewünschte Zeile zu löschen folgenden Befehl ausführen ("2" hier mit der Zeilennummer ersetzen):

sudo iptables -t nat --delete PREROUTING 2
Zusammenfassung

Das eigentliche "Routing" - also die Freigabe und die Verwaltung der Ports - findet auf dem NEO3 (dem OpenVPN Client) statt.

pi@nanopi-neo3-001:~$ sudo iptables -t nat -v -L PREROUTING -n --line-number
Chain PREROUTING (policy ACCEPT 4149 packets, 764K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1     4939  296K DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3001 to:192.168.178.55:8080
2     1372 82324 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3002 to:192.168.178.33:9981
3        0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3003 to:192.168.178.33:9982

Ist dies erfolgt, kann auf dem OpenVPN Server eine nginx-Konfiguration erstellt werden. Als proxy_pass wird der VPN-IP-Client Destination Port genutzt (dpt, hier 3001-3003).

Alternativen

OpenWRT mit LUCI / Wireguard

  • OpenWRT/FriendlyWRT mit LUCI-Weboberfläche und IPTables
  • Wireguard anstelle von OpenVPN!