Aus Linux-Magazin 05/2020

Flynet über DNS-Tunnel nutzen

© Victor Zastolskiy, 123RF

Damit die Reisezeit wie im Flug vergeht, gibt es in vielen Verkehrsflugzeugen mittlerweile WLAN. Steht dem Vergnügen aber eine Paywall entgegen, heißt das alternative Entertainment-Programm eben, diese zu umgehen.

Während manche Airlines ihren Gästen ein Gratis-WLAN anbieten (wie die australische Qantas), verlangen andere von ihren Gästen, den Service zu bezahlen (wie die Lufthansa). Zwar ist WLAN im Flieger durchaus auch lästig, weil so noch die letzten erzwungenen Offline-Minuten im Leben verloren gehen. Andererseits hilft Online-Zugang mitunter, etwa wenn wie auf meinem letzten Flug das Entertainment-System nicht verrät, wann der Flieger landet. Dann lässt sich über Flightradar [1] die eigene Position verfolgen. Allerdings mindern die exorbitanten Preise für das fliegende WLAN das Vergnügen und halten mich normalerweise von der Nutzung ab.

Neulich installierte ich jedoch vor einem Langstreckenflug noch schnell ein Update auf meinem Reise-Macbook. Funktionierte das früher noch problemlos, hat Apple seit “Catalina” die schlechte Angewohnheit, die »/etc/ssh/ssh_config« zu überschreiben – extrem ärgerlich, wenn da Dutzende Tunnel und Hosts drin stehen. Noch ärgerlicher, wenn das Backup daheim liegt.

Am Flughafen fehlte die Zeit, die Datei neu zu justieren. Also begann ich im Zubringer zum Langstreckenflug, die »/etc/ssh/ssh_config« nach und nach zu rekonstruieren. Dazu musste ich für einige Hostnamen die IP-Adressen herausfinden und hoffte dabei auf Hilfe vom DNS-Cache meines Systems.

Doch vor lauter Frust über das nervige Update hatte ich das WLAN nicht ausgeschaltet und zugleich einen Flieger mit Flynet erwischt – interessanterweise gingen die Namensauflösungen durch.

Die Chemie macht’s

Das weckte meine Neugier: Lässt sich die Paywall mit einem DNS-Tunnel untergraben? Einen Versuch wäre es wert, um den langweiligen Langstreckenflug etwas aufregender zu gestalten. Zum Glück muß ich die Leistung nicht widerrechtlich erschleichen, weil ich auf der Strecke ohnehin einen Voucher für die Paywall bekommen würde.

Ein probates Werkzeug zum Bau von DNS-Tunneln ist Iodine [2], so benannt wegen der zufälligen Klanggleichheit von IoD (IP over DNS) mit dem 53. Element im Periodensystem, dem Jod. Wie es der Zufall will, nutzt DNS ebenfalls Port 53. Iodine hat einige geschickte Performance-Optimierungen in petto und setzt für viele Tunneleinstellungen gute automatische Defaults. Zudem ist es Teil von Kali Linux, das als VM auf meinem Laptop läuft.

Installation

Während der Zwischenlandung war Iodine schnell auf dem Server installiert. Ich entschied mich für die Quellcode-Installation, die – nach dem Einspielen eines grundlegenden Build-Systems – wie in Listing 1 gezeigt funktioniert.

Listing 1

Iodine installieren

$ wget https://code.kryo.se/iodine/iodine-0.7.0.tar.gz
$ tar -xzf iodine-0.7.0.tar.gz
$ cd iodine-0.7.0
$ make

Das »make« stößt die lokale Installation im Home-Verzeichnis an, die Binaries für den Server und den Client liegen dann im Unterverzeichnis »bin/«. Optional erledigt ein »make install« noch die Installation in die Systemverzeichnisse; für die spontane Spielerei genügt jedoch die lokale Lösung. Läuft der Server unter einem Debian oder Raspbian, muss man ihn unter Umständen neu starten, damit das System das nötige Tunnel-Device anlegt.

