1

I am attempting to create a web terminal that connects to a remote host and allows the running of normal terminal commands. I have it able to connect to the remote server and to my understanding stream.write(data) should be what triggers the command to be run on the remote server and return the output, however I get the input returned to the frontend instead.

term.html

<!doctype html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script src="/socket.io/socket.io.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" charset="utf-8">
      var socket = io.connect('http://localhost:8080', {query: 'host=IP_Address&port=22&username=user&password=password'});

      // Display the resonse from the server
      function add_content(str){
        console.log(str);
        $('div').append('<p>' + $('<div/>').text(str).html() + '</p>');
        $(window).scrollTop($('body').height() - $(window).height() + 80);
      }

      // Backend -> Browser
      socket.on('server_data', function(data) {
          add_content(data);
      });

      // Disconnect message
      socket.on('disconnect', function() {
          add_content('\r\n*** Disconnected from backend***\r\n');
      });

      // Browser -> Backend
      $(function(){
        $('form').submit(function(e){
          e.preventDefault();
          var input = $('input');
          socket.emit('client_data', input.val());
          input.val('');
          return false;
        });
        $('input').focus();
      });
    </script> 

    <style type="text/css">
      body, p, input {
        font-family: fixed;
        font-size: 13px;
        border: none;
      }
      p { white-space: pre; }
      p, form, input { margin:0; padding:0; }
      input:focus { outline: none; border: none; }
    </style>
  </head>

  <body>
    <div></div>
    <form>
      &gt; <input>
    </form>
  </body>

</html>

server.js

    var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
var SSHClient = require('ssh2').Client;

var listener = app.listen(8080);

var current_directory = null;


function handler (req, res) {
  fs.readFile(__dirname + '/term.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading term.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.on('connection', function(socket) {
  var conn = new SSHClient();
  conn.on('ready', function() {
    socket.emit('server_data', '\r\n*** SSH CONNECTION ESTABLISHED ***\r\n');
    conn.shell(function(err, stream) {
      if (err)
        return socket.emit('server_data', '\r\n*** SSH SHELL ERROR: ' + err.message + ' ***\r\n');
      socket.on('client_data', function(data) {
        stream.write(data);
      });
      stream.on('data', function(data) {
        socket.emit('server_data', data.toString('binary'));
        //console.log('STDOUT: ' + data);  
      }).stderr.on('data', function(data){
        //console.log('STDERR: ' + data);
        socket.emit('server_data', data.toString('binary'));
      }).on('close', function() {
        conn.end();
      });
    });
  }).on('close', function() {
    socket.emit('server_data', '\r\n*** SSH CONNECTION CLOSED ***\r\n');
  }).on('error', function(err) {
    socket.emit('server_data', '\r\n*** SSH CONNECTION ERROR: ' + err.message + ' ***\r\n');
  }).connect({
    host: socket.handshake.query.host,
    port: socket.handshake.query.port,
    username: socket.handshake.query.username,
    password: socket.handshake.query.password
  });
});
Rob
  • 14,746
  • 28
  • 47
  • 65
AndrewVT
  • 335
  • 1
  • 8
  • @mscdex - any chance you can answer this one? – AndrewVT Sep 26 '17 at 15:40
  • Have you tried [this example](https://stackoverflow.com/questions/38689707/connecting-to-remote-ssh-server-via-node-js-html5-console/38690242#38690242)? Is that the kind of thing you're looking for? – mscdex Sep 26 '17 at 22:38
  • mcsdex - I did explore that option but I am not entirely happy with xterm (your example there was great by the way). My hope was to build up my understanding of the moving parts in all this by bringing everything back a step to see what socket io and ssh2 are capable on their own. I just seem to be missing something in how the shell in ssh2 actually runs the command and passes the output back to the client side. Any help in getting this basic implementation running would further my understanding greatly. Thanks! – AndrewVT Sep 27 '17 at 00:00
  • 1
    You're probably missing the `\n` at the end (to simulate the pressing of the 'enter' key) of the input/command since you're using `.shell()`, which is an interactive shell. Try: `stream.write(data + '\n')` – mscdex Sep 27 '17 at 02:32
  • That was it! Thanks for the help and thanks for your work on ssh2 module. – AndrewVT Sep 27 '17 at 04:03

0 Answers0