Question Un tunnel SSH via plusieurs sauts


La mise en tunnel des données via SSH est assez simple:

ssh -D9999 username@example.com

met en place le port 9999 sur votre localhost comme un tunnel à example.com, mais j'ai un besoin plus spécifique:

  • Je travaille localement sur localhost
  • host1 est accessible à localhost
  • host2 accepte uniquement les connexions de host1
  • Je dois créer un tunnel à partir de localhost à host2

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


287
2018-01-16 05:58


origine


Pourquoi l'avez-vous utilisé? Je veux l'utiliser pour proxy de chaussettes. Est-ce que ça marchera? - prongs
Oui, vous devriez pouvoir utiliser la connexion tunnelisée en tant que proxy SOCKS, sauf si host2 nie le transfert - Mala
Je pensais à créer un wrapper sur SSH qui configurerait cela en utilisant plusieurs utilisations de ProxyCommand. - Pavel Šimerda
@prongs Avez-vous réussi à l'utiliser pour le proxy SOCKS (il y a toutes ces années)? - Drux


Réponses:


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é.

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

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

    Cela va ouvrir 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 va ouvrir un tunnel de localhost à host1 à travers lequel le service SSH sur host2 peut être utilisé. Puis un deuxième tunnel est ouvert de localhost à host2 à travers le premier tunnel.

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


272
2018-01-17 21:31