Verteilt

Viel länger dauerte es, den DNS-Server korrekt zu konfigurieren. Auf meinem legte ich eine neue Subdomain für eine meiner Domains an, mit einem eigenen Nameserver. Der verwies auf die IP-Adresse (192.0.2.215) des Servers, auf dem ich gerade Iodine installiert hatte (Listing 2).

Listing 2

Neue Subdomain

fun.example.org IN NS funns.example.org
funns.example.org IN A 192.0.2.15

Noch schnell die SOA (Start of Authority [3]) der Domain heraufgesetzt, damit die Änderung auch bei Abfragen auffällt – anschließend war Geduld nötig, damit der Eintrag sich im DNS propagiert. Für meine Spiel- und Test-Domain stelle ich die TTL (Time to Live) stets niedrig ein, damit ich bei Bedarf schnell etwas ausprobieren kann.

Client

Auch auf dem Client muss Iodine laufen. Auf dem Mac erfordert das Einrichten des dafür nötigen TUN-Device allerdings viel Nachinstalliererei. Auf dem Flughafen fehlte dafür die Zeit. Zudem wollte ich das Ganze ja nicht ernsthaft nutzen, sondern nur prüfen, ob es überhaupt funktioniert. Also sparte ich mir die Umstände und griff auf meine Kali-VM zurück. Dort wartet der Client unter »/usr/sbin/«. Sonst helfen auch hier Tar und Make weiter.

Noch am Boden fand ein erster Probelauf statt, der dem späteren Angriff im Flieger entsprach. Der Befehl aus der ersten Zeile von Listing 3 startet auf dem Server den Iodine-Daemon, der für den Einsatz von Port 53 Root-Rechte benötigt. Der Tunnelendpunkt auf dem Server bekommt die IP 10.10.10.1. Abbildung 1 zeigt den groben Paketweg.

Listing 3

Angriffstest

# ./bin/iodined -c -P geheim 10.10.10.1 fun.example.org
$ nslookup -query=txt z123.fun.example.org
$ dig -t TXT z123.fun.example.org
# /usr/sbin/iodine -d tun0 -P geheim -f fun.example.org

<a href="#artRef-f1">Abbildung 1</a>: So reisen die Pakete &uuml;ber DNS.

Abbildung 1: So reisen die Pakete über DNS.

Wer das Licht am Ende des Tunnels sehen möchte, testet schnell, ob die Befehle aus den Zeilen 2 und 3 einen »TXT«-Record mit scheinbar zufälligem Text zurück liefern, wie es Abbildung 2 zeigt.

<a href="#artRef-f2">Abbildung 2</a>: Ein schneller Test zeigt: Der Iodine-Daemon l&auml;uft und ist per DNS zu erreichen.

Abbildung 2: Ein schneller Test zeigt: Der Iodine-Daemon läuft und ist per DNS zu erreichen.

Auf dem Client baut das Kommando aus der letzten Zeile von Listing 3 die Verbindung auf. Auch dieser Aufruf braucht Root-Rechte und dasselbe Passwort, das der Tunnelbauer dem Server mit auf den Weg gegeben hat. Der Client erhält gewöhnlich die Tunnel-Adresse 10.10.10.2, die bestehende Verbindung lässt sich etwa über »ping 10.10.10.1« testen. Allerdings fällt die Ausgabe von Iodine selbsterklärend aus (Abbildung 3).

<a href="#artRef-f3">Abbildung 3</a>: Iodine &uuml;berpr&uuml;ft die Verbindung und optimiert alle Parameter. Daran ist leicht zu erkennen, dass es funktioniert.

Abbildung 3: Iodine überprüft die Verbindung und optimiert alle Parameter. Daran ist leicht zu erkennen, dass es funktioniert.

Auf geht’s

