461 votes

Un tunnel SSH via plusieurs sauts

La mise en place d'un tunnel de données via SSH est assez simple :

ssh -D9999 username@example.com

configure le port 9999 sur votre localhost comme un tunnel vers example.com mais j'ai un besoin plus spécifique :

  • Je travaille localement sur localhost
  • host1 est accessible à localhost
  • host2 n'accepte que les connexions provenant de host1
  • Je dois créer un tunnel à partir de localhost a host2

En fait, je veux créer un tunnel SSH "multi-sauts". Comment puis-je le faire ? Idéalement, j'aimerais faire cela sans avoir besoin d'être superutilisateur sur tout des machines.

2 votes

Pour quoi l'avez-vous utilisé ? Je veux l'utiliser pour la procuration de chaussettes. Cela fonctionnera-t-il ?

2 votes

Oui, vous devriez pouvoir utiliser la connexion tunnelée comme un proxy SOCKS, à moins que host2 refuse le transfert

0 votes

J'ai pensé à créer une enveloppe sur SSH qui permettrait de mettre en place ce système en utilisant plusieurs fois ProxyCommand.

424voto

Mika Fischer Points 4839

Vous avez essentiellement trois possibilités :

  1. Tunnel de localhost a host1 :

    ssh -L 9999:host2:1234 -N host1

    Comme indiqué ci-dessus, la connexion de host1 a host2 ne seront pas sécurisés.

  2. Tunnel de localhost a host1 et de host1 a host2 :

    ssh -L 9999:localhost:9999 host1 ssh -L 9999:localhost:1234 -N host2

    Cela ouvrira un tunnel de localhost a host1 et un autre tunnel de host1 a host2 . Cependant, le port 9999 a host2:1234 peut être utilisé par n'importe qui sur host1 . Cela peut être un problème ou non.

  3. Tunnel de localhost a host1 et de localhost a host2 :

    ssh -L 9998:host2:22 -N host1
    ssh -L 9999:localhost:1234 -N -p 9998 localhost

    Cela ouvrira un tunnel de localhost a host1 par lequel le service SSH sur host2 peut être utilisé. Ensuite, un deuxième tunnel est ouvert de localhost a host2 à travers le premier tunnel.

Normalement, je choisirais l'option 1. Si la connexion de host1 a host2 doit être sécurisé, choisissez l'option 2. L'option 3 est principalement utile pour accéder à un service sur host2 qui n'est accessible que depuis host2 lui-même.

1 votes

Je veux faire de la navigation de cette façon. Laquelle est la meilleure ? J'ai essayé la première mais ça n'a pas marché. J'ai configuré un proxy socks dans mon navigateur localhost:1234 mais pas de chance. :( s'il vous plaît aidez..

2 votes

@prongs essayez l'option 3

1 votes

Existe-t-il un moyen de transférer ma clé publique de localhost, à travers le tunnel de l'hôte 1, sur l'hôte 2 ?

195voto

kynan Points 3086

Il existe un excellente réponse expliquant l'utilisation de la ProxyCommand directive de configuration pour SSH :

Ajoutez ceci à votre ~/.ssh/config (voir man 5 ssh_config pour plus de détails) :

Host host2
  ProxyCommand ssh host1 -W %h:%p

Puis ssh host2 va automatiquement passer par le tunnel host1 (fonctionne aussi avec la redirection X11, etc.).

Cela fonctionne également pour une classe entière d'hôtes, par exemple identifiés par un domaine :

Host *.mycompany.com
  ProxyCommand ssh gateway.mycompany.com -W %h:%p

Mise à jour

OpenSSH 7.3 introduit a ProxyJump ce qui simplifie le premier exemple en

Host host2
  ProxyJump host1

3 votes

Existe-t-il un moyen de faire cela de manière conditionnelle ? Je ne veux le faire que parfois. En outre, ceci est spécifiquement pour les commandes, mais je cherche quelque chose pour l'ensemble du port 22 (ssh, sftp, etc).

1 votes

@Stephane que voulez-vous dire par spécifiquement pour les commandes ? Votre configuration SSH est utilisée par tout ce qui utilise ssh dont git , sftp etc.

1 votes

