NodeJS SSH authentication host and command execution

I want to have a NodeJS application to which I can connect over SSH with a public key and send some data to. To be more explicit it should go as follow:

  • NodeJS application has some functions written
  • From a server I ssh the nodejs application and tries to identify me by my public key
  • After I am authenticated, I can send some strings to it, the app is going to parse the string and execute different functions

The only problem is that I cannot manage to do this with any SSH npm package existing. I want the nodejs app to just accept SSH connection and do the authentication and wait for some strings. Is this possible?

EDIT: I want to go with this approach because I only want to call the node functions to execute something only from some allowed clients (servers) and I don't want to send those requests via HTTP so anyone could access it

You're probably better off using HTTPS with client certificates rather than using an SSH server within node (although you can do that with the ssh module, a binding to libssh2), if you want to use certificates.

Here's how you'd set up the HTTPS server:

var https = require('https'),
    fs = require('fs');

var options = {
  key: fs.readFileSync('server.key'), // server private key
  cert: fs.readFileSync('server.crt'), // server certificate
  ca: fs.readFileSync('server_ca.crt'), // server CA, this can be an array of CAs too
  requestCert: true
};

https.createServer(options, function(req, res) {
  if (req.client.authorized) {
    res.writeHead(200);
    res.end('Hello world!');
  } else {
    res.writeHead(401);
    res.end();
  }
}).listen(443);

Then it's just a matter of generating a client certificate using the server's CA that you use with your HTTPS client.

For connecting to the HTTPS server:

For cURL, the command line would look something like: curl -v -s --cacert server_ca.crt --key client.key --cert client.crt https://localhost or to skip server verification: curl -v -s -k --key client.key --cert client.crt https://localhost

For node.js, you might use client code like:

var https = require('https'),
    fs = require('fs');

var options = {
  // normal http.request()-specific options
  method: 'GET',
  path: '/',

  // tls.connect()-specific options
  key: fs.readFileSync('client.key'), // client private key
  cert: fs.readFileSync('client.crt'), // client certificate
  ca: fs.readFileSync('server_ca.crt'), // server CA, this can be an array of CAs too
  // or comment out the `ca` setting and use the following to skip server verification,
  // similar to cURL's `-k` option:
  //rejectUnauthorized: false
};

https.request(options, function(res) {
  if (res.statusCode === 200)
    console.log('Accepted!');
  else
    console.log('Rejected!');

  // drain and discard any response data
  res.resume();
}).end();