Leiten Sie den lokalen Port oder die Socket-Datei an die Remote-Socket-Datei weiter

24

Kurze Frage - Ich verwende zwei Linux-Boxen, eine auf meinem eigenen Desktop und die andere auf meinem VPS. Aus Sicherheitsgründen habe ich mich auf der VPS-Seite für Socket-Verbindungen zu MySQL ( /var/run/mysqld/mysql.sock) entschieden. Ich weiß, dass ich so tunneln kann: ssh -L 3307:127.0.0.1:3306 [email protected]Wenn ich den Remote-SQL-Server so einrichte, dass er auf einen Port lauscht, möchte ich aber wissen, ob ich ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sockdamit zwei Sockets tunneln kann und nicht zwei Ports?

Eine durchaus akzeptable Lösung wäre auch, einen lokalen Port an die Remote-Socket-Datei weiterzuleiten, aber wo möglich versuche ich, keine TCP-Server auf der Remote-Box laufen zu lassen.

(und ja, ich weiß, tcp wäre einfacher).


quelle
Wenn der Grund, warum Sie kein TCP auf der mySQL-Box verwenden möchten, Sicherheitsbedenken (z. B. Remoteangriffe usw.) zugrunde liegt, können Sie natürlich auch eine Firewall verwenden. Wenn dies nicht ausreicht, lassen Sie mySQL nur 127.0.0.1 abhören Für seine TCP-Verbindungen können Sie dann problemlos durch SSH tunneln. Wenn nicht, unterstütze ich die unten stehende Socat-Lösung.
Mattias Ahnberg
lwn.net/Articles/609321 OpenSSH 6.7 bringt Socket Forwarding
Hubbitus
@ Hubbitus ist diese Funktion jetzt verfügbar. Wenn ja, können Sie eine Beispielantwort geben?
CMCDragonkai
Dieser Kommentar war in Antwortform, wurde aber von jemandem in einen Kommentar umgewandelt. Und wie ich sehe, schlagen Sie unten bereits eine Antwort vor.
Hubbitus

Antworten:

35

Leiten Sie eine lokale Steckdose auf Anfrage weiter

  • Richten Sie die SSH-Authentifizierung mit öffentlichem Schlüssel ein
  • socatAn beiden Enden installieren
  • Erstellen Sie lokal ein Verzeichnis für Ihre Sockets, auf das andere Benutzer keinen Zugriff haben.
export SOCKET_DIR=~/.remote-sockets
mkdir -p $SOCKET_DIR
socat "UNIX-LISTEN:$SOCKET_DIR/mysqld.sock,reuseaddr,fork" \
EXEC:'ssh user@server socat STDIO UNIX-CONNECT\:/var/run/mysqld/mysqld.sock'

dann

mysql -S $SOCKET_DIR/mysqld.sock -u mysqluser -p

gestohlen von der Weiterleitung von Unix-Domain-Sockets mit ssh und socat

ijk
quelle
Das ist großartig und sollte die akzeptierte Antwort sein.
John Smith Optional
32

Zu der Zeit, als die Frage gestellt wurde, war es wirklich unmöglich, aber heutzutage ist es möglich.

Sie können sowohl UNIX => TCP als auch UNIX => UNIX weiterleiten.

Beispielsweise:

ssh \
  -R/var/run/mysql.sock:/var/run/mysql.sock \
  -R127.0.0.1:3306:/var/run/mysql.sock \
  somehost

Es ist seit OpenSSH 6.7 möglich.

Igor Chubin
quelle
1
Ich habe es geschafft, meinen lokalen Socket mit dem obigen ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
Befehl
11

Ich habe das nicht getan, aber ich würde es mit socat versuchen . vielleicht so etwas wie:

ssh [email protected] -L 9999:localhost:9999 "socat TCP-LISTEN:localhost:9999 UNIX-CONNECT:/var/run/mysqld/mysql.sock"
socat UNIX-LISTEN:/path/to/local/socket TCP:localhost:9999

wieder habe ich so etwas noch nie gemacht.

Javier
quelle
Ich werde es versuchen und dich wissen lassen, wie es geht. Ich habe die TCP-basierte Implementierung verwendet.
Ich kann es im Moment nicht zum Laufen bringen, aber trotzdem +1 für die Idee, ich mag es. Ich werde es Sie wissen lassen, wenn ich es behebe.
+1 sieht aus wie ein nützliches Dienstprogramm.
Warner
5

