Pages

Thursday, 23 September 2021

GoTTY - Share your terminal as a web application


Share your terminal as a web application.

All Contributors

GitHub release MIT License

GoTTY is a simple command line tool that turns your CLI tools into web applications.

Original work by Iwasaki Yudai. There would be no GoTTY without him. 

Screenshot

Installation

go get Installation (Development)

If you have a Go language environment, you can install GoTTY with the go get command. However, this command builds a binary file from the latest master branch, which can include unstable or breaking changes. GoTTY requires go1.9 or later.

$ go get github.com/sorenisanerd/gotty

Usage

Usage: gotty [options] <command> [<arguments...>]

Run gotty with your preferred command as its arguments (e.g. gotty top).

By default, GoTTY starts a web server at port 8080. Open the URL on your web browser and you can see the running command as if it were running on your terminal.

Options

   --address value, -a value     IP address to listen (default: "0.0.0.0") [$GOTTY_ADDRESS]
   --port value, -p value        Port number to liten (default: "8080") [$GOTTY_PORT]
   --path value, -m value        Base path (default: "/") [$GOTTY_PATH]
   --permit-write, -w            Permit clients to write to the TTY (BE CAREFUL) (default: false) [$GOTTY_PERMIT_WRITE]
   --credential value, -c value  Credential for Basic Authentication (ex: user:pass, default disabled) [$GOTTY_CREDENTIAL]
   --random-url, -r              Add a random string to the URL (default: false) [$GOTTY_RANDOM_URL]
   --random-url-length value     Random URL length (default: 8) [$GOTTY_RANDOM_URL_LENGTH]
   --tls, -t                     Enable TLS/SSL (default: false) [$GOTTY_TLS]
   --tls-crt value               TLS/SSL certificate file path (default: "~/.gotty.crt") [$GOTTY_TLS_CRT]
   --tls-key value               TLS/SSL key file path (default: "~/.gotty.key") [$GOTTY_TLS_KEY]
   --tls-ca-crt value            TLS/SSL CA certificate file for client certifications (default: "~/.gotty.ca.crt") [$GOTTY_TLS_CA_CRT]
   --index value                 Custom index.html file [$GOTTY_INDEX]
   --title-format value          Title format of browser window (default: "{{ .command }}@{{ .hostname }}") [$GOTTY_TITLE_FORMAT]
   --reconnect                   Enable reconnection (default: false) [$GOTTY_RECONNECT]
   --reconnect-time value        Time to reconnect (default: 10) [$GOTTY_RECONNECT_TIME]
   --max-connection value        Maximum connection to gotty (default: 0) [$GOTTY_MAX_CONNECTION]
   --once                        Accept only one client and exit on disconnection (default: false) [$GOTTY_ONCE]
   --timeout value               Timeout seconds for waiting a client(0 to disable) (default: 0) [$GOTTY_TIMEOUT]
   --permit-arguments            Permit clients to send command line arguments in URL (e.g. http://example.com:8080/?arg=AAA&arg=BBB) (default: false) [$GOTTY_PERMIT_ARGUMENTS]
   --width value                 Static width of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_WIDTH]
   --height value                Static height of the screen, 0(default) means dynamically resize (default: 0) [$GOTTY_HEIGHT]
   --ws-origin value             A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default [$GOTTY_WS_ORIGIN]
   --term value                  Terminal name to use on the browser, one of xterm or hterm. (default: "xterm") [$GOTTY_TERM]
   --enable-webgl                Enable WebGL renderer (default: true) [$GOTTY_ENABLE_WEBGL]
   --close-signal value          Signal sent to the command process when gotty close it (default: SIGHUP) (default: 1) [$GOTTY_CLOSE_SIGNAL]
   --close-timeout value         Time in seconds to force kill process after client is disconnected (default: -1) (default: -1) [$GOTTY_CLOSE_TIMEOUT]
   --config value                Config file path (default: "~/.gotty") [$GOTTY_CONFIG]
   --help, -h                    show help (default: false)
   --version, -v                 print the version (default: false)

