Beispiel 1: Will man aus der Ferne z.B. einen Router zuhause konfigurieren, der aber nur lokalen Zugriff erlaubt, kann man dies mit Hilfe von SSH recht einfach bewerkstelligen. Hierzu benötigt der Linuxuser zuhause einen Linuxrechner mit installiertem OpenSSH und einen dynamischen DNS-Provider wie dyn-dns oder no-ip (z.B.).
Mit dem folgenden Befehl kann dann der Tunnel angelegt werden:
$ ssh -C -L 12345:192.168.0.1:80 user@meinhost.dyndns.org
Nun kann man auf dem lokalen Rechner den Webbrowser starten und gibt als URL den Tunneleingang an:
http://localhost:12345/
und schon wird über den Tunnel die Seite unseres Routers geladen.
+---------------+ +-----------+ +-------------+ |1. $ ssh ... |__Inter__|DSL-Router |__Heim-_| SSH-Server | |2. http://... | -net |192.168.0.1| netz |192.168.0.xxx| +---------------+ +-----------+ +-------------+
Beispiel 2 ermöglicht jetzt anders herum einem Remotepartner auf einen Telnet Server im lokalen Netz zuzugreifen. Das kann z.B. eine Receiverbox sein, die eben nur FTP oder Telnet anbietet, aber kein SSH um selbst als Tunnelserver wie in Beispiel 1 zu dienen.
$ ssh -C -R 2300:192.168.0.42:23 user@seinhost.dyndns.org
Jetzt kann der Benutzer auf der Remoteseite bei seinhost.dyndns.org den Tunnel benutzen mit
$ telnet 127.0.0.1 2300
+---------------+ +-----------+ +-------------------+ |Lokaler Rechner| Heim- |DSL-Router | In- | Remote - Partner | |$ ssh -C -R ...|__netz__| |__ter-__| mit SSH-Server | |192.168.0.2 | | |192.168.0.1| net |seinhost.dyndns.org| +---------------+ | +-----------+ +-------------------+ +---------------+ | | Receiver |__+ |192.168.0.42 | +---------------+
Versuche mit Weiterleitung von FTP Verbindungen hat leider noch nicht funktioniert. Wir arbeiten daran.
Was nun, wenn man während eine Verbindung beseht, noch einen weiteren Port tunneln will? Dafür gibt es die Escape Character, um auf eine Art Hintergrundshell zu kommen. Beispiel:
[host-1]$ ssh -L 1380:10.11.12.13:80 userx@host-2 Enter Password for user userx: [host-2]$
Jetzt sind wir auf host-2 eingeloggt und haben auf host-1 die Möglichkeit mit dem Browser auf http://127.0.0.1:1380/ zuzugreifen. Dies wird auf host-2 weiter geleitet auf 10.11.12.13, Port 80.
Durch drücken der Tastenkombination ~C (je nach Tastatur auch ~[SPACE]C) kommen wir auf den ssh-Prompt und können einen weiteren Tunnel hinzufügen:
[host-2]$ ~C //(wird nicht angezeigt)// ssh> help Commands: -L[bind_address:]port:host:hostport Request local forward -R[bind_address:]port:host:hostport Request remote forward -D[bind_address:]port Request dynamic forward -KR[bind_address:]port Cancel remote forward [ENTER] [host-2]$ ~C ssh> -L1480:10.11.12.14:80 Forwarding port. [ENTER]
Ab jetzt haben wir einen zweiten Port weiter geleitet und greifen mit einem weiteren Browserfenster über http://127.0.0.1:1480/ auf 10.11.12.14, Port 80 zu.
Mit [ENTER] ~# kann man die aktiver Verbindungen anschauen.
[ENTER] [host-2]$ ~# The following connections are open: #2 client-session (t4 r0 i0/0 o0/0 fd 6/7 cc -1) #3 direct-tcpip: listening port 10000 for 192.168.178.1 port 80 [ENTER]
Ist man online können folgende Befehle durch Betätigen von '~' eingegeben werden:
~. Disconnect.
~^Z Background ssh.
~# List forwarded connections.
~& Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.
~? Display a list of escape characters.
~B Send a BREAK to the remote system (only useful if the peer sup‐ ports it).
~C Open command line. Currently this allows the addition of port forwardings using the -L, -R and -D options (see above). It also allows the cancellation of existing port-forwardings with -KL[bind_address:]port for local, -KR[bind_address:]port for remote and -KD[bind_address:]port for dynamic port-forwardings. !command allows the user to execute a local command if the PermitLocalCommand option is enabled in ssh_config(5). Basic help is available, using the -h option.
~R Request rekeying of the connection (only useful if the peer supports it).
~V Decrease the verbosity (LogLevel) when errors are being written to stderr.
~v Increase the verbosity (LogLevel) when errors are being written to stderr.
Man kann SSH auch in einem bestehenden Tunnel machen, wenn man z.B. einen Server (B) von extern erreichen will, der keinen direkten Internetzugang hat. Man baut dazu einen Tunnel zu einem Gateway auf und baut dann einen zweiten Tunnel darin auf. Beispielnetz:
+---------------+ Inter- +-------------+ Intern +-------------+ | Rechner A |__net___| SSH-Gateway |__Netz-_| Server B | |192.168.0.2 | |gw.domain.xyz| werk | 172.16.3.28 | +---------------+ +-------------+ +-------------+
Rechner A $ ssh -L 2200:172.16.3.28:22 gw-user@gw.domain.xyz Enter Password for gw-user: SSH-Gateway $ Rechner A $ ssh -p 2200 srv-user@127.0.0.1 Enter Password for srv-user: Server B $
Das erste Fenster, mit dem Login auf dem Gateway, muss solange offen bleiben, wie man auf Server B arbeiten will. Wenn man fertig ist, schließt man die Verbindung zu Server B und dann die zum Gateway.
Wenn nun z.B. hinter Server B ein weiterer Rechner (C) ist, der eine Weboberfläche bietet, die aber nur von Server B aus aufrufbar ist, kann man dies im zweiten Tunnel oben einpacken. Dann ändert sich der Befehl wie folgt:
Rechner A $ ssh -p 2200 -L 8000:172.16.7.8:80 srv-user@127.0.0.1 Enter Password for srv-user: Server B $
Jetzt kann man auf Rechner A auf http://127.0.0.1:8000/ im Browser aufrufen und bekommt über den getunnelten HTTP-tunnel im getunnelten SSH-Tunnel die Webseite von 172.16.7.8 angezeigt. Man kann auch aus dem Tipp zuvor den bestehenden Tunnel 2 erweitern mit der ~C Funktion (s.o.).
Will man über eine SSH Verbindung die Internetanbindung des entfernten Rechnes benutzen, kann man dazu einen Socks-Proxy verwenden, wenn z.B. das Routing nicht geht. Mit folgendem Befehl wird die SSH-Verbindung hergestellt.
ssh -D 10000 user@host
Anschließend muß im lokalen Browser unter Proxyeinstellungen den Socks-Proxy einstellen:
Host: localhost Port: 10000
Jetzt kann man im Browser über die Internetverbindung des entfernten Host-Rechners surfen.
Öffnen der Verbindung mit:
ssh -R 9000 user@host
Dann im Remote System das eingeben:
apt -o Acquire::http::proxy="socks5h://localhost:9000" -o Acquire::https::proxy="socks5h://localhost:9000" update
Will man einen Rechner hinter einem Router erreichen ohne Portweiterleitung, so muß dieser Rechner bzw. Client aktiv eine SSH Verbindung zu einem SSH-Server aufnehmen um einen Tunnel aufzubauen, der dann rückwärts verwendet wird, um wiederum eine SSH Console auf dem Client zu öffnen.
Auf dem Server muss ein neuer User angelegt werden, der keine „root“ Rechte hat z.B.:
adduser tun
Bei diesem sollte man später zur Sicherheit in der /etc/passwd die Shell abschalten indem der Shelleintrag /bin/bash durch /bin/true ersetzt wird. Allerdings erst nach dem Kopieren des Keys.
Zusätzlich müssen in der Datei /etc/ssh/sshd_config die beiden folgenden Zeilen eingebaut werden.
ClientAliveInterval 20 ClientAliveCountMax 3
Dies ist notwendig, da bei einem IP-Wechsel am Client Rechner sonst die Verbindung nicht geschlossen wird und der Tunnelport nicht mehr geöffnet werden kann.
Auf dem Client Rechner verwenden wir autossh. Zuerst muss als root ein RSA Key angelegt werden. Root deswegen, da via rc.local das autossh als root ausgeführt wird und die id_ras.pub von root verwendet wird:
sudo -i (oder 'su -' je nach Linux-System) cd ~/.ssh ssh-keygen -t rsa
Diesen nun auf den Server kopieren:
cat ~/.ssh/id_rsa.pub | ssh [-p <port>] tun@<server> \ -c "cat - >> ~/.ssh/authorized_keys
Kopieren mit scp wäre ebenfalls möglich, aber dieser Befehl überschreibt grundsätzlich bereits vorhandene Dateien, was hier unerwünschte Effekte erzeugen kann. Sollen oder müssen mehrere Keys angelegt werden ist der Befehl „ssh-copy-id“ besser, mit welchem ebenfalls Keys an die Datei „.ssh/authorized_keys“ angehängt werden können:
ssh-copy-id tun@<server>
muß ein Port angegeben werden, so sieht das so aus:
ssh-copy-id "-p <port> tun@<server>"
Achtung: /etc/passwd Eintrag nicht vergessen !
Jetzt muß noch der folgende Befehl in die /etc/rc.local rein:
/usr/bin/autossh -f -N -R 2222:127.0.0.1:22 \ -oServerAliveInterval=20 \ -oServerAliveCountMax=3 \ -oStrictHostKeyChecking=no \ -oUserKnownHostsFile=/dev/null \ -oExitOnForwardFailure=yes \ -oCompression=yes \ [-p <port>] tun@<server>
Hinweis: Wird der Server unter einem anderen Port betrieben, muß bei ssh der Parameter „-p <port>“ angegeben werden. ssh-copy-id verwendet ssh und hier muß wieder eine kleines p verwendet werden, jedoch sind hier Anführungsstriche nötig (siehe Beispiel oben).
Wenn alles richtig ist, wird man nach Neustart des Client oder Ausführen der Datei /etc/rc.local sofort zuhause auf dem Server angerufen und der SSH-Hilfs-Tunnel erzeugt.
Jetzt kann man auf seinem Server zuhause über diesen Hilfs-Tunnel mit:
ssh -C -p 2222 <user>@127.0.0.1
auf dem Client Rechner eine Shell öffnen. Weiterhin kann man mit den bekannten -L oder -R Parametern weitere Ports tunneln.
Will man den Hilfs-Tunnel auf einer anderen localhost IP laufen lassen z.B. 127.0.0.2, um z.B. mehrere solcher Clients immer auf Port 2222 zu tunneln, so muß in der sshd_config auf dem Server die folgende Zeile eingebaut werden:
GatewayPorts clientspecified
Anschließend wird auf dem Client autossh angepasst auf: „… -R 127.x.y.z:2222:127.0.0.1:22“ und autossh neu gestartet. z.B.:
/usr/bin/autossh -f -N -R 127.0.1.8:2222:localhost:22 \
Vorteil ist jetzt, das man in der Hosts Datei auf dem Server dem Tunnel einen Namen geben kann:
sudo -i vi /etc/hosts ... 127.0.0.2 client-muenchen 127.0.0.3 client-hamburg ...
Danke an Klaus für den Tipp
Eine einfache Möglichkeit X-Programme eines entfernten Rechners auf dem lokalen Rechner anzuzeigen, bietet eine Option von SSH:
ssh -X -C user@host
Das -C aktiviert einen zusätzliche Kompression der übertragenen Daten. Man kann es mal mit und ohne -C probieren, ob sich dies bemerkbar macht, oder nicht. Das hängt von der Bandbreite der Verbindung und der Leistungsfähigkeit der CPU ab, die ja den Traffic komprimieren muss.
Auf dem entfernten Rechner kann man nun ein beliebiges Programm öffnen und das Fenster dazu erscheint auf meinem lokalen Desktop:
firefox &