Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Net::SSH2 and Trapeze, in-band authentication

by FloydATC (Chaplain)
on Apr 04, 2013 at 10:44 UTC ( #1026968=perlquestion: print w/ replies, xml ) Need Help??
FloydATC has asked for the wisdom of the Perl Monks concerning the following question:

Net::SSH2 and Trapeze When connecting manually to our Juniper Trapeze MX200 WLAN controllers, authentication appears to take place "in-band" rather than via SSH:
$ ssh 10.10.8.128 Copyright (c) 2002 - 2012 Juniper Networks, Inc. All rights reserved. Username: admin Password: MX200-1> enable Enter password: MX200-1#
I'm trying to emulate this using Net::SSH2 but (as you probably guessed already) I'm not doing all that well. Here's the code:
#!/usr/bin/perl use strict; use warnings; use Carp; use Net::SSH2; my %hosts = ( "MX200-1" => "10.10.8.128" ); my $DEBUG = 1; foreach my $name (sort keys %hosts) { my $ip = $hosts{$name}; $DEBUG && print "check $name ($ip)\n"; my $ssh2 = Net::SSH2->new(); if ($ssh2->connect($ip)) { $DEBUG && print "connected\n"; $ssh2->debug($DEBUG); $DEBUG && print "version=".join(', ', $ssh2->version())."\n"; $DEBUG && print "error=".$ssh2->error()."\n"; $ssh2->auth_list(); # Returns undef, auth_ok() will return 0 unles +s we call this(?) if ($ssh2->auth_ok()) { # Returns 4 (= true, we have been authenti +cated OK) $DEBUG && print "authenticated ok\n"; if (my $chan = $ssh2->channel()) { $DEBUG && print "channel open\n"; foreach my $line (get_channel_lines($chan)) { print $line."\n"; } $DEBUG && print "done\n"; } else { croak "Error opening channel"; } } else { croak "Expected to be authenticated: ".$ssh2->auth_ok()."\n"; } } else { warn "Error connecting to $name ($ip); please check host status\n" +; } } sub get_channel_lines { my $chan = shift; my $output = ""; until ($chan->eof) { my $bytes = $chan->read(my $buffer, 1024); # Blocks if (defined $bytes) { $DEBUG && print "$buffer($bytes)\n"; $output .= $buffer; } } return split(/\n/, $output); }
And the output:
check MX200-1 (10.10.8.128) connected version=1.2.6, 66054, SSH-2.0-libssh2_1.2.6 error=0 authenticated ok libssh2_channel_open_ex(ss->session, pv_channel_type, len_channel_type +, window_size, packet_size, ((void *)0) , 0 ) -> 0x9d08468 channel open Net::SSH2::Channel::read(size = 1024, ext = 0)
I expected $chan->read() to receive the in-band login prompt but instead it appears to hang forever. I understand that this is kinda hard to reproduce/test without having access to the same kind of equipment, so what I need is a nudge in the right direction. What am I doing wrong? Has anyone else solved a similar problem with other types of exotic hardware?

-- Time flies when you don't know what you're doing

Comment on Net::SSH2 and Trapeze, in-band authentication
Select or Download Code
Re: Net::SSH2 and Trapeze, in-band authentication
by salva (Monsignor) on Apr 04, 2013 at 11:17 UTC
    It is difficult to know what is going on without any low level debug information. Activate debugging passing -vvvv to ssh and post here the full output.

    Anyway, as it seems you are running your script in a Linux/Unix box, you may like to try with Net::OpenSSH in combination using Expect (see how).

    update: BTW, you have to run something in the channel before doing any IO. For instance, a shell, calling the shell method.

      Thanks for your input, I'll look into these things tomorrow morning. I am indeed running this on a Linux host so there should be plenty of tracing options available, and other ways to solve the problem. I've only done scripted ssh a few times against Linux and BSD-based systems before so I kinda got lost when the standard auth_* methods didn't work as they did before :-)

      Update:

      $ ssh -vvvv 10.10.8.128 OpenSSH_4.3p2, OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug2: ssh_connect: needpriv 0 debug1: Connecting to 10.10.8.128 [10.10.8.128] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type 1 debug3: Not a RSA1 key file /root/.ssh/id_rsa. debug2: key_type_from_name: unknown key type '-----BEGIN' debug3: key_read: missing keytype debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug3: key_read: missing whitespace debug2: key_type_from_name: unknown key type '-----END' debug3: key_read: missing keytype debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type -1 debug1: loaded 3 keys debug1: Remote protocol version 2.0, remote software version NOS-SSH_2 +.0 debug1: no match: NOS-SSH_2.0 debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_4.3 debug2: fd 3 setting O_NONBLOCK debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha1,diffie-h +ellman-group14-sha1,diffie-hellman-group1-sha1 debug2: kex_parse_kexinit: ssh-rsa,ssh-dss debug2: kex_parse_kexinit: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cb +c,arcfour128,arcfour256,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@ly +sator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr debug2: kex_parse_kexinit: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cb +c,arcfour128,arcfour256,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@ly +sator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripe +md160@openssh.com,hmac-sha1-96,hmac-md5-96 debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripe +md160@openssh.com,hmac-sha1-96,hmac-md5-96 debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: first_kex_follows 0 debug2: kex_parse_kexinit: reserved 0 debug2: kex_parse_kexinit: diffie-hellman-group14-sha1,diffie-hellman- +group1-sha1 debug2: kex_parse_kexinit: ssh-rsa debug2: kex_parse_kexinit: 3des-cbc debug2: kex_parse_kexinit: 3des-cbc debug2: kex_parse_kexinit: hmac-sha1 debug2: kex_parse_kexinit: hmac-sha1 debug2: kex_parse_kexinit: none debug2: kex_parse_kexinit: none debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: debug2: kex_parse_kexinit: first_kex_follows 0 debug2: kex_parse_kexinit: reserved 0 debug2: mac_init: found hmac-sha1 debug1: kex: server->client 3des-cbc hmac-sha1 none debug2: mac_init: found hmac-sha1 debug1: kex: client->server 3des-cbc hmac-sha1 none debug2: dh_gen_key: priv key bits set: 189/384 debug2: bits set: 1010/2048 debug1: sending SSH2_MSG_KEXDH_INIT debug1: expecting SSH2_MSG_KEXDH_REPLY debug3: check_host_in_hostfile: filename /root/.ssh/known_hosts debug3: check_host_in_hostfile: match line 91 debug1: Host '10.10.8.128' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:91 debug2: bits set: 1001/2048 debug1: ssh_rsa_verify: signature correct debug2: kex_derive_keys debug2: set_newkeys: mode 1 debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug2: set_newkeys: mode 0 debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug2: service_accept: ssh-userauth debug1: SSH2_MSG_SERVICE_ACCEPT received debug2: key: /root/.ssh/identity (0x9f70f88) debug2: key: /root/.ssh/id_rsa (0x9f70fa0) debug2: key: /root/.ssh/id_dsa ((nil)) debug1: Authentication succeeded (none). debug1: channel 0: new [client-session] debug3: ssh_session2_open: channel_new: 0 debug2: channel 0: send open debug1: Entering interactive session. debug2: callback start debug2: client_session2_setup: id 0 debug2: channel 0: request pty-req confirm 0 debug3: tty_make_modes: ospeed 38400 debug3: tty_make_modes: ispeed 38400 debug3: tty_make_modes: 1 3 debug3: tty_make_modes: 2 28 debug3: tty_make_modes: 3 127 debug3: tty_make_modes: 4 21 debug3: tty_make_modes: 5 4 debug3: tty_make_modes: 6 0 debug3: tty_make_modes: 7 0 debug3: tty_make_modes: 8 17 debug3: tty_make_modes: 9 19 debug3: tty_make_modes: 10 26 debug3: tty_make_modes: 12 18 debug3: tty_make_modes: 13 23 debug3: tty_make_modes: 14 22 debug3: tty_make_modes: 18 15 debug3: tty_make_modes: 30 0 debug3: tty_make_modes: 31 0 debug3: tty_make_modes: 32 0 debug3: tty_make_modes: 33 0 debug3: tty_make_modes: 34 0 debug3: tty_make_modes: 35 0 debug3: tty_make_modes: 36 1 debug3: tty_make_modes: 37 0 debug3: tty_make_modes: 38 1 debug3: tty_make_modes: 39 0 debug3: tty_make_modes: 40 0 debug3: tty_make_modes: 41 0 debug3: tty_make_modes: 50 1 debug3: tty_make_modes: 51 1 debug3: tty_make_modes: 52 0 debug3: tty_make_modes: 53 1 debug3: tty_make_modes: 54 1 debug3: tty_make_modes: 55 1 debug3: tty_make_modes: 56 0 debug3: tty_make_modes: 57 0 debug3: tty_make_modes: 58 0 debug3: tty_make_modes: 59 1 debug3: tty_make_modes: 60 1 debug3: tty_make_modes: 61 1 debug3: tty_make_modes: 62 0 debug3: tty_make_modes: 70 1 debug3: tty_make_modes: 71 0 debug3: tty_make_modes: 72 1 debug3: tty_make_modes: 73 0 debug3: tty_make_modes: 74 0 debug3: tty_make_modes: 75 0 debug3: tty_make_modes: 90 1 debug3: tty_make_modes: 91 1 debug3: tty_make_modes: 92 0 debug3: tty_make_modes: 93 0 debug1: Sending environment. debug3: Ignored env HOSTNAME debug3: Ignored env TERM debug3: Ignored env SHELL debug3: Ignored env HISTSIZE debug3: Ignored env SSH_CLIENT debug3: Ignored env SSH_TTY debug3: Ignored env USER debug3: Ignored env LS_COLORS debug3: Ignored env MAIL debug3: Ignored env PATH debug3: Ignored env WWW_HOME debug3: Ignored env INPUTRC debug3: Ignored env PWD debug1: Sending env LANG = en_US.UTF-8 debug2: channel 0: request env confirm 0 debug3: Ignored env PS1 debug3: Ignored env SHLVL debug3: Ignored env HOME debug3: Ignored env LOGNAME debug3: Ignored env SSH_CONNECTION debug3: Ignored env LESSOPEN debug3: Ignored env G_BROKEN_FILENAMES debug3: Ignored env _ debug2: channel 0: request shell confirm 0 debug2: fd 3 setting TCP_NODELAY debug2: callback done debug2: channel 0: open confirm rwindow 1048576 rmax 16384 Copyright (c) 2002 - 2012 Juniper Networks, Inc. All rights reserved. Username:

      Now... This isn't exactly my field of expertice but I notice the following, which I will need to emulate:

      debug1: Authentication succeeded (none). debug1: channel 0: new [client-session] debug3: ssh_session2_open: channel_new: 0 debug2: channel 0: send open debug1: Entering interactive session.

      So, as per your suggestion I tried $chan->shell() and it seems to have brought me one step further. $chan->read() now produces the following debug output: - read -37 bytes After a little bit more experimentation, I have rewritten my script slightly and arrived at the following slightly hackish but fully working solution:

      #!/usr/bin/perl use strict; use warnings; use Carp; use Net::SSH2; my %hosts = ( "MX200-1" => "10.10.8.128" ); my $DEBUG = 1; foreach my $name (sort keys %hosts) { my $ip = $hosts{$name}; $DEBUG && print "check $name ($ip)\n"; my $ssh2 = Net::SSH2->new(); if ($ssh2->connect($ip)) { $DEBUG && print "connected\n"; $ssh2->debug($DEBUG); $DEBUG && print "version=".join(', ', $ssh2->version())."\n"; $DEBUG && print "error=".$ssh2->error()."\n"; $ssh2->auth_list(); # Returns undef, auth_ok() will return 0 unles +s we call this(?) if ($ssh2->auth_ok()) { # Returns 4 (= true, we have been authenti +cated OK) $DEBUG && print "authenticated ok\n"; if (my $chan = $ssh2->channel()) { $DEBUG && print "channel open\n"; $chan->shell(); $chan->blocking(0); print $chan "admin\n"; print $chan "********\n"; # Password print $chan "enable\n"; print $chan "********\n"; # Enable password print get_response($chan); print $chan "set length 0\n"; print get_response($chan); print $chan "show configuration\n"; print get_response($chan); $chan->close; $DEBUG && print "done\n"; } else { croak "Error opening channel"; } } else { croak "Expected to be authenticated: ".$ssh2->auth_ok()."\n"; } $ssh2->disconnect; } else { warn "Error connecting to $name ($ip); please check host status\n" +; } } sub get_response { my $chan = shift; my $res = ""; until ($res =~ /^\S+\#\s$/m) { # Keep reading until we see what look +s like a prompt $res .= get_channel($chan); $DEBUG && print "res='$res'\n"; } return $res; } sub get_channel { my $chan = shift; my $output = ""; my $bytes = -1; until ($chan->eof || !defined $bytes) { $bytes = $chan->read(my $buffer, 1024); # Blocks unless we set $ch +an->blocking(0) $DEBUG && print "bytes=".($bytes || 'undef')."\n"; if (defined $bytes) { $DEBUG && print "buffer=$buffer\n"; $output .= $buffer; } } return $output; }

      -- Time flies when you don't know what you're doing
        I don't think the get_channel sub is reliable. If for whatever reason the data coming from the remote side is delayed, the non-blocking read call is going to return undef and any additional data will be lost.

        Doing non-blocking IO with Net::SSH2 is far from being easy. You can see how it is done in my module Net::SSH::Any using select to check when new data arrives on the SSH socket (the code is here, see the __io3 method).

        Another possibility that usually works is to send all the input data (login and commands) in one go and then capture everything in blocking mode until you get and EOF. You will have to add an additional command to close the connection from the remote side (i.e. exit).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1026968]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2014-11-28 04:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (193 votes), past polls