Config File

You can customize default options and your terminal (hterm) by providing a config file to the gotty command. GoTTY loads a profile file at ~/.gotty by default when it exists.

// Listen at port 9000 by default
port = "9000"

// Enable TSL/SSL by default
enable_tls = true

// hterm preferences
// Smaller font and a little bit bluer background color
preferences {
    font_size = 5
    background_color = "rgb(16, 16, 32)"
}

See the .gotty file in this repository for the list of configuration options.

Security Options

By default, GoTTY doesn't allow clients to send any keystrokes or commands except terminal window resizing. When you want to permit clients to write input to the TTY, add the -w option. However, accepting input from remote clients is dangerous for most commands. When you need interaction with the TTY for some reasons, consider starting GoTTY with tmux or GNU Screen and run your command on it (see "Sharing with Multiple Clients" section for detail).

To restrict client access, you can use the -c option to enable the basic authentication. With this option, clients need to input the specified username and password to connect to the GoTTY server. Note that the credentials will be transmitted between the server and clients in plain text. For more strict authentication, consider the SSL/TLS client certificate authentication described below.

The -r option is a little bit more casual way to restrict access. With this option, GoTTY generates a random URL so that only people who know the URL can get access to the server.

All traffic between the server and clients are NOT encrypted by default. When you send secret information through GoTTY, we strongly recommend you use the -t option which enables TLS/SSL on the session. By default, GoTTY loads the crt and key files placed at ~/.gotty.crt and ~/.gotty.key. You can overwrite these file paths with the --tls-crt and --tls-key options. When you need to generate a self-signed certification file, you can use the openssl command.

openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout ~/.gotty.key -out ~/.gotty.crt

(NOTE: For Safari uses, see how to enable self-signed certificates for WebSockets when use self-signed certificates)

For additional security, you can use the SSL/TLS client certificate authentication by providing a CA certificate file to the --tls-ca-crt option (this option requires the -t or --tls to be set). This option requires all clients to send valid client certificates that are signed by the specified certification authority.

Sharing with Multiple Clients

GoTTY starts a new process with the given command when a new client connects to the server. This means users cannot share a single terminal with others by default. However, you can use terminal multiplexers for sharing a single process with multiple clients.

Screen

After installing GNU screen, start a new session with screen -S name-for-session and connect to it with gotty in another terminal window/tab through screen -x name-for-session. All commands and activities being done in the first terminal tab/window will now be broadcasted by gotty.

Tmux

For example, you can start a new tmux session named gotty with top command by the command below.

$ gotty tmux new -A -s gotty top

This command doesn't allow clients to send keystrokes, however, you can attach the session from your local terminal and run operations like switching the mode of the top command. To connect to the tmux session from your terminal, you can use following command.

$ tmux new -A -s gotty

By using terminal multiplexers, you can have the control of your terminal and allow clients to just see your screen.

Quick Sharing on tmux

To share your current session with others by a shortcut key, you can add a line like below to your .tmux.conf.

# Start GoTTY in a new window with C-t
bind-key C-t new-window "gotty tmux attach -t `tmux display -p '#S'`"

Playing with Docker

When you want to create a jailed environment for each client, you can use Docker containers like following:

$ gotty -w docker run -it --rm busybox

Development

You can build a binary by simply running make. go1.16 is required.

To build the frontend part (JS files and other static files), you need npm.

Architecture

GoTTY uses xterm.js and hterm to run a JavaScript based terminal on web browsers. GoTTY itself provides a websocket server that simply relays output from the TTY to clients and receives input from clients and forwards it to the TTY. This hterm + websocket idea is inspired by Wetty.

Alternatives

Command line client

  • gotty-client: If you want to connect to GoTTY server from your terminal

Terminal/SSH on Web Browsers

  • Secure Shell (Chrome App): If you are a chrome user and need a "real" SSH client on your web browser, perhaps the Secure Shell app is what you want
  • Wetty: Node based web terminal (SSH/login)
  • ttyd: C port of GoTTY with CJK and IME support

