Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: SSH to remote subsystem (Net::OpenSSH?)

by salva (Abbot)
on Mar 19, 2013 at 16:48 UTC ( #1024341=note: print w/ replies, xml ) Need Help??


in reply to SSH to remote subsystem (Net::OpenSSH?)

yes, for instance:

my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$pass); $ssh->error and die "unable to connect to remote host: " . $ssh->error +; my ($socket, $pid) = $ssh->open2socket({ssh_opts => '-s'}, 'xmlagent') +; talk_to_subsystem($socket); waitpid($pid, 0);

Depending on the way the subsystem works there may be better ways to interact with it.


Comment on Re: SSH to remote subsystem (Net::OpenSSH?)
Download Code
Re^2: SSH to remote subsystem (Net::OpenSSH?)
by sojourner9 (Initiate) on Mar 19, 2013 at 21:23 UTC

    Once you're logged into the subsytem, you get a hello message like this:

    <?xml version="1.0" encoding="ISO-8859-1"?> <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <capabilities> <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability> <capability>urn:ietf:params:netconf:base:1.0</capability> </capabilities> <session-id>25470</session-id> </hello> ]]>]]>

    You reply with a client hello message that is formatted very similarly, and then you send it XML/NETCONF formatted messages and it replies with XML formatted responses.

    Using your suggestion, I tried this:

    my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$pass); $ssh->error and die "unable to connect to remote host: " . $ssh->error +; my ($socket, $pid) = $ssh->open2socket({ssh_opts => '-s'}, 'xmlagent') +; ($socket, $pid) = $ssh->open2socket; while (<$socket>) { print }; waitpid($pid, 0);

    Expecting to either see the XML hello message in the debug, or in the socket print. However, it appears that it first makes a connection to the main system, authenticates, and then tries to connect to the subsystem. I'm not good enough with SSH to know if that's how it works with except/shell version or not. Debug shows this:

    # call args: ['ssh','-o','ServerAliveInterval=30','-x2MN','-o','Number +OfPasswordPrompts=1','-o','PreferredAuthentications=keyboard-interact +ive,password','-S','/home/user/.libnet-openssh-perl/user-host-31054-2 +7407','-l','user','host','--']

    Then I see the banner go by and the password prompt as expected, but no XML hello. Then I see:

    # call args: ['ssh','-s','-S','/home/user/.libnet-openssh-perl/user-ho +st-31054-27407','-l','user','host','--','xmlagent'] # open_ex: ['ssh','-s','-S','/home/user/.libnet-openssh-perl/user-host +-31054-27407','-l','user','host','--','xmlagent'] # call args: ['ssh','-S','/home/user/.libnet-openssh-perl/user-host-31 +054-27407','-l','user','host','--'] # open_ex: ['ssh','-S','/home/user/.libnet-openssh-perl/user-host-3105 +4-27407','-l','user','host','--'] Pseudo-terminal will not be allocated because stdin is not a terminal. stty: standard input: Invalid argument

    And then it hangs there, probably looping on the "while". But, the important bit for this step is that it does not look this this creates a properly formatted SSH command either. The "-s" flag is at the beginning, but the "xmlagent" value is at the end - I would expect that it would need to send "-s xmlagent" in order for the -s flag to have meaning. I'm also suspecting that it needs to do so in the first connection, not later (but I'm not positive if that is how SSH should work or not).

      Using your suggestion, I tried...

      You have two calls to open2socket, the first establishes a connection to the Netconf subsystem, but then on the next line it opens a new one to a shell overwriting $socket.

      The correct way to do it is as follows:

      my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$pass); $ssh->error and die "unable to connect to remote host: " . $ssh->error +; my ($socket, $pid) = $ssh->open2socket({ssh_opts => '-s'}, 'xmlagent') +; while (<$socket>) { print };
      Expecting to either see the XML hello message in the debug, or in the socket print. However, it appears that it first makes a connection to the main system, authenticates, and then tries to connect to the subsystem. I'm not good enough with SSH to know if that's how it works with except/shell version or not.

      This is how the SSH protocol works, first a TCP connection is established, then encryption and authentication are negotiated and from that point, bidirectional channels can be open freely between the client and server even in parallel (though, most servers set a limit on the number of concurrent channels, typically 10).

      When you run ssh from the command line or using Expect, the two phases are performed under the hood by the ssh client, though just one channel is open.

      The "-s" flag is at the beginning, but the "xmlagent" value is at the end

      Yes, it works that way, the subsystem name is not an argument to the -s flag but it is taken from the remote command at the end of the ssh argument list (see ssh).

      BTW, the specification for NETCONF over SSH (rfc4742) says the server must listen not at the default SSH port (22) but at port 830. Have you activated the subsystem also at port 22?

        Derp! Thanks! That extra line of "open2socket" was what was what was causing the problems. Don't know how I missed that creeping in there.

        As for SSH/830 - It looks like the RFC says it must go into NETCONF subsystem when connected on port 830, but should be allowed access to NETCONF when connected to on other ports. Looks like Cisco's implementation is to have the user connect on port 22 and then call the susbsystem

        So, once I got rid of that extra line, it seems to be connecting just fine. I see the banner and logon prompt, and then the remote device's hello message.

        I had issues figuring out how to send queries and receive replies using open2socket, but got it to work using open_ex. Here's what I currently have:

        #!/usr/bin/perl ## CALL MODULES use strict; use warnings; use Net::OpenSSH; ## SET VARIABLES my $host = 'host'; my $user = 'user'; my $pass = 'pass'; my ($ssh, $out, $in, $pid); my ($message); ## OPEN THE SSH SESSION $ssh = Net::OpenSSH->new($host, user=>$user, password=>$pass); $ssh->error and die "unable to connect to remote host: " . $ssh->error +; ($out, $in, undef, $pid) = $ssh->open_ex( { stdin_pipe=>1, stdout_pipe +=>1, ssh_opts=>'-s'},'xmlagent' ) or die "open_ex failed: " . $ssh->e +rror; ## SEND THE CLIENT HELLO $message = qq~ <?xml version="1.0"?> <nc:hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <nc:capabilities> <nc:capability>urn:ietf:params:xml:ns:netconf:base:1.0 +</nc:capability> </nc:capabilities> </nc:hello> ]]>]]>~; print $out $message; ## SEND THE QUERY FOR THE ARP TABLE $message = qq~ <?xml version="1.0" encoding="UTF-8"?> <nf:rpc message-id="1" xmlns="http://www.cisco.com/nxos:1.0:arp" xmlns +:nf="urn:ietf:params:xml:ns:netconf:base:1.0"> <nf:get> <nf:filter type="subtree"> <show> <ip> <arp/> </ip> </show> </nf:filter> </nf:get> </nf:rpc> ]]>]]>~; print $out $message; ## PRINT THE RESULTS while (<$in>) { print; last if $_ =~ m/\/nf:rpc-reply/; }; waitpid($pid, 0); exit;

        And, here's a snippet of the results

        <ROW_adj> <intf-out>Vlan852</intf-out> <ip-addr-out>10.7.252.191</ip-addr-out> <time-stamp>00:00:50</time-stamp> <mac>0050.56ab.2d52</mac> </ROW_adj> </TABLE_adj> </ROW_vrf> </TABLE_vrf> </__readonly__> </__XML__OPT_Cmd_arp_show_adj_cmd___readonly__> </__XML__OPT_Cmd_arp_show_adj_cmd_ip-address> </arp> </ip> </show> </nf:data> </nf:rpc-reply>

        My main problem right now is that I expected the "last" statement of the while loop to find the last line ("/nf:rpc-reply") of the switch's reply and move on to whatever we wanted to do next (In this case, close everything down). But, instead it seems to hang there, so I must still be missing something).

        And, would open2socket be better than open_ex? And if so, can you show a sample of how to print to and read from it? I tried a couple different ways, but wasn't getting it

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (6)
As of 2014-12-28 08:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (179 votes), past polls