Add small changes to document the project here and there

pull/14/merge
Vasile Popescu 6 years ago
parent aee0834308
commit a34033d92e

@ -35,11 +35,13 @@ clean:
rm -fr frontend/out/
@echo "Cleaned"
# Runs the server, without TLS/HTTPS (no need for localhost testing)
runs: $(TTY_SERVER)
./$(TTY_SERVER) --url http://localhost:9090 --web_address :9090 --sender_address :7654 -frontend_path ./frontend/public
# Runs the sender, without TLS (no need for localhost testing)
runc: $(TTY_SENDER)
./$(TTY_SENDER) --logfile output.log --useTLS=false
./$(TTY_SENDER) --useTLS=false
test:
@go test github.com/elisescu/tty-share/testing -v

@ -1,24 +1,91 @@
TTY Share
========
=========
A small tool to allow sharing a terminal command with others via Internet.
Shortly, the user can start a command in the terminal and then others can watch that command via
Internet in the browser.
More info to come.
A small tool that allows sharing the terminal over the Internet, in the web browser. It works with a shell command, or any other utility that relies on the unix PTY architecture.
It consists of two command line utilities: `tty_sender` and `tty_server`. The server is only needed if you want to host it yourself.
Run the code
===========
The `tty_sender` is used on the machine that wants to share the terminal, and it connects to the server to generate a unique URL, over which the terminal can be viewed in the browser.
* Build the frontend
Read more about how it works in the [documentation](doc/architecture.md).
[demo](doc/demo.gif)
Building and running the code
=============================
For an easy deployment, the server can bundle inside the binary all the frontend resources, so in the end, there will be only one file to be copied and deployed. However, the frontend resources, can also be served from a local folder, with a command line flag.
### Build all
```
cd tty-share/frontend
cd frontend
npm install
npm run build
npm run build # builds the frontend
cd -
make all # builds both the sender and server
```
### Run the server
```
make runs
```
Will run the server on the localhost.
* Run the server
### Run the sender
```
cd tty-share
make run
make runc
```
Will run the sender and connect it to the server running on the local host (so the above command has
to be ran first).
For more info, on how to run, see the Makefile, or the help of the two binaries (`tty_sender` and `tty_receiver`)
The project didn't follow the typical way of building go applications, because everything is put in one single project and package, for the ease of development, and also because the bundle containing the frontend has to be built as well. Perhaps there's a better way, but this works for now.
TLS and HTTPS
=============
At the moment the `tty_sender` supports connecting over a TLS connection to the server, but the
server doesn't have that implemented yet. However, the server can easily run behind a proxy which
can take care of encrypting the connections from the senders and receivers (doing both TLS and
HTTPS), without the server knowing about it.
However, the server should have support for being able to listen on TLS connections from the sender
as well, and this will be added in the future.
TODO
====
There are several improvements, and additions that can be done further:
* Update the tests and write some more.
* Add support for listening on sender connections over TLS.
* React on the `tty_receiver` window size as well. For now, the size of the terminal window is
decided by the `tty_sender`, but perhaps both the sender and receiver should have a say in this.
* Read only sessions, where the `tty_reciver` side can only watch, and cannot interact with the
terminal session on the sender side.
* Non-web based `tty_receiver` can be implemented as well, without the need of a browser, but using
it from the command line.
* End-to-end encryption. Right now, the server can see what messages the sender and receiver are
exchanging, but an end-to-end encryption layer can be built on top of this. It has been thought
from the beginning, but it's just not implemented. The terminal IO messages are packed in protocol
messages, and the payload can be easily encrypted with a shared key derived from a password that
only the sender and receiver sides know.
* Notify the `tty_sender` user when a `tty_receiver` got connected.
* Many other
Other solutions
==============
* [tmate](https://tmate.io/) - is a very similar solution, which I have been using several times. It
works really well - the only disadvantage, being that it doesn't support sharing it via the
browser.
Credits
=======
* [xterm.js](https://xtermjs.org/) - used in the browser receiver.
* [gotty](https://github.com/yudai/gotty) - used for inspiration and motivation.
* [tmate](https://tmate.io/) - inspiration and motivation.
* [https://codepen.io/chiaren/pen/ALwnI](https://codepen.io/chiaren/pen/ALwnI) - for the free 404
page.

@ -0,0 +1,24 @@
High level architecture
=======================
```
Alice
+-tty_sender--------------+ +-tty_server----------------+ Bob
| | | | https:// +------------+
| +------+ +-----+ | TLS | +------+ +---------+ | wss:// |tty_receiver|
| | bash | <-+-> |proto| <---------------> | proto| <-> | session | +-----+------> | 1 |
| +------+ | +-----+ | | +------+ +---------+ | | +------------+
| | | | | |
| +-> pty | +---------------------------+ | +------------+
+-------------------------+ +------> |tty_receiver|
| 2 |
+------------+
```
Alice wants to share a terminal session with Bob, so she starts `tty_sender` on her machine, inside the terminal. `tty_sender` then connects to the `tty_server` and starts inside a `bash` process. It then puts the terminal in which it was started in RAW mode, and the stdin and stdout are multiplexed to/from the `bash` process it started, and the remote connection to the `tty_server`. On the server side, a session is created, which connects the `tty_sender` connection with the future `tty_receiver` instances, running in the browser. The `tty_receiver` runs inside the browser, on top of [xterm.js](https://xtermjs.org/), and is served by the server, via a unique session URL. Alice has to send this unique URL to Bob.
Once the connection is established, Bob can then interact inside the browser with the `bash` session started by Alice. When Bob presses, for example, the key `a`, this is detected by `xterm.js` and sent via a websockets connection to the server side. From there, it is sent to the `tty_sender` which sends it to the pseudo terminal attached to the `bash` process started inside `tty_sender`. Then character `a` is received via the standard output of the `bash` command, and is sent from there both to the standard output of the `tty_sender`, so Alice can see it, and also to the `tty_receiver` (via the server), so Bob can see it too.
More specific details on how this is implemented, can be seen in the source code of the `tty_sender`.

@ -1,22 +1,24 @@
## Overview of the architecture
Information here might not be accurate, as this file was used as a dump of all random ideas that came at the beginning of the project. Many of them are not implemented, or were abandoned.
## Architecture
```
B
A +-------------+
+-----------------+ | | C
| TTYSender(cmd) | <+-> | TTYProxy | +-------------------+
+-----------------+ | Server | <-+->| TTYReceiver(web) |
| tty_sender(cmd) | <+-> | tty_server | +-------------------+
+-----------------+ | | <-+->| tty_receiver(web) |
| | +-------------------+
| |
| | D
| | +-------------------+
| | <-+->| TTYReceiver(ssh) |
| | <-+->| tty_receiver(ssh) |
| | +-------------------+
| |
M | | N
+-----------------+ | | +-------------------+
| TTYSender(cmd) | <+-> | | <-+->| TTYREceiver(web) |
| tty_sender(cmd) | <+-> | | <-+->| tty_receiver(web) |
+-----------------+ +-------------+ +-------------------+
```
##
@ -26,7 +28,7 @@ M <-> N
```
### A
Where A is the TTYSender, which will be used by the user Alice to share her terminal session. She will start it in the command line, with something like:
Where A is the tty_sender, which will be used by the user Alice to share her terminal session. She will start it in the command line, with something like:
```
tty-share bash
```
@ -42,7 +44,7 @@ Url number 2. will allow the user to interact with the terminale.
Url number 3. ssh access, to follow the remote command from a remote terminal.
Url number 4. provides an interface to control various options related to sharing.
### B
B is the TTYProxyServer, which will be publicly accessible and to which the TTYSender will connect to. On the TTYProxyServer will be created te sessions (read-only and write), and URLs will be returned back to A. Whent the command that A started exits, the session will end, so C should know.
B is the tty_server, which will be publicly accessible and to which the tty_sender will connect to. On the tty_server will be created te sessions (read-only and write), and URLs will be returned back to A. Whent the command that A started exits, the session will end, so C should know.
### C
C is the browser via which user Chris will receive the terminal which Alice has shared.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@ -1,2 +0,0 @@
# Sat Oct 28 16:42:04 CEST 2017
Got the first end-to-end communication between the tty-share command and the

@ -1,45 +0,0 @@
- process reads input
- key shortcuts . same as input?
- process writes to output?
Notes:
- background programs are suspended when they try to run to the terminal
- user input redirected to foreground program only
- UART driver, line discipline instance and TTY driver compose a TTY device
- job = process group (jobs, fg, bg)
- session, session leader (shell - talks to the kernel through signals and system calls)
```
cat &
ls | sort
```
As you can see in the diagram above, several processes have /dev/pts/0 attached to their standard input.
But only the foreground job (the ls | sort pipeline) will receive input from the TTY.
Likewise, only the foreground job will be allowed to write to the TTY device (in the default configuration).
If the cat process were to attempt to write to the TTY, the kernel would suspend it using a signal.
End-to-end encryption:
======================
* sender:
- generate salt, and the shared key from the password
- connect to the server sending the session start info:
SessionStart {
salt String
passwordVerifierA String
passwordVerifierB String
allowSSHNotEndToEnd bool
}
- gets one of the two replies:
SessionStartNotOk - should stop; or
SessionStartOK {
webTTYUrl string
sshTTYUrl string
}
* web-receiver:
- open the link: get the html page and try to open the WS connection.
- has the same salt as the sender, served in the web page
- asks the user for the password and checks the password and asks server to validate password verifier
* ssh-receiver:
- connects with ssh to some-random-string@tty-share.io

@ -255,6 +255,7 @@ func (server *TTYProxyServer) Listen() (err error) {
wg.Done()
}()
// TODO: Add support for listening for connections over TLS
// Listen on connections on the tty sender side
server.ttySendersListener, err = net.Listen("tcp", server.config.TTYSenderAddress)
if err != nil {

Loading…
Cancel
Save