Pergunta

I am attempting to login to an HP Switch (3500) from a Perl script on a Linux server. I'm stuck with using Net::OpenSSH as the only module available to me.

It hangs everytime I try to log in, though. The code works fine when it's hitting a webserver and I'm just logging in, taking a directory listing, and getting out. When run against a switch, it hangs up.

When logging in manually, here's how it goes:

$ ssh -luser_name 20.xxx.xxx.xxx
We'd like to keep you up to date about:
  * Software feature updates
  * New product announcements
  * Special events
Please register your products now at:  www.hp.com/networking/register


user_name@20.xxx.xxx.xxx's password: [I type that in, hit enter]
ProCurve J8693A Switch 3500yl-48G
Software revision K.15.04.1018m

Copyright (C) 1991-2013 Hewlett-Packard Development Company, L.P.

                   RESTRICTED RIGHTS LEGEND
 Confidential computer software.  Valid license from HP required for possession,
 use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer
 Software, Computer Software Documentation, and Technical Data for Commercial
 Items are licensed to the U.S. Government under vendor's standard commercial
 license.
                   HEWLETT-PACKARD DEVELOPMENT COMPANY, L.P.
                   20555 State Highway 249, Houston, TX 77070

[delete lots of lines here]

Press any key to continue

I wrote a short script to attempt to log in and issue a single simple command:

use strict;
use Net::OpenSSH;

my $host = '20.xxx.xxx.xxx';
my $user = 'user_name';
my $password = 'password';

my $login_string = $user . ':' . $password . '@' . $host;
my $ssh = Net::OpenSSH->new($login_string);
$ssh->error and die "Cannot open the connection " . $ssh->error;

my @results = $ssh->capture2('show cpu');
map { print;} @results;

It doesn't get very far:

$ perl testopenssh.pl
We'd like to keep you up to date about:
  * Software feature updates
  * New product announcements
  * Special events
Please register your products now at:  www.hp.com/networking/register

That's where it hangs. It's like it doesn't recognize that it's looking for a password and never gets past that point. I hit CTRL-C and it dies. When I do that, debug mode shows this afterwards:

# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# passwd/passphrase requested (user_name@20.xxx.xxx.xxx's password:)
# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# file object found at /home/xxxxxx/.libnet-openssh-perl/app-20.xxx.xxx.xxx-21357-620440
# call args: ['ssh','-O','check','-T','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--']
# open_ex: ['ssh','-O','check','-T','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--']
# io3 mloop, cin: 0, cout: 1, cerr: 0
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 28 at offset 0
#> 4d 61 73 74 65 72 20 72 75 6e 6e 69 6e 67 20 28 70 69 64 3d 32 31 33 35 38 29 0d 0a             | Master running (pid=21358)..
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 0 at offset 28
# leaving _io3()
# _waitpid(21362) => pid: 21362, rc:
# call args: ['ssh','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--','show cpu']
# open_ex: ['ssh','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--','show cpu']
# io3 mloop, cin: 0, cout: 1, cerr: 1
# io3 fast, cin: 0, cout: 1, cerr: 1

Does that mean it's hanging BEFORE it's even looking for the password?

Any ideas for what else I might be able to try?

Thanks!

Foi útil?

Solução

As you probably know, there is no way to present a password non-interactively when you use SSH, i.e. no command-line option to include it. If you use password auth with SSH, it has to be interactively provided.

Net::OpenSSH's way of connecting calling one single string:

my $ssh2 = Net::OpenSSH->new('jack:secret@foo.bar.com:10022');

is just a nice way for the programmer to provide a password, but then it mimics interactive password auth. The docs say: "For password authentication, IO::Pty has to be installed"

I'm thinking that switch's pty implementation is probably different than the web servers you log into, therefore the Net::OpenSSH module - or rather, IO::Pty - is unable to get through password auth?

I agree with @Marlon above that expect would fit nicely here. Anywhere you need to emulate human behavior, expect is a good fit. And you don't have to use SSH keys, although it is recommended so as not to have passwords in clear text in a script file. But, your Perl program above is not exactly top-security stuff with the password listed in there, either. So you could easily switch to an expect script that would be able to handle interactive password login easily, at the same security level you are now.

Just my 2c.

Outras dicas

I'm using expect and private-key authentication to accomplish this.

I've got a simple expect-script, that I invoke with the IP and the command which is to be executed after the login:

#!/usr/bin/expect
#
# sendswitchcmd.exp
#
set timeout 60

spawn ssh -t -t -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i PATHTOYOURKEY]
expect -re "Press any key to continue"
send "X"
expect -re ".*#"
send "config\n"
expect -re ".*#"
send "[lindex $argv 1] [lindex $argv 2]\n     "
expect -re ".*#"
send "ex\n"
expect -re ".*#"
send "ex\n"
expect -re ".*>"
send "ex\n"
expect -re ".*you want to log out.*"
send "y"

With that I can do things like

./sendswitchcmd.exp [switch-IP] "show vlans"

This I also invoke in some Bash-Scripts that I built for simpler configuration of our switches.

Maybe that helps you along.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top