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
  });
});
5
  • @mscdex - any chance you can answer this one? Commented Sep 26, 2017 at 15:40
  • Have you tried this example? Is that the kind of thing you're looking for? Commented Sep 26, 2017 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! Commented Sep 27, 2017 at 0: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') Commented Sep 27, 2017 at 2:32
  • That was it! Thanks for the help and thanks for your work on ssh2 module. Commented Sep 27, 2017 at 4:03

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.