- SSH-Tunneling transportiert TCP-Traffic über eine sichere SSH-Verbindung und wird genutzt, um eingeschränkte Pfade sicher zu öffnen, etwa für die Verschlüsselung von Legacy-Protokollen, den Zugriff auf Admin-Panels oder Verbindungen zu Servern hinter NAT
- Auf der Serverseite ist
AllowTcpForwarding yes erforderlich; um Ports auf Interfaces statt nur auf Loopback zu öffnen, sind die Einstellung GatewayPorts yes und ein Neustart des SSH-Servers nötig
ssh -J, ssh -L, ssh -R, ssh -D stehen jeweils für Jump Host, lokales Forwarding, Remote-Forwarding und dynamisches Forwarding auf Basis von SOCKS5
- Um einen Tunnel im Hintergrund aktiv zu halten, verwendet man
ssh -fN; die Erkennung von Verbindungsabbrüchen lässt sich über Heartbeat-Einstellungen wie ClientAliveInterval und ClientAliveCountMax steuern
- SSH-Tunneling unterstützt UDP nicht direkt, und bei TCP-over-TCP können Latenz- und Durchsatzprobleme auftreten; es ist daher eher ein Werkzeug zum Öffnen bestimmter TCP-Pfade als ein VPN-Ersatz
Situationen, in denen SSH-Tunneling sinnvoll ist
- SSH-Tunneling und Port Forwarding leiten TCP-Traffic über eine SSH-Verbindung vom Client zum Server oder vom Server zum Client weiter
- Es können TCP-Ports und UNIX-Sockets verwendet werden, die Beispiele konzentrieren sich jedoch auf TCP-Ports
- Typische Einsatzfälle lassen sich in Sicherheit, Fehlersuche und Verbindungsumgehung einteilen
- Sicherheit
- Unsichere Verbindungen wie FTP oder andere Legacy-Protokolle werden verschlüsselt
- Zugriff auf ein webbasiertes Admin-Panel über einen SSH-Tunnel mit Public-Key-Authentifizierung
- Statt zusätzlicher Ports wie 80/443 muss nur Port 22 geöffnet werden
- Fehlersuche
- Umgehung von Firewalls oder Content-Filtern
- Auswahl eines anderen Netzwerkpfads
- Verbindung
- Zugriff auf Server hinter NAT
- Zugriff aus dem Internet auf interne Server über einen Jump Host
- Lokale Ports im Internet verfügbar machen
Einstellungen, die vor Port Forwarding geprüft werden sollten
- Die Optionen in den Beispielen lassen sich je nach Umgebung kombinieren und anpassen
- Wenn keine
bind_address angegeben wird, ist der Standardwert localhost
- Lokale und entfernte Benutzer benötigen auf der jeweiligen Maschine die Berechtigung, Ports zu öffnen
- Für Ports
0-1024 sind ohne zusätzliche Konfiguration root-Rechte erforderlich
- Andere Ports können auch von normalen Benutzern eingerichtet werden
- Auch Client- und Netzwerk-Firewalls müssen passend zum Forwarding-Pfad geöffnet sein
- Auf dem SSH-Server muss Port Forwarding aktiviert sein
AllowTcpForwarding yes
- Oft ist dies standardmäßig aktiv, die Serverkonfiguration sollte aber geprüft werden
- Wenn ein Port auf ein Interface statt auf
127.0.0.1 weitergeleitet werden soll, muss auf dem SSH-Server GatewayPorts aktiviert werden
GatewayPorts yes
- Danach muss der SSH-Serverdienst neu gestartet werden
SSH-Jump-Hosts und mehrstufige Tunnel
ssh -J wird verwendet, um transparent über einen oder mehrere Hosts hinweg eine Verbindung zu einem entfernten Host herzustellen
ssh -J user@REMOTE-MACHINE:22 -p 22 user@10.99.99.1
- Wenn der Standardport
22 verwendet wird, kann die Portangabe weggelassen werden
- Wird REMOTE-MACHINE als Jump Host verwendet, lässt sich die Verbindung wie folgt prüfen
[user@REMOTE-MACHINE]$ ss | grep -i ssh
tcp ESTAB 0 0 167.135.173.108:ssh 192.160.140.207:45960
tcp ESTAB 0 0 10.99.99.2:49770 10.99.99.1:ssh
- Die Beispieladressen haben folgende Rollen
167.135.173.108: öffentliche IP von REMOTE-MACHINE
192.160.140.207: öffentliche IP von LOCAL-MACHINE
10.99.99.2: interne IP von REMOTE-MACHINE
10.99.99.1: interne IP von REMOTE-WEBAPP
- Mehrere Jump Hosts werden durch Kommata getrennt
ssh -J user@REMOTE-MACHINE:22,user@ANOTHER-REMOTE-MACHINE:22 -p 22 user@10.99.99.1
Lokales Port Forwarding
- Lokales Port Forwarding verwendet die Option
ssh -L
- Das erste Beispiel leitet
10.10.10.1:8001 auf LOCAL-MACHINE an localhost:8000 auf REMOTE-MACHINE weiter
ssh -L 10.10.10.1:8001:localhost:8000 user@REMOTE-MACHINE
- Das Zugriffslog des Webservers auf REMOTE-MACHINE, der nur an
127.0.0.1 gebunden ist, sieht dann so aus
127.0.0.1 - - [30/Dec/2022 18:05:15] "GET / HTTP/1.1" 200
- Diese Anfrage stammt von LOCAL-MACHINE
- Das zweite Beispiel leitet den lokalen Port
8001 über REMOTE-MACHINE an 10.99.99.1:8000 weiter
ssh -L 8001:10.99.99.1:8000 user@REMOTE-MACHINE
- Im Zugriffslog des Webservers auf REMOTE-WEBAPP erscheint die Anfrage als Zugriff von der internen IP von REMOTE-MACHINE
10.99.99.2 - - [30/Dec/2022 21:28:42] "GET / HTTP/1.1" 200
Remote-Port-Forwarding
- Remote-Port-Forwarding verwendet die Option
ssh -R
- Das Beispiel leitet
8000 auf REMOTE-MACHINE an lokales localhost:8001 oder 10.10.10.2:8001 weiter
ssh -R 8000:localhost:8001 user@REMOTE-MACHINE
ssh -R 8000:10.10.10.2:8001 user@REMOTE-MACHINE
- Es kann auch so konfiguriert werden, dass auf einem bestimmten Remote-Interface
10.99.99.2:8000 gelauscht wird
ssh -R 10.99.99.2:8000:10.10.10.2:8001 user@REMOTE-MACHINE
- Damit auf etwas anderem als dem Loopback-Interface gelauscht werden kann, muss auf dem SSH-Server
GatewayPorts yes aktiviert sein
Dynamisches Port Forwarding und SOCKS5
- Wenn mehrere Ports weitergeleitet werden, verwendet SSH das SOCKS-Protokoll
- SOCKS ist ein transparentes Proxy-Protokoll, und SSH nutzt die aktuelle Version SOCKS5
- Der Standardport eines SOCKS5-Servers ist
1080, wie in RFC 1928 definiert
- Der Client muss so konfiguriert sein, dass er den SOCKS-Proxy auf Anwendungs- oder Betriebssystemebene verwendet
- Das Beispiel mit
ssh -D öffnet einen SOCKS-Proxy auf 10.10.10.1:5555
ssh -D 10.10.10.1:5555 user@REMOTE-MACHINE
- Auf dem LOCAL-Client kann der Verbindungspfad mit
curl getestet werden
curl -L -x socks5://10.10.10.1:5555 brrl.net/ip
- Wenn alles korrekt funktioniert, wird die öffentliche IP von REMOTE-MACHINE zurückgegeben
SSH-TUN/TAP-Tunneling
- Mit dem Flag
-w kann ein bidirektionaler Tunnel erstellt werden
- Die Interfaces müssen vorher angelegt worden sein
- Für diese Methode gibt es den Hinweis, dass sie nicht getestet wurde
-w local_tun[:remote_tun]
Ausführung im Hintergrund und Beenden
- Um einen Tunnel nativ im Hintergrund auszuführen, wird
-fN verwendet
-f: im Hintergrund ausführen
-N: keine Shell öffnen
ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
- Alternativ können
screen oder andere Werkzeuge verwendet werden
- Ein im Hintergrund laufender SSH-Prozess wird über seine PID ermittelt und beendet
user@pleasejustwork:~$ ps -ef | grep ssh
[...]
user 19255 1 0 11:40 ? 00:00:00 ssh -fN -L 8001:127.0.0.1:8000 user@REMOTE-MACHINE
[...]
kill 19255
SSH-Verbindung aufrechterhalten und neu verbinden
- Es gibt mehrere Möglichkeiten, eine SSH-Verbindung aktiv zu halten
- Heartbeat-Optionen für Timeouts können auf dem Client, dem Server oder auf beiden Seiten gesetzt werden
ClientAliveInterval sendet zur Aufrechterhaltung der Verbindung alle n Sekunden eine Anfrage
ClientAliveInterval 15
ClientAliveCountMax ist die Anzahl der Heartbeat-Anfragen, die gesendet werden, bevor die Verbindung beendet wird, wenn von der Gegenseite keine Antwort kommt
ClientAliveCountMax 3
3 ist der Standardwert; bei 0 wird das Beenden der Verbindung deaktiviert
- In dieser Beispielkonfiguration wird die Verbindung nach etwa 45 Sekunden ohne Antwort getrennt
- Für automatische Wiederverbindungen nach einem Verbindungsabbruch können
autossh, Skripte oder Cronjobs verwendet werden
Einschränkungen und Sicherheitshinweise
-
UDP
- SSH ist für die korrekte Entschlüsselung auf zuverlässige Übertragung angewiesen
- UDP bietet diese Zuverlässigkeit nicht und wird in SSH-Tunneln daher nicht unterstützt und nicht empfohlen
- Es gibt Methoden für UDP over SSH tunneling, allerdings mit dem Hinweis, dass sie nicht getestet wurden
-
TCP-over-TCP
- Durch den Overhead sinkt der Durchsatz und die Latenz steigt
- Bei Verbindungen mit Paketverlust oder hoher Latenz kann es zu TCP meltdown kommen
- Weitere Informationen bietet dieser Artikel zu TCP over TCP
- Bei der zeitweisen Nutzung von OpenVPN-over-TCP war der Durchsatz niedriger als mit UDP, der Betrieb aber stabil; das Ergebnis hängt stark von der Konfiguration ab
-
Grenzen als VPN-Ersatz
- SSH-Tunneling kann zwar wie ein VPN verwendet werden, für bessere Performance ist jedoch meist ein VPN besser geeignet
-
Sicherheitsrisiken
- Wenn diese Funktion nicht benötigt wird, wird empfohlen, sie zu deaktivieren
- Angreifer können SSH-Tunneling und Port Forwarding nutzen, um Firewalls und andere Sicherheitsmaßnahmen zu umgehen
-
Referenzdokumente
1 Kommentare
Hacker-News-Kommentare
Im Jahr 2024 ist es besser, statt lange SSH-Befehle direkt auszuschreiben, LocalForward, RemoteForward und ProxyJump in
~/.ssh/configzu konfigurieren.Das spart viel Zeit, wenn man mit
ssh,scpoderrsyncauf entfernte Server zugreift, die über mehrere zwischengeschaltete SSH-Verbindungen erreichbar sind.Zum Beispiel kann man
jump-host-1,jump-host-2undjump-host-3perProxyJumpverketten und sich dann per Alias mittarget-serververbinden.LocalForward 0.0.0.0:8080 0.0.0.0:80leitet den entfernten Port 80 auf den lokalen Port 8080 weiter, undRemoteForward 0.0.0.0:9022 0.0.0.0:22leitet SSH-Anfragen, die auf dem entfernten Port 9022 ankommen, an den lokalen Port 22 weiter.Bei
LocalForwardundRemoteForwardist links der Zielserver und rechts lokal; außerdem gibt es den Tipp, stattlocalhostoder127.0.0.1lieber0.0.0.0zu verwenden.ssh_config-Tipp: Im Heimnetz oder im selbst gehosteten VPN ist es nützlich, direkt per SSH auf jedes Gerät zuzugreifen und außerhalb automatisch über einen Jump Host zu gehen.Mit etwas wie
Match host *.example.org exec "getent ahosts router.example.org | grep -q ^10.0.0.1"kann man zuerst anhand der Router-Adresse erkennen, ob man zu Hause bzw. im VPN ist, und falls die MAC-Adresse perarpnicht dem erwarteten Wert entspricht,ProxyJump jump.example.orgverwenden lassen.Die Reihenfolge ist wichtig: Erst Heim-/VPN-Netzwerk erkennen, dann nur im externen Fall den Jump Host anwenden.
Wenn man etwa kurzlebige VPS nutzt, um SSH als SOCKS-Proxy zu verwenden und Geoblocking zu umgehen, oder wenn man vorübergehend einem anderen Team hilft und einmalig auf einen Server muss, auf den man sonst nie zugreift, sind Kommandozeilenoptionen wohl besser.
0.0.0.0zu verwenden kann riskant sein.Damit kann der Port auf allen Netzwerk-Interfaces geöffnet werden, und besonders wenn auf dem entfernten Server keine Firewall aktiv ist, setzt man womöglich etwas dem gesamten Internet aus.
Für häufig genutzte Tunnel oder Port-Weiterleitungen ist eine Konfigurationsdatei gut, aber für einmalige oder seltene Aufgaben sind Kommandozeilenoptionen wahrscheinlich besser.
Ich suche nach einer Art GitOps-ähnlicher Lösung für einen einzelnen Benutzer auf mehreren Maschinen, die Konfigurationen etwa von GitHub holt, ohne dass dafür dauerhaft ein separater Server laufen muss.
bash-/fish-Funktionen gebaut, sodass ich mir nur die minimalen Argumente merken muss.Wenn ich es vergesse, schaue ich einfach in die dokumentierte Funktionsdefinition.
In dem absurden Unternehmensumfeld, in dem ich arbeite, ist SSH-Tunneling unverzichtbar.
Wegen der Bürokratie kann es Wochen dauern, Zugriffsrechte zu bekommen, Ports öffnen zu lassen oder Ausnahmen bei Firewall/VPN zu erhalten.
Der Artikel erwähnt
-D, erklärt aber seine Möglichkeiten nicht ausreichend.Wenn man
ssh -D 8888 someserverausführt und im Browser den SOCKS-Proxy auflocalhost:8888setzt, wird der gesamte Browser-Traffic übersomeservergeroutet.Firefox ist dabei sehr nützlich, weil man diese Einstellung dort immer noch vornehmen kann, ohne die Systemstandardwerte zu ändern.
Als ich dann in ein Unternehmen kam, konnte ich wegen IP-Allowlists nicht einmal eine SSH-Verbindung zu irgendeinem Server im Internet aufbauen; das war so unerquicklich, dass ich sogar nach Wegen gesucht habe, einen HTTP-Tunnel zu bauen und einen von mir kontrollierten Server auf die Allowlist zu bekommen, und am Ende habe ich einfach den Job gewechselt.
Solche Einschränkungen existieren aus einem Grund, und ihre Umgehung kann wie ein Mangel an Fachwissen über die Abläufe und die Sicherheit der Organisation wirken – oder wie deren Missachtung.
Wenn es Wochen oder Monate dauert, Zugriff zu erhalten, dann muss man eben so lange warten; schließlich will niemand dafür verantwortlich sein, eine Hintertür zu vertraulichen Informationen zu öffnen oder die Sicherheit zu beeinträchtigen.
Der dreckigste SSH-Tunneling-Hack, den ich je um 3 Uhr morgens gemacht habe, war die Verbindung von drei Rechenzentren.
Drei Standorte in derselben Metropolregion hingen zwar am übergeordneten Internet, aber wegen seltsamer Routing-Policies konnte A nur B erreichen, und nur B konnte C erreichen.
Am Ende musste ich rsync + SSH-Tunnel + Schlüssel + Routing-Tricks zusammenwürfeln, um Daten von A über B nach C zu verschieben, und nachdem ich den Befehl ein paarmal wie eine Bestellung angepasst hatte, war es fast magisch zu sehen, wie am Ende alles auf einmal funktionierte.
Heute wäre völlig klar, wie ich das machen würde, aber damals war ich noch Anfänger; es war ein großer Erfolg, und ich erinnere mich noch an den Adrenalinkick, als ich bestätigt bekam, dass die Synchronisierung abgeschlossen war.
~/.ssh/configund ProxyJump kann man praktisch über beliebig viele Stufen wie A, B, C, D, E weiterhüpfen.Die Details der Visualisierung sind gut.
Gerade im Networking würde ich mir viel mehr Werkzeuge wünschen, die Traffic auf niedrigeren Verbindungsebenen visuell darstellen.
Natürlich zeigen sie nur statische Konzepte; die meisten Netzwerkhersteller bieten zwar ebenfalls irgendeine Form der Traffic-Visualisierung an, aber meist bleibt es bei einzelnen Metriken oder Grafiken.
Wenn ein Linux-Server oder ein IoT-Gerät hinter einer Firewall steht, keine feste IP hat und man trotzdem per SSH darauf zugreifen möchte, kann man einen Tunneling-Dienst wie https://sshreach.me verwenden.
Ich habe Tunneling über Jahre ziemlich oft genutzt, kannte aber die Option
-Jnicht.Statt jedes Mal wieder 30 Minuten mit der Einrichtung zu verbringen, wenn ich alle paar Monate einmal einen Tunnel brauche, hätte ich gern ein visuelles Tool, das solche Tunnel für mich zusammenstellt.
Es wird erklärt, dass TCP-over-TCP den Overhead erhöht, den Durchsatz senkt, die Latenz steigert und bei Paketverlust oder Verbindungen mit hoher Latenz wie Satellitennetzen zu einem TCP-Meltdown führen kann
Bei SSH-Tunneln ist das in der Praxis jedoch kein Problem, solange kein TAP/TUN verwendet wird
Der Grund ist, dass SSH den TCP-Stream entpackt und weiterleitet
Wenn allerdings mehrere Kanäle verwendet werden, kann die Performance durch Head-of-Line-Blocking sinken
Vor etwa 15 Jahren habe ich SSH-Tunnel gelernt, um die Firewall des Uni-Netzwerks zu umgehen, und musste den Standardport auf 443 ändern
Seitdem nutze ich sie weiterhin für weit mehr als nur zum Umgehen von Firewalls
Mit
sshuttleist Tunneling deutlich bequemerMit
sshuttle -r user@host 10.0.0.0/8wird zum Beispiel der Bereich10/8automatisch getunnelt und verhält sich praktisch wie ein VPN über SSHIch frage mich, ob SSH selbst eine Redirect-Funktion hat
Zum Beispiel so, dass A sich per SSH zu B verbinden will, B aber mitteilt, stattdessen C zu verwenden, und A sich dann transparent direkt mit C verbindet, sodass B nicht mehr im eigentlichen Datenpfad bleibt
Meine Firewall bzw. mein Router leitet DHCP Option 67 nicht korrekt weiter und sendet immer seine eigene Adresse, daher musste ich eine virtuelle IP bzw. entsprechende Regeln einrichten, damit PXE-Boot-Traffic auf diesem Port, der zur Router-IP geht, zum eigentlichen PXE-Boot-Server geroutet wird
Andernfalls kann man einfach die Jump-Funktion verwenden:
ssh -J B CWenn B nicht im Pfad sein muss und eine direkte Verbindung zu C möglich ist, kann man sich einfach direkt mit C verbinden; wenn das nicht geht, muss B ohnehin als Hop dazwischenliegen
Mit etwas mehr Kontext zum Problem gäbe es vielleicht eine passendere Lösung
Bei einigermaßen eingebetteten Hosts kann DNS das „Routing“ übernehmen, aber in diesem Fall muss die Host-Key-Fingerprint-Prüfung selbst gehandhabt werden