l'option 3 était ce que je cherchais, merci! - Mala
Je veux faire de la navigation de cette façon. Lequel est le meilleur? J'ai essayé le premier mais ça n'a pas marché. Je mets un proxy de chaussettes dans mon navigateur localhost: 1234 mais pas de chance. :( s'il vous plaît aider .. - prongs
@prongs essayez l'option 3 - Mala
existe-t-il un moyen de transférer ma clé publique de localhost, via le tunnel de l'hôte 1, vers l'hôte2? - Noli
@Noli Si vous utilisez ssh-agent (ce que vous devriez), vous pouvez le transférer via les connexions en utilisant le -Aoption à ssh. - Mika Fischer


Il y a 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

alors ssh host2 traversera automatiquement le tunnel host1 (fonctionne également avec le transfert X11, etc.).

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

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

Mettre à jour

OpenSSH 7.3 introduit une ProxyJump directive, simplifiant le premier exemple pour

Host host2
  ProxyJump host1

138
2017-08-01 17:10



Y a-t-il un moyen de le faire conditionnellement? Je veux seulement le faire parfois. En outre, cela concerne spécifiquement les commandes, mais je recherche quelque chose pour tout le port 22 (ssh, sftp, etc.). - Stephane
@ Stéphane Que voulez-vous dire par spécifiquement pour les commandes? Votre configuration SSH est utilisée par n'importe quoi en utilisant ssh, comprenant git, sftp etc. - kynan
@ Stéphane Je ne suis pas au courant d'un moyen d'activer cette option (par exemple, uniquement lorsque vous êtes hors du réseau de l'hôte cible). Je mets cette option pour tous les hôtes en question dans un bloc de configuration, puis (dés) commente la ligne si nécessaire. Pas parfait, mais ça marche. - kynan
@Stephane sûr: ssh -F /path/to/altconfig. Attention, cela ne tiendra pas compte du système /etc/ssh/ssh_config. - kynan
Un moyen simple de rendre les paramètres «conditionnels» consiste à définir deux hôtes différents dans .ssh / config, qui ont le même nom d'hôte. Connectez-vous à host2-tunnel lorsque vous voulez le tunnel, et host2 lorsque vous ne le souhaitez pas. - Steve Bennett


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 du réseau privé, je devrai ssh dans la passerelle et de là dans 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 est réussi, ssh dans la machine privée en utilisant le tunnel. (l'opérateur && assure cela).
  3. Après avoir fermé la session ssh privée, je souhaite que le tunnel ssh se ferme également. Cela se fait via l'astuce "sleep 10". Habituellement, la première commande ssh se ferme après 10 secondes, mais pendant ce temps, la deuxième commande ssh établira une connexion en utilisant le tunnel. En conséquence, la première commande ssh maintient le tunnel ouvert tant que les deux conditions suivantes ne sont pas remplies: le sommeil 10 est terminé et le tunnel n'est plus utilisé.

20
2018-01-24 18:47



Très intelligent!!! AIMER! - Hendy Irawan


Après avoir lu ce qui précède et collé le tout, j'ai créé le script Perl suivant (sauvegardez-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 différents utilisateurs:

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

16
2018-01-11 11:02



C'est génial - Mala
Je ne peux pas sérieusement vous remercier, ce script me facilite la vie au quotidien. La seule chose que j'ai changée était d'ajouter int (rand (1000)) à iport, pour permettre à plusieurs instances de s'exécuter en même temps. Je vous dois certainement une bière. - Mala
Cela fonctionne vraiment bien. Une autre amélioration serait de résoudre HOSTB, HOSTC, etc. en utilisant / etc / hosts et ~ / .ssh / config de localhost - Steve Bennett
Aussi, j'appuie le commentaire de Mala. Sans le port aléatoire, si vous essayez ensuite de mssh HOSTA HOSTD vous allez vous retrouver à HOSTB (et peut-être ne réaliserez pas ..) - Steve Bennett


OpenSSH v7.3 prend en charge un -J interrupteur et un ProxyJump option, 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

16
2017-08-10 09:11



ssh -J user1 @ host1 -YC4c arcfour, blowfish-cbc utilisateur2 @ host2 firefox -no-remote Cela accélérera le passage de firefox de host2 à localhost. - Jaur


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

Si vous avez netcat installé 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/:/ /')

alors

ssh -D9999 host1+host2 -l username

fera ce que vous avez demandé.

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


8
2018-03-13 09:57



Je crois que c'est l'origine de l'astuce: wiki.gentoo.org/wiki/SSH_jump_host - slm
@slm oui, c'est ça! Merci! - silviot


ssh -L 9999:host2:80 -R 9999:localhost:9999 host1

-L 9999: hôte2: 80

Les moyens se lient à localhost: 9999 et tout paquet envoyé à localhost: 9999 le transfère à host2: 80

-R 9999: localhost: 9999

Signifie tout paquet reçu par host1: 9999 retransmettre à localhost: 9999


4
2018-01-19 02:03



Une réponse brillante et la plus simple pour créer un tunnel afin que vous puissiez accéder à l'application sur host2 directement à partir de localhost: 9999 - dvtoever
Suite à cette réponse, je reçois un channel 3: open failed: administratively prohibited: open failed  Message d'erreur. - Franck Dernoncourt


vous devriez pouvoir utiliser le transfert de port pour accéder à un service sur host2 de localhost. Un bon guide est situé ici. Extrait:

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

Par exemple, si vous émettez la commande

ssh2 -L 1234:localhost:23 username@host

tout le trafic entrant sur le port 1234 du client sera transféré au port 23 du serveur (hôte). Notez que localhost sera résolu par le 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 fait le contraire: il transfère le trafic arrivant sur un port distant vers un port local spécifié.

Par exemple, si vous émettez la commande

ssh2 -R 1234:localhost:23 username@host

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

Dans ta distribution, remplace localhost dans l'exemple avec host2 et host avec host1.


2
2018-01-16 06:34



Selon cet article, la connexion ne sera sécurisée que jusqu'à la machine intermédiaire (host1). Y a-t-il un moyen de s'assurer que tout reste sécurisé? - Mala
Je n'ai jamais essayé ceci, mais si host1 et host2 sont tous les deux des serveurs ssh, vous pourrez peut-être configurer un tunnel de host1 à host2, puis configurer un tunnel de localhost vers host1 pour le même service (obtenir votre ports à droite). Je ne sais pas si cela est possible dans une commande de localhost. - fideli


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

ssh -D 9999 -J host1 host2

Je suis invité pour les deux mots de passe, puis je peux utiliser localhost: 9999 pour un proxy SOCKS à host2. C'est le plus proche que je puisse penser à l'exemple que vous avez montré en premier lieu.


2
2017-11-21 11:06