Ssh Port forwarding

aus PUG, der Penguin User Group
Wechseln zu: Navigation, Suche

(work in progress ...)

Einleitung

Da ich mich die Tage mal wieder mit ssh beschäftigt habe und nun zum x-ten mal die Grundlagen zum 'port forwarding' durchgearbeitet habe, nutze ich die Gelegenheit diese für das nächste mal hier zu dokumentieren. :-)

Grundsätzlich ist festzuhalten das ein ssh-Client keine Möglichkeit hat einen Port auf einem beliebigen externen Host weiterzuleiten oder einen Tunnel auf einem externen Host zu initiieren. Eine Port-Weiterleitung kann jedoch unter gewissen Umständen von einem 'externen' Host genutzt und/oder auf einen externen Host weitergeleitet werden. Der Tunnel, und somit auch die Verschlüsselung, existiert jedoch nur zwischen dem ssh-Client (ssh) und dem ssh-Server (sshd).

Die Begriffe local und remote bezeichnen den Ort des Ursprungs einer Port-Weiterleitung. D.h. wenn der Ursprung der Weiterleitung auf dem Host liegt auf welchem der ssh-Client ausgeführt wird, bezeichnet man dies als 'local'. Liegt der Ursprung jedoch auf dem Host des ssh-Servers, wird dies als 'remote' bezeichnet.

Der in den Beispielen verwendete Telnet-Client dient hierbei nur als Beispielapplikation zur Darstellung wie der weitergeleitete Port genutzt werden kann.

-L / local port forwarding

Die Weiterleitung eines lokalen Ports (local port forwarding) verbindet einen Port auf dem Host des ssh-Clients mit einem Port auf dem Host des ssh-Servers. (oder einem Host welcher über den ssh-Server erreichbar ist, siehe Beispiel Nr.4). Die allgemeine Syntax für ein local port forwarding sieht wie folgt aus:

ssh -L [[source_ip]:]source_port:target_ip:target_port [-g] [<user>@]ssh-server

ssh [user@]ssh-server sind die Informationen für den Verbindungsaufbau zwischen Client und Server, wobei 'ssh-server' die IP des Hosts oder eine über DNS auflösbarer Hostname sein kann.

-L [[source_ip]:]source_port:target_ip:target_port -[g] sind die Parameter und Optionen für die einzurichtente Weiterleitung.

Zu beachten ist hierbei das die optional anzugebende IP Adresse 'source_ip' sich auf den lokalen Host bezieht. Gültige IP Adressen sind Local IP (127.0.0.1), eine IP Adresse eines Interfaces (z.B. 192.168.1.1) oder alle IP's (0.0.0.0).

Soll der lokale Port über alle IP Adressen zu erreichen sein, kommt der Paramater -g (oder GatewayPorts yes in der config des Clients) ins Spiel.

[todo: Zusammenhang zwischen -g, GatewayPorts und source_ip klären]

Beispiele für ein local port forwarding

-L 10023:localhost:23

Mit dem Aufruf ssh -L 10023:localhost:23 user@ssh-server auf dem SSH_CLIENT wird der 'interne' Port 127.0.0.1:10023 auf den 'internen' Port 127.0.0.1:23 des SSH_SERVER weitergeleitet. Da ohne weitere Maßnahmen (z.B. iptables) der Port 127.0.0.1:10023 nur von Applikationen auf dem SSH_CLIENT erreichbar ist, können auch nur Applikationen, welche auf dem SSH_CLIENT ausgeführt werden, diese Weiterleitung nutzen.

             Tunnel:  127.0.0.1:10023 ----> 127.0.0.1:23
                       +----------+         +----------+
                       |SSH_CLIENT|---/ /---|SSH_SERVER|
                       +----------+         +----------+
                         telnet ----------------^

