2013-02-02 35 views
0

通过多个系统的代理隧道我需要一些关于如何使用Ruby Net :: SSH和Net :: SCP gem通过多个系统进行代理以执行命令或复制文件的建议。使用Ruby Net :: SSH

这与我之前发表的文章非常相似(如果不是几乎完全一样),使用基于Linux命令行的ssh。

How to script multiple ssh and scp commands to various systems

例如,LOCAL是我的本地系统。

系统A是连接到LOCAL

系统B的第二系统仅被连接到系统A的第三系统。此外,系统B被配置为只允许通过ssh密钥从系统A进行访问。

对于命令行正常的ssh,我有我的.ssh/config文件中设置了这样:

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 

从这一点来说,只要我的酒馆关键是在sysA中的authorized_hosts(让我们假设它总是会),并sysA中的酒吧关键是在authorized_hosts SYSB(同样的假设),下面将无缝工作:

ssh systemB 

我想在Ruby中实现这一具体行为。我有一些代码类似于以下内容:

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 

不幸的是,这是行不通的。我得到一个身份验证失败。

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

我在这里错过了什么?

回答

1

您是否验证了您的代理命令实际上是从命令行独立运行的?看起来你可能混合了身份密钥的顺序。

SystemA已经知道你(?),你不需要为它指定一个标识。这也是基于您发布的config设置。

相反,对我来说,似乎你需要系统A的身份转发到系统B在start命令:

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

,然后跳到只是跳过的代理设置命令身份文件。

+0

是的!事实上,你似乎是对的。我已经通过Net :: SSH.start选项进行了扫描,并以某种方式通过了:密钥。我认为我的眼睛更喜欢“IdentityFile”,因为这是我以前在ssh-config中看到的。 – Raj

0

我用Net :: SSH解决了这个问题,但不需要外部配置文件。 Net :: SSH :: Gateway在我的解决方案中也很有帮助。我把解决方案包装成一个名为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)