The maze book for programmers!
mazesforprogrammers.com

Algorithms, circle mazes, hex grids, masking, weaving, braiding, 3D and 4D grids, spheres, and more!

DRM-Free Ebook

The Buckblog

assorted ramblings by Jamis Buck

Net::SSH 1.1.0

30 April 2007 — 2-minute read

Net::SSH is a pure-Ruby implementation of an SSH (v2) client. It can be used to execute tasks on and forward connections to and from remote hosts via SSH.

You can grab version 1.1.0 now via RubyGems:

gem install net-ssh

Or, you can grab a package via the project’s page at RubyForge.

Version 1.1.0 has three significant changes from the previous release:

  • A script that implements a subset of the ssh-keygen functionality is now provided, called “rb-keygen”. This is probably only going to be useful in environments where there is no command-line ssh client installed.
  • SSH agent forwarding is now supported. It is disabled by default, but to enable it just pass :forward_agent => true to the start method:
1
2
3
Net::SSH.start("the.host.com", :forward_agent => true) do |ssh|
  # ...
end

Many thanks to Chris Andrews for implementing this!

  • Server key verification has been implemented. It is enabled by default. The first time a key is encountered for a particular host and port, it is remembered. If that key ever changes, an exception will be raised. If you want the new key to be remembered, you can rescue the exception, call the “remember_host!” on it, and retry the block:
1
2
3
4
5
6
7
8
9
begin
  Net::SSH.start(...) do |ssh|
    # ...
  end
rescue Net::SSH::HostKeyMismatch => e
  puts "remembering new key: #{e.fingerprint}"
  e.remember_host!
  retry
end

If, on the other hand, you want to disable server key verification altogether, you can simply pass :paranoid => false and be done with it:

1
2
3
Net::SSH.start(..., :paranoid => false) do |ssh|
  # ...
end

Lastly, note that the default setting will not verify server keys if the host is the localhost and the port is something other than 22, since that will typically indicate a connection being made over a forwarded port, and the key will very likely be different on subsequent calls. If, however, you want server key verification in spite of that, you can pass :paranoid => :very,

1
2
3
Net::SSH.start(..., :paranoid => :very) do |ssh|
  # ...
end

If none of those options suit you, you can implement your own class that implements the #verify method, accepting a single Hash as argument, which should return true if the key is accepted:

1
2
3
Net::SSH.start(..., :paranoid => CustomClass.new) do |ssh|
  # ...
end

Enjoy!

Reader Comments

I’m having some trouble with the key verification. My ~/.ssh/known_hosts has a few entries where a bunch of aliases for a machine are listed with the same key. (Something I manually tidied up because I keep my known_hosts in subversion.) That works fine with openssh, but net-ssh seems to be getting a little upset. I’ve changed Net::SSH::HostKeyVerifier#load_keys_from to the following:

        def load_keys_from(path)
          File.readlines(path).map do |line|
            hosts, type, key = line.chomp.split
            key = key.unpack("m*").first

            hosts.split(/,/).map do |host|
              host, port = host.split(/:/, 2)
              host = host.gsub(/[\[\]]/, "")
              { :host => host, :port => port, :type => type, :key => key }
            end
          end.flatten
        end

which now appears to do the job. Unfortunately, it loses the IP address verification in addition to the hostname.

I’ve also had issues with key verification and the new Net-SSH.

It seems to be utilizing an “ssh-dss” authentication key from the server vs the “ssh-rsa” key which I already have in my known_hosts. I’m now ending up with duplicate host entries in my known_hosts file, one for each type of key (depending on if I’ve used net-ssh to connect, ssh-dss, or connected via an interactive ssh session, ssh-rsa).

Since it seems to be a DSA vs RSA thing, I’m guessing it has something to do with SSH vs SSH2?

At first it wouldn’t allow connections to known servers, as the provided DSA key didn’t match the stored RSA key. My immediate fix was to just rename my known_hosts file, which seemed to work fine. Then, after I manually ssh in (after net-ssh creates its own known_host entry), I’ll pick up the RSA key for the interactive prompts.