Wenn sich ein auf dem SSH_CLIENT ausgeführter Telnet-Client mit Port 10023 verbindet (z.B. telnet 127.0.0.1 10023) wird diese Verbindung, für die Applikation transparent, auf den SSH_SERVER weitergeleitet. Diese Weiterleitung ist nicht von außerhalb des SSH_CLIENT erreichbar!


-L 192.168.1.1:10023:localhost:23

Mittels des Aufrufes von ssh -L 192.168.1.1:10023:localhost:23 user@ssh-server auf dem SSH_CLIENT, wird der Port 192.168.1.1:10023 des SSH_CLIENT auf den internen Port 23 (127.0.0.1:23) des SSH_SERVER weitergeleitet. Hierbei muss 192.168.1.1 jedoch eine gültige IP Adresse auf einem existierenden Interface des SSH_CLIENT sein. Die Weiterleitung ist hierbei jedoch über dem internen Port 10023 (127.0.0.1:10023) des SSH_CLIENT nicht erreichbar.

Wird die IP-Adresse, des lokalen Anfang der Weiterleitung, mit einem Hostnamen angegeben, muss dieser vom SSH_CLIENT aufgelöst werden können!

Bei der Angabe von -L ssh-client-eth0:10023:localhost:23 anstatt -L 192.168.1.1:10023:localhost:23 muss sich also für den SSH_CLIENT der Hostname 'ssh-client-eth0' mittels DNS oder /etc/hosts zu 192.168.1.1 auflösen lassen.

       Tunnel:  192.168.1.1:10023 --------> 127.0.0.1:23
  +----------+         +----------+         +----------+
  |  HOME_PC |---------|SSH_CLIENT|---/ /---|SSH_SERVER|
  +----------+         +----------+         +----------+
    telnet -------------------------------------^

Ein auf einem externen Host ausgeführter Telnet-Client, welcher sich mit dem port 192.168.1.1:10023 verbindet (z.B. telnet 192.168.1.1 10023) wird nun, wiederum für die Applikation transparent, auf den lokalen Port 23 (127.0.0.1:23) des SSH_SERVER verbunden.


-g -L 10023:localhost:23

Eine 'globale' Weiterleitung des Port 10023 auf dem SSH_CLIENT wird mit dem zusätzlichen Parameter '-g' im Aufruf von ssh -g -L 10023:localhost:23 user@ssh-server erreicht. Hierbei wird der Port 10023 von allen existierenden Interfaces (0.0.0.0:10023) des SSH_CLIENT an den internen Port 23 (127.0.0.1:23) des SSH_SERVER weitergeleitet.

              Tunnel:  0.0.0.0:10023 -----> 127.0.0.1:23
  +----------+         +----------+         +----------+
  |  HOME_PC |---------|SSH_CLIENT|---/ /---|SSH_SERVER|
  +----------+         +----------+         +----------+
    telnet -------------------------------------^

Somit kann auch jeder Telnet-Client der auf einem externen Host ausgeführt wird, welcher irgendwie mit dem SSH_CLIENT kommunizieren kann, die Weiterleitung zum SSH_SERVER mit folgendem Aufruf nutzen: telnet ssh_client 10023

Jedoch sollte man sich klar darüber sein das die ssh-Verschlüsselung nur zwischen SSH_CLIENT und SSH_SERVER stattfindet. D.h. die Verbindung zwischen HOME_PC und SSH_CLIENT ist hier nicht verschlüsselt und somit nicht geschützt!


-g -L 10023:172.16.2.2:23

Eine Weiterleitung muss nicht wirklich auf dem SSH_SERVER enden. Wird im Aufruf 'ssh -g -L 10023:localhost:23' die target_ip 'localhost', welche der SSH_SERVER letztendlich zu 127.0.0.1 auflöst, gegen eine externe IP-Adresse oder einen Hostnamen ersetzt, endet die Weiterleitung nicht auf dem SSH_SERVER sondern auf dem angegebenen Host. Mit dem Aufruf ssh -L 192.168.1.1:10023:work-pc:23 user@ssh-server kann also folgende Weiterleitung realisiert werden:

              Tunnel:  0.0.0.0:10023 ------------|-------> 172.16.2.2:23
  +----------+         +----------+         +----------+         +-----------+
  |  HOME_PC |---------|SSH_CLIENT|---/ /---|SSH_SERVER|---------|  WORK_PC  |
  +----------+         +----------+         +----------+         +-----------+
    telnet ----------------------------------------------------------^