Seit ssh 6.7 wird kein socat mehr benötigt. Sie können Unix-Domain-Sockets wie folgt direkt weiterleiten:

ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

Weitere Informationen: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160

CMCDragonkai
quelle
Ich fand dies auch nützlich, um als anderer Benutzer eine Verbindung zu einem lokalen Socket herzustellen. Auf diese Weise kann ich Client-Programme für einen Server-Prozess ausführen, bei dem bestimmte Benutzer-IDs (Verbindungen von eigenen Job-Läufern) getrennt werden.
Warbo
Weiterleiten eines Sockets an denselben Computer, aber ein anderes Verzeichnis, das von einem anderen Benutzer gesteuert wird. Verwenden Sie sshd, um den Zugriff zu authentifizieren. Was ist dein Usecase?
CMCDragonkai
Verzeichnisberechtigungen / -zugriff sind kein Problem. Ein bestimmter Daemon löscht vielmehr alle Verbindungsversuche von Benutzern in einer bestimmten Gruppe (angeblich, um zu verhindern, dass Neulinge verwirrt werden). Mit ssh können diese Benutzer (über den Tunnel-Socket) eine Verbindung herstellen, als ob sie ein Benutzer wären, der nicht zu dieser Gruppe gehört, und daher nicht getrennt werden.
Warbo
Interessant, lustig, wie du den Nix-Daemon meinst, ich beschäftige mich auch damit. Ich frage mich, warum nix-daemon Verbindungen zu Benutzern in einer bestimmten Gruppe beendet. Ist das eine Sicherheitskonfigurationssache? Oder verwandt mit: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai
Gemäß der Festschreibungsmeldung soll eine "versehentliche" Verwendung verhindert werden. Ich habe es hier
hochgebracht
2

Eine weitere Modifikation von @mpontes / @ Javiers Antwort darauf

ssh user@remoteserver -L 9999:localhost:9999 'socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

Reiniger

ssh user@remoteserver -L 9999:localhost:9999 '
  socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock&
  pid=$!
  trap "kill $pid" 0
  while echo -ne " \b"; do
    sleep 5
  done
'

PROS

  1. Funktioniert auf openssh früher als 6.7 (wie CentOS 7)
  2. Beendet socat bei der SSH-Beendigung, anstatt erneut auf den Remote-Server zugreifen zu müssen
  3. Ermöglicht nicht öffentliches SSH-Login (im Gegensatz zur ijk-Lösung)

Feature

  1. Da die -fOption nicht verwendet wird, können Sie entweder einen öffentlichen Schlüssel verwenden und über im Hintergrund ausführen &oder sich interaktiv anmelden und Strg + Z verwenden und $!die PID auf dieselbe Weise speichern.

CONS

  1. Die -fOption ssh kann nicht einfach verwendet werden , da die pid von ssh auf diese Weise verloren geht. Diese Methode basiert auf der Ausführung im Vordergrund und Strg + C zum Beenden.
  2. Weitaus komplizierter

Erläuterung

  • socat ...& - Führen Sie socat im Hintergrund auf einem Remote-Server aus
  • pid=$! - Speichern Sie die PID
  • trap kill\ $pid 0- Bei kill $pidBash-Terminierung ausführen
  • while :; sleep... - in einer Endlosschleife sitzen
  • echo -ne \ \b- Echo Space gefolgt von Backspace. Dies schlägt fehl, sobald die Verbindung zum ssh getrennt wird. Mit a sleep 5bedeutet dies, dass socatbis zu 5 Sekunden nach ssh ausgeführt werden können

Hinweis: Eigentlich getestet mit Docker, Port 2375, /var/run/docker.sockund die Umgebungsvariable DOCKER_HOST='tcp://localhost:2375', sollte aber für mysql alle die gleiche Arbeit

Aktualisieren

Wenn Sie SSH-Steuerelemente verwenden , können Sie das -fFlag auf meine Weise verwenden. Fügen Sie einfach die folgenden Flags hinzu

-f -o ControlPath=~/.ssh/%C -o ControlMaster=auto

Und du wirst bekommen

ssh -f -o ControlPath=~/.ssh/%C -o ControlMaster=auto user@remoteserver -L 9999:localhost:9999 'set -m; socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

