OpenVPN mit iPhone, iPad und MacBook Air — aber nicht mit Travel Router TP-LINK TL-MR3020

Auf Grund der bald bevorstehenden Reise in die USA habe ich mir heute Zeit genommen, einen VPN-Server einzurichten, mit welchem ich mich unterwegs in den USA mit iPhone, iPad und MacBook Air verbinden kann.

Obwohl heutzutage die meisten Web-Sites mit HTTPS kommunizieren, stelle ich damit sicher, dass allfällige unverschlüsselte Kommunikation im Hotel-WiFi nicht abgehört werden kann. Als netten Nebeneffekt gaukle ich meinen Geräten weiter vor, dass sie sich in der Schweiz befinden und umgehe so allfällige Geoblocks. Da wir seit einem Jahr eine Glasfaster-Internet-Anbindung mit 1 GBit/s symmetrischem Datenverkehr verfügen, sollte die Performance höchstens noch von der hohen Latenz getrübt werden.

Ich hatte bisher bereits eine Lösung im Einsatz (im Grunde zwei, PPTP sowie OpenVPN mit einem Shared Key), doch nun war es an der Zeit, das Gefrickel aufzuräumen und eine zukunftstaugliche, performante und sichere Lösung zu bauen, welche (fast) nativ mit macOS und iOS funktioniert — konkret mit Tunnelblick unter macOS sowie mit OpenVPN.app unter iOS.

Die beiden Applikationen kann man mittels .ovpn-Textdateien als VPN-Clients konfigurieren.

Ich bin im Grossen und Ganzen der Anleitung „How To Set Up an OpenVPN Server on Ubuntu 16.04“ von DigitalOcean gefolgt, habe die Konfiguration dabei aber meiner Heimnetzwerk-Architektur angepasst und mittels Bash-Scripts automatisiert. Denn irgendeinmal muss ich den OpenVPN-Server aktualisieren und bin mit dem DevOps-Ansatz sicher, mittels Knopfdruck wieder eine funktionierende Lösung bereit zu haben.

Die Anleitung zeigt einen netten Weg auf, wie man sich die .ovpn-Dateien vollautomatisierte mittels eines bash-Scripts erstellt.

Ich verwende nun für alle meine Geräte ein eigenständiges Zertifikat, damit ich diese im Notfall einzeln revozieren kann.

Die Konfiguration funktioniert tadellos — einzig bei Tunnelblick (d.h. unter macOS) musste ich die Passagen

...
user nobody
group nogroup
...

wieder auskommentieren, da es sonst zu komischen Fehlermeldungen im OpenVPN-Log des Clients kam. Ausserdem muss man im GUI anklicken, dass der gesamte IPv4-Verkehr durch das VPN geroutet wird:

Wehrmutstropfen: Eigentlich war der Aufbau eines VPN-Tunnels pro Device nur als Plan B gedacht. Denn bei Reisen verwende ich einen TP-LINK TL-MR3020 „Reiserouter“ (klitzekleiner Wireless Access Point, der sich mit USB-Stromversorgung betreiben lässt), um diesen mit Hotel-WiFis zu verbinden und die SSID mit den Zugangsdaten meines Heimnetzwerkes anzubieten. So spare ich es mir, dass das Hotel-WiFi auf all meinen Geräten konfiguriert werden muss.

Auf dem Router habe ich mir das quelloffene OpenWrt (Version Attitude Adjustment) installiert und mittlerweile so konfiguriert, damit es mit allen möglichen WLAN-Netzwerken von Unterkünften funktioniert (einige Hersteller von Gästeportalen frickeln massiv mit dem Netzwerk herum, um Clients auf die Landing Pages zu bringen).

Plan A war es nun eigentlich, OpenVPN auf dem Router selbst zu installieren und jedes Mal automatisch eine Verbindung mit meinem OpenVPN-Server in der Schweiz herzustellen, sobald der Router eine Internet-Verbindung herstellen kann. So hätte ich nicht pro Endgerät einzeln eine VPN-Verbindung aufbauen müssen und die Verschlüsselung wäre ohne weitere Interaktion standardmässig aktiviert gewesen.

