29

I came across this awesome library xterm.js which is also the base for Visual Studio Code's terminal. I have a very general question.

I want to access a machine(ssh into a machine ) on a local network through a web based terminal(which is out of network, may be on a aws server). I was able to do this in a local network successfully but I could not reach to a conclusion to do it from Internet-->local network .

As an example - An aws server running the application on ip 54.123.11.98 which has a GUI with a button to open terminal. I want to open terminal of a local machine which is in a local network somewhere behind some public ip on local ip 192.168.1.7.

Can the above example be achieved using some sort of solutions where i can use xterm.js so that I don't have to go for building a web based terminal? What are the major security concerns I should keep in mind while exposing the terminals this way ?

I was thinking in line with using a fixed intermediate server between AWS and local network ip and use some sort of reverse ssh tunnel process to do this but I am not sure if this is the right way or could there be a more simple/better way to achieve this.

I know digital ocean, google cloud , they all do this but they have to connect to a computer which has public ip while I have a machine in a local network. I don't really want to configure router to do any kind of setup .

Community
  • 1
  • 1
Ankit Kulkarni
  • 1,065
  • 3
  • 13
  • 23
  • xterm.js has a bug. The bug is that it uses textbox-selection instead of term-selection. –  Apr 07 '20 at 22:40

2 Answers2

19

After a bit of research here is working code.

Libraries:

1) https://socket.io/

This library is used for transmit package from client to server.

2) https://github.com/staltz/xstream

This library is used for terminal view.

3) https://github.com/mscdex/ssh2

This is the main library which is used for establishing a connection with your remote server.

Step 1: Install Library 3 into your project folder

Step 2: Start from node side create a server.js file for open socket

Step 3: Connection client socket to node server (both are in local machine)

The tricky logic is how to use socket and ssh2.

On emission of socket you need to trigger an SSH command using the ssh2 library. On response of the ssh2 library (from server) you need to transmit the socket package to the client. That's it.

Click here to find an example.

That example will have these files & folders:

Type    Name
------------
FILE    server.js
FILE    package.json
FOLDER  src
FOLDER  xtream

First you need to configure your server IP, user and password or cert file on server.js and just run node server.js.

P.S.: Don't forget to run npm install

Let me know if you have any questions!

Ankit vadariya
  • 1,177
  • 10
  • 13
  • Thanks Ankit, for so much of help(the first part of flow was really helpul). I will test the code too as soon as possible and let you know. Will accept the answer too soon – Ankit Kulkarni Sep 02 '17 at 06:24
  • Sure .. please let me know if you got any problem or question. happy to help. Thanks – Ankit vadariya Sep 04 '17 at 07:12
  • Thanks @Ankitvadariya. The code worked perfectly after making few changes. Could you also describe how would you approach the same thing if you have 1)- a number of linux clients behind NAT(which do not have public IP) 2)- an aws server 3)- the client wants to give server access to its terminal Since client is behind NAT, server can't directly ssh to it. I think we can use client to ssh into server and use reverse ssh tunneling to get the client access but what would be the flow of the process and how would it work. Is it possible to do this by modifying above code? – kartik Sep 06 '17 at 07:20
  • @kartik yes you can do that. You have to trigger socket package in private channel instated of global channel. ssh2 support almost things. https://github.com/mscdex/ssh2 You have to just implement tricky logic like this ! – Ankit vadariya Sep 06 '17 at 08:12
  • @Ankitvadariya can you shed a little more light on it , I don't have any of the node experience. If you can point to documentation that would be great – Ankit Kulkarni Sep 06 '17 at 11:06
  • @AnkitKulkarni , Sure please let me know what you want to understand. i will do that. – Ankit vadariya Sep 07 '17 at 05:10
2

After some research later I came across this service : https://tmate.io/ which does the job perfectly. Though if you need a web-based terminal of tmate you have to use their ssh servers as a reverse proxy which ideally I was not comfortable with. However, they provide tmate-server which can be used to host your own reverse proxy server but lacks web UI. But to build a system where you have to access a client behind NAT over ssh on web, below are the steps.

  • Install and configure tmate-server on some cloud machine.
  • Install tmate on the client side and configure to connect to a cloud machine.
  • Create a nodejs application using xterm.js(easy because of WebSocket based communication) which connects to your tmate-server and pass commands to the respective client. (Beware of security issues of exposing this application, since you will be passing Linux commands ).
  • Depending on your use case you might need a small wrapper around tmate client on client-side to start/stop it automatically or via some UI/manual action.

Note: I wrote a small wrapper on client-side as well to start/stop and pass on the required information to an API server (written in nodejs) which then pass on the information to another API which connects the browser to the respective client session. Since we had written this application it included authentication as well as command restrictions of what can be run on terminal. You can customize it a lot.

Community
  • 1
  • 1
Ankit Kulkarni
  • 1,065
  • 3
  • 13
  • 23