SSH für Fortgeschrittene I - SSH Tunnel

Veröffentlicht am 30. October 2008

Unter SSH (Secure Shell) versteht man ein Netzwerkprotokoll, über das man eine sichere Verbindung zu einem anderen Computer aufbauen kann.

Normalerweise benutzt man dieses Protokoll, um über eine sichere Leitung Kommandos auf dem entfernten Rechner auszuführen oder Dateien zu übertragen.

Aber die Vielseitigkeit dieses Protokolls erlaubt auch zahlreiche weitere Anwendungen, die einen Vorteil aus dieser sicheren Verbindung ziehen können.

Die wohl wichtigste Anwendung des Protokolls über seine Basisfunktionen hinaus sind die sogenannten SSH-Tunnel.

Der Grundgedanke ist folgendermaßen:

Wurde erst einmal eine sichere SSH-Verbindung zwischen zwei Rechnern etabliert, lässt sich der Datenverkehr (nahezu) jedes beliebigen netzwerkfähigen Programms durch diesen sicheren Tunnel leiten.

Sogar, wenn diese Nutzprogramme keinen verschlüsselten Datenverkehr unterstützen.

Sogar, wenn diese Nutzprogramme nur lokale Verbindungen zum eigenen Rechner erlauben.

Sogar wenn zwischen den Rechnern eine Firewall steht.

Der Ablauf ist folgendermaßen:

1. Voraussetzungen

Die wichtigste Voraussetzung ist natürlich erst einmal: Es muss eine SSH-Verbindung von Rechner1 zu Rechner2 möglich sein. Das bedeutet:

  • Auf Rechner2 muss ein laufender SSH-Server installiert sein
  • Auf Rechner1 muss ein SSH-Clientprogramm installiert sein (z.B. PuTTY unter Windows, OpenSSH unter Linux/Unix)
  • Der Verbindungsaufbau von Rechner1 zu Rechner2 darf nicht durch Firewallregeln oder Diskonnektivität blockiert sein (TPC, normalerweise Port 22)
  • Der Anwender muss sich auf Rechner2 mit einem Benutzernamen username seiner Wahl anmelden können (Passwort oder Public-Key-Verfahren)

Eine weitere Bedingung ist noch: Die Netzwerkfähigkeit des Nutzprogramms muss auf TCP/IP beruhen. Da aber heute fast alle in Frage kommenden netzwerkfähigen Nutzprogramme TCP/IP einsetzen, ist dies keine große Einschränkung.

2. Binden der Adressen

Der nächste Schritt ist auch schon das Erstellen des eigentlichen SSH-Tunnels.

Dazu muss man zunächst überlegen, welche Endpunkte der Tunnel haben soll.

Ein Tunnel arbeitet immer folgendermaßen:

Er verknüpft auf Rechner1 den Port A mit dem Port B auf Rechner2.

Im Klartext heißt das: Baut man eine Verbindung mit Rechner1:A auf, so wird diese Verbindung dann durch den Tunnel geleitet (“getunnelt”) und man baut durch den Tunnel eine Verbindung mit Rechner2:B auf.

Wenn also z.B. auf Rechner2 auf Port B ein Webserver lauscht und man auf Rechner1 im Webbrowser die Adresse http://localhost:A/ ansteuert, bekommt man im Erfolgsfall das Webangebot des Webservers auf Rechner2 angezeigt.

Nun genug der Theorie, schreiten wir zur Praxis. Ich werde hier alle nötigen Schritte mit OpenSSH unter Linux beschreiben.

Wer mit PuTTY unter Windows das gleiche versucht, möge die PuTTY-Dokumentation zu Rate ziehen.

Unter Linux helfen im Allgemeinen die Manual-Pages (man ssh).

Die Grundlegende Syntax des nötigen Befehls zum Aufbau des Tunnels sieht so aus:

ssh -N -f -L <localport>:<targethost>:<targetport> <username>@<targethost>

Hierbei beschreibt <localport> den lokalen Port A auf Rechner1, <targethost> den Hostnamen des Rechner2, <targetport> den Port B auf Rechner2 und <username> den Benutzernamen username, mit dem sich der Anwender auf Rechner2 anmelden kann.

Der Parameter -L gibt hier an, dass ein Tunnel mit den gewählten Koordinaten erstellt werden soll.

