Transparentes NordVPN Gateway auf Fedora 30 Minimal installieren

Dieser Artikel hat 2021 einen aktualisierten Nachfolger bekommen!

Diese Zusammenfassung baut auf der Arbeit anderer netter Leute auf, die ihre Leitfäden veröffentlichten: Quelle, Quelle 2, Quelle 3, Quelle 4, Quelle 5, Quelle 6 und Quelle 7.

Feste IP vergeben

Da wir die IP von unserem Router als Standardgateway an die Geräte im LAN verteilen möchten, sollten wir diese an das gewünschten Interface binden. Nicht vergessen, dass diese IP außerhalb Bereichs des verantwortlichen DHCP Servers liegen sollte. Mit ip addr show werden alle Interfaces und derzeitigen IPs angezeigt.

nmcli ist das Kommandozeileninterface des praktischen NetworkManagers:

# nmcli dev status
DEVICE  TYPE      STATE            CONNECTION 
eth0    ethernet  verbunden        eth0       
wlan0   wifi      nicht verbunden  --         
lo      loopback  nicht verwaltet  --    

Wir nutzen hier das Interface eth0. Dessen Konfiguration liegt in der Datei /etc/sysconfig/network-scripts/ifcfg-eth0. Hier steht bei Bezug einer Adresse via DHCP folgendes z.B. drin:

TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="dhcp"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="eth0"
UUID="3596b2fb-5acc-3da8-8666-a2dc63bcd6ba"
ONBOOT="yes"
AUTOCONNECT_PRIORITY="-999"
DEVICE="eth0"

Nun fügen wir eine neue Verbindung hinzu, die unseren vorhandenen Router als Standardgateway (192.168.178.1) und zwei DNS-Servern von OpenNIC nutzt. Die VPN-Gateway-IP setzen wir auf 192.168.178.2 fest:

# nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method static ipv4.addresses 192.168.178.2/24 ipv4.gateway 192.168.178.1 ipv4.dns "172.104.136.243 51.15.98.97"
Verbindung »eth0-static« (79a6d197-5c11-4010-92a2-58a36d42c99a) erfolgreich hinzugefügt.

Die Verbindung ist nun erstellt, aber noch nicht aktiv. Die frisch erzeugte Konfigurationsdatei enthält nun folgendes:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=192.168.178.2
PREFIX=24
GATEWAY=192.168.178.1
DNS1=172.104.136.243
DNS2=51.15.98.97
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=eth0-static
UUID=79a6d197-5c11-4010-92a2-58a36d42c99a
DEVICE=eth0
ONBOOT=yes

Mit dem Namen „eth0“ (wurde auch oben Verbindungsstatus angezeigt) oder der UUID können wir die alte Verbindung löschen. Achtung: Wenn man dieses remote macht, kann es natürlich sein, dass man seine SSH-Verbindung tötet.

# nmcli con del eth0
Verbindung »eth0« (3596b2fb-5acc-3da8-8666-a2dc63bcd6ba) erfolgreich gelöscht.

Danach mit reboot neu starten und der NetworkManager wird die nun einzig verbleibende Verbindung mit der statischen IP automatisch nutzen.
Um vorhandene Verbindungen zu verändern könnte man (zukünftig) nmcli con mod nutzen (nur als Information).

OpenVPN installieren

Nachdem ein VPN-Anbieter auserkoren ist, durch den man seinen Internetverkehr routen möchte, muss man sich OpenVPN und unzip installieren: dnf install openvpn unzip

NordVPN Server und Zertifikate

Die Zugangsdaten für NordVPN legen wir in einer Textdatei unter /etc/openvpn/nordvpn ab. Erste Zeile der Benutzername, zweite Zeile das Passwort. Sie soll nur für uns als Besitzer lesbar sein.

# cd /etc/openvpn
# mkdir nordvpn
# cd nordvpn
# echo -e "Benutzername\nPasswort" > auth.txt
# chmod 600 auth.txt

NordVPN bietet eine Zip-Datei an, in der alle OpenVPN-Konfigurationen in passendem Dateiformat enthalten sind. Auch die nötigen Zertifikate sind hier bereits enthalten. Man muss in der Zeile auth-user-pass dahinter die Datei mit den Zugangsdaten angeben und das Ergebnis danach umbenennen, da OpenVPN lediglich Dateien mit .conf-Suffix automatisch startet.

