rubysshtelnetnet-ssh

Create a Telnet connection via SSH using Ruby


I am having a slight issue. First and foremost, I had never written a single line of Ruby until being given this task so it is somewhat outwith my remit and comfort zone. This may well be a stupid question but I have searched for what feels like an eternity and found nothing.

I have found a wealth of information on how to telnet from my local machine using Net::Telnet and how to create a Telnet session based on the current SSH session using Net::SSH:Telnet but haven't found anything specifically dealing with my issue.

I need to SSH onto a machine using a set of credentials; this is no issue:

objSsh=Net::SSH.start("xxx.xxx.xxx.xx",
                        "sshUser", 
                        :Password=>"sshPass")

The above works a treat and I can get, for example, the output from ls (I know, the simplest of simpleton tasks).

The issue that I am having is that I need to Telnet from the SSH session using different credentials, so the below does not fit my purpose:

ssh = Net::SSH.start("xxx.xxx.xxx.xxx",
      :username=>"sshUser",
      :password=>"sshPass"
)
s = Net::SSH::Telnet.new(
      "Dump_log" => "/dev/stdout",
      "Session" => ssh
)

That would Telnet using the same credentials and so is not what I require.

But at the same time I cannot use the below because it would just try to Telnet from the executing machine, which is not what is required.

s = Net::SSH::Telnet.new(
    "Dump_log" => "/dev/stdout",
    "Host" => "0",
    "Username" => "telnetUser",
    "Password" => "telnetUser"
)

Basically, I need to SSH to a machine then, using different credentials, Telnet to the localhost using "telnet 0 xxxxx" but can't figure out for the life of me how to do it.

I've tried running telnet 0 xxxxx at the ssh prompt but that just hangs, presumably because the username/password prompts are shown.

I am wandering in confused circles, here. Any assistance with regards to a kick in the right direction would be appreciated.

Thanks,

CJL.

Update 1:

Thank you cherrysoft for your rapid and helpful replies. I'll look into whether or not we are able to chuck files onto their servers to trigger via SSH directly. It would make life simpler!

Update 2:

OK, so in desperation I tried something and it got me a step further than I was getting before. The following code connects via SSH, creates a Telnet session based on the SSH, ensures everything is still working by outputting a simple SSH command, tries to kick off a Telnet session....and then fails.

#Create SSH connection.
objSsh=Net::SSH.start("xxx.xxx.xxx.xxx",
                    "sshPass", 
                    :password=>"sshPass")
#Crete a Net:SSH:Telnet object based on the SSH connection.
objTelnet = Net::SSH::Telnet.new("Session" => objSsh)
#Ensure simple SSH commands can still be run by outputting ls results.
p objTelnet.cmd("ls")
#Try to kick off a telnet session and show what is displayed.
p objTelnet.cmd("telnet 0 xxxxx")
#Wait for the Username prompt.
objTelnet.waitfor("Match" => /.*?Username:.$/)
#Enter username.
objTelnet.puts("telnetUser")
#Wait for password prompt.
objTelnet.waitfor("Match" => /.*?Password:.$/)
#enter password.
objTelnet.puts("telnetPass")
#Try the command.
p objTelnet.cmd("cluster stats")

It gets as far as the Telnet connection but the Waitfor calls don't seem to be working. When the below line runs the result in the output is a prompt for Username:

objTelnet.cmd("telnet 0 xxxxx")

"telnet 0 xxxxx\nTrying 0.0.0.0...\r\nConnected to 0.\r\nEscape character is '^]'.\r\nUsername: "

I would have expected the Waitfor to match what was shown in the output and for the Username then to be entered. Is this possibly a RegEx issue? I have run it through Rubular and it seems to match but I may be missing something syntax related?

Thanks again for your time.

CJL.

UPDATE 3 AND RESOLUTION:

Thank you Kimmo Lehto. With only minor tweeking that worked perfectly. It was still getting stuck at Telnet loggin but when passing credentials as shown below (as opposed to user/pass) it works a treat!

loginInfo = {"Name" => telnetUser,
          "Password" => telnetpass,
          "LoginPrompt" => /Username:/
         }
objGateway = Net::SSH::Gateway.new(hostIp, user, :password => password)
objLocalPort = objGateway.open("localhost", port)
objTelnet = Net::Telnet::new("Host" => "127.0.0.1", "Port" => objLocalPort)
objTelnet.login(loginInfo) 
objTelnet.cmd("cluster lrm res sum") { |c| print c}
objTelnet.close
objGateway.shutdown!

Thanks again for your time and effort in resolving this issue.

CJL out...


Solution

  • You could try using net-ssh-gateway for tunneling and use the regular net-telnet for telnet (which itself is horribly outdated and net-telnet-ssh is a drop-in replacement of that horribleness):

    gateway = Net::SSH::Gateway.new(ssh_host, ssh_user)
    local_port = gateway.open(target_host, target_port)
    telnet = Net::Telnet::new("Host" => "localhost", "Port" => local_port)
    telnet.login(telnet_user, telnet_password)
    telnet.cmd("ls -al") { |c| print c }
    telnet.close
    gateway.shutdown!
    

    Quick googling did not bring up any alternative telnet libraries that would look like the ruby of today.