Steht der Tunnel, gibt es viele Wege, ihn zu nutzen. SSH bietet einen eingebauten Socks-Proxy an. Diese Variante ist schnell, sicher und effektiv, solange die verwendete Software Socks-Proxies unterstützt. SSH kann ebenfalls ein VPN aufbauen. Dazu muss der Admin deutlich mehr an den Netzwerkeinstellungen fummeln.

Zu guter Letzt lässt sich auch ohne SSH sämtlicher Traffic über das neue »tun«-Interface lenken. Der große Nachteil: Bei ähnlichem Aufwand wie für das SSH-VPN-Szenario fehlt hier eine Verschlüsselung.

Socks-Proxy: ohne kalte Füße

Soll der Tunnel sicher und schnell sein, drängt sich SSH auf. Die schnellste und simpelste Lösung bietet der SSH-Socks-Proxy [4]:

$ ssh 10.10.10.1 -D 12345

Im Browser rasch unter den Netzwerkeinstellungen als Socks-Proxy »localhost« und Port »12345« eingetragen, und schon geht es verschlüsselt ins Netz (Abbildung 4). Auf demselben Weg lässt sich oft ein systemweiter Proxy in den Netzwerkeinstellungen beziehungsweise über Umgebungsvariablen einrichten.

<a href="#artRef-f4">Abbildung 4</a>: Der Socks-Proxy, in Firefox eingetragen.

Abbildung 4: Der Socks-Proxy, in Firefox eingetragen.

Nebenbei: Wer den Parameter »-C« aktiviert, der die Kompression für SSH einschaltet, um die schlechte Bandbreite zu verbessern, erzielt nicht den gewünschten Effekt. Iodine komprimiert die übertragenen Daten ohnehin per Gzip, eine doppelte Kompression wirkt sich eher negativ aus.

VPN over SSH

SSH bietet neben dem beliebten Socks-Proxy ab Werk die Option an, ein VPN aufzubauen. Anders als manche Anleitungen im Netz es beschreiben, braucht man dazu keine Zusatzsoftware wie BadVPN [5], die wieder auf den Socks-Proxy aufsetzen würde. Dennoch erfordert es etwas Übung, ein VPN über SSH im Netzwerk einzurichten.

Zunächst muss der SSH-Server über den Eintrag »PermitTunnel yes« in der Datei »/etc/ssh/sshd_config« davon erfahren, dass er Tunneling erlauben soll – standardmäßig ist das deaktiviert. Ein »kill -HUP« schickt das nötige »SIGHUP« an den SSH-Daemon, um die veränderte Konfiguration neu einzulesen.

Im nächsten Schritt gilt es, auf dem Client das Netz passend zu konfigurieren. Angenommen, er hängt in einem lokalen Netz 10.2.5.0/24 mit dem Gateway 10.2.5.1. Dann muss der Besitzer zunächst sicherstellen, dass er den SSH-Server 10.10.10.1 weiter erreicht (Listing 4, erste Zeile). Als nächstes wirft er die Default-Route raus (Zeile 2) und startet die SSH-Verbindung mit Tunnel (Zeile 3). Die Option »-w« aktiviert das Tunnel-Device-Forwarding.

Listing 4

Netz konfigurieren auf dem Client

# route add -net 10.10.10.0/24 gw 10.10.10.1 metric 100 dev tun0
# route del default
# ssh -w 1:1 10.10.10.1
[...]
# ifconfig tun1 10.10.11.11 netmask 255.255.255.0
# route add default gw 10.10.11.10 dev tun1

Auf dem SSH-Server sind nun einige Kommandos fällig, um diesen dazu zu bringen, die Pakete weiterzuleiten (Listing 5). Dadurch erhält das Tunnel-Interface im Server die IP 10.10.11.10, und das Weiterreichen von IP-Paketen ist aktiviert. Auf dem Client bekommt jetzt auch das Tunnel-Interface eine IP-Adresse, und die Routing-Tabelle erhält einen Eintrag für den Tunnel (Listing 4, Zeile 5 und 6).

Listing 5

Iptables lässt Pakete aus dem Tunnel weiterreisen