# cd /etc/openvpn/nordvpn
# curl -L -o nordvpn.zip https://nordvpn.com/api/files/zip
# unzip nordvpn.zip
# for FILE in *nordvpn*.ovpn; do
     while read LINE; do
         echo ${LINE/auth-user-pass/auth-user-pass /etc/openvpn/nordvpn/auth.txt}
     done < "$FILE" > "$(basename -s .ovpn ${FILE}).conf"
 done
# rm nordvpn.zip

Zu der Frage, ob man nun eine UDP oder TCP-Verbindung nutzen soll, gibt es einige Abhandlungen. Wenn man (zu Hause) nicht zwingend auf Port 443 an einer Firewall unauffällig „vorbei“ muss, dann kann man getrost das schnellere UDP nehmen. Eventueller Datenverlust wird innerhalb der getunnelten TCP-Verbindungen sowieso ausgeglichen.
Man kann der Verbindungsaufbau direkt testen (mit CTRL+C beenden):

# openvpn --config Konfigurationsdatei.conf
[...] Initialization Sequence Completed

Damit systemd selbst OpenVPN mit gewünschter Konfiguration starten kann, müssen sie im entsprechenden Verzeichnis liegen. Wir legen uns einfach einen symbolischen Link an, der auf die eigentliche Konfiguration verweist. So kann man diese aktivierte Konfiguration durch überschreiben des Links auch schnell austauschen. Danach wird der Start direkt getestet:

# ln -s /etc/openvpn/client/nordvpn/Konfigurationsdatei.conf /etc/openvpn/client/nordvpn.conf
# curl http://ipinfo.io/ip
<öffentliche IP>
# systemctl start openvpn-client@nordvpn.service
# curl http://ipinfo.io/ip
<IP des VPN-Servers>
# systemctl status openvpn-client@nordvpn.service
● openvpn-client@nordvpn.service - OpenVPN tunnel for nordvpn
    Loaded: loaded (/usr/lib/systemd/system/openvpn-client@.service; disabled; vendor preset: disabled)
    Active: active (running) since <Datum>; 1min 13s ago
      Docs: man:openvpn(8)
            https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
            https://community.openvpn.net/openvpn/wiki/HOWTO
  Main PID: 11009 (openvpn)
    Status: "Initialization Sequence Completed"
     Tasks: 1 (limit: 1044)
    Memory: 1.6M
    CGroup: /system.slice/system-openvpn\x2dclient.slice/openvpn-client@nordvpn.service
            └─11009 /usr/sbin/openvpn --suppress-timestamps --nobind --config nordvpn.conf
# systemctl stop openvpn-client@nordvpn.service

Wenn dies alles erfolgreich ist, aktiviert man den OpenVPN-Dienst für den Bootvorgang und nach einem Neustart sollte der VPN-Tunnel von selbst stehen.

# systemctl enable openvpn-client@nordvpn.service
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-client@nordvpn.service → /usr/lib/systemd/system/openvpn-client@.service.

Routing aktivieren

Wenn man das Kernel IP-forwarding aktiviert, dann kann der Raspberry als Router zwischen Netzen und Interfaces fungieren. Um dies dauerhaft zu tun, muss ein Eintrag in /etc/sysctl.conf hinzugefügt werden. Direkt danach wird die Datei eingelesen.

# echo -e "\n# IP forwarding\nnet.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
# cat /proc/sys/net/ipv4/ip_forward
1

Die letzte Zeile ist lediglich die Prüfung, ob die Einstellung nun aktiv ist und Daten durch das System, durch den VPN-Tunnel in das Internet routet werden können.

iptables (NAT und Routing)

Vorhandene Regeln in der Standardeinstellung der iptables verhindern, die darauf folgenden Einstellungen funktionieren.

# iptables -vL

Diese kommen wahrscheinlich daher, dass in Fedorafirewalld statt iptables standardmäßig genutzt wird. Aus diesem Grund installieren wir iptables, deaktivieren firewalld, und aktivieren iptables:

