SSH-Portweiterleitungen für autonome Agenten: sicherere Tunnel
SSH-Portweiterleitungen für autonome Agenten brauchen strenge Routenbegrenzungen, ablaufende Zugriffsrechte und Genehmigungsdatensätze, die einer Untersuchung nach einem Vorfall standhalten.

SSH-Portweiterleitungen für autonome Agenten brauchen ein strengeres Design als gewöhnlicher Entwicklerzugriff. Ein Tunnel kann eine Datenbank, ein Administrationspanel oder einen Staging-Dienst, die sonst nur auf localhost erreichbar wären, über einen einzigen SSH-Befehl für einen Agenten zugänglich machen. Hält der Agent weitreichende SSH-Zugangsdaten, ist der Tunnel nur ein Symptom. Das eigentliche Problem ist, dass niemand Ziel, Dauer oder Berechtigung hinter diesem Befehl begrenzt hat.
Ich habe erlebt, dass Teams einen Tunnel als «vorübergehend» bezeichneten, weil jemand ssh -L in einem Terminal eingegeben hatte. Danach lief das Terminal tagelang, sein Port wurde zur Abhängigkeit eines anderen Prozesses, und die Person, die ihn geöffnet hatte, war nicht erreichbar, als die Sicherheitsabteilung wissen wollte, warum ein produktionsnaher Dienst einen ungeklärten Listener hatte. Autonome Arbeit verschärft dieses Muster, weil ein Agent wesentlich konsequenter als ein abgelenkter Mensch Wiederholungen und neue Verbindungen versuchen und einen Tunnel weiterverwenden kann.
Der sichere Ansatz ist einfach: Geben Sie einem Agenten einen eng begrenzten Verbindungsweg, genehmigen Sie eine genau beschriebene zeitweilige Freigabe, protokollieren Sie genügend Kontext für eine spätere Rekonstruktion und machen Sie das Schließen zu einem erzwingbaren Ereignis statt zu einer Absicht.
Ein Tunnel verändert die Netzwerkerreichbarkeit, nicht nur das SSH-Verhalten
Eine SSH-Portweiterleitung erstellt auf einer Seite der SSH-Verbindung einen Listener und transportiert dessen Datenverkehr zu einem Ziel, das von der anderen Seite aus erreichbar ist. Dieser Listener ist ein Zugangsweg. Wer ihn nur als «SSH-Zugriff» prüft, übersieht den riskanten Teil: Wer kann sich verbinden, wo endet der Datenverkehr und was kann durch den Tunnel übertragen werden?
Angenommen, ein Agent läuft auf einem Build-Host und muss db-admin.internal.example auf Port 5432 abfragen. Ein lokales Forwarding kann diesen Dienst auf dem Build-Host als 127.0.0.1:15432 erscheinen lassen. Die Datenbank bleibt aus dem öffentlichen Internet verborgen, aber jeder Prozess auf diesem Host, der den Listener erreicht, kann nun eine Verbindung versuchen. Der SSH-Server wird außerdem zu einer autorisierten Route zur Datenbank.
Das kann vertretbar sein. Es ist nicht dasselbe, wie dem Agenten «SSH für Wartungsarbeiten» zu geben. Die Genehmigung sollte genau diese Route beschreiben:
- auslösender Workload und Host
- Listener-Adresse und Port
- Zielhost und Zielport
- Grund für die Route
- Ablaufzeit und genehmigende Person
Bei einem Remote-Forwarding befindet sich der Listener auf der jeweils anderen Seite. Verbindet sich ein Agent beispielsweise mit einem Bastion-Host und bittet ihn, auf Port 18080 zu lauschen, kann ein Prozess, der diesen Listener erreicht, Daten zurück zum Agent-Host senden. Remote-Forwarding überrascht Teams häufig, weil es einen Dienst hinter einer Firewall freigeben kann, ohne eine eingehende Firewall-Regel zu öffnen.
OpenSSH beschreibt diese Modi in ssh(1) getrennt: -L erstellt lokale Weiterleitungen, -R Remote-Weiterleitungen und -D einen SOCKS-Proxy. Diese Trennung ist im Betrieb hilfreich. Genehmigen Sie «Portweiterleitung» nicht als eine einheitliche Berechtigung. Jeder Modus erstellt einen anderen Listener und braucht andere Einschränkungen.
Lokales, remotes und dynamisches Forwarding brauchen unterschiedliche Entscheidungen
Ein lokales Forwarding passt meist zu einem Agent-Auftrag, wenn der Agent einen bekannten Dienst über einen kontrollierten Sprungserver benötigt. Der Listener liegt auf der Agent-Seite, während der SSH-Server eine Verbindung zum internen Ziel herstellt:
ssh -N \\
-L 127.0.0.1:15432:db-admin.internal.example:5432 \\
[email protected]
-N weist SSH an, keinen Remote-Befehl auszuführen. Dadurch wird die Verbindung nicht harmlos. Die Bind-Adresse 127.0.0.1 begrenzt den Listener auf den lokalen Host, während db-admin.internal.example:5432 das gewünschte Ziel angibt. Das sind getrennte Eigenschaften und beide müssen im Genehmigungsdatensatz auftauchen.
Ein Remote-Forwarding ist nur dann angemessen, wenn ausdrücklich ein Listener auf der entfernten Seite gewünscht ist:
ssh -N \\
-R 127.0.0.1:18080:127.0.0.1:8080 \\
[email protected]
Behandeln Sie einen entfernten Loopback-Listener nicht automatisch als sicher. Ein lokaler Prozess auf dem Bastion-Host kann deutlich mehr Zugriff haben als der Quellrechner des Agenten, und andere Nutzer eines gemeinsam verwendeten Bastion-Hosts können ihn möglicherweise erreichen. Prüfen Sie vor der Freigabe die Nutzer und lokalen Prozesse des entfernten Hosts.
Für autonome Agenten sollte dynamisches Forwarding standardmäßig verboten werden:
ssh -N -D 127.0.0.1:1080 [email protected]
Damit wird ein SOCKS-Listener gestartet. Der Client wählt Ziele später über SOCKS-Anfragen aus, statt im SSH-Befehl ein Ziel zu nennen. Diese Bequemlichkeit beseitigt die Zielgrenze, die Sie für unbeaufsichtigte Arbeit brauchen. Ein Prüfer kann keine einzelne Route genehmigen, und gewöhnliche SSH-Zielbeschränkungen können keine sinnvolle Allowlist für beliebigen SOCKS-Datenverkehr ausdrücken.
Lösen Sie dieses Problem nicht mit einem längeren Genehmigungsformular. Verbieten Sie dynamisches Forwarding für das Agent-Konto. Wenn die Aufgabe mehrere Ziele braucht, definieren Sie jede Weiterleitung einzeln oder setzen Sie einen zweckgebundenen Proxy mit eigener Authentifizierung und Protokollierung vor die Dienste.
Die Bind-Adresse entscheidet, wer den Listener verwenden kann
Die Bind-Adresse ist Teil der Sicherheitsentscheidung, weil sie bestimmt, welche Rechner eine Verbindung zum Tunnel-Listener herstellen können. Ein Forwarding an Loopback und eines an alle Schnittstellen kann dasselbe Ziel verwenden, aber völlig unterschiedliche Freigaben erzeugen.
Verwenden Sie bei lokalem Forwarding eine ausdrückliche Loopback-Adresse:
-L 127.0.0.1:15432:db-admin.internal.example:5432
Verlassen Sie sich nicht auf den Standardwert. OpenSSH bindet lokale Weiterleitungen normalerweise an Loopback, wenn keine Bind-Adresse angegeben wird. Eine explizite Adresse macht Prüfung, Protokolle und spätere Untersuchungen eindeutiger. Sie verhindert außerdem, dass eine spätere Änderung der Client-Konfiguration den Umfang des Listeners unbemerkt erweitert.
Das ist die gefährliche Variante:
-L 0.0.0.0:15432:db-admin.internal.example:5432
Sie veröffentlicht Port 15432 auf jeder IPv4-Schnittstelle des Client-Hosts. Jeder erreichbare Host kann den Tunnel versuchen. Ein Build-Runner in einem gemeinsam genutzten Subnetz kann so zu einer Brücke in eine interne Datenbank werden, obwohl die Datenbank selbst nur Verbindungen vom Bastion-Host akzeptiert.
Auch IPv6 braucht Aufmerksamkeit. ::1 ist Loopback, :: lauscht auf allen IPv6-Schnittstellen. Prüfen Sie beide Adressfamilien. Teams stellen manchmal fest, dass 127.0.0.1 sicher war, die Automatisierung aber über einen separaten Konfigurationsweg zusätzlich einen IPv6-Listener geöffnet hatte.
Bei Remote-Weiterleitungen kontrolliert der SSH-Server, welche Bind-Adressen er akzeptiert. In sshd_config beeinflusst GatewayPorts das Verhalten der Bind-Adresse. Lassen Sie GatewayPorts no aktiviert, sofern es keinen geprüften Grund für breitere entfernte Listener gibt. GatewayPorts clientspecified gibt einem Agent-Konto zu viel Kontrolle.
Prüfen Sie nach dem Öffnen einer Weiterleitung den Listener auf dem zuständigen Rechner:
lsof -nP -iTCP:15432 -sTCP:LISTEN
Die Ausgabe sollte einen ssh-Prozess mit einer Adresse wie 127.0.0.1:15432 oder ::1:15432 zeigen. Bei *:15432 stoppen Sie den Auftrag und prüfen Befehl und Client-Konfiguration. Dieser Befehl bestätigt nur die lokale Listener-Adresse. Er beweist nicht, dass die entfernte Seite auf das vorgesehene Ziel beschränkt ist.
Ein dediziertes SSH-Konto muss die erlaubte Route ausdrücken
Ein dediziertes SSH-Konto mit serverseitigen Einschränkungen ist die kleinste sinnvolle Grenze für Agent-Tunnel. Eine Client-Konfigurationsdatei kann nichts gegen einen Agenten erzwingen, der seine eigenen Argumente ändern kann. Legen Sie die Grenzen dort fest, wo der SSH-Server die Verbindung annimmt.
Beginnen Sie für ein Konto mit ausschließlich lokalem Forwarding mit einem Block wie diesem in sshd_config:
Match User agent-db-tunnel
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitTTY no
X11Forwarding no
AllowAgentForwarding no
AllowStreamLocalForwarding no
AllowTcpForwarding local
PermitOpen db-admin.internal.example:5432
GatewayPorts no
PermitUserEnvironment no
AllowTcpForwarding local erlaubt lokale Weiterleitungen und verweigert Remote-Weiterleitungen. PermitOpen benennt das Ziel, das dieses Konto anfordern darf. Das ist wichtig, weil ein lokaler Forwarding-Befehl sonst auf jeden Host und Port zeigen kann, der vom Bastion-Host aus erreichbar ist. Ohne PermitOpen könnte ein Agent, der die Datenbank benötigt, auch eine Weiterleitung zu einer Administrations-API, einem Cache, einem Metadatendienst oder einem weiteren SSH-Server anfordern.
Gehen Sie mit Hostnamen sorgfältig um. Der SSH-Server löst das Ziel auf, daher muss der Name in PermitOpen dort auflösbar sein. Verwenden Sie einen stabilen Namen, der Ihrer Infrastruktur gehört. Wenn sich ein DNS-Name auf beliebige Adressen ändern kann, wirkt die Konfiguration eng, während sich das tatsächliche Ziel unbemerkt verschiebt.
Das Handbuch sshd_config(5) beschreibt PermitOpen als Zielbeschränkung im Format host:port. Die Option macht aus dem Konto keine Policy-Engine. Sie erfüllt genau eine Aufgabe: Eine Weiterleitungsanfrage abzulehnen, deren Ziel nicht aufgeführt ist. Halten Sie das Kontodesign ebenso präzise.
Geben Sie dem Konto keine Shell, nur weil «der Agent sie nicht verwenden wird». Entfernen Sie die Möglichkeit stattdessen. Ein dediziertes Konto sollte für eine einzige Verbindungsrolle existieren. Konfigurieren Sie bei Bedarf einen erzwungenen Befehl für den autorisierten öffentlichen Schlüssel, der bei interaktiver Nutzung beendet wird. Testen Sie diese Entscheidung aber mit dem Forwarding-Verhalten Ihrer Umgebung. Manche Wrapper stören erwartete SSH-Sitzungen, und eine fehlerhafte Einschränkung führt unter Zeitdruck schnell dazu, dass jemand den gesamten Block entfernt.
Vermeiden Sie außerdem Agent-Forwarding. AllowAgentForwarding no verhindert, dass der verbundene Server den clientseitigen SSH-Agenten um Signaturen für Authentifizierungsanfragen bittet. Ein SSH-Tunnel-Konto soll Daten übertragen und nicht zum Sprungbrett für andere Hosts werden.
Für ein Ziel mit zwei legitimen Diensten listen Sie zwei ausdrückliche PermitOpen-Einträge auf. Verwenden Sie keinen Wildcard-Eintrag und ersetzen Sie das Konto nicht durch ein allgemeines Bastion-Konto, nur um ein weiteres Konto zu vermeiden. Ein zusätzliches Konto ist günstiger als die Erklärung, warum ein Code-Agent ein ganzes internes Subnetz erreichen konnte.
Temporär bedeutet erzwungenes Ablaufdatum und sauberes Schließen
Ein Tunnel ist nur dann temporär, wenn etwas anderes als gute Absichten ihn beendet. SSH hält eine Verbindung offen, bis der Client sie schließt, das Netzwerk ausfällt oder ein Timeout greift. Ein autonomer Agent kann einen Prozess nach Erfolg, Fehler oder Timeout eines Tests weiterlaufen lassen.
Geben Sie jedem Auftrag eine feste maximale Sitzungsdauer, die nicht im Ermessen des Agenten liegt. Ein Job-Runner kann dies, sofern verfügbar, mit timeout erzwingen:
timeout 20m ssh -N \\
-o ExitOnForwardFailure=yes \\
-o ServerAliveInterval=30 \\
-o ServerAliveCountMax=3 \\
-L 127.0.0.1:15432:db-admin.internal.example:5432 \\
[email protected]
ExitOnForwardFailure=yes verhindert, dass der Auftrag fortfährt, wenn SSH den gewünschten Listener nicht erstellen kann. Ohne diese Option meldet ein Agent möglicherweise einen verwirrenden Anwendungsfehler statt eines Problems beim Tunnelaufbau. Die ServerAlive-Einstellungen lassen SSH nach mehreren unbeantworteten Nachrichten beenden. Sie ersetzen nicht die Obergrenze von 20 Minuten.
macOS enthält den GNU-Befehl timeout standardmäßig nicht. Verwenden Sie die Timeout-Funktion Ihres Runners, einen überwachten Prozess mit Frist oder einen kleinen Wrapper, der TERM sendet und anschließend bestätigt, dass der Prozess beendet wurde. Ersetzen Sie eine fehlende Frist nicht durch einen Cronjob, der «alte SSH-Prozesse» beendet. Dabei werden unabhängige Aufgaben getroffen, und Sie können nicht nachweisen, welche Verbindung beendet wurde.
Der Auftrag sollte den Tunnel zusätzlich in seinem eigenen Aufräumpfad schließen. Behalten Sie für einen gestarteten Prozess seine PID, senden Sie nach Abschluss TERM, warten Sie kurz und prüfen Sie anschließend mit lsof oder ss, dass der Listener verschwunden ist. Die Frist fängt Abstürze ab, der Aufräumpfad kümmert sich um den normalen Abschluss.
Multiplexing braucht besondere Vorsicht. Mit ControlMaster und einem gemeinsamen ControlPath können mehrere SSH-Aufrufe dieselbe Master-Verbindung wiederverwenden. Für Agenten verwischt das Zuständigkeit und Ablauf: Ein Auftrag kann eine für einen anderen Auftrag genehmigte Verbindung übernehmen, und das Schließen eines Clients beendet möglicherweise nicht den Master. Deaktivieren Sie Multiplexing für das Tunnel-Konto oder erzeugen Sie pro genehmigtem Auftrag einen eindeutigen Control-Pfad.
Ein Wartungsablauf mit regelmäßigem Zugriff sollte regelmäßig wiederkehrende, jeweils begrenzte Sitzungen anfordern. Lassen Sie einen Tunnel nicht offen, weil ein neuer Aufbau unbequem erscheint. Die beim Aufbau gesparten Sekunden erzeugen bei jeder Untersuchung eines unerwarteten Zugriffs neue Unklarheit.
Eine Genehmigung muss eine rekonstruierbare Verbindung beschreiben
Ein Genehmigungsdatensatz sollte einem Prüfer zeigen, wer eine Route genehmigt hat, was sie geöffnet hat und ob sie innerhalb ihrer Grenze blieb. Ein allgemeiner Ticketkommentar wie «Agent-Zugriff genehmigt» ist kein Beleg. Er nennt weder Listener noch Ziel noch Dauer.
Erfassen Sie die Genehmigung, bevor der Tunnel startet. Halten Sie Identität und Zeitpunkt der genehmigenden Person, Auftrags- oder Lauf-ID, Identität des Agent-Prozesses, Quellrechner, dediziertes SSH-Konto und Fingerabdruck des öffentlichen Schlüssels fest. Erfassen Sie anschließend die Weiterleitung vollständig: Richtung, Bind-Adresse, Listener-Port, Zielhost, Zielport, Zweck und Ablauf.
Der Ergebnisdatensatz braucht eigene Felder. Dazu gehören, ob SSH die Weiterleitung erstellt hat, die Prozess-ID des Clients, Startzeit, endgültiger Exit-Status, Schließzeit und Schließgrund. Timeout, normales Aufräumen, Widerruf durch einen Operator und Netzwerkausfall haben bei einer Prüfung unterschiedliche Bedeutungen.
Verwenden Sie strukturierte Datensätze statt Prosa, aus der jemand Felder herauslesen muss:
{
"run_id": "run-7c31",
"approved_by": "oncall-engineer",
"approved_at": "2025-04-12T14:03:00Z",
"ssh_account": "agent-db-tunnel",
"direction": "local",
"listen": "127.0.0.1:15432",
"destination": "db-admin.internal.example:5432",
"expires_at": "2025-04-12T14:23:00Z",
"purpose": "run migration compatibility check"
}
Die Bezeichner in diesem Beispiel sind Platzhalter, keine zwingende Vorlage für Ihr Schema. Entscheidend ist die Disziplin: Ein Datensatz muss Person, Prozess, Route und Zeitfenster miteinander verbinden.
Lassen Sie nicht denselben Agenten die Genehmigung erzeugen und sie als menschliche Autorisierung behandeln. Der Agent kann erklären, warum er eine Verbindung braucht, aber ein Mensch oder ein separat kontrollierter Ablauf muss die Freigabeentscheidung treffen. Wenn eine Aktion routiniert genug für automatische Genehmigung ist, bilden Sie diese Entscheidung in einer eng begrenzten Auftragsdefinition mit Ablaufzeit ab und bewahren Sie die Regelversion auf, die sie erlaubt hat.
Genehmigungsmüdigkeit ist ein Designfehler. Wer jede Übertragung absegnen soll, erzeugt bedeutungslose Klicks. Eine Genehmigung pro temporärer, konkreter Route gibt dem Prüfer etwas Greifbares. Halten Sie die Anfrage kurz, aber nennen Sie Bind-Adresse und exaktes Ziel. Diese beiden Angaben erkennen überraschend viele fehlerhafte Anfragen.
Zugangsdaten außerhalb des Agenten und Berechtigungen außerhalb seines Prompts halten
Ein autonomer Agent sollte eine Verbindung anfordern und keinen privaten Schlüssel erhalten, mit dem er später beliebige Verbindungen herstellen kann. Sobald ein Agent einen weitreichenden SSH-Schlüssel in seiner Prozessumgebung oder seinem Arbeitsbereich besitzt, kann er ihn kopieren, einen anderen SSH-Client aufrufen, ihn nach dem genehmigten Auftrag weiterverwenden oder an ein nicht vorgesehenes Werkzeug übergeben. Ein Prompt mit «nur für die Datenbank verwenden» verhindert keine dieser Aktionen.
Ein besseres Design verwahrt SSH-Zugangsdaten in einer separaten Ausführungsgrenze. Der Agent übermittelt eine Aktion mit den Routenfeldern. Diese Grenze prüft die Verfügbarkeit des Tresors, die Autorisierung der Sitzung und gegebenenfalls die Genehmigung für die angeforderten Zugangsdaten. Sie führt die SSH-Aktion aus und gibt das Ergebnis zurück, ohne den privaten Schlüssel an den Agenten zu übergeben.
Sallyport verwendet dieses Modell unter macOS: Der mitgelieferte Helfer sp-ssh führt SSH-Aktionen aus, während die SSH-Schlüssel im verschlüsselten Tresor der App bleiben und den MCP-Agenten nicht erreichen.
Diese Unterscheidung ist bei der Untersuchung eines Fehlers wichtig. Die Verwahrung der Zugangsdaten beantwortet: «Konnte der Agent das Geheimnis anderswo wiederverwenden?» Die Routenbeschränkung beantwortet: «Konnte dieses Konto ein nicht genehmigtes Ziel erreichen?» Die Genehmigung beantwortet: «Wer hat genau diese Nutzung erlaubt?» Teams fassen diese Fragen oft zu einer Kontrolle zusammen und stellen später fest, dass ihr Audit-Log zwar die Nutzung eines Schlüssels, nicht aber die dadurch mögliche Route beschreibt.
Machen Sie die Anfrageschnittstelle enger als rohe SSH-Argumente. Akzeptieren Sie Felder wie destination_host, destination_port, listen_address, listen_port und max_duration. Lehnen Sie vom Client gelieferte Optionen ab, die Proxying, Weiterleitungsrichtung, Remote-Befehle, Identitätsdateien oder Control-Sockets ändern. Wer einen beliebigen ssh-Befehlsstring akzeptiert, überträgt die Policy-Auslegung an das Parsen von Zeichenketten. Das scheitert, sobald jemand -R, -D, ProxyCommand oder eine zweite Weiterleitung ergänzt.
Bieten Sie für einen Tunnel-Ablauf keine allgemeine Shell als Ausweg an. Der Agent muss ssh nicht interaktiv ausführen, wenn die Aktion aus einem einzigen begrenzten Kanal besteht. Enge Aktionen lassen sich leichter genehmigen und widerrufen.
Audit-Belege müssen einer feindseligen Prüfung standhalten
Tunnelprotokolle sind nur dann nützlich, wenn ein kompromittierter Agent oder lokaler Prozess sie nachträglich nicht umschreiben kann. Textdateien neben dem Agent-Arbeitsbereich sind bequem, beweisen aber wenig, wenn dieselbe Identität sowohl den Tunnelbefehl als auch dessen Historie bearbeiten kann.
Protokollieren Sie Genehmigung, Anfrage, Ausführungsergebnis und Schließergebnis als getrennte Ereignisse mit einer gemeinsamen Lauf-ID. Bewahren Sie die ursprünglichen Anfragefelder auf, statt nur eine dargestellte Befehlszeile zu speichern. Eine Befehlszeile kann Werte in einer Konfigurationsdatei verbergen oder Standardwerte auslassen, die den Listener beeinflusst haben.
Sammeln Sie bestätigende Datensätze aus mehreren Quellen. Die SSH-Protokolle des Bastion-Hosts können angenommene Authentifizierung und fehlgeschlagene Weiterleitungen zeigen. Der Job-Runner zeigt Prozesserstellung und Ende. Der Zieldienst kann eine Verbindung vom Bastion-Host protokollieren. Keiner dieser Belege erklärt allein das gesamte Ereignis, zusammen machen sie Widersprüche sichtbar.
Sallyport schreibt Sitzungs- und einzelne Aufrufjournale in ein verschlüsseltes, Hash-verkettetes Audit-Log. sp audit verify prüft diese Kette offline, ohne den Tresorschlüssel zu benötigen. Das ist stärker als eine Protokolldatei, die ein Agent-Prozess verändern kann, ersetzt aber keine schwachen Kontobeschränkungen.
Führen Sie die Prüfung im normalen Betrieb durch, nicht erst nach einem Vorfall. Eine manipulationssichere Kette zeigt, ob die aufgezeichnete Historie vollständig fortgesetzt wurde. Sie sagt nicht, ob Sie anfangs genügend Felder aufgezeichnet haben. Entscheiden Sie, was Sie an einem schlechten Tag wissen müssen, und sorgen Sie dafür, dass diese Felder vor Beginn der Verbindung ins Ereignis gelangen.
Widerrufen Sie den Weg, bevor Sie die Geschichte untersuchen
Wenn Sie einen falschen oder missbrauchten Tunnel vermuten, stoppen Sie zuerst den Verbindungsweg. Die Untersuchung kann einige Minuten warten. Eine offene Route kann in dieser Zeit Daten übertragen oder lateralen Zugriff ermöglichen.
Beenden Sie den Client-Prozess und bestätigen Sie, dass sein Listener verschwunden ist. Deaktivieren Sie das dedizierte SSH-Konto oder entfernen Sie seinen öffentlichen Schlüssel auf dem annehmenden Server. Wenn ein über den Tunnel übermitteltes Zugangsmittel einem nicht vertrauenswürdigen Prozess zugänglich gewesen sein könnte, rotieren Sie es nach dem Verfahren des jeweiligen Dienstes. Rotieren Sie nicht allein deshalb unabhängige Zugangsdaten, weil ein Tunnel existierte.
Sichern Sie danach die Belege: Genehmigungsdatensatz, angeforderte Route, Prozessprotokolle, SSH-Serverprotokolle, Verbindungsdaten des Zieldienstes und Schließergebnis. Verwenden Sie eine gemeinsame Zeitzone, vorzugsweise UTC. Bei Untersuchungen gehen viele Stunden verloren, wenn ein Runner lokale Zeit, ein Bastion-Host UTC und eine Anwendung Zeitstempel ohne Zeitzone verwendet.
Prüfen Sie vor der Einstufung als eingedämmt, ob ein zweiter Listener existiert. Untersuchen Sie auf dem Agent-Host den angeforderten Port und nahegelegene Weiterleitungsprozesse. Prüfen Sie auf dem Bastion-Host aktive SSH-Sitzungen und Authentifizierungsprotokolle des dedizierten Kontos. Suchen Sie am Ziel nach Verbindungen, die nach dem vorgesehenen Ablauf begonnen haben. Ziel ist es, verbliebene Zugangswege zu finden, nicht schnell eine aufgeräumte Geschichte zu erzählen.
Wenn eine menschliche Genehmigung die falsche Route ermöglicht hat, verbessern Sie zuerst die Anfrageschnittstelle. Eine schönere Prüfseite, die weiterhin beliebige SSH-Flags akzeptiert, wird denselben Fehler wiederholen. Wenn eine Serverbeschränkung versagt hat, testen Sie nach der Reparatur den exakt abgelehnten Befehl und bewahren Sie die Fehlermeldung auf. Kontrollen schaffen Vertrauen, wenn Sie bestätigen, dass sie genau die vorgesehene Route ablehnen.
Testen Sie Ablehnungspfade, bevor ein Agent vom Tunnel abhängt
Ein Tunnel-Design ist erst fertig, wenn Sie sowohl die genehmigte Verbindung als auch verbotene Varianten testen. Erfolgsfalltests finden Tippfehler. Ablehnungstests zeigen, ob die Grenze tatsächlich existiert.
Verwenden Sie ein Nichtproduktionskonto und versuchen Sie zunächst eine erlaubte Weiterleitung:
ssh -N -o ExitOnForwardFailure=yes \\
-L 127.0.0.1:15432:db-admin.internal.example:5432 \\
[email protected]
Versuchen Sie danach ein Ziel, das PermitOpen nicht erlaubt:
ssh -N -o ExitOnForwardFailure=yes \\
-L 127.0.0.1:15433:admin-api.internal.example:443 \\
[email protected]
Der zweite Befehl sollte beim Aufbau der Weiterleitung scheitern. Speichern Sie Clientausgabe und Serverprotokolleintrag. Versuchen Sie anschließend -R und -D; beide sollten bei einem Konto mit AllowTcpForwarding local fehlschlagen. Fordern Sie zuletzt einen Listener mit 0.0.0.0 an und bestätigen Sie, dass Ihre Anfrageschnittstelle ihn vor dem Start von SSH ablehnt oder die lokale Umgebung die zu verhindernde Freigabe tatsächlich verhindert.
Testen Sie den Ablauf mit einer kurzen Dauer. Starten Sie den erlaubten Tunnel, lassen Sie die Frist des Supervisors greifen und prüfen Sie drei Dinge: Der SSH-Prozess endet, lsof findet den Listener nicht mehr und der Schließdatensatz nennt die Frist, statt fälschlich einen normalen Abschluss zu behaupten. Diese kleine Übung findet verwaiste Prozesse, bevor Produktionsarbeit von einem Tunnel abhängt, der nie geschlossen wird.
Halten Sie sich bei Zeitdruck an eine einfache Regel: Ein autonomer Agent darf für seinen aktuellen Auftrag für eine begrenzte Zeit und unter einer benannten Genehmigung nur die unbedingt erforderliche Route erhalten. Wenn Sie diese Route nicht in einer Zeile benennen und ihr späteres Schließen beweisen können, hat der Agent mehr Netzwerkberechtigungen, als die Aufgabe rechtfertigt.
FAQ
Was ist der Unterschied zwischen lokalem und remote SSH-Port-Forwarding?
Ein lokales Forwarding lauscht auf dem Rechner, der SSH startet, und leitet Verbindungen durch den SSH-Server an ein Ziel weiter, das von diesem Server aus erreichbar ist. Bei einem Remote-Forwarding lauscht dagegen der SSH-Server und leitet den Datenverkehr durch den Client zurück. Behandeln Sie beide Varianten als Änderungen der Netzwerkerreichbarkeit, denn jede Richtung kann eine Grenze überschreiten, die Ihre Firewall nicht überschreiten sollte.
Ist ein SSH-Tunnel sicher, wenn er an 127.0.0.1 gebunden ist?
Nein. Eine Bindung an die Loopback-Adresse begrenzt, wer den lauschenden Port erreichen kann. Sie begrenzt aber nicht, welche Ziele der SSH-Server auf der anderen Seite erreichen darf. Beschränken Sie deshalb sowohl die Listener-Adresse als auch das erlaubte Ziel in der SSH-Kontenkonfiguration.
Sollte ein autonomer Agent ssh -D verwenden dürfen?
Dynamisches Forwarding erstellt einen SOCKS-Proxy. Der Client kann dadurch viele Ziele anfordern, statt nur einen benannten Dienst zu nutzen. Das macht die Prüfung, sinnvolle Protokollierung und Begrenzung mit gewöhnlichen SSH-Regeln schwierig. Geben Sie autonomen Agenten diese Möglichkeit nicht, außer Sie verfügen dafür über ein separates, streng kontrolliertes Gateway.
Wie beschränke ich ein SSH-Konto auf einen internen Dienst?
Verwenden Sie ein dediziertes Konto, deaktivieren Sie den Shell-Zugriff und die PTY-Zuweisung sowie das Agent-Forwarding. Erlauben Sie mit PermitOpen nur ausdrücklich benannte Host-Port-Paare. Legen Sie außerdem eine Sitzungsdauer außerhalb von SSH fest, denn eine SSH-Konfiguration entscheidet nicht, wann ein legitimer Tunnel enden soll.
Was sollte ein Genehmigungsdatensatz für einen SSH-Tunnel enthalten?
Protokollieren Sie die genehmigende Person, den gestarteten Agent-Prozess oder Workload, den Quellhost, das SSH-Konto, die Tunnelrichtung, die Listener-Adresse, den Zielhost und Zielport, den Öffnungszeitpunkt, den geplanten Ablauf und das Ergebnis der Schließung. Ein Eintrag mit nur «SSH genehmigt» hilft bei einer Untersuchung nicht weiter.
Wie lange sollte ein temporärer SSH-Tunnel geöffnet bleiben?
Verwenden Sie einen Tunnel pro Auftrag, wenn der Auftrag einen klaren Zweck und eine kurze Laufzeit hat. Lang laufende Tunnel lassen sich schwerer zuordnen, werden leicht von unabhängigen Aufgaben wiederverwendet und bleiben oft länger bestehen als die Änderung, die sie gerechtfertigt hat. Wenn ein Dienst dauerhafte Konnektivität braucht, bauen Sie einen verwalteten Zugriffsweg statt eine dauerhafte SSH-Sitzung als vorübergehend zu bezeichnen.
Verhindert AllowTcpForwarding local den Zugriff auf alle internen Hosts?
AllowTcpForwarding local erlaubt lokales Forwarding, blockiert aber Remote-Forwarding. Die Option beschränkt die Ziele nicht selbst. Kombinieren Sie sie deshalb mit PermitOpen-Einträgen wie host:port. Legen Sie diese Einschränkungen auf dem Konto fest, das die Verbindung annimmt, nicht nur in einer Client-Konfiguration, die ein Agent ändern kann.
Kann ich einem KI-Agenten ein SSH-Passwort statt eines Gateways geben?
Ein Passwort gibt einem Agenten keinen begrenzten und prüfbaren Aktionsweg. Meist kann der Agent damit eine Shell öffnen, Daten kopieren, beliebige Weiterleitungen einrichten und ohne brauchbaren Genehmigungsdatensatz handeln. Verwenden Sie ein Konto, dessen serverseitige Regeln genau die eine Verbindung erlauben, die Sie freigeben wollen.
Wie kann ich prüfen, ob eine SSH-Portweiterleitung tatsächlich geschlossen wurde?
ss oder lsof zeigen, ob lokal ein Prozess lauscht, und die SSH-Debugausgabe kann die angeforderte Weiterleitung bestätigen. Beides beweist nicht, dass der Server nur ein genehmigtes Ziel akzeptiert hat oder dass der Tunnel später geschlossen wurde. Prüfen Sie zusätzlich die Serverkonfiguration, den Sitzungsdatensatz und die Verbindungsprotokolle des Zieldienstes.
Was soll ich tun, wenn ein Agent den falschen SSH-Tunnel öffnet?
Beenden Sie den SSH-Client-Prozess, widerrufen oder deaktivieren Sie sein dediziertes Konto und entfernen Sie den Zugriff auf dem Zieldienst, wenn Sie Missbrauch vermuten. Bewahren Sie anschließend die Genehmigungs- und Verbindungsdatensätze auf, bevor Sie weitere Einstellungen ändern. Rotieren Sie nicht automatisch alle Zugangsdaten, außer der Tunnel hat ein Geheimnis transportiert, das die andere Seite hätte abfangen können.