# ifconfig tun1 10.10.11.10 netmask 255.255.255.0
# echo "1" > /proc/sys/net/ipv4/ip_forward
# iptables -A FORWARD -i tun1 -o eth0 -j ACCEPT
# iptables -A FORWARD -i eth0 -o tun1 -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.10.11.0/24 -o eth0 -j MASQUERADE

Nun wandern schon Pakete zwischen den Geräten hin und her, wie zum Beispiel ein »ping 10.10.11.10« demonstriert. Oft steht auch noch ein Update der »/etc/resolv.conf« an, denn sie enthält womöglich einen nicht via Tunnel erreichbaren Nameserver. Ungeachtet datenschutzrechtlicher Bedenken bieten sich hier zumindest zum Testen die Nameserver von Google an (Listing 6).

Listing 6

/etc/resolv.conf

nameserver 8.8.8.8
nameserver 8.8.4.4

Unverschlüsselt unterwegs

Der dritte Weg bietet weniger Sicherheit, weil ihm die Verschlüsselung fehlt. Zugleich ist er fast so aufwendig einzurichten wie das VPN über SSH. Die Default-Route auf 10.10.10.1 umzusetzen, funktioniert analog zum oben beschriebenen Prozess (Listing 7).

Listing 7

Default-Route umsetzen

# route add -net 10.10.10.0/24 gw 10.10.10.1 metric 100 dev tun0
# route del default
# route add default gw 10.10.10.1

Dabei muss das Zielsystem Datenpakete von »tun0« auf »eth0« weiterleiten, was man unter Linux am einfachsten über Iptables realisiert. Das zeigt Listing 8, das bis auf IP-Adressen und Geräte Listing 5 gleicht.

Listing 8

Tunnel ohne SSH oder VPN

# echo "1" > /proc/sys/net/ipv4/ip_forward
# iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT
# iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE

Auch damit lässt sich trefflich in der Luft surfen. Allerdings wandern die Datenpakete im Klartext über das Netzwerk – eher ungünstig, sowohl in forensischer Hinsicht als unberechtigter Nichtzahler als auch im Hinblick auf die Privatsphäre. Freilich lassen sich auch die in einem früheren Artikel [4] beschriebenen Nebenwege verwenden.

Wie der DNS-Tunnel arbeitet

Dass der DNS-Tunnel langsam ist, liegt am Protokoll: Jedes Paket, das der lokale Client verschickt, muss in einem Rechnernamen kodiert sein, also etwa »xyz.fun.example.org«. Als Antwort kommt dann durch die langwierige DNS-Kette ein »TXT«-, »SRV«- oder »CNAME«-Record zurück, der die Antwortdaten enthält. Welcher Antworttyp am günstigsten ist, ermittelt Iodine beim Starten. Eine solche Anfrage zeigt Abbildung 5.

<a href="#artRef-f5">Abbildung 5</a>: Hier schickt Iodine eine Anfrage nach einem &raquo;TXT&laquo;-Record als Teil eines Tunnels.

Abbildung 5: Hier schickt Iodine eine Anfrage nach einem »TXT«-Record als Teil eines Tunnels.

Nun kann DNS nicht einfach Binärdaten übertragen, sondern ist auf eine Untermenge der ASCII-Zeichen beschränkt. Von E-Mail-Attachments kennt man das Encoding Base64 [6], das mehrere 8-Bit-Zeichen durch 6-Bit-Folgen kodiert und mit dem Alphabet (A-Z, a-z, 0-9, +/) darstellt. Das kann bei DNS funktionieren, muss aber nicht: Es gibt DNS-Server, die nicht zwischen Groß- und Kleinschreibung unterscheiden. Dann bleibt nur noch der Rückgriff auf Base32, das in 5-Bit-Folgen kodiert. Dazu nutzt es die Buchstaben von A bis Z sowie die Ziffern von 2 bis 7.

