Implementierung von lokalem und remoteem SSH-Port-Forwarding für Tunneling
Ermöglichen Sie sicheren Netzwerkzugriff und Firewall-Umgehung mittels SSH-Port-Forwarding. Diese umfassende Anleitung beschreibt die praktische Implementierung sowohl lokaler (`-L`) als auch entfernter (`-R`) SSH-Tunneling-Techniken. Lernen Sie die wesentliche Syntax, verstehen Sie die Hauptunterschiede zwischen dem Zugriff auf entfernte Dienste und dem Freigeben lokaler Dienste, und sehen Sie klare Beispiele für Aufgaben wie die Sicherung von Datenbankverbindungen oder das Teilen von Entwicklungsumgebungen. Enthält bewährte Methoden für die Erstellung dauerhafter, sicherer Hintergrundtunnel mit schlüsselbasierter Authentifizierung.
Implementierung von lokalem und remoteem SSH-Port-Forwarding für Tunneling
SSH-Port-Forwarding ist eines dieser Werkzeuge, an die man erst denkt, wenn eine Firewall, ein privates Subnetz oder ein umständliches Anbieternetzwerk den einfachen Weg blockiert. Dann wird es zur schnellsten sauberen Lösung. Sie können es nutzen, um eine Datenbank über einen Bastion-Host zu erreichen, eine private Admin-Seite von Ihrem Laptop aus zu testen oder einen lokalen Entwicklungsserver für eine Maschine freizugeben, die Ihren Laptop nicht direkt erreichen kann.
Die grundlegende Idee ist einfach: SSH öffnet einen Listening-Port auf einer Seite der Verbindung und leitet den Datenverkehr durch die verschlüsselte SSH-Sitzung zu einem Ziel auf der anderen Seite. Was die Leute oft verwirrt, ist die Richtung. Lokales Forwarding mit -L ermöglicht es Ihrer Maschine, etwas in der Nähe des SSH-Servers zu erreichen. Remote-Forwarding mit -R ermöglicht es etwas in der Nähe des SSH-Servers, etwas in der Nähe Ihrer Maschine zu erreichen.
Lokales Forwarding: Einen entfernten Dienst auf Ihren Laptop bringen
Verwenden Sie lokales Forwarding, wenn der benötigte Dienst vom SSH-Server aus erreichbar ist, aber nicht von Ihrer Workstation.
ssh -L 15432:db.internal.example:5432 [email protected]
Nachdem diese Verbindung hergestellt ist, hört Ihr Laptop auf 127.0.0.1:15432. Wenn Sie psql, DBeaver oder eine Anwendungskonfiguration auf diesen lokalen Port verweisen, sendet SSH den Datenverkehr an bastion.example.com, und der Bastion öffnet eine Verbindung zu db.internal.example:5432.
Lesen Sie den Befehl von links nach rechts:
lokaler Port auf meiner Maschine : Zielhost, wie vom SSH-Server gesehen : Zielport
Dieses "wie vom SSH-Server gesehen" ist wichtig. Wenn die Datenbank nur innerhalb des privaten Netzwerks db.internal.example heißt, muss Ihr Laptop diesen Namen nicht auflösen. Der Bastion tut das. Wenn die Datenbank nur auf localhost auf dem Bastion hört, verwenden Sie stattdessen:
ssh -L 15432:127.0.0.1:5432 [email protected]
Lokales Forwarding ist normalerweise die sicherere Standardeinstellung, da der Listening-Port auf Ihrer Workstation liegt. Standardmäßig bindet OpenSSH lokal weitergeleitete Ports an die Loopback-Schnittstelle, sodass andere Maschinen in Ihrem WLAN oder Büronetzwerk den Tunnel nicht nutzen können. Sie können es explizit angeben:
ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]
Vermeiden Sie die Bindung an 0.0.0.0, es sei denn, Sie möchten den Tunnel wirklich mit anderen Hosts teilen. Ein Befehl wie dieser macht Ihren Laptop zu einem Proxy für die private Datenbank für jeden, der Port 15432 auf Ihrem Laptop erreichen kann:
ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]
Das kann in einem Labor nützlich sein. Auf einer normalen Workstation ist es selten das, was Sie wollen.
Remote-Forwarding: Einen lokalen Dienst über den Server freigeben
Remote-Forwarding dreht die Lauschseite um. Verwenden Sie es, wenn ein Dienst auf Ihrer Maschine läuft, aber jemand oder etwas in der Nähe des SSH-Servers ihn erreichen muss.
ssh -R 18080:127.0.0.1:3000 [email protected]
Dies fordert public.example.com auf, auf Port 18080 zu lauschen. Verbindungen zu diesem Port werden über SSH zurück zu 127.0.0.1:3000 auf Ihrem Laptop geleitet. Dies ist praktisch, wenn Sie einen Webhook-Empfänger testen, eine temporäre Demo teilen oder einen Callback von einem Staging-System debuggen, das Ihren Laptop nicht direkt anrufen kann.
Es gibt eine häufige Überraschung: Remote weitergeleitete Ports binden standardmäßig normalerweise an Loopback auf dem SSH-Server. Das bedeutet, dass curl http://127.0.0.1:18080 funktioniert, wenn es auf public.example.com ausgeführt wird, aber http://public.example.com:18080 von Ihrem Browser möglicherweise nicht.
Um einen remote weitergeleiteten Port für andere Maschinen erreichbar zu machen, muss der SSH-Server dies erlauben. In /etc/ssh/sshd_config ist die relevante Einstellung üblicherweise:
GatewayPorts clientspecified
Dann können Sie eine öffentliche Bindung anfordern:
ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]
Verwenden Sie dies mit Vorsicht. Sie veröffentlichen einen lokalen Dienst über den Server. Setzen Sie eine Firewall davor, verwenden Sie einen hohen zufälligen Port und setzen Sie keine Admin-Tools, Entwicklungsdatenbanken oder nicht authentifizierte Apps dem Internet aus.
Tunnel langweilig und zuverlässig halten
Für einen langlebigen Tunnel möchten Sie normalerweise keine Shell auf dem entfernten Host:
ssh -N -L 15432:db.internal.example:5432 [email protected]
-N bedeutet "keinen entfernten Befehl ausführen". Fügen Sie Keepalives hinzu, wenn der Tunnel NAT, VPN oder Cloud-Load-Balancer überquert, die inaktive TCP-Sitzungen beenden:
ssh -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 15432:db.internal.example:5432 \
[email protected]
Für unbeaufsichtigte Nutzung bevorzugen Sie einen systemd-User-Service, autossh oder Ihren Prozess-Supervisor gegenüber einem nackten ssh -f-Befehl. Das Ausführen im Hintergrund mit -f funktioniert, aber es macht fehlgeschlagene Starts und veraltete Tunnel schwerer erkennbar.
ssh -fN -L 15432:db.internal.example:5432 [email protected]
Wenn Sie -fN verwenden, testen Sie denselben Befehl zuerst ohne -f. Passwortabfragen, unbekannte Host-Key-Abfragen und Portkonflikte sind im Vordergrund viel einfacher zu diagnostizieren.
Fehlerbehebungs-Checkliste
Wenn ein Tunnel verbunden ist, die Anwendung aber immer noch fehlschlägt, überprüfen Sie jeden Hop, anstatt zu raten.
Bestätigen Sie zuerst, dass der lokale Listener existiert:
ss -ltnp | grep 15432
Testen Sie dann das Ziel vom SSH-Server aus:
ssh [email protected] 'nc -vz db.internal.example 5432'
Wenn das fehlschlägt, ist SSH-Forwarding nicht das Problem. Der Bastion kann den Dienst nicht erreichen, der Name wird dort nicht aufgelöst, eine Sicherheitsgruppe blockiert den Port oder der Dienst ist an die falsche Schnittstelle gebunden.
Wenn der Listener nicht startet, ist der lokale Port möglicherweise bereits belegt:
lsof -iTCP:15432 -sTCP:LISTEN
Wenn Remote-Forwarding mit einer Meldung wie remote port forwarding failed fehlschlägt, blockiert der Server möglicherweise TCP-Forwarding. Überprüfen Sie AllowTcpForwarding in sshd_config und prüfen Sie, ob der angeforderte Port bereits belegt ist.
Sicherheitsgewohnheiten, die es wert sind, beibehalten zu werden
Verwenden Sie schlüsselbasierte Authentifizierung und schränken Sie das Konto ein, das für Tunnel verwendet wird. Für einen dedizierten Tunnelbenutzer können Sie begrenzten Shell-Zugriff, Firewall-Regeln und SSH-Optionen wie PermitOpen oder PermitListen kombinieren, je nach benötigter Richtung. Diese Kontrollen verhindern, dass ein Bequemlichkeitstunnel zu einem breiten Netzwerkzugang wird.
Benennen Sie Tunnel in Ihren Notizen oder Runbooks nach Absicht, nicht nur nach Befehl. "Laptop 15432 zu Produktions-Reporting-Replikat über Bastion" ist einfacher zu auditieren als eine mysteriöse ssh -L-Zeile in der Shell-Historie.
Lokales Forwarding hilft Ihnen, nach innen zu gelangen. Remote-Forwarding ermöglicht es anderen, zu Ihnen zurückzugelangen. Sobald dieser Unterschied klar ist, werden die meisten SSH-Tunneling-Probleme zu einer Frage der Überprüfung, welche Seite lauscht, welche Seite das Ziel auflöst und welche Firewall dazwischen sitzt.
Einige reale Muster, die Sie sehen werden
Ein häufiges Produktionsmuster ist der Datenbank-Wartungstunnel. Sie haben ein Reporting-Replikat in einem privaten Subnetz, einen Bastion-Host mit strengem SSH-Zugriff und ein Analysten-Tool auf Ihrem Laptop. Lokales Forwarding passt sauber:
ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]
Die Anwendung auf Ihrem Laptop sollte 127.0.0.1 verwenden, nicht den privaten Datenbank-Hostnamen. Wenn das Tool auf SSL-Hostnamen-Überprüfung gegen den Datenbank-Host besteht, müssen Sie möglicherweise mit dem Datenbank-Hostnamen verbinden und einen lokalen Hosts-Eintrag hinzufügen oder den Client mit dem richtigen SSL-Modus konfigurieren. Der Tunnel bewegt nur TCP-Bytes; er schreibt keine Datenbankprotokolldetails um.
Ein weiteres Muster ist ein temporärer Webhook-Empfänger:
ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]
In dieser Version ist der weitergeleitete Port absichtlich nur vom Gateway selbst nutzbar. Sie könnten dann einen Staging-Dienst auf dem Gateway konfigurieren, der http://127.0.0.1:19090/hook aufruft. Dies ist sicherer, als den Port für das gesamte Netzwerk zu veröffentlichen.
Für eine kurze öffentliche Demo verwenden Sie eine öffentliche Bindung nur nachdem Sie eine Firewall-Regel hinzugefügt haben:
ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]
Schränken Sie dann das Gateway ein:
sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp
Ohne diese Einschränkung kann jeder, der das Gateway erreichen kann, den weitergeleiteten Dienst ausprobieren.
Was SSH-Tunneling nicht löst
SSH-Forwarding ist kein Ersatz für Dienstauthentifizierung. Wenn die Datenbank lokale Verbindungen ohne Passwort akzeptiert, kann ein Tunnel diese schwache Vertrauensgrenze weiter ausdehnen als beabsichtigt. Wenn eine lokale Entwicklungs-App keine Anmeldeseite hat, kann Remote-Forwarding sie unverändert veröffentlichen.
Es macht auch kein unzuverlässiges Ziel zuverlässig. Wenn der Bastion den internen Namen nicht auflösen kann, der Dienst ausgefallen ist oder eine Sicherheitsgruppe den Pfad blockiert, kann der Tunnel trotzdem erfolgreich aufgebaut werden, während die Anwendung fehlschlägt. Deshalb ist das Testen vom SSH-Server aus so nützlich.
Schließlich sind Tunnel leicht zu vergessen. Ein veralteter Tunnel auf einem gemeinsamen Jump-Host kann einen unerwarteten Port offen lassen. Für alles Langlebige setzen Sie den Befehl in eine Servicedatei mit einem klaren Namen, Besitzer und Neustartrichtlinie. Für alles Temporäre schließen Sie es, wenn die Arbeit erledigt ist, und überprüfen Sie, ob der Listener mit ss -ltnp verschwunden ist.