@Stephane Je n'ai pas connaissance d'un moyen d'activer cette fonction de manière conditionnelle (par exemple, uniquement lorsque vous êtes en dehors du réseau de l'hôte cible). Je définis cette option pour tous les hôtes en question dans un bloc de configuration, puis je (dé)commente la ligne selon les besoins. Ce n'est pas parfait, mais cela fonctionne.

71voto

nikolay Points 693

OpenSSH v7.3 et suivants prennent en charge un fichier -J et un ProxyJump qui autorise un ou plusieurs hôtes de saut séparés par des virgules. Vous pouvez donc simplement le faire maintenant :

ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@host

0 votes

Ssh -J user1@host1 -YC4c arcfour,blowfish-cbc user2@host2 firefox -no-remote Cela accélérera l'obtention de firefox de l'hôte2 vers l'hôte local.

0 votes

Je ne savais pas que tu pouvais le faire comme ça. Merci de l'avoir fait partager !

21voto

Pokot0 Points 338

Nous avons une passerelle ssh vers notre réseau privé. Si je suis à l'extérieur et que je veux un Shell distant sur une machine à l'intérieur du réseau privé, je devrais m'introduire par ssh dans la passerelle et de là sur la machine privée.

Pour automatiser cette procédure, j'utilise le script suivant :

#!/bin/bash
ssh -f -L some_port:private_machine:22 user@gateway "sleep 10" && ssh -p some_port private_user@localhost

Ce qui se passe :

  1. Établir un tunnel pour le protocole ssh (port 22) vers la machine privée.
  2. Seulement si cela est réussi, ssh dans la machine privée en utilisant le tunnel. (l'opérateur && s'en assure).
  3. Après avoir fermé la session ssh privée, je veux que le tunnel ssh soit également fermé. Ceci est fait via l'astuce "sleep 10". Normalement, la première commande ssh se ferme après 10 secondes, mais pendant ce temps, la deuxième commande ssh aura établi une connexion en utilisant le tunnel. Par conséquent, la première commande ssh maintient le tunnel ouvert jusqu'à ce que les deux conditions suivantes soient remplies : sleep 10 est terminé et le tunnel n'est plus utilisé.

1 votes

Très astucieux ! !! J'AIME !

20voto

Bob Muller Points 191

Après avoir lu ce qui précède et collé tout ensemble, j'ai créé le script Perl suivant (enregistrez-le sous le nom de mssh dans /usr/bin et rendez-le exécutable) :

#!/usr/bin/perl

$iport = 13021;
$first = 1;

foreach (@ARGV) {
  if (/^-/) {
    $args .= " $_";
  }
  elsif (/^((.+)@)?([^:]+):?(\d+)?$/) {
    $user = $1;
    $host = $3;
    $port = $4 || 22;
    if ($first) {
      $cmd = "ssh ${user}${host} -p $port -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
      $args = '';
      $first = 0;
    }
    else {
      $cmd .= " -L $iport:$host:$port";
      push @cmds, "$cmd -f sleep 10 $args";
      $cmd = "ssh ${user}localhost -p $iport -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no";
      $args = '';
      $iport ++;
    }
  }
}
push @cmds, "$cmd $args";

foreach (@cmds) {
  print "$_\n";
  system($_);
}

Utilisation :

Pour accéder à HOSTC via HOSTA et HOSTB (même utilisateur) :

mssh HOSTA HOSTB HOSTC

Pour accéder à HOSTC via HOSTA et HOSTB et utiliser des numéros de port SSH par défaut et des utilisateurs différents :

mssh user1@HOSTA:1234 user2@HOSTB:1222 user3@HOSTC:78231

Pour accéder à HOSTC via HOSTA et HOSTB et utiliser le X-forwarding :

mssh HOSTA HOSTB HOSTC -X

Pour accéder au port 8080 sur HOSTC via HOSTA et HOSTB :

mssh HOSTA HOSTB -L8080:HOSTC:8080

1 votes

C'est génial

1 votes

Je ne peux sérieusement pas vous remercier assez, ce script me facilite la vie au quotidien. La seule chose que j'ai changée est d'ajouter int(rand(1000)) à iport, pour permettre à plusieurs instances de fonctionner en même temps. Je vous dois définitivement une bière.

0 votes

Cela fonctionne très bien. Une autre amélioration serait de résoudre HOSTB, HOSTC etc. en utilisant le /etc/hosts de localhost et ~/.ssh/config.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X