2013-02-02 5 views
0

J'ai besoin de quelques suggestions sur l'utilisation de la gemme Ruby Net :: SSH et Net :: SCP pour passer par plusieurs systèmes afin d'exécuter des commandes ou de copier des fichiers.Tunnel proxy via plusieurs systèmes avec Ruby Net :: SSH

C'est très similaire (si ce n'est presque exactement le même) que ce post précédent que j'ai fait, en utilisant ssh de base de la ligne de commande linux.

How to script multiple ssh and scp commands to various systems

Par exemple, LOCAL est mon système local.

Système A est un second système connecté au système local

B est un troisième système connecté au système A uniquement. En outre, le système B est configuré pour autoriser uniquement l'accès du système A à l'aide de sa clé ssh.

Pour ssh normal à partir de la ligne de commande, j'ai mon .ssh/fichier de configuration mis en place ainsi:

Host systemA 
     HostName  192.168.0.10 
     User   A-user 

Host systemB 
     ProxyCommand ssh -e none systemA exec /bin/nc %h %p 2>/dev/null 
     HostName  192.168.0.11 
     User   B-user 
     IdentityFile ~/.ssh/systemA_id_dsa 

De ce point, aussi longtemps que la clé de la pub est dans les authorized_hosts de SYSa (supposons que ce sera toujours), et la clé de pub SYSa est dans les authorized_hosts SYSB (même hypothèse), ce qui suit fonctionnera de façon transparente:

ssh systemB 

Je voudrais mettre en œuvre ce comportement exact à Ruby. J'ai un code semblable au suivant:

require 'net/ssh' 
require 'net/ssh/proxy/command' 

str = 'ssh -l A-user -i /home/A-user/.ssh/id_dsa -e none 192.168.0.10 exec /bin/nc %h %p 2>/dev/null' 
proxy = Net::SSH::Proxy::Command.new(str) 

Net::SSH.start('192.168.0.11', 'B-user', :proxy => proxy) do |ssh| 
    ssh.exec! "ls -lA" 
end 

Malheureusement, cela ne fonctionne pas. Je reçois un échec d'authentification.

~/.rvm/gems/ruby-1.9.3-p327/gems/net-ssh-2.6.2/lib/net/ssh.rb:201:in `start': root (Net::SSH::AuthenticationFailed) 

Que manque-t-il ici?

Répondre

1

Avez-vous vérifié que votre commande proxy fonctionne réellement à partir de la ligne de commande? Il semble que vous ayez mélangé l'ordre des clés d'identité. SystemA vous connaît déjà (?), Vous ne devriez pas avoir besoin de spécifier une identité pour cela. Cela est également basé sur la configuration config que vous avez publiée.

Au lieu de cela me semble que vous avez besoin il de transmettre l'identité de Systema à SystemB dans la commande start:

Net::SSH.start('192.168.0.11', 'B-user', 
       :proxy => proxy, 
       :keys => [ "~/.ssh/systemA_id_dsa" ]) do |ssh| 
    ssh.exec! "ls -lA" 
end 

Et puis passez juste sauter le fichier d'identité dans la commande de configuration du proxy.

+0

Oui! En effet, vous semblez avoir raison. J'avais scanné à travers les options Net :: SSH.start et je suis passé d'une façon ou d'une autre: clés. Je pense que mes yeux se fendaient de quelque chose comme "IdentityFile" parce que c'est ce que j'ai l'habitude de voir dans ssh-config. – Raj

0

J'ai résolu ce problème avec Net :: SSH, mais sans avoir besoin de fichiers de configuration externes. Net :: SSH :: Gateway a également été utile dans ma solution. J'ai enveloppé la solution dans une gemme appelée tunneler.

require "tunneler" 

# Create SSH tunnel 
tunnel = Tunneler::SshTunnel.new(bastion_user, bastion_host, {:keys => [bastion_key]}) 

# Establish remote connection 
destination_host_connection = tunnel.remote(destination_user, destination_host, {:keys => [destination_key]}) 

# Upload file to destination host via tunnel 
destination_host_connection.scp(local_file_path, destination_file_path) 

# Execute command on destination host via tunnel 
response = destination_host_connection.ssh(command)