Der Parameter -N sorgt dafür, dass keine Eingabe-Shell auf Rechner2 geöffnet wird, sondern nur der Tunnel geöffnet wird.

Und der (optionale) Parameter -f gibt an, dass die Verbindung im Hintergrund gehalten werden soll. Wird der Parameter -f weggelassen, so bleibt der SSH-Prozess im Vordergrund geöffnet und blockiert eine Shell.

Möchte man zusätzlich, dass eingehende Verbindungen von außen auf dem lokalen Port A ebenfalls durch den Tunnel laufen, so muss zusätzlich der Parameter -g angegeben werden.

Der lokale Rechner fungiert dann gewissermaßen als Proxy oder Relais zwischen den beiden anderen Rechnern. Hierbei muss allerdings beachtet werden:
Nur die Verbindung von localhost:A nach Zielhost:B ist hier sicher (bzw. verschlüsselt). Für die eingehende Verbindung trifft dies im Allgemeinen nicht zu.

Hierbei noch zu beachten: Dies wird nur funktionieren, wenn der Benutzer die nötigen Rechte hat, um einen Serverport nach außen zu öffnen. Eine Firewall kann dies verhindern. Für Ports < 1024 werden immer root-Rechte benötigt (Linux).

Um den Tunnel zu trennen, muss der erstellende SSH-Prozess beendet werden. Ist sonst kein SSH-Prozess am laufen, kann dies z.B. mit killall ssh erledigt werden. Ansonsten kann man hier einen Taskmanager wie z.B. htop verwenden.

3. Beispiel

Um hier ein Beispiel zu bringen, sei noch einmal die Situation von oben zu nennen.

Auf dem Host myhost.myserver.de läuft auf Port 1234 ein Webserver, der nur Verbindungen von localhost entgegennimmt. Ich sitze an einem anderen Rechner, kann mich aber über das kommando ssh metax@myhost.myserver.de auf dem Zielrechner erfolgreich anmelden.

Ich stelle fest, dass auf meinem PC der Port 8888 noch unbenutzt ist. Also eignet er sich, um einen SSH-Tunnel aufzubauen.

Ich stelle fest: Mein lokaler Port ist 8888, der Zielhost ist myhost.myserver.de, der Zielport ist 1234 und der Benutzername ist metax.

Ich öffne also eine Kommandozeile und setze folgendes Kommando ab:

ssh -N -f -L 8888:myhost.myserver.de:1234 metax@myhost.myserver.de

Jetzt ist also ein digitales Wurmloch zwischen localhost:8888 und myhost.myserver.de:1234 erstellt.

4. Aufrufen der Anwendungsprogramme

Hat man nun den Tunnel erstellt (es können natürlich mehrere Tunnel auf verschiedenen Ports parallel etabliert werden!), so muss dies dem Anwenderprogramm natürlich noch mitgeteilt werden.

Dies gestaltet sich allerdings meist recht einfach: An der Stelle, wo Zielhost und Zielport für eine Netzwerkverbindung anzugeben sind, ist statt zielhost:B einfach localhost:A bzw. 127.0.0.1:A anzugeben. Dann wird eine Netzwerkverbindung zu localhost:A erstellt. Dort lauscht der SSH-Tunnel, baut eine Verbindung nach zielhost:B auf und leitet allen TCP/IP Verkehr durch den Tunnel.

Kann man bei einem Anwenderprogramm den Zielport nicht wählen, so ist darauf zu achten, dass dieser Port auf dem lokalen Rechner noch nicht durch eine andere Verbindung besetzt ist und man wählt A = B beim Tunnelaufbau.

Um das Beispiel von oben weiterzuführen:

Der Tunnel steht nun. Ich öffne einen Webbrowser auf dem lokalen Rechner. Ich möchte die Seite http://myhost.myserver.de:1234/path/index.htm ansurfen.

Da der Webserver myhost.myserver.de:1234 für mich aber vom lokalen Rechner nicht erreichbar ist, gebe ich statt dessen die Adresse des Tunnels in die Adresszeile ein: http://localhost:8888/path/index.htm. Ich bekomme umgehend die gewünschte Seite angezeigt.

Kategorie: Technik
Schlagworte: