Wie Skype & Co. Firewalls umgehen

Seite 2: Klinken putzen

Inhaltsverzeichnis

Natürlich ist diese Beschreibung etwas vereinfacht und die Details hängen sehr stark von den konkreten Eigenschaften der eingesetzten Firewalls ab. Doch sie entspricht im Prinzip unseren Beobachtungen beim Verbindungsaufbau zwischen zwei Skype-Clients, die sich jeweils hinter einer Linux-Firewall befanden. Diese waren auf NAT für ein LAN konfiguriert und gestatteten ausgehenden UDP-Verkehr.

Die NAT-Funktionen von Linux haben nämlich die VoIP-freundliche Eigenschaft, die Ports ausgehender Pakete zunächst mal nicht zu ändern. Der NAT-Router ersetzt lediglich die private, lokale IP-Adresse durch seine eigene; der von Skype gewählte UDP-Quell-Port bleibt erhalten. Erst wenn mehrere Clients im lokalen Netz denselben Quell-Port verwenden, greift der NAT-Router ein und setzt ihn auf einen noch unbenutzten Wert um. Denn jeder Satz aus den jeweils zwei IP-Adressen und Ports muss sich jederzeit eindeutig einer Verbindung zwischen zwei Rechnern zuordnen lassen. Der Router muss unter anderem später aus dem Ziel-Port der Antwortpakete die interne IP-Adresse des ursprünglichen Absenders rekonstruieren.

Andere NAT-Router bilden Ports möglichst direkt auf einen bestimmten Bereich, beispielsweise den ab 30 000, ab und schreiben dabei den UDP-Port 1414 wenn möglich auf 31414 um. Das bereitet Skype natürlich keine Probleme; das oben skizzierte Szenario funktioniert damit analog und ohne Einschränkungen.

Etwas komplizierter wird es, wenn eine Firewall wie Checkpoints Firewall-1 die Ports einfach der Reihe nach vergibt: Die erste Verbindung bekommt 30001, die nächste 30002 und so weiter. Damit weiß der Skype-Server zwar, dass Bob mit ihm gerade auf Port 31234 spricht, die Verbindung zu Alice wird allerdings über einen anderen laufen. Doch auch in solchen Fällen kann Skype die Firewall austricksen. Es klappert dann einfach der Reihe nach Ports oberhalb von 31234 ab, in der Hoffnung, irgendwann den richtigen zu treffen. Funktioniert das nicht auf Anhieb, bleibt Skype hartnäckig: Bobs Skype öffnet auf dessen Anweisung eine neue Verbindung zum Skype-Server, deren Quellport dann sofort für eine neue Versuchsreihe herhalten muss.

Zur Not geht Skype Klinken putzen und probiert alle Ports in einem ganzen Bereich aus. Hier wird es auf Port 38901 fündig.

Trotzdem kann es natürlich bei besonders aktiven Netzen passieren, dass Alice den richtigen Port mit dem Loch nicht trifft. Selbiges gilt auch für eine spezielle Firewall-Gattung, die jeder neuen Verbindung einen zufälligen Quellport zuweist. Damit kann der Skype-Server Alice keinen erfolgversprechenden Tipp mehr geben, wo ein passendes Loch in Bobs Firewall zu finden ist.

Doch selbst dann gibt Skype nicht auf. In solchen Fällen kommt ein Skype-Server als Vermittler (Relay) zum Einsatz. Er nimmt jeweils ankommende Verbindungen von Alice und Bob entgegen und leitet die Pakete entsprechend weiter. Diese Lösung lässt sich immer realisieren, sofern die Firewall ausgehenden UDP-Verkehr gestattet. Sie bedeutet allerdings eine zusätzliche Belastung der Infrastruktur, da die kompletten Audiodaten über Skype-Server laufen müssen. Die verlängerten Paketlaufzeiten machen sich unter Umständen auch als unangenehme Verzögerungen bemerkbar.

Das beschriebene Verfahren kommt keineswegs nur bei Skype zum Einsatz und ist als "UDP hole punching" bekannt. Auch andere Netzwerkdienste wie das Gamer-VPN Hamachi, das auf Peer-to-Peer-Kommunikation von Rechnern hinter Firewalls angewiesen ist, setzen auf ähnliche Verfahren. Eine weiterentwickelte Form hat es sogar in den Rang eines Quasistandards geschafft: RFC 3489 beschreibt mit "Simple Traversal of UDP through NAT" - kurz STUN - ein Protokoll, mit dem zwei STUN-Clients unter Mithilfe eines STUN-Servers die Beschränkungen von NAT in vielen Fällen umgehen können. Der Entwurf Traversal Using Relay NAT (TURN) beschreibt einen möglichen Standard für Vermittlungs-Server (Relays).

UDP Hole Punching kann man mit ein paar kleinen Hilfsmitteln auch selbst ausprobieren. Die benötigten Tools hping2 und netcat finden sich in den meisten Linux-Distributionen. Dabei ist local ein Rechner hinter einer Linux-Firewall (local-fw) mit Stateful Firewall, die (UDP-)Verbindungen nur von drinnen nach draußen gestattet. Der Testrechner remote hing in unserem Test der Einfachheit halber ganz ohne Firewall direkt am Internet.

Zunächst mal auf der Konsole local/1 hinter der Firewall einen UDP-Listener auf UDP-Port 14141 starten:

local/1# nc -u -l -p 14141

Den versucht ein externer Rechner "remote" dann zu erreichen

remote# echo "hello" | nc -p 53 -u local-fw 14141

Doch da kommt wie erwartet nichts auf local/1 an und dank Firewall auch nichts zu remote zurück. Jetzt stanzt das Universal-Tool zum Erzeugen von IP-Paketen hping2 auf einer zweiten Konsole local/2 ein Loch in die Firewall:

local/2# hping2 -c 1 -2 -s 14141 -p 53 remote

Sofern sich remote anständig verhält, meldet er via ICMP "Port Unreachable" zurück - das spielt für das Weitere jedoch keine Rolle. Beim zweiten Übertragungsversuch

remote# echo "hello" | nc -p 53 -u local-fw 14141

spuckt der netcat-Listener auf Konsole local/1 das "hello" aus - das UDP-Paket von außen hat die Firewall passiert und gelangte zum Rechner dahinter.

Netzwerk-Administratoren, die diese Art von Löchern in ihrer Firewall nicht schätzen und Missbrauch fürchten, haben eigentlich nur eine Option: Sie müssen ausgehenden UDP-Verkehr sperren beziehungsweise auf notwendige Einzelfälle beschränken. UDP wird für die normale Internet-Kommunikation ohnehin nicht benötigt: Web, E-Mail und ähnliches arbeiten mit TCP. Probleme dürften vor allem Streaming-Protokolle bereiten, die aufgrund des geringeren Ballasts bevorzugt auf UDP setzen.

Das Löcherbohren funktioniert erstaunlicherweise auch mit TCP. Nach einem ausgehenden SYN-Paket befördert der Firewall/NAT-Router eingehende Pakete mit passenden IP-Adressen und Ports auch dann ins LAN, wenn sie keine oder die falsche Sequenznummer bestätigen (ACK). Zumindest Linux-Firewalls werten diese Information offenbar nicht konsequent aus. Der Aufbau einer TCP-Verbindung klappt jedoch auf diesem Weg nicht ohne Weiteres, da Alice die im ersten Paket von Bob gesendete Sequenznummer nicht kennt. Das Paket mit dieser Information hatte ja ihre eigene Firewall verworfen. (ju)