Pankaj Pankaj - 3 months ago 56
Node.js Question

node.js ssh2shell wrapper fails to login to cisco devices

I'm using node to manage some of our cisco devices and am running into an issue which I haven't been able to resolve in last two days.

Using SSH2 module I am able to connect and execute commands on Cisco gear, but that is limiting me to run only one command at a time. For a follow up command it requires me to establish a new connection and then run another command. This does not work for my needs.

Reading up on some of the answers in SO I started using SSH2Shell wrapper for SSH2 as it allows multiple commands to be executed in a sequential order. But using SSH2Shell I am not able to establish a connection to Cisco gear because the Ciphers offered by Client do not match what are supported on Server. I had the same problem with SSH2 module, but I was able to resolve that by adding the Cipher and KEX. When I do the same in SSh2Shell it does not work. I have tried adding them in several different ways and different places, it just wouldn't connect.

I think I am on the right track, I just don't know the right place to add the Ciphers and KEX.

Here is my code for SSH2Shell:

var host = {
server: {
host: "<host IP>",
port: "22",
userName: "<username>",
password: "<password>"
},
connection: require ('ssh2'),
commands: [
"show version",
"show ssh"
],
algorithms: {
kex: [
'diffie-hellman-group1-sha1',
'ecdh-sha2-nistp256',
'ecdh-sha2-nistp384',
'ecdh-sha2-nistp521',
'diffie-hellman-group-exchange-sha256',
'diffie-hellman-group14-sha1'],
cipher: [
'aes128-ctr',
'aes192-ctr',
'aes256-ctr',
'aes128-gcm',
'aes128-gcm@openssh.com',
'aes256-gcm',
'aes256-gcm@openssh.com',
'aes256-cbc'
]
},
msg: {
send: function( message ) {
console.log("message: " + message);
}
},
verbose: true,
debug: true,
idleTimeOut: 15000,
connectedMessage: "connected",
readyMessage: "ready",
closedMessage: "closed",

onCommandComplete: function( command, response, sshObj ) {

console.log("------------- onCommandComplete ---------");
console.log(command + ": " + response);
},
onEnd: function( sessionText, sshObj ) {
console.log("--------- onEnd has ------------");
console.log(sessionText);
}
};



//Create a new instance
var SSH2Shell = require ('ssh2shell'),
SSH = new SSH2Shell(host);

//Start the process
SSH.connect();


I get 'connected' followed by 'closed' on the terminal when I execute this. Debugging on Cisco Router shows me that my ciphers do not match.

Aug 22 12:06:59: %SSH-3-NO_MATCH: No matching cipher found: client aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm,aes128-gcm@openssh.com,aes256-gcm,aes256-gcm@openssh.com server aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc

Answer

I logged an issue on Github for SSH2Shell and thanks to the author "cmp-202" this issue is now resolved. Here is a copy of the script that works in providing Cipher and KEX. An additional issue was uncovered and resolved in SSH2Shell version 1.5.1, where "keyboard-interactive" event is now implemented. The script below uses both - user defined ciphers and "keyboard-interactive" event:

var host = {
   server: {
      host: "<hostname or IP>",
      port: "22",
      userName: "<username>",
      password: "<password>",
      hashMethod:     "md5", 
      readyTimeout: 50000,
      tryKeyboard: true,
      algorithms: {
         kex: [
            'diffie-hellman-group1-sha1',
            'ecdh-sha2-nistp256',
            'ecdh-sha2-nistp384',
            'ecdh-sha2-nistp521',
            'diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group14-sha1'],
         cipher: [
            'aes128-ctr',
            'aes192-ctr',
            'aes256-ctr',
            'aes128-gcm',
            'aes128-gcm@openssh.com',
            'aes256-gcm',
            'aes256-gcm@openssh.com',
            'aes256-cbc' ]
         }
      },
      commands: [
         "show deviceport global",
         "show deviceport names" ],
      msg: {
         send: function( message ) {
            console.log("message: " + message);
         }
      },
      verbose: true,
      debug: true,
      idleTimeOut: 10000,
      ["keyboard-interactive"]: function(name, instructions, instructionsLang, prompts, finish){
         console.log('Connection :: keyboard-interactive');
         console.log(prompts);
         finish(["<password>"]);
      },
      onEnd: function( sessionText, sshObj ) {
         sshObj.msg.send("--------- onEnd has ------------");
         sshObj.msg.send(sessionText);
      }

};

//Create a new instance
var SSH2Shell = require ('ssh2shell-ssh2.connect-options'),
SSH = new SSH2Shell(host);

//Start the process
SSH.connect();

Hopefully this will save someone some time.

Comments