Jetzt können Sie alle gesteuerten Sitzungen mit beenden

ssh -o ControlPath=~/.ssh/%C -O exit remoteserver

Die -oOptionen können in Ihrer .ssh/configDatei gespeichert werden, oder Sie können stattdessen -S verwenden (Sie benötigen jedoch weiterhin -o ControlMaster).

Andy
quelle
Ich verwende Skripts in einem Docker-Container, um Code für andere Hosts bereitzustellen. Ihre Verbindungslogik ist erstaunlich, endet jedoch mit dem Ende der Bash-Sitzung. Dies verhindert, dass ich docker run ... connect.shanrufe, um den Tunnel einzurichten, gefolgt von docker run ... deploy.sh. Ich habe versucht nohup, &und disownsie scheinen zu brechen, socatindem sie schließen stdoutund auslösen kill. Irgendwelche Ideen für Optimierungen, um diesen Fall zu unterstützen (dh immer noch nah dran, wenn SSH eine Verleugnung überlebt)?
Claytond
OKAY. Dies funktioniert tatsächlich gut (w / -fund & disown) in einem Terminal. Anscheinend wird das Problem durch das Skript "Wrapper" erstellt. Ich würde mich über eine Eingabe freuen, aber ich suche jetzt nach angemesseneren Fragen und Antworten.
1.
@claytond Ich weiß nicht genau, was Sie tun, aber ja, alle anderen Befehle werden beendet, wenn PID 1 eines Containers endet. In Ihrem Bereitstellungsskript-Szenario verwende ich normalerweise den Befehl "deploy" und schreibe einen Eintrittspunkt für meinen Container image, das sagt "if $ 1 (the command) == deploay then" führe die ssh-Befehle und die deploy-Befehle aus und beende dann, wodurch die ssh-Verbindung geschlossen wird. Sie können auch docker run ... connect.shund docker exec {container name/id} deploy.sh, also spielen sie zusammen.
Andy
Du hast recht. Ich benutze tatsächlich execeinen bereits vorhandenen runContainer und die SSH-Pipe blieb nach dem Beenden nicht bestehen exec. Ich habe klargestellt, dass dies auf eine Eigenart bei der Ausführung von Skripten zurückzuführen ist. Wenn ich den Aufruf in ein eigenes Skript verschoben und aufgerufen habe nohup <script.sh> & disown, überlebt er die Fertigstellung von exec.
2.
1

Um auf Javiers Antwort einzugehen, funktioniert das für mich:

ssh -f [email protected] -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

Sie müssen forkin der Lage sein, mehrere Male eine Verbindung herzustellen, ohne zu sterben, sobald Sie die erste Verbindung schließen. Außerdem können Sie mit socat über die bindOption eine Adresse angeben, an die gebunden werden soll , und nicht als Adresse vor dem Port.

Verbinden Sie sich danach localhost:9999wie gewohnt mit. Dann, um den Tunnel abzureißen:

ssh -f [email protected] "killall socat"

(oder etwas Ähnliches, Sie können ausführlichere Dinge tun, bei denen die PID von socat beibehalten wird)

mpontes
quelle
1

Ja, Sie können socat verwenden.

Führen Sie zuerst den TCP-Tunnel mit SSH durch. Dann benutze socat wie folgt:

socat unix-listen: /var/run/mysqld/mysqld.sock,fork,unlink-early tcp: 127.0.0.1: 3306

Geben Sie dann die Berechtigungen für den neu erstellten Socket (möglicherweise chmod 777).

user190133
quelle
Dies ist seit OpenSSH 6.6 möglich.
ysdx
3
chmod 777: Nein nein Nein Nein Nein! Niemals rennen chmod 777. Es ist praktisch nie erforderlich! Nicht einmal zu "Testzwecken". Wenn die Datei lesbar ist, ist sie lesbar. Wenn es von dem useroder dem group, der darauf schreiben muss, beschreibbar ist, dann ist es beschreibbar. Es gibt absolut keine Notwendigkeit, jedem Schreibzugriff zu erteilen, und chmodes ist genau so, wie multinationale Unternehmen gehackt werden, wenn man es auf etwas Vernünftiges zurücklässt. Tu es einfach nicht. Je. Ich habe eine Einführung in Unix-Berechtigungen geschrieben . Bitte lies es!
Martin Tournoij