Welche Kodierung die jeweilige Verbindung hergibt, testet Iodine selbst, wie das Beispiel aus Abbildung 3 zeigt. Im günstigsten Fall könnte es sogar Base128 verwenden. Um Bandbreite zu sparen, komprimiert Iodine die Daten zudem vorher noch mit Gzip.

Gegenmaßnahmen

Potenzielle Maßnahmen gegen die DNS-Umleitung gibt es gleich mehrere. Die einfachste bestünde darin, den HTTP-Traffic nicht erst auf die Paywall umzuleiten, sondern einen kleinen DNS-Server zu betreiben, der alle Anfragen mit einer sehr kurzen TTL und der Paywall-IP beantwortet. Dank der kurzen TTL speichert der eigene Rechner die falsche Namensauflösung nicht lange, sodass nach der Bezahlung der Zugang frei wird.

Auch könnte der Betreiber einer Paywall sein IDS darauf schulen, bei auffällig vielen »TXT«- oder »SRV«-Anfragen sowie bei auffällig vielen und langen Rechnernamen unter einer Subdomain Alarm zu schlagen. Beides ist grundsätzlich sinnvoll, weil auch Schadsoftware DNS-Tunnel für Command- und Control-Verbindungen nutzt, eben wegen der häufig schlechten Filterung [7]. So gibt es für Snort bereits eine vorgefertigte Regel, um den Iodine-Handshake zu erkennen [8].

Daneben fällt auf, dass die Base32-, Base64- und Base128-Kodierung eine höhere Entropie aufweisen als normale Rechnernamen. Aufgrund der Kompression und der Kodierung kommen alle Zeichen aus dem Vorrat etwa gleich häufig vor, was bei normalen DNS-Anfragen kaum der Fall ist.

Zu guter Letzt erweist sich der DNS-Verkehr schlicht als ungewöhnlich hoch. Im Fall der Paywall geht der Traffic zudem von einem Gerät aus, mit dem noch gar keine Verbindung besteht. Auch die zahlreichen und typischen DNS-Anfragen, die Mailserver aufgrund vieler MX-Auflösungen erzeugen, fehlen in diesem Szenario.

Alternativen zum DNS-Tunnel

Wie die Erfahrung lehrt, lassen Paywalls und andere Internet-Sperren häufig die Ports 80, 443 und 53 TCP offen. Daher bietet es sich stets an, einen im Internet erreichbaren SSH-Server auf diesen Ports zu betreiben, um sich aus Netzen herauszutunneln. Dabei hilft es zudem oft, IP-Adressen anstelle von Hostnamen zu verwenden, um eine eventuell nicht zuverlässige Namensauflösung zu umgehen. Hier hilft es, die »/etc/ssh/ssh_config« auf dem Laptop zum Beispiel um die Zeilen aus Listing 9 zu ergänzen.

Listing 9

IP-Adresse statt Namen

Host tunnel
  Hostname 192.0.2.15
  Port 443
  DynamicForward 60808

Anschließend genügt es, auf der Kommandozeile den Befehl »ssh tunnel« einzugeben, um per SSH einen Socks-Proxy bereitzustellen. Ist Port 443 ausnahmsweise dicht, wechselt der Tunnelbauer mit »-p 53« zum Beispiel auf Port 53/tcp. Der Server braucht dafür ein kleines Update seiner »/etc/ssh/sshd_config« (Listing 10).

Listing 10

Ports für den SSH-Server

Port 22
Port 53
Port 143
Port 443

Oft bietet auch der von DNS genutzte Port 53/udp einen Pfad an, um sich hinaus zu tunneln – ganz ohne DNS-Tunnel. Zwar hört SSH nicht auf UDP, doch heißt das ja nicht, dass dort nicht der eigene VPN-Server lauschen dürfte, auch wenn OpenVPN [9] UDP-Anfragen standardmäßig auf Port 1194 erwartet. Anders als bei SSH gibt es bei OpenVPN allerdings nicht die Option, einen Server auf mehreren Ports lauschen zu lassen, doch lässt sich das Problem mithilfe von Iptables und Port-Forwarding lösen (Listing 11).

