Der in OpenSSH eingebaute SOCKS-Proxy und das auf SSH aufbauende Python-Programm Sshuttle springen in die Bresche zwischen einfachem Port-Forwarding und einem vollwertigen VPN.
Transparente Netzwerk-Verbindungen via Tunnel in ein virtuelles privates Netz (VPN) helfen nicht nur, wenn Sie sich als Mitarbeiter von zu Hause oder beim Außentermin in das interne Netzwerk einer Firma einklinken möchten. Sie eignen sich auch, um ohne HTTPS-Verschlüsselung in offenen WLANs zu surfen, auf Rechner hinter dem NAT-Router zu Hause zu zugreifen oder überhaupt erst ins Internet zu gelangen.
Einen eigenen VPN-Server aufzusetzen setzt selbst mit OpenVPN [1] zumindest entsprechende Kenntnisse voraus, viel Zeit und vor allem einen Server, der die Möglichkeit bietet, den VPN-Endpunkt einzurichten [2]. Dazu brauchen Sie in fast allen Fällen Root-Rechte auf dem Server, und gerade die stehen selten bereit.
Ein Rechner, der ein Login per SSH (Secure Shell, heute meist in Form der OpenSSH-Implementation [3]) erlaubt, lässt sich jedoch einfach organisieren – und das reicht oft schon für ein rudimentäres VPN aus.
SOCKS-Proxy mit SSH
Das Protokoll SOCKS [4] erlaubt es prinzipiell, beliebige Client-Server-Protokolle über einen Proxy-Dienst zu tunneln. OpenSSH als SSH-Client bringt bereits seit langer Zeit einen solchen generischen SOCKS-Proxy mit. Es leitet alle über diesen Proxy gemachten Verbindungen über einen Tunnel zur Endstelle der SSH-Verbindung auf den entfernten Rechner weiter. Dazu braucht am anderen Ende nicht einmal ein OpenSSH-Server laufen: Es genügt ein schlanker Dropbear-SSH-Server [5], wie man ihn oft auf WLAN-Routern mit OpenWRT [6] findet.
Das ermöglicht es bereits, über einen SSH-Tunnel Webseiten in einem Intranet anzusteuern oder unverschlüsselt in einem offenen WLAN zu surfen, ohne dass jemand im selben Netzwerk mitliest, wohin Sie surfen oder welche Dateien Sie herunterladen. Das klappt bereits nur mit Bordmitteln von OpenSSH und ohne besondere Berechtigungen auf dem entfernten Rechner.
Das Bereitstellen eines SOCKS-Proxys erledigen Sie bei OpenSSH über den Parameter -D und die Angabe der vom Proxy zu verwendenden Port-Nummer (üblicherweise 1080):
$ ssh -D 1080 Host
Das aktiviert den SOCKS-Proxy zusätzlich zum normalen Shell-Login auf dem entfernten Rechner.
Möchten Sie ausschließlich den SOCKS-Proxy nutzen und keine Shell auf dem entfernten Rechner starten, so empfehlen sich zusätzlich die Optionen -N und -f: Erstere bewirkt, dass keine Shell auf dem entfernten Rechner startet, und Letztere, dass SSH nicht im Vordergrund arbeitet und somit die lokale Shell wieder freigibt.
Eine weitere nützliche Option ist -o ExitOnForwardFailure=yes. Sie sorgt dafür, dass SSH die Verbindung wieder abbaut, wenn es den SOCKS-Proxy nicht einrichten konnte. Der Fall tritt ein, wenn der lokale Port bereits belegt ist, weil schon ein SOCKS-Proxy auf dem lokalen Rechner läuft.
Konfiguration
Viele Anwendungen bieten die Möglichkeit, direkt auf einen SOCKS-Proxy zuzugreifen, etwa der Webbrowser Firefox (Abbildung 1) oder das Chat-Programm Pidgin (Abbildung 2). Oft, aber nicht immer, ist die für SOCKS-Proxies übliche Portnummer 1080 voreingestellt.

