web-dev-qa-db-fra.com

Un tunnel SSH via plusieurs sauts

La tunnellisation des données via SSH est assez simple:

ssh -D9999 [email protected]

configure le port 9999 sur votre localhost en tant que tunnel sur example.com, mais j'ai un besoin plus spécifique:

  • Je travaille localement sur localhost
  • Host1 est accessible à localhost
  • Host2 accepte uniquement les connexions à partir de Host1
  • J'ai besoin de créer un tunnel de localhost à Host2

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

319
Mala

Vous avez essentiellement trois possibilités:

  1. Tunnel de localhost à Host1:

    ssh -L 9999:Host2:1234 -N Host1
    

    Comme indiqué ci-dessus, la connexion de Host1 à Host2 ne sera pas sécurisée.

  2. Tunnel de localhost à Host1 et de Host1 à Host2:

    ssh -L 9999:localhost:9999 Host1 ssh -L 9999:localhost:1234 -N Host2
    

    Cela ouvrira un tunnel de localhost à Host1 et un autre tunnel de Host1 à Host2. Cependant, le port 9999 à Host2:1234 peut être utilisé par n'importe qui sur Host1. Cela peut ou peut ne pas être un problème.

  3. Tunnel de localhost à Host1 et de localhost à Host2:

    ssh -L 9998:Host2:22 -N Host1
    ssh -L 9999:localhost:1234 -N -p 9998 localhost
    

    Cela ouvrira un tunnel de localhost à Host1 à travers lequel le service SSH sur Host2 pourra être utilisé. Ensuite, un second tunnel est ouvert de localhost à Host2 via le premier tunnel.

Normalement, je choisirais l'option 1. Si la connexion de Host1 à Host2 doit être sécurisée, choisissez l'option 2. L'option 3 est principalement utile pour accéder à un service sur Host2 accessible uniquement à partir de Host2.

306
Mika Fischer

Il y a une excellente réponse expliquant l'utilisation de la directive de configuration ProxyCommand 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

Ensuite, ssh Host2 tunnelera automatiquement à travers Host1 (fonctionne également avec le transfert X11, etc.).

Cela fonctionne également pour toute une classe d'hôtes, par exemple. identifié par domaine:

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

Mettre à jour

OpenSSH 7.3 introduit } _ une directive ProxyJump, simplifiant le premier exemple

Host host2
  ProxyJump Host1
149
kynan

OpenSSH v7.3 prend en charge un commutateur -J et une option ProxyJump, qui autorisent un ou plusieurs hôtes de saut séparés par des virgules. Vous pouvez donc le faire maintenant:

ssh -J jumpuser1@jumphost1,jumpuser2@jumphost2,...,jumpuserN@jumphostN user@Host
21
nikolay

Nous avons une passerelle SSH dans 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 me connecter à la passerelle et de là à 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

Qu'est-ce qui se passe:

  1. Établissez un tunnel pour le protocole ssh (port 22) vers la machine privée.
  2. Seulement si cela réussit, ssh dans la machine privée en utilisant le tunnel. (L’opérateur && assure cela).
  3. Après la fermeture de la session ssh privée, je souhaite également que le tunnel ssh se ferme. Cela se fait via l'astuce "sommeil 10". Habituellement, la première commande ssh se ferme au bout de 10 secondes, mais pendant ce temps, la deuxième commande ssh aura établi une connexion à l'aide du tunnel. Par conséquent, la première commande ssh maintient le tunnel ouvert jusqu'à ce que les deux conditions suivantes soient remplies: la veille 10 est terminée et le tunnel n'est plus utilisé.
21
Bernhard Kausler

Après avoir lu ce qui précède et avoir tout collé, j'ai créé le script Perl suivant (enregistrez-le sous 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($_);
}

Usage:

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 autres que ceux 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 transfert X:

mssh HOSTA HOSTB HOSTC -X

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

mssh HOSTA HOSTB -L8080:HOSTC:8080
18
Bob Muller

Cette réponse est similaire à kynan, car elle implique l'utilisation de ProxyCommand. Mais il est plus pratique d'utiliser IMO.

Si vous avez installé netcat sur vos machines de saut, vous pouvez ajouter cet extrait à votre ~/.ssh/config:

Host *+*
    ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') nc $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /')

Ensuite

ssh -D9999 Host1+Host2 -l username

fera ce que vous avez demandé.

Je suis venu ici à la recherche du lieu d'origine où j'ai lu cette astuce. Je posterai un lien quand je le trouverai.

8
silviot
ssh -L 9999:Host2:80 -R 9999:localhost:9999 Host1

-L 9999: hôte 2: 80

Signifie bind to localhost: 9999 et tout paquet envoyé à localhost: 9999 le transmet à Host2: 80

-R 9999: localhost: 9999

Signifie que tout paquet reçu par l'hôte 1: 9999 le renvoie à l'hôte local: 9999

4
chinmaya

J'ai fait ce que je pense tu voulais faire avec

ssh -D 9999 -J Host1 Host2

