Transférer le port local ou le fichier socket vers le fichier socket distant

24

Question rapide - je lance deux boîtiers Linux, l'un mon propre bureau et l'autre mon VPS. Pour des raisons de sécurité du côté VPS, j'ai opté pour des connexions socket à MySQL ( /var/run/mysqld/mysql.sock). Je sais que je peux tunneler comme ceci: ssh -L 3307:127.0.0.1:3306 [email protected]si je configure le serveur SQL distant pour écouter sur un port, mais ce que je veux savoir, est-ce que je peux faire quelque chose comme: ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.socktunneler ainsi deux sockets, par opposition à deux ports?

Une solution parfaitement acceptable serait également de transférer un port local vers le fichier de socket distant, mais dans la mesure du possible, j'essaie de ne pas avoir de serveurs TCP fonctionnant sur le boîtier distant.

(et oui, je sais que tcp serait plus facile).


la source
Si la raison pour laquelle vous ne souhaitez pas utiliser TCP sur la boîte mySQL est à cause de problèmes de sécurité (c.-à-d. Attaques à distance, etc.), vous pouvez bien sûr le pare-feu, et si cela ne suffit pas, faites en sorte que mySQL n'écoute que 127.0.0.1 pour ses connexions TCP, vous pouvez facilement passer par SSH. Sinon, je soutiens la solution socat ci-dessous.
Mattias Ahnberg
lwn.net/Articles/609321 OpenSSH 6.7 apportera la redirection de socket
Hubbitus
@Hubbitus cette fonctionnalité est-elle disponible maintenant? Si oui, pouvez-vous fournir un exemple de réponse?
CMCDragonkai
Ce commentaire était sous forme de réponse, mais converti en commentaire par quelqu'un. Et je vois maintenant que vous proposez déjà une réponse ci-dessous.
Hubbitus

Réponses:

35

Transférer une prise locale à la demande

  • Configurer l'authentification par clé publique SSH
  • Installer socataux deux extrémités
  • créer localement un répertoire pour vos sockets, inaccessible aux autres utilisateurs.
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'

puis

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

volé lors du transfert de sockets de domaine Unix avec ssh et socat

ijk
la source
C'est génial et devrait être la réponse acceptée.
John Smith Facultatif
32

A l'époque, quand la question a été posée, c'était vraiment impossible, mais c'est possible de nos jours.

Vous pouvez à la fois: UNIX => TCP et UNIX => transfert UNIX.

Par exemple:

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

C'est possible depuis OpenSSH 6.7.

Igor Chubin
la source
1
J'ai réussi à transmettre mon socket local à un socket de serveur distant en utilisant ci-dessus et à exécuter le client Docker à distance (cela pourrait être fait directement par ssh, mais où est le plaisir :) :)ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
sdkks
11

je n'ai pas fait ça, mais j'essaierais avec socat . peut-être quelque chose comme:

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

encore une fois, je n'ai jamais rien fait de tel.

Javier
la source
Je vais essayer et vous faire savoir comment ça se passe. J'utilise l'implémentation basée sur TCP.
Je ne peux pas le faire fonctionner pour le moment mais +1 quand même pour l'idée, j'aime ça. Je vous ferai savoir si je le répare.
+1 ressemble à un utilitaire utile.
Warner
5

Plus besoin de socat depuis ssh 6.7. Vous pouvez transférer des sockets de domaine Unix directement comme:

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

Plus d'informations: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160

CMCDragonkai
la source
J'ai également trouvé cela utile pour se connecter à une prise locale en tant qu'utilisateur différent. Cela m'a permis d'exécuter des programmes clients sur un processus serveur qui déconnecte certains ID utilisateur (connexions provenant de ses propres exécuteurs de travaux).
Warbo
Transférer un socket vers la même machine, mais un répertoire différent contrôlé par un utilisateur différent, en utilisant sshd pour authentifier l'accès? Quelle est votre cas d'utilisation?
CMCDragonkai
Les autorisations / accès au répertoire ne sont pas un problème. Au contraire, un démon particulier supprime toutes les tentatives de connexion effectuées par les utilisateurs d'un certain groupe (censé éviter que les débutants ne se trompent). L'utilisation de ssh permet à ces utilisateurs de se connecter (via le socket tunnellisé) comme s'ils étaient un utilisateur n'appartenant pas à ce groupe, et donc de ne pas se déconnecter.
Warbo
Intéressant, drôle de voir comment vous entendez le démon nix, je traite également des problèmes à ce sujet. Je me demande pourquoi nix-daemon abandonne les connexions aux utilisateurs d'un certain groupe? Est-ce une chose de configuration de sécurité? Ou lié à: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai
Selon le message de validation, c'est pour empêcher une utilisation "accidentelle". Je l'ai apporté ici
Warbo
2

Une autre modification de la réponse de @mpontes / @ javier qui

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'

Nettoyeur

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
'

AVANTAGES

  1. Fonctionne sur openssh antérieur à 6.7 (comme CentOS 7)
  2. Tue socat lors de la terminaison ssh au lieu d'avoir à relancer ssh dans le serveur distant
  3. Permet une connexion ssh non publique (contrairement à la solution ijk)