Abbildung 2: Bei Bedarf wickeln Sie die Kommunikation von Pidgin über den SOCKS-Proxy von OpenSSH ab.
Unterstützt eine Applikation nur Version 4 des SOCKS-Protokolls, so löst das Programm die Namen der Rechner immer lokal auf dem Rechner auf. Version 5 des SOCKS-Protokolls unterstützt dagegen das Weiterleiten von DNS-Anfragen und IPv6-Verbindungen über den Proxy.
Bietet eine Software keinen direkten Support für einen SOCKS-Proxy, verhilft ihr in den meisten Fällen das Helferprogramm Tsocks [7] zu den entsprechenden Fähigkeiten. Dieser Helfer biegt durch vorhergehendes Laden einer bestimmten Bibliothek alle Systemaufrufe zum Aufbau einer TCP/IP-Verbindung auf einen SOCKS-Proxy um (Listing 1).
Listing 1
$ ssh -D 1080 -f -o ExitOnForwardFailure=yes -N 192.0.2.42 $ lynx -dump http://checkip.dyndns.org/ Current IP Address: 192.0.2.23 $ tsocks lynx -dump http://checkip.dyndns.org/ 00:14:56 libtsocks(398): Call to connect received on completed request 3 Current IP Address: 192.0.2.42
Über die Konfigurationsdatei /etc/tsocks.conf teilen Sie Tsocks mit, dass es Verbindungen zu gewissen IP-Bereichen nicht durch den SOCKS-Proxy umleiten soll, weil diese beispielsweise zum lokalen Netzwerks gehören. In vielen Distributionen fungiert dies als Standard-Einstellung für die typischen privaten IP-Ranges.
Sshuttle
Manchmal genügt jedoch ein SOCKS-Proxy nicht den Anforderungen, oder der Einsatz eines Proxys erweist sich als zu umständlich für die gewünschte Funktion. OpenSSH bietet zwar seit einigen Versionen ebenfalls die Möglichkeit, mit Bordmitteln einen TUN/TAP-basierten VPN-Tunnel aufzubauen, braucht dazu aber auf beiden Seiten des Tunnels Root-Rechte: Sie müssen die SSH-Verbindung also als root starten.
Dabei liegt es in der Verantwortung desjenigen, der einen solchen Tunnel aufbaut, sich um das korrekte Netzwerk-Setup zu kümmern – entweder mittels selbst geschriebener Skripte oder manuell. In diesem Fall kann es passieren, dass es zu Problemen mit dem TCP-über-TCP kommt [8], also die Mechanismen zum Regeln “äußeren” TCP-Verbindung den Betrieb der geschachtelten, “inneren” TCP-Verbindung stören.
Einfacher und mit wesentlich weniger heftigen Anforderungen geht es mit Sshuttle [9], das ein Zwischending zwischen VPN und Port-Weiterleitung verwendet. Der Name ist ein Wortspiel aus SSH und Shuttle, wobei Letzteres im Englischen für Zubringer oder Pendelverkehr steht. Sshuttle braucht zwar auf dem lokalen Rechner nach wie vor Root-Rechte, um per Iptables mittels Redirect-Regeln das notwendige Routing automatisch einzurichten, kommt aber dabei problemlos mit sudo oder su klar.
Der große Vorteil von Sshuttle: Wie der SOCKS-Proxy braucht es auf dem entfernten Rechner keine Root-Rechte. dort muss lediglich eine Python-Installation vorliegen, Sshuttle selbst braucht nicht installiert zu sein. Es überträgt sich per SSH selbst und wird vom Python-Interpreter auf dem entfernten Rechner direkt ausgeführt.
Von außen wirkt Sshuttle ähnlich wie ein VPN. Ohne dass man jede einzelne Verbindung vorher konfigurieren muss, tunnelt es beliebige (TCP-)Verbindungen auf eine auf der Kommandozeile angegebene Menge von IP-Bereichen. Intern funktioniert es jedoch eher wie ein transparenter Proxy oder eine dynamische SSH-Port-Weiterleitung – es kann wie der SOCKS-Proxy nur TCP-Sitzungen und DNS weiterleiten.
Allerdings baut Sshuttle die Pakete der TCP-Verbindungen vor dem Tunnel lokal wieder zusammen, überträgt deren Daten als Datenstrom durch den SSH-Tunnel und macht am entfernten Ende des Tunnels wieder TCP-Verbindungen daraus. Damit umgeht es die oben angeschnittene TCP-über-TCP-Problematik: Solange die Daten durch den Tunnel übertragen werden, gibt es keine zweite Verstopfungserkennung.
Eine weitere nette Eigenschaft: Sshuttle kann die lokale /etc/hosts mit den auf dem entfernten Rechner gefundenen Einträgen aus der dortigen /etc/hosts-Datei erweitern kann. Dies erledigt die Option --auto-hosts. Alternativ leiten Sie mit der Option --dns auch DNS-Abfragen durch den Tunnel.
Sshuttle-Sitzung
Listing 2 zeigt den Ablauf eines Verbindungsaufbaus aus einem LAN mit dem IP-Bereich 192.168.1.* mit einem extern per SSH erreichbaren Rechner in einem anderen LAN mit dem selben IP-Bereich. Dazu müssen Sie das lokale Gateway (192.168.1.1) aus der Weiterleitung ausschließen.
Listing 2
$ sshuttle --dns --verbose --remote=anderer.rechner --exclude=192.168.1.1/32 192.168.1.0/24
Starting sshuttle proxy.
Listening on ('127.0.0.1', 12300).
DNS listening on ('127.0.0.1', 12300).
[local sudo] Password:
firewall manager ready.
c : connecting to server...
s: latency control setting = True
c : connected.
Connected.
s: available routes:
s: 192.168.1.0/24
firewall manager: starting transproxy.
>> iptables -t nat -N sshuttle-12300
>> iptables -t nat -F sshuttle-12300
>> iptables -t nat -I OUTPUT 1 -j sshuttle-12300
>> iptables -t nat -I PREROUTING 1 -j sshuttle-12300
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 192.168.1.1/32 -p tcp
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 192.168.1.0/24 -p tcp --to-ports 12300 -m ttl ! --ttl 42
>> iptables -t nat -A sshuttle-12300 -j RETURN --dest 127.0.0.0/8 -p tcp
>> iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 192.168.1.1/32 -p udp --dport 53 --to-ports 12300 -m ttl ! --ttl 42
In Listing 3 sehen Sie, was Sshuttle macht, wenn Sie eine SSH-Verbindung zu einem Rechner im entfernten LAN auf- und wieder abbauen. Mit c markiert die Software alle Ausgaben des lokalen Clients, mit s die Meldungen des entfernten Servers. Über [Strg]+[C] beenden Sie Sshuttle und damit seine eigene SSH-Verbindung sowie den Tunnel wieder (Listing 4).
Listing 3
c : DNS request from ('192.168.1.101', 55245): 41 bytes
c : Accept: 192.168.1.101:38221 -> 192.168.1.131:22.
c : DNS request from ('192.168.1.101', 36978): 27 bytes
c : DNS request from ('192.168.1.101', 36978): 27 bytes
s: warning: closed channel 2 got cmd=STOP_SENDING len=0
s: SW'unknown':Mux#2: deleting (1 remain)
s: SW#7:192.168.1.131:22: deleting (0 remain)
Listing 4
firewall manager: undoing changes. >> iptables -t nat -D OUTPUT -j sshuttle-12300 >> iptables -t nat -D PREROUTING -j sshuttle-12300 >> iptables -t nat -F sshuttle-12300 >> iptables -t nat -X sshuttle-12300 c : c : Keyboard interrupt: exiting. c : SW#8:192.168.1.101:38221: deleting (1 remain) c : SW'unknown':Mux#2: deleting (0 remain)
Neben dem Einsatz im Vordergrund bietet Sshuttle mit der Option --daemon die Möglichkeit für den Einsatz als Daemon im Hintergrund. Alle Meldungen der Software landen dann im Syslog.
Fazit
Sowohl ein SOCKS-Proxy als auch Sshuttle erlauben das dynamische Tunneln beliebiger TCP-Verbindungen über SSH, ohne dass auf dem entfernten Rechner Root-Rechte notwendig wären. Beide Ansätze eignen sich jedoch nicht für UDP-Pakete, das Tunneln von DNS bleibt in beiden Fällen optional. In Bezug auf Flexibilität und Anforderungen an das System bestehen teils gravierende Unterschiede.
Der in OpenSSH eingebaute SOCKS-Proxy stellt geringere Anforderungen, erweist sich aber in der Praxis als weniger flexibel: Sie müssen ihn für jede Anwendung extra konfigurieren. Im Falle von Tsocks gilt es sogar, die Software neu zu starten.
Sshuttle bietet dagegen die Möglichkeit, den Tunnel unabhängig von Anwendungen an- und auszuschalten. Andererseits braucht es aber lokal Root-Rechte und setzt auf dem entfernten Rechner Python voraus.
Danksagung
Der Autor bedankt sich bei Peter Beckert, Frank Hofmann und Thomas Osterried für ihre kritischen Anmerkungen und konstruktiven Kommentare im Vorfeld des Artikels.
Glossar
-
VPN
-
Virtual Private Network. Bezeichnung für abgeschlossene virtuelle Teilnetze innerhalb eines öffentlichen Netzwerks. VPNs binden meist entweder externe Rechner an (“End-to-Site”, “Roadwarrior”) oder koppeln zwei Netze (“Site-to-Site”).
-
SOCKS
-
Abkürzung für Sockets. Internet-Protokoll, das Client/Server-Anwendungen erlaubt, protokollunabhängig und transparent die Dienste eines Proxy-Servers zu nutzen.
-
TUN/TAP
-
Virtuelle Netzwerk-Kerneltreiber. TUN simuliert ein Point-to-Point-Netzwerkgerät und kommuniziert über IP-Pakete, TAP dagegen ein Ethernet-Gerät simuliert, das Ethernet-Frames verwendet.
Infos
[1] OpenVPN: http://openvpn.net
[2] OpenVPN-Workshop: Falko Benthin, “Sicherer Tunnel”, LU 11/2011, S. 28, https://www.linux-community.de/24374
[3] OpenSSH: http://www.openssh.org
[4] SOCKS-Protokoll: http://de.wikipedia.org/wiki/SOCKS
[5] Dropbear: http://matt.ucc.asn.au/dropbear/dropbear.html
[6] OpenWRT: https://openwrt.org
[7] Tsocks: http://tsocks.sf.net
[8] “Why TCP Over TCP Is A Bad Idea”: http://sites.inka.de/W1011/devel/tcp-tcp.html
[9] Sshuttle: https://github.com/apenwarr/sshuttle/