On me demande les deux mots de passe, puis je peux utiliser localhost: 9999 pour un proxy SOCKS vers Host2. Je pense le plus près de l'exemple que vous avez montré en premier lieu.

3
Cheryl

vous devriez pouvoir utiliser la redirection de port pour accéder à un service sur Host2 à partir de localhost. Un bon guide est situé ici . Extrait:

Il existe deux types de transfert de port: le transfert local et le transfert distant. Ils sont également appelés tunnels sortants et entrants, respectivement. La redirection de port local transfère le trafic arrivant sur un port local à un port distant spécifié.

Par exemple, si vous exécutez la commande

ssh2 -L 1234:localhost:23 username@Host

tout le trafic arrivant sur le port 1234 du client sera transféré sur le port 23 du serveur (hôte). Notez que localhost sera résolu par le serveur sshdserver une fois la connexion établie. Dans ce cas, localhost fait donc référence au serveur (hôte) lui-même.

Le transfert de port distant a l'effet inverse: il transfère le trafic arrivant sur un port distant à un port local spécifié.

Par exemple, si vous exécutez la commande

ssh2 -R 1234:localhost:23 username@Host

tout le trafic qui arrive au port 1234 sur le serveur (hôte) sera transféré au port 23 sur le client (localhost).

Dans votre distribution, remplacez localhost dans l'exemple par Host2 et Host par Host1.

2
fideli

Dans cette réponse, je vais passer à travers un exemple concret. Il vous suffit de remplacer les noms d'hôte, noms d'utilisateur et mots de passe des ordinateurs par les vôtres.

Déclaration du problème

Supposons que nous ayons la topologie de réseau suivante:

our local computer <---> server 1 <---> server 2

Pour des raisons concrètes, supposons que nous possédons les noms d'hôte, noms d'utilisateur et mots de passe des ordinateurs suivants:

LocalPC            <--->  hostname: mit.edu         <---> hec.edu
                          username: bob                   username: john 
                          password: dylan123              password: doe456

Objectif: nous voulons configurer un proxy SOCKS qui écoute sur le port 9991 de LocalPC de sorte que chaque fois qu'une connexion sur LocalPC est établie à partir du port 9991, elle passe par mit.edu puis hec.edu.

Exemple de cas d'utilisation: hec.edu possède un serveur HTTP uniquement accessible sur http://127.0.0.1:8001 , pour des raisons de sécurité. Nous aimerions pouvoir visiter http://127.0.0.1:8001 en ouvrant un navigateur Web sur LocalPC.


Configuration

Dans LocalPC, ajoutez ~/.ssh/config:

Host HEC
    HostName hec.edu
    User john
    ProxyCommand ssh [email protected] -W %h:%p

Ensuite, dans le terminal de LocalPC, exécutez:

ssh -D9991 HEC

Il vous demandera le mot de passe de bob sur mit.edu (i.e., dylan123), puis vous demandera le mot de passe de john sur hec.edu (c.-à-d. doe456).

À ce stade, le proxy SOCKS s'exécute maintenant sur le port 9991 de LocalPC.

Par exemple, si vous souhaitez visiter une page Web sur LocalPC à l'aide du proxy SOCKS, vous pouvez le faire dans Firefox:

 enter image description here

Quelques remarques:

  • dans ~/.ssh/config, HEC est le nom de la connexion: vous pouvez le changer en tout ce que vous voulez.
  • Le -D9991 indique à ssh de configurer un proxy SOCKS4 sur le port 9991.
1
Franck Dernoncourt

Si vous pouvez utiliser SSH sur les deux machines, jetez un coup d'œil à la directive ProxyCommand de ssh. Cela vous permettra d'aller directement de localhost à Host2 (en une seule commande si vous utilisez des clés publiques !!). Ensuite, vous pouvez faire ce que vous voulez avec Host2.

http://www.statusq.org/archives/2008/07/03/1916/

0
Andrew

Dans mon cas j'ai fait

localhost$ ssh -D 9999 Host1
Host1$ ssh -L 8890:localhost:8890 Host2

Host2:8890 est exécuté sur un bloc-notes Jupyter.

Ensuite, j'ai configuré Firefox pour utiliser localhost:9999 en tant qu'hôte SOCKS.

Alors maintenant, le cahier fonctionne sous Host2 accessible par Firefox à localhost:8890 sur ma machine.

0
amarion

L'option 2 de meilleure réponse pourrait être utilisée avec des utilisateurs de ssh différents de l'actuel aka: utilisateur @ hôte

    export local_Host_port=30000
    export Host1_user=xyz
    export Host1=mac-Host
    export Host1_port=30000
    export Host2=192.168.56.115
    export Host2_user=ysg
    export Host2_port=13306

    # Tunnel from localhost to Host1 and from Host1 to Host2
    # you could chain those as well to Host3 ... hostn
    ssh -tt -L $local_Host_port:localhost:$Host1_port $Host1_user@$Host1 \
    ssh -tt -L $Host1_port:localhost:$Host2_port $Host2_user@$Host2
0
Yordan Georgiev