Terminal Sharing

  • tmate: Forked-Tmux based Terminal-Terminal sharing
  • termshare: Terminal-Terminal sharing through a HTTP server
  • tmux: Tmux itself also supports TTY sharing through SSH)
from  https://github.com/sorenisanerd/gotty
-------
 

使用GoTTY访问内网服务器

之前一直使用 'frp内网穿透' 将内部服务器暴露在公网方便ssh访问。然而就在前不久,合作单位出于安全考虑全面排查FRP,并禁止在内部主机上使用该软件。向相关部门保证不会再使用该软件后解封了服务器ip,但带来的挑战是如何访问内网资源?

方案

除了FRP类隧道型工具,还有向日葵等远控工具,也能较为方便的访问内网资源。但是今年年初 向日葵爆出了严重的远程命令执行(RCE)漏洞,在内部也是被明令禁止。加之向日葵等远控工具基本上都基于图形界面,对带宽要求高操作不流畅,非不得已不会考虑。

单位允许通过VPN客户端访问内网白名单的HTTP资源,但也仅限于HTTP资源,SSH等协议不在授权范围内。好消息是恰好有个服务器运行着白名单网站,可以考虑从这里入手访问内网资源。

限于HTTP协议访问,想到的方案是SSH over HTTP,或者网页终端。第一个出现在脑海里的东西是 宝塔面板,其内置网页终端,完全满足要求。但宝塔要求在全新的服务器上部署,并且素有“删库塔”美誉及安全忧虑,念头刚出现就被否定了。

一番搜索,选择了 GoTTY 这款能将终端映射到网页的工具。其优点有:1. 使用Golang编写,下载即可运行,不需要安装额外依赖;2. 可设置网页终端的读写模式,方便不同场景使用;3. 可设置用户名和密码鉴权,提高安全性。

GoTTY使用较为简单,从官网下载编译好的二进制即可运行,本文仅指出几个需要注意的点:

1. 本人希望通过这个终端访问内网资源,即需要在提供的网页终端输入,因此启动命令要加上-w选项:./gotty -w bash

2. 即使在内网,安全性也是很重要的,需要-c选项设置Basic Auth:./gotty -c username:password

3. 在本人的情况中,必须通过VPN网关提供的主机名和端口访问网站,因此需要通过网站的Nginx将请求转发到GoTTY;

4. 因为经过了VPN网关着一层代理,外部访问的域名端口和服务器配置的已经截然不同。GoTTY基于websocket协议在浏览器和服务端通信,并且会校验origin。官方文档有--ws-origin选项可设置Origin,但是编译好的稳定版并不支持。为了在Nginx中转后还能访问到GoTTY,需要用go命令自行编译最新版。

解决上述问题后,终于可以在接入VPN后通过网页访问内网资源了。

安全性探究

单位为了安全性禁止了FRP类应用,因此不希望GoTTY会给内部网络带来威胁。

一番思量后,确定GoTTY有三重安全保障机制:

1. 必须登陆单位VPN才又可能访问到GoTTY,安全性与VPN提供的相同;

2. 只能通过自定义的特定路径才能访问GoTTY,并且因为不能影响网站运行,路径不可能是根路径;

3. 即使登陆了VPN,知晓了访问路径,还需要输入用户名密码才能最终访问GoTTY提供的资源。

有了这三重保障,可以说GoTTY基本不会给内网带来威胁,相较于FRP直接暴露公网提高了许多。

总结

通过GoTTY,可以成功的在不给内网带来安全威胁的情况下访问内网资源。然而由于GoTTY基于网页终端,适合于运行命令和做简单交互,但无法使用scp/sftp等方式上传文件到服务器,使用上较之前少了许多便利。

---------------------------------

相关帖子:

https://briteming.blogspot.com/2021/07/gotty-share-your-terminal-as-web.html


 

 

 

 

 

 

 

No comments:

Post a Comment