SSH Portforwarding: DynDNS Alternative

DynDNS ist eine bekannte, aber umständliche Lösung, seinen heimischen Rechner vom Internet aus überall erreichen zu können.
Bedeutet, man hat nachher eine Domain, die immer auf die aktuelle öffentliche IP des Rechners auflöst. Dazu muss man

  • sich bei einem dyn-DNS Dienst registrieren
  • Portforward einrichten im Router
  • Dyn-DNS Updates einrichten im Router

uvm...
Nimmt man den Rechner irgendwo hin mit, klemmt ihn dort ans Internet, ist er nicht öffentlich erreichbar. Logischerweise geht das nicht, der Router kann ja nicht einfach woanders angeschlossen werden.

Warum kompliziert, wenn es auch einfach geht?
export AUTOSSH_GATETIME=0; autossh -fNR 2222:localhost:22 user@linuxbox.tld


Eine Zeile. Mehr ist nicht erforderlich. Das in den Crontab rein, und der Rechner wird sich automatisch bei jedem Neustart permanent mit dem Server verbinden, dort seinen SSH Port weiterleiten. Selbst Verbindungsabbrüche sind belanglos, diese wird von autossh automatisch wiederhergestellt.

Zur Syntax:

Local Port Forwarding
-L [bind_addr_local:]local_port:bind_addr_remote:remote_port


Remote Port Forwarding
-R [bind_addr_remote:]remote_port:bind_addr_local:local_port


Proxy (TCP SOCKS5), der Vollständigkeit halber:
ssh -D [bind_addr_local:]local_port


Die Option "GatewayPorts" muss in der /etc/ssh/sshd_config auf yes gesetzt bzw. eingefügt werden.
GatewayPorts
Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd(8) binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be ''no'' to force remote port forwardings to be available to the local host only, ''yes'' to force remote port forwardings to bind to the wildcard address, or ''clientspecified'' to allow the client to select the address to which the forwarding is bound. The default is ''no''.
Auszug aus man sshd_config

Zum SSH-Portforwarding braucht man als Gegenpart einen Zugang zu einem öffentlichen Linuxserver, oder man kennt jemanden, der irgendwo eine Linuxbox stehen hat 😉.

Beispiel Remote Port Forwarding, auf der lokalen Maschine:
ssh -R 1234:localhost:22 someuser@linuxbox.tld


Hier wird Port 1234 auf der Linuxbox an localhost:22 weitergeleitet, auf dem der sshd listen sollte.

Ergibt auf dem Server:
user@host / # netstat -plunt 
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN 2293/sshd: user
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2262/sshd
tcp6 0 0 :::1234 :::* LISTEN 2293/sshd: user
tcp6 0 0 :::22 :::* LISTEN 2262/sshd


Von überall aus kann sich nun à
ssh local_user@linuxbox.tld -p 1234

auf der lokalen Maschine eingeloggt werden.

Remote Port Forwarding ist also nützlich, wenn ich einen lokalen Service remote bereitstellen möchte.

Läuft auf dem Server irgendein Dienst, der z.B. nur auf localhost sein listen macht, so kann dieser lokal bereitgestellt werden:
ssh -L 3307:localhost:3306

Leitet beim Verbinden mit localhost:3307 auf die MySQL (3306) Datenbank auf dem Server weiter.

Möchte man die Portforwards nicht öffentlich preisgeben:
ssh -R [localhost:]1234:localhost:22 user@linuxbox (*oder GatewayPorts no)
ssh -L 12345:localhost:1234 user@linuxbox
ssh -p 12345 localhost

In diesem Beispiel (Syntax ungetestet)

  1. bindet sich der SSHD der lokalen Maschine an den localhost der Linuxbox
  2. loggt sich ein user (von unterwegs) in die Linuxbox ein, forwarded den SSHD der lokalen Maschine, der schon auf localhost der Linuxbox listened, auf seinen localhost
  3. ssh auf localhost


Zum Schluß möchte ich noch erwähnen, dass mit local/reverse Port Forwarding sehr einfach ein Reverse Proxy eingerichtet werden kann, der den Ursprungsort eines Services verschleiert und so eine zusätzliche Hürde für Angreifer darstellen kann.

Update 19.11.2017
root@client ~ # cat /etc/ssh/ssh_config | grep Alive
ServerAliveInterval 15
ServerAliveCountMax 3

root@server ~ # cat /etc/ssh/sshd_config | grep Alive
ClientAliveInterval 300

Der default Alive Count ist 3, Interval allerdings 0 (deaktiviert).
Per default gibt es keinen keep-alive bei SSH Verbindungen. Rebootet man z.B. den Client/Server, schlägt selbst mit autossh die erneute Verbindung fehl, da der entsprechende Port noch auf dem Server für eine tote TCP-Verbindung offengehalten wird.
Und einen Port kann man nur einmal belegen.