# dnf -y install iptables-services
# systemctl mask firewalld.service
Created symlink /etc/systemd/system/firewalld.service → /dev/null.
# systemctl enable iptables.service
Created symlink /etc/systemd/system/basic.target.wants/iptables.service → /usr/lib/systemd/system/iptables.service.
# systemctl enable ip6tables.service
 Created symlink /etc/systemd/system/basic.target.wants/ip6tables.service → /usr/lib/systemd/system/ip6tables.service.
# systemctl stop firewalld.service
# systemctl start iptables.service
# systemctl start ip6tables.service

Dazu löschen wir erst mal die vorhandenen Regeln. Diese, oder deren Löschung, werden sofort nach der Eingabe/Löschung aktiv, aber nicht gespeichert. Wenn also am Ende nichts mehr geht: Einfach neu starten.

# iptables -P INPUT ACCEPT
# iptables -P FORWARD ACCEPT
# iptables -P OUTPUT ACCEPT
# iptables -t nat -F
# iptables -t mangle -F
# iptables -F
# iptables -X

Um die Clients im lokalen Netz auseinander halten können, müssen wir mit NAT für das Interface tun0 aktivieren. Dieses wird von OpenVPN als virtuelles Interface angelegt, sobald der Tunnel aufgebaut ist.

# iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

Nun muss der Verkehr von eth0 nach tun0 möglich werden. Anders herum ebenfalls, jedoch nur, wenn bereits eine ausgehende Verbindung vorhanden war. Dadurch kann von außen niemand auf das LAN zugreifen.

# iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
# iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT

Noch einige weitere einstellungen: Datenverkehr innerhalb des Hosts erlauben (loopback), Pings (ICMP) und SSH-Verbindungen (TCP Port 22) aus dem lokalen Netz erlauben. Die letzte Zeile erlaubt allen Datenverkehr in Gegenrichtung, die vom Raspberry initiiert wurde.

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -i eth0 -p icmp -j ACCEPT
# iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Eingehender Verkehr oder weiterleitungen, der diesen Regeln nicht entspricht, wird fallen gelassen:

# iptables -P FORWARD DROP
# iptables -P INPUT DROP

Damit sollten die Regeln schlussendlich so aussehen:

# iptables -vL
Chain INPUT (policy DROP 0 packets, 0 bytes)
  pkts bytes target     prot opt in     out     source               destination
     0     0 ACCEPT     all  --  lo     any     anywhere             anywhere            
     0     0 ACCEPT     icmp --  eth0   any     anywhere             anywhere            
   147  9420 ACCEPT     tcp  --  eth0   any     anywhere             anywhere             tcp dpt:ssh
  5521 7642K ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED

Chain FORWARD (policy DROP 0 packets, 0 bytes)
  pkts bytes target     prot opt in     out     source               destination
     0     0 ACCEPT     all  --  eth0   tun0    anywhere             anywhere            
     0     0 ACCEPT     all  --  tun0   eth0    anywhere             anywhere             state RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT 7 packets, 725 bytes)
  pkts bytes target     prot opt in     out     source               destination

Um die Einstellungen ein eine Datei zu schreiben und wieder her zu stellen kann man folgendes verwenden:

# iptables-save > Dateiname
# iptables-restore < Dateiname

Eine eigene Datei mit den Regel herumliegen zu haben schadet sicherlich nicht. Damit die aktiven Regeln beim Herunterfahren (nicht beim Stromausfall!) automatisch gespeichert und beim nächsten Start geladen werden, kann man in der Konfigurationsdatei /etc/sysconfig/iptables-config folgendes einstellen (dies ist unabhängig vom manuellen Dump):

IPTABLES_SAVE_ON_STOP="yes"
IPTABLES_SAVE_ON_RESTART="yes"

Damit die Konfiguration neu eingelesen wird

# systemctl restart iptables.service
# iptables-restore < Dateiname
# systemctl restart iptables.service

Nun sollte die Datei /etc/sysconfig/iptables die Regel enthalten sie von dort auch beim Neustart automatisch geladen werden.

Performance und Stromaufnahme

Auf einen Raspberry PI 3B+ zeigt top auf einem Kern 51 % Auslastung bei 47 MBit/s Download an. Da ein Tunnel sicherlich nicht auf die vier Kerne der CPU verteilt wird, ist damit rechnerisch bei 92 MBit/s schluss. Allerdings langweilen sich die 3 weiteren Kerne zu Tode, sodass man da sicherlich noch hübsche Sachen parallel laufen lassen könnte. Das Gateway läuft ja sowieso durch.