Eine Anleitung zur Installation von OpenVPN als VPN-Client auf einem TP-LINK TL-MR3020 findet sich dazu im Netz (plus eine generische Anleitung für OpenWRT), doch leider habe ich erst während der Installation bemerkt, dass der Router nicht genügend Speicherplatz mit sich bringt, um die Pakete openvpn, openssl und andere Libraries zu installieren:

Da opkg nicht komplett durchgelaufen ist, musste ich die über das Router-Filesystem verstreute Überreste der Pakete eigenhändig entfernen (indem ich die .ipks vom offiziellen Repository händisch herunterlud, mit gzip entpackte und die resultierenden Dateien dann erneut mit tar und gzip entpackte):

.
./kmod-tun_3.3.8-1_ar71xx
./kmod-tun_3.3.8-1_ar71xx/etc
./kmod-tun_3.3.8-1_ar71xx/etc/modules.d
./kmod-tun_3.3.8-1_ar71xx/etc/modules.d/30-tun
./kmod-tun_3.3.8-1_ar71xx/lib
./kmod-tun_3.3.8-1_ar71xx/lib/modules
./kmod-tun_3.3.8-1_ar71xx/lib/modules/3.3.8
./kmod-tun_3.3.8-1_ar71xx/lib/modules/3.3.8/tun.ko
./kmod-tun_3.3.8-1_ar71xx/postinst
./liblzo_2.06-1_ar71xx
./liblzo_2.06-1_ar71xx/usr
./liblzo_2.06-1_ar71xx/usr/lib
./liblzo_2.06-1_ar71xx/usr/lib/liblzo2.so
./liblzo_2.06-1_ar71xx/usr/lib/liblzo2.so.2
./liblzo_2.06-1_ar71xx/usr/lib/liblzo2.so.2.0.0
./libopenssl_1.0.1h-1_ar71xx
./libopenssl_1.0.1h-1_ar71xx/usr
./libopenssl_1.0.1h-1_ar71xx/usr/lib
./libopenssl_1.0.1h-1_ar71xx/usr/lib/libcrypto.so.1.0.0
./libopenssl_1.0.1h-1_ar71xx/usr/lib/libssl.so.1.0.0
./openvpn_2.2.2-2_ar71xx
./openvpn_2.2.2-2_ar71xx/conffiles
./openvpn_2.2.2-2_ar71xx/etc
./openvpn_2.2.2-2_ar71xx/etc/config
./openvpn_2.2.2-2_ar71xx/etc/config/openvpn
./openvpn_2.2.2-2_ar71xx/etc/init.d
./openvpn_2.2.2-2_ar71xx/etc/init.d/openvpn
./openvpn_2.2.2-2_ar71xx/etc/openvpn
./openvpn_2.2.2-2_ar71xx/lib
./openvpn_2.2.2-2_ar71xx/lib/upgrade
./openvpn_2.2.2-2_ar71xx/lib/upgrade/keep.d
./openvpn_2.2.2-2_ar71xx/lib/upgrade/keep.d/openvpn
./openvpn_2.2.2-2_ar71xx/usr
./openvpn_2.2.2-2_ar71xx/usr/sbin
./openvpn_2.2.2-2_ar71xx/usr/sbin/openvpn
./zlib_1.2.7-1_ar71xx
./zlib_1.2.7-1_ar71xx/usr
./zlib_1.2.7-1_ar71xx/usr/lib
./zlib_1.2.7-1_ar71xx/usr/lib/libz.so
./zlib_1.2.7-1_ar71xx/usr/lib/libz.so.1
./zlib_1.2.7-1_ar71xx/usr/lib/libz.so.1.2.7

So konnte ich die Überreste schlussendlich entfernen (der Router bootete nach der Bereinigungsaktion tatsächlich noch) und der Router hat nun wieder 800 KB Speicher frei … wie zu DOS-Zeiten!