Fonctionnalité

  1. Étant donné que l' -foption n'est pas utilisée, vous pouvez soit utiliser une clé publique et exécuter en arrière-plan via, &soit vous connecter de manière interactive et utiliser Ctrl + Z et l'utiliser $!pour stocker le pid.

LES INCONVÉNIENTS

  1. Impossible d'utiliser facilement l' -foption ssh, car vous perdrez le pid de ssh de cette façon. Cette méthode repose sur l'exécution au premier plan et sur Ctrl + C pour tuer.
  2. Beaucoup plus compliqué

Explication

  • socat ...& - exécuter socat en arrière-plan sur le serveur distant
  • pid=$! - stocker le pid
  • trap kill\ $pid 0- exécuter kill $pidsur la terminaison bash
  • while :; sleep... - asseyez-vous dans une boucle infinie
  • echo -ne \ \b- Espace d'écho suivi d'un retour arrière. Cela échoue dès que le ssh est déconnecté. Avec un sleep 5, cela signifie que socatpeut s'exécuter jusqu'à 5 secondes après ssh

Remarque: En fait , testé à l' aide docker, le port 2375, /var/run/docker.socket variable d'environnement DOCKER_HOST='tcp://localhost:2375', mais devrait fonctionner pour mysql tous les mêmes

Mise à jour

En utilisant les contrôles SSH , vous pouvez utiliser le -fdrapeau à ma façon, ajoutez simplement les drapeaux suivants

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

Et vous obtiendrez

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'

Vous pouvez maintenant terminer toutes les sessions contrôlées à l'aide de

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

Les -ooptions peuvent être enregistrées dans votre .ssh/configfichier, ou vous pouvez utiliser -S à la place (mais vous en aurez toujours besoin -o ControlMaster)

Andy
la source
J'utilise des scripts à l'intérieur d'un conteneur Docker pour déployer du code sur d'autres hôtes. Votre logique de connexion est incroyable mais se termine à la fin de la session bash. Cela m'empêche d'appeler docker run ... connect.shpour configurer le tunnel suivi de docker run ... deploy.sh. J'ai essayé nohup, &et , disownmais ils semblent briser socaten fermant stdoutet le déclenchement de la kill. Avez-vous des idées de modifications pour soutenir cette affaire (c'est-à-dire toujours fermée lorsque SSH ne fait que survivre à un reniement)?
claytond
D'ACCORD. Cela fonctionne très bien (w / -fand & disown) dans un terminal. Apparemment, le problème est créé par le script "wrapper". J'accueillerais volontiers vos commentaires, mais je recherche des questions et réponses plus appropriées maintenant.
claytond
@claytond Je ne sais pas exactement ce que vous faites, mais oui, toutes les autres commandes sont terminées lorsque le pid 1 d'un conteneur se termine. Ce que je fais généralement dans votre scénario de script de déploiement est d'utiliser la commande "déployer" et d'écrire un point d'entrée pour mon conteneur image qui dira "si $ 1 (la commande) == déployer alors" exécutez les commandes ssh et les commandes de déploiement, puis terminez, ce qui fermera la connexion ssh. Vous pouvez aussi docker run ... connect.sh, et docker exec {container name/id} deploy.sh, donc ils jouent ensemble.
Andy
Tu as raison. J'utilise actuellement execsur un runconteneur déjà et le tuyau SSH ne persistait pas après la execfin. J'ai précisé que c'était dû à une bizarrerie avec la façon dont les scripts sont exécutés. Si j'ai déplacé l'appel vers son propre script et que j'ai appelé nohup <script.sh> & disown, il survit à la fin de la exec.
claytond
1

En élaborant la réponse de Javier, cela fonctionne pour moi:

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

Vous avez besoin forkpour pouvoir vous connecter plusieurs fois sans mourir après avoir fermé la première connexion. De plus, la façon dont socat vous permet de spécifier une adresse à laquelle se lier se fait via l' bindoption, pas comme une adresse avant le port.

Après cela, connectez-vous localhost:9999normalement comme vous le feriez. Puis pour démonter le tunnel:

ssh -f [email protected] "killall socat"

(ou quelque chose de similaire, vous pouvez faire des choses plus élaborées qui impliquent de conserver le PID de socat)

mpontes
la source
1

Oui, vous pouvez utiliser socat.

Faites d'abord le tunnel TCP avec SSH. Utilisez ensuite socat comme ceci:

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

Donnez ensuite des autorisations à la nouvelle socket créée (chmod 777 peut-être)

user190133
la source
Cela est possible depuis OpenSSH 6.6.
ysdx
3
chmod 777: non non Non Non Non! Ne jamais courir chmod 777. Ce n'est pratiquement jamais nécessaire! Pas même à des "fins de test". Si le fichier est lisible, il est lisible. S'il est accessible en écriture par userou groupqui doit y écrire, il est accessible en écriture. Il n'y a absolument aucun besoin de donner à tout le monde des autorisations d'écriture, et oublier de chmodrevenir à quelque chose de sain est exactement la façon dont les multinationales sont piratées. Ne le fais pas. Déjà. J'ai écrit une introduction aux autorisations Unix . Lisez-le s'il vous plaît!
Martin Tournoij