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