Mit einem nicht kalibriertem USB-Billigstmessgerät nimmt der Kleinrechner 0.44 A bei 4.94 V Bei 47 MBit/s 0.56 A. Die meiste Zeit ist sicher Langweilen angesagt. Insofern kann man bei einem Netzteilwirkungsgrad von vllt. 80 % sicherlich von einen Jahresverbrauch von um die 25 kWh ausgehen.

Einstellungen auf den Endgeräten

Am einfachsten ist, man stellt in den bekannten Rechnern händisch die IP, das neue Gateway und die DNS-Server ein. Durch ein Umstellen auf den Router als Standardgateway kann man immer noch am Tunnel vorbei, falls nötig. Doch ist bei jedem Client auch Handarbeit nötig und neue Clients sind per se über das non-VPN Gateway unterwegs, welches der DHCP-Server verteilt.
Oder, man richtet auf dem Raspberry noch einen DHCP-Server ein, der IPs an die Geräte im LAN verteilt und dabei die neue Gateway-IP als Standardgateway und die neuen DNS-Server ausliefert. So sind alle automatisch über den Tunnel unterwegs, mit allen Vorteilen und Nachteilen. So kann es natürlich sein, dass die Netzgeschwindigkeit bei starker Auslastung des Ausgangsservers für alle (etwas) leidet.

DHCP-Server

Um an das VPN-Gateway automatisiert an Geräte im lokalen Netz zu verteilen, brauchen wir einen DHCP-Server. D.h. jedoch auch, dass der bereits vorhandene Server auf dem Router deaktiviert werden muss (oder eben dort das neue Gateway und die DNS-Server eintragen, falls möglich).
Die Installation wird mit folgenden Kommando angestoßen:

# dnf install -y dhcp

Die Konfiguration findet man unter /etc/dhcp/dhcpd.conf. Diese passen wir folgendermaßen an:

# DHCP Server Configuration file.
# see /usr/share/doc/dhcp-server/dhcpd.conf.example
# see dhcpd.conf(5) man page

# Options common to all networks
option domain-name "ich-war-hier.de";
option domain-name-servers 172.104.136.243, 51.15.98.97;

# Default lease time is 7 days
default-lease-time 604800;
# Maximum lease time is 31 days
max-lease-time 2678400;

# This server is active!
authoritative;

subnet 192.168.178.0 netmask 255.255.255.0
{
    range 192.168.178.64 192.168.178.192;
    option routers 192.168.178.2;
    option broadcast-address 192.168.178.255;
}

So verteilen wir das VPN-Gateway als Standard. Auch die neuen DNS-Server bekommen die Clients mitgeteilt.
In vielen HowTos findet man die Konfiguration des firewalld als firewall-cmd --add-service=dhcp --permanent. Da wir diesen Dienst deaktiviert und durch das klassische iptables ersetzt haben, müssen wir Port 67 und 68 (UDP) dafür noch freigeben:

# iptables -A INPUT -i eth0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT

Von dieser Konfiguration machen wir uns auch einen Dump, starten den DHCP-Server und aktivierten ihn dauerhaft danach:

# iptables-save > Dateiname_dhcp
# systemctl start dhcpd
# systemctl enable dhcpd
Created symlink /etc/systemd/system/multi-user.target.wants/dhcpd.service → /usr/lib/systemd/system/dhcpd.service.

Backup der SD-Karte

Wenn man alles fertig eingestellt hat ist das Anlegen einer Sicherheitskopie der Installation sicherlich eine gute Idee. Wenn man weiß, welches Device das die SD-karte nach dem Einstecken mit einem Kartenleser ist stellt man sicher, dass man keine der Partitionen gemountet hat (df -h) und dump alles:

# sudo umount /dev/sdb1
# sudo umount /dev/sdb2
# sudo umount /dev/sdb3
# sudo dd if=/dev/sdb of=~/image.img

Wiederherstellen eines Abbildes:

# sudo dd bs=4M if=~/image.img of=/dev/sdb
# sync
# eject /dev/sdb

Dieser Beitrag wurde unter Computer abgelegt und mit , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert