Ich betreibe diesezwei Befehledie ganze Zeit, um eine Verbindung zu meiner RDS-Instanz auf AWS herzustellen, die durch eine Firewall geschützt ist (also tunnele ich durch die EC2-Instanz), und zwar so:
Befehl 1: Tunnel öffnen (im Hintergrund ausführen)
ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &
Befehl 2: Verbindung zur Datenbank über Tunnelport herstellen:
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
das ist super, aber ich würde beides gerne in einer einzigen Funktion unterbringen. Aber bei mir hat nichts funktioniert:
Versuch 1: Ausführen ohne Hintergrundmaterial:
function db()
{
ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub &
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
}
sagt mir einfach dies:
$proddb
[1] 62924
psql: could not connect to server: Connection refused
Is the server running on host "127.0.0.1" and accepting
TCP/IP connections on port 6666?
obwohl der ursprüngliche Befehl im Hintergrund läuft:
ps aux | grep host
(standard input):435:abdullah 62924 0.0 0.0 4315660 5828 s006 S 3:06PM 0:00.03 ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub
und wenn ich unmittelbar danach den nächsten Befehl ausführe, erfolgt die Verbindung zur Datenbank problemlos!
PGPASSWORD=password psql dbname -U user -h ip_address -p port;
user=>
wie bekomme ich das hin?
Antwort1
Der erste Befehl hatte nicht genug Zeit, einen Tunnel aufzubauen, als der zweite Befehl ausgeführt wurde, und gab daher die Meldung „Verbindung abgelehnt“ aus.
Benutzen Sie diese Option nicht &
, sondern verwenden Sie stattdessen die Option-f
:
-f
fordert ssh auf, kurz vor der Befehlsausführung in den Hintergrund zu gehen. Dies ist nützlich, wenn ssh nach Passwörtern oder Passphrasen fragt, der Benutzer dies aber im Hintergrund möchte. Dies impliziert -n. Die empfohlene Methode zum Starten von X11-Programmen auf einem Remote-Standort ist etwas wie ssh -f host xterm.
Wenn die Konfigurationsoption ExitOnForwardFailure auf „yes“ eingestellt ist, wartet ein mit -f gestarteter Client, bis alle Remote-Portweiterleitungen erfolgreich eingerichtet wurden, bevor er sich in den Hintergrund versetzt.
Um all dies zusammenzufassen, ersetzen Sie die SSH-Zeile in der Funktion durch:
ssh -o ExitOnForwardFailure=yes -f -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub
Auf diese Weise wird beim mehrmaligen Ausführen der Funktion kein (multiple-1) nutzloses SSH ausgeführt.
Es ist auch möglich, es durch einen kurzen Remote-Sleep-Befehl zu ersetzen -N
. Auf diese Weise gibt es keinen langlebigen, inaktiven SSH-Befehl, der gesucht werden muss, wenn er beendet werden muss. SSH wartet immer noch auf das Ende der Tunnelnutzung, bevor es beendet wird, sodass die kurze Verzögerung kein Problem darstellt:
ssh -o ExitOnForwardFailure=yes -f -L port:host:5432 user@$ip -i ~/.ssh/key.pub sleep 15
Antwort2
Diese Lösung von @AB kann auch verwendet werden, um einen „Jump-Server“ zwischen DMZ (Internet oder Edge-Endpunkte) und MZ (Backend) mit SSH-Port-Forward-Tunnel zu Backend-Hosts zu erstellen, zum Beispiel:
(alle entsprechenden Ports müssen per Firewall-Eingabeaufforderung geöffnet werden)
desthost_ip ist die Ziel-IP für den Dienst, auf den zugegriffen wird. Daran sollte ein Antwortprozess gebunden sein, z. B. Tomcat, Webapp usw.
Am DMZ-Rand:
ssh -o ExitOnForwardFailure=yes -f -L localhost_ip:port:desthost_ip:port user@dest_ip -i xyz.key sleep 15
Wenn also localhost auch eine öffentliche IP hat (vorausgesetzt, desthost hat einen https-basierten Dienst ausgeführt), kann so etwas funktionieren:
https://public_ip_of_localhost:port
Dadurch sollte die Dienstwebseite desthost_ip:port aufgerufen werden.
ssh -o ExitOnForwardFailure=yes -f -L 192.168.1.199:8001:192.168.2.10:8081 [email protected] -i xyz.key sleep 15
Und
https://192.168.1.199:8001
oder
https://public_ip_for_192.168.1.199:8001
ruft die Serviceseite auf auf 192.168.2.10:8081
.