home_pc: telnet ssh-client 10023

Hierbei kann jeder Telnet-Client der auf einem externen Host ausgeführt wird , welcher irgendwie mit dem SSH_CLIENT kommunizieren kann, die Weiterleitung zum WORK_PC mit folgendem Aufruf nutzen: telnet ssh-client 10023

Auch hier muss man sich jedoch klar darüber sein das die ssh-Verschlüsselung nur zwischen SSH_CLIENT und SSH_SERVER stattfindet. D.h. die Kommunikation zwischen HOME_PC und SSH_CLIENT sowie zwischen SSH_SERVER und WORK_PC sind in dieser Konstellation nicht verschlüsselt und somit nicht geschützt!

-R / remote port forwarding

-R [[source_ip]:]source_port:target_ip:target_port

Mit 'remote' ist in der Regel der ssh-Server gemeint, also der Rechner zu welchem die Verbindung zwischen Client (ssh) und Server (sshd) aufgebaut wird/wurde. Die allgemeine Syntax für ein remote port forwarding sieht wie folgt aus:

ssh -R [[source_ip]:]source_port:target_ip:target_port [<user>@]ssh_server_ip

ssh [user@]ssh_server_ip sind die Informationen für den Verbindungsaufbau zwischen Client und Server

-R [[source_ip]:]source_port:target_ip:target_port sind die Parameter und Optionen für die Weiterleitung.

Zu beachten ist hierbei das die optional anzugebende IP Adresse 'Source_ip' sich auf den remote Host bezieht. Gültige IP Adressen sind Local IP's (z.b. 127.0.0.1), Interface IP's (z.B. 192.168.1.1), 'alle' IP's (0.0.0.0).



shh_client: ssh -R 10023:localhost:23
             Tunnel:  127.0.0.1:23 <------- 127.0.0.1:10023
                       +----------+         +----------+
                       |ssh_client|---/ /---|ssh_server|
                       +----------+         +----------+
                              ^--------------- telnet
ssh_server: telnet localhost 10023

shh_client: ssh -R 10023:192.168.1.2:23

Tunnel: 192.168.1.2:23 <------------------- 127.0.0.1:10023

  +----------+         +----------+         +----------+
  |  home_pc |---------|ssh_client|---/ /---|ssh_server|
  +----------+         +----------+         +----------+
         ^------------------------------------ telnet
ssh_server: telnet localhost 10023

---

shh_client: ssh -R :10023:192.168.1.2:23               (only localhost)
shh_client: ssh -R *:10023:192.168.1.2:23              (all interfaces)
shh_client: ssh -R 172.16.2.1:10023:192.168.1.2:23     (only 172.16.2.1)

Tunnel: 192.168.1.2:23 <------------------- 127.0.0.1:10023 Tunnel: 192.168.1.2:23 <-------------------- 0.0.0.0:10023 Tunnel: 192.168.1.2:23 <------------------------ 172.16.2.1:10023

  +----------+         +----------+         +----------+*        +-----------+
  |  home_pc |---------|ssh_client|---/ /---|ssh_server|---------|  work_pc  |
  +----------+         +----------+         +----------+         +-----------+
         ^--------------------------------------------------------- telnet
work_pc: telnet 172.16.2.1 10023
  • (in ssh_server /etc/ssh/sshd_config: 'GatewayPorts clientspecified')

ssh_client: ssh -R 127.0.1.1:10023:localhost:23