Listing 11

Port-Forwarding für Port 53/udp

# iptables -t nat -A PREROUTING -i $EXT_INF -p UDP -d 192.0.2.2 --dport 53 -j DNAT --to 192.0.2.2:1194

Danach ist OpenVPN von außen weiter über den Standard-Port 1194 erreichbar, aber eben auch über Port 53 und weitere UDP-Ports, die einem als geeignet erscheinen. Alle diese Varianten sind deutlich schneller als der DNS-Tunnel, der damit eine Notlösung für besonders hartnäckige Fälle bleibt. (kki)

VPN-Varianten

VPN gibt es in vielen Geschmacksrichtungen. Das Original IPSec [10] sah neben anderen (praktisch untauglichen) Mechanismen vor, verschlüsselte IP-Pakete in IP-Paketen zu tunneln. Dazu setzte es im IP-Header den Wert für Next-Header auf ESP (Encapsulated Security Payload). ESP sieht vor, dass Absender und Empfänger eine Verschlüsselung aushandeln. Dabei schickt der Absender die Liste seiner in der Reihenfolge sinkenden Präferenz, der Empfänger nimmt den höchsten Match – fertig ist die Entscheidung. Fatal: ESP sieht auch eine »NUL«-Verschlüsselung vor – also keine.

Wireguard [11] wird derzeit heiß gehandelt und schickt seine verpackten IP-Pakete über UDP [12]. Dabei verwendet es eine eigene Verschlüsselung, die nach diversen Tests wohl als sicher gelten darf.

OpenVPN und SSH nutzen SSL und handeln dabei die Parameter aus, wie stets bei SSL. Dabei stören unter Umständen Seiteneffekte in den alten SSL-Libraries wie OpenSSL: FREAK [13] und Heartbleed [14] sind nur zwei Beispiele für die Folgen gewachsener Bibliotheken. Die neu entstandene LibreSSL soll zumindest die gröbsten Schnitzer verhindern. Die Sicherheit der Verschlüsselung hängt also am Ende (auch) davon ab, gegen welche Bibliothek der Admin verlinkt.

Ein VPN über SSH verpackt die IP-Pakete in SSH-Paketen, die eine Schicht tiefer als TCP-Pakete durch das Netz reisen. OpenVPN bietet mehr Flexibilität: Abhängig von der Konfiguration des Servers lassen sich Tunnel über UDP oder TCP realisieren.

Oftmals blockieren Firewalls IPSec-Tunnel, sei es mit Absicht oder aus Unverständnis respektive Unkenntnis von IPSec. Häufig verhindern sie auch UDP-Kommunikation, selten allerdings TCP-Pakete auf den Ports 80 und 443. Für reisende VPN-Nutzer sind daher TCP-Tunnel oft die einzig verfügbaren. In diesem Fall bleibt nur OpenVPN als Alternative übrig.

Der Autor

Tobias Eggendorfer, Professor für IT-Sicherheit in Ravensburg und freiberuflicher IT-Berater (http://eggendorfer.info), ist aktuell ziemlich genervt von den Updates im Windows-Stil auf seinem Macbook. Er freut sich über Hinweise auf einen BSD-tauglichen Laptop, der vor allem beim Anschließen von Beamern keinen Ärger macht, auf Reisen flexibel mit fremden WLANs umgeht, ohne dass ihm die Akku-Puste ausgeht, und der ähnlich leicht und robust wie ein Macbook ist.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 5 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
2 Kommentare
Älteste
Neuste Beste Bewertung
Faruk
6 Jahre her

Interessant, vor allem da flightradar.live seit kurzem auch Satelliten einsetzt. Diese so erkannten Flugzeuge werden in blauer Farbe dargestellt.
 

Last edited 6 Jahre her by Faruk
bliff
3 Jahre her

Wieso in Gottes Namen legt man seine ssh config unter /etc ab? Dafür gibt es $HOME/.ssh?

Last edited 3 Jahre her by bliff
Nach oben