Upterm is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels.

Overview

Upterm

Upterm is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels. Upterm is good for

  • Remote pair programming
  • Access remote computers behind NATs and firewalls
  • Remote debugging

This is a blog post to describe Upterm in depth.

Usage

The host starts a terminal session:

$ upterm host -- bash

The host displays the ssh connection string:

$ upterm session current
=== IQKSFOICLSNNXQZTDKOJ
Command:                bash
Force Command:          n/a
Host:                   ssh://uptermd.upterm.dev:22
SSH Session:            ssh IqKsfoiclsNnxqztDKoj:[email protected]

The client opens a terminal and connects to the host's session:

$ ssh IqKsfoiclsNnxqztDKoj:[email protected]

Installation

Mac

brew install owenthereal/upterm/upterm

Standalone

upterm can be easily installed as an executable. Download the latest compiled binaries and put it in your executable path.

From source

git clone [email protected]:owenthereal/upterm.git
cd upterm
go install ./cmd/upterm/...

Upgrade

upterm comes with a command to upgrade

$ upterm upgrade # upgrade to the latest version

$ upterm upgrade VERSION # upgrade to a version

Mac

brew upgrade upterm

Quick Reference

# Host a terminal session that runs $SHELL with
# client's input/output attaching to the host's
$ upterm host

# Display the ssh connection string and share it with
# the client(s)
$ upterm session current
=== SESSION_ID
Command:                /bin/bash
Force Command:          n/a
Host:                   ssh://uptermd.upterm.dev:22
SSH Session:            ssh [email protected]

# A client connects to the host session with ssh
$ ssh [email protected]

# Host a terminal session that only allows specified client public key(s) to connect
$ upterm host --authorized-key PATH_TO_PUBLIC_KEY

# Host a session with a custom command
$ upterm host -- docker run --rm -ti ubuntu bash

# Host a session that runs 'tmux new -t pair-programming' and
# force clients to join with 'tmux attach -t pair-programming'.
# This is similar to what tmate offers.
$ upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming

# Connect to uptermd.upterm.dev via WebSocket
$ upterm host --server wss://uptermd.upterm.dev -- bash

# A client connects to the host session via WebSocket
$ ssh -o ProxyCommand='upterm proxy wss://[email protected]' [email protected]:443

More advanced usage is here.

Tips

Why doesn't upterm session current show current session in Tmux?

upterm session current needs the UPTERM_ADMIN_SOCKET environment variable to function. And this env var is set in the specified command. Unfotunately, Tmux doesn't carry over environment variables that are not in its default list to any Tmux session unless you tell it to (Ref). So to get upterm session current to work, add the following line to your ~/.tmux.conf

set-option -ga update-environment " UPTERM_ADMIN_SOCKET"

How to make it obvious that I am in an upterm session?

It can be confusing whether your shell command is running in an upterm session or not, especially if the shell command is bash or zsh. Add the following line to your ~/.bashrc or ~/.zshrc and decorate your prompt to show a sign if the shell command is in a terminal session:

export PS1="$([[ ! -z "${UPTERM_ADMIN_SOCKET}"  ]] && echo -e '\xF0\x9F\x86\x99 ')$PS1" # Add an emoji to the prompt if `UPTERM_ADMIN_SOCKET` exists

Demo

asciicast

How it works

You run the upterm program by specifying the command for your terminal session. Upterm starts an SSH server (a.k.a. sshd) in the host machine and sets up a reverse SSH tunnel to a Upterm server (a.k.a. uptermd). Clients connect to your terminal session over the public internet via uptermd using ssh using TCP or WebSocket. A community Upterm server is running at uptermd.upterm.dev and upterm points to this server by default.

upterm flowchart

Deploy Uptermd

Kubernetes

You can deploy uptermd to a Kubernetes cluster. Install it with helm:

$ helm repo add upterm https://upterm.dev
$ helm repo update
$ helm search repo upterm
NAME            CHART VERSION   APP VERSION     DESCRIPTION
upterm/uptermd  0.1.0           0.4.1           Secure Terminal Sharing
$ helm install uptermd upterm/uptermd

Heroku

The cheapest way to deploy a worry-free Upterm server (a.k.a. uptermd) is to use Heroku. Heroku offers free Dyno hours which should be sufficient for most casual uses.

You can deploy with one click of the following button:

Deploy

You can also automate the deployment with Heroku Terraform. The Heroku Terraform scripts are in the terraform/heroku folder. A util script is provided for your convenience to automate everything:

$ git clone https://github.com/owenthereal/upterm
$ cd upterm

# Provinsion uptermd in Heroku Common Runtime.
# Follow instructions
$ bin/heroku-install

# Provinsion uptermd in Heroku Private Spaces.
# Follow instructions
$ TF_VAR_heroku_region=REGION TF_VAR_heroku_space=SPACE_NAME TF_VAR_heroku_team=TEAM_NAME bin/heroku-install

You must use WebScoket as the protocol for a Heroku-deployed Uptermd server because the platform only support HTTP/HTTPS routing. This is how you host a session and join a session:

# Use the Heroku-deployed Uptermd server via WebSocket
$ upterm host --server wss://YOUR_HEROKU_APP_URL -- YOUR_COMMAND

# A client connects to the host session via WebSocket
$ ssh -o ProxyCommand='upterm proxy wss://[email protected]_HEROKU_APP_URL' [email protected]_HEROKU_APP_URL:443

Digital Ocean

There is an util script that makes provinsioning Digital Ocean Kubernetes and an Upterm server easier:

TF_VAR_do_token=$DO_PAT \
TF_VAR_uptermd_host=uptermd.upterm.dev \
TF_VAR_uptermd_acme_email=YOUR_EMAIL \
TF_VAR_uptermd_helm_repo=http://localhost:8080 \
TF_VAR_uptermd_host_keys_dir=PATH_TO_HOST_KEYS \
bin/do-install

How is Upterm compared to prior arts?

Upterm is an alternative to Tmate.

Tmate is a fork of an older version of Tmux. It adds terminal sharing capability on top of Tmux 2.x. Tmate doesn't intend to catch up with the latest Tmux, so any Tmate & Tmux users must maintain two versions of the configuration. For example, you must bind the same keys twice with a condition.

Upterm is designed from the group up not to be a fork of anything. It builds around the concept of linking the input & output of any shell command between a host and its clients. As you see above, you can share any command besides tmux. This opens up a door for securely sharing a terminal session using containers.

Upterm is written in Go. It is more friendly hackable than Tmate that is written in C because Tmux is C. The Upterm CLI and server (uptermd) are compiled into a single binary. You can quickly spawn up your pairing server in any cloud environment with zero dependencies.

License

Apache 2.0

Issues
  • Private key required when ssh-agent already populated

    Private key required when ssh-agent already populated

    Hello, we are trying upterm as an alternative to tmate, and it's seems to be working great, so, first of all, thanks for this project!

    On my machine though, I don't have any private key files, they are stored in a safe (KeePassXC) and, when I unlock my safe, my key is added to my ssh-agent.

    My workaround for upterm is to create an ssh-key, but I wonder if we could have an option to specify an ssh-agent directly where it could retrieve the keys and the signers.

    If you agree with that, I could try and create a PR

    opened by MichaelBitard 7
  • Heroku hosted server and permission denied

    Heroku hosted server and permission denied

    I've used your instructions to deploy to Heroku. I have the host running and the session current command is giving the appropriate ssh command pointing at the Heroku app. But when executed on the Mac to connect, I get a Permission denied (publickey). Here are the logs from the Heroku app:

    2021-11-03T22:58:24.656438+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=7c41e010-56d7-4381-938e-9febbf558f88 fwd="198.217.125.15" dyno=web.1 connect=0ms service=772ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:30.721907+00:00 app[web.1]: time="2021-11-03T22:58:30Z" level=info msg="dialing sshproxy session" addr="0.0.0.0:2222" app=uptermd com=ws-sshproxy-dialer network=mem network-opt="[]" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" sshproxy-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:31.052368+00:00 app[web.1]: time="2021-11-03T22:58:31Z" level=info msg="dialing session" addr="0.0.0.0:2222" app=uptermd com=ssh-conn-dialer network=mem network-opt="[]" node="0.0.0.0:2222" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:31.567653+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=62845bfc-7769-41bd-9f9a-55410f3de5cf fwd="198.217.125.15" dyno=web.1 connect=0ms service=845ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:31.567441+00:00 app[web.1]: time="2021-11-03T22:58:31Z" level=error msg="error piping" app=uptermd com=ws-proxy error="readfrom tcp 127.0.0.1:53424->127.0.0.1:2222: websocket: close 1006 (abnormal closure): unexpected EOF" network=mem network-opt="[]" node-addr="0.0.0.0:2222" ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.138609+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=info msg="dialing sshproxy session" addr="0.0.0.0:2222" app=uptermd com=ws-sshproxy-dialer network=mem network-opt="[]" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" sshproxy-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.460306+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=info msg="dialing session" addr="0.0.0.0:2222" app=uptermd com=ssh-conn-dialer network=mem network-opt="[]" node="0.0.0.0:2222" node-addr="0.0.0.0:2222" session=sRiv4wTY6mtuYtBedj0w ssh-addr="[::]:2222" ws-addr="[::]:36680"
    2021-11-03T22:58:49.971328+00:00 heroku[router]: at=info method=GET path="/" host=cdr-upterm.herokuapp.com request_id=f3603b62-d4be-4a48-9195-04b74629b484 fwd="198.217.125.15" dyno=web.1 connect=0ms service=832ms status=101 bytes=1240 protocol=https
    2021-11-03T22:58:49.971068+00:00 app[web.1]: time="2021-11-03T22:58:49Z" level=error msg="error piping" app=uptermd com=ws-proxy error="readfrom tcp 127.0.0.1:54220->127.0.0.1:2222: websocket: close 1006 (abnormal closure): unexpected EOF" network=mem network-opt="[]" node-addr="0.0.0.0:2222" ssh-addr="[::]:2222" ws-addr="[::]:36680"
    

    Any suggestions?

    opened by chrisdrobison 6
  • Cannot build in Windows inside MINGW32 bash session

    Cannot build in Windows inside MINGW32 bash session

    Hello!

    I'm unable to build from sources for Windows running inside a bash session of Mingw32:

    $ go build ./cmd/upterm/...
    # github.com/jingweno/upterm/host/internal
    host\internal\command.go:86:21: undefined: syscall.SIGWINCH
    host\internal\command.go:87:9: undefined: syscall.SIGWINCH
    host\internal\pty.go:13:12: undefined: pty.Start
    host\internal\pty.go:33:9: undefined: pty.Getsize
    host\internal\pty.go:54:11: undefined: pty.Winsize
    host\internal\pty.go:58:9: undefined: pty.Setsize
    ```
    opened by Dnm-28 4
  • Add --read-only flag

    Add --read-only flag

    This adds a read-only flag that allows hosting an upterm session that is read-only. Clients can connect as normal but won't be able to interact with the session. All other functionality remains as is, this simply doesn't attach the stdin of the client to the session pty.

    opened by staaldraad 2
  • Add view only mode

    Add view only mode

    Are there any plans to add a view only mode anyone could join? Right now that seems to be not possible and this was one of the bigger use cases for tmate.

    opened by SuperSandro2000 2
  • missing flag private-key

    missing flag private-key

    Hello, I'm trying to use self-hosted server, after deployment I can host sessions from same machine that I've run terraform deployment. But other machine returns this error:

    # upterm host --server wss://<deleted>.herokuapp.com -- bash
    Error: 1 error occurred:
    	* missing flag --private-key
    

    Where I can get this private key?

    opened by islander 2
  • QUESTION: Use with Visual Studio Code possible?

    QUESTION: Use with Visual Studio Code possible?

    The Question

    I am an avid terminal user, Neovim, tmux, and all the like so Upterm is amazing for me. However, some of my co-workers and friends do not live inside the terminal and use GUI IDE's such as Visual Studio Code. Is there a way use VSCode's Remote Development -SSH extension to connect to Upterm's SSH Server and be able to view with me as I work?

    Current Error Output

    [12:54:26.383] Log Level: 2
    [12:54:26.386] [email protected]
    [12:54:26.386] linux x64
    [12:54:26.387] SSH Resolver called for "ssh-remote+uptermd.upterm.dev", attempt 1
    [12:54:26.388] "remote.SSH.useLocalServer": true
    [12:54:26.388] "remote.SSH.path": undefined
    [12:54:26.388] "remote.SSH.configFile": undefined
    [12:54:26.388] "remote.SSH.useFlock": true
    [12:54:26.389] "remote.SSH.lockfilesInTmp": false
    [12:54:26.389] "remote.SSH.localServerDownload": auto
    [12:54:26.389] "remote.SSH.remoteServerListenOnSocket": false
    [12:54:26.389] "remote.SSH.showLoginTerminal": false
    [12:54:26.389] "remote.SSH.defaultExtensions": []
    [12:54:26.390] "remote.SSH.loglevel": 2
    [12:54:26.390] SSH Resolver called for host: uptermd.upterm.dev
    [12:54:26.390] Setting up SSH remote "uptermd.upterm.dev"
    [12:54:26.395] Acquiring local install lock: /tmp/vscode-remote-ssh-48a5ecb6-install.lock
    [12:54:26.430] Looking for existing server data file at /var/home/dudleyp/.var/app/com.visualstudio.code/config/Code/User/globalStorage/ms-vscode-remote.remote-ssh/vscode-ssh-host-48a5ecb6-507ce72a4466fbb27b715c3722558bb15afa9f48-0.65.8/data.json
    [12:54:26.431] Using commit id "507ce72a4466fbb27b715c3722558bb15afa9f48" and quality "stable" for server
    [12:54:26.439] Install and start server if needed
    [12:54:26.476] PATH: /app/bin:/usr/bin:/app/tools/podman/bin:/usr/lib/sdk/golang/bin:/var/home/dudleyp/.var/app/com.visualstudio.code/data/node_modules/bin
    [12:54:26.476] Checking ssh with "ssh -V"
    [12:54:26.485] > OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    
    [12:54:26.490] askpass server listening on /run/user/1000/vscode-ssh-askpass-59f8107e5f8a89dfd1a5728c561edb170e91f293.sock
    [12:54:26.490] Spawning local server with {"serverId":1,"ipcHandlePath":"/run/user/1000/vscode-ssh-askpass-a68ca513540bb777882508442662771abd6fea3c.sock","sshCommand":"ssh","sshArgs":["-v","-T","-D","42591","-o","ConnectTimeout=15","uptermd.upterm.dev"],"dataFilePath":"/var/home/dudleyp/.var/app/com.visualstudio.code/config/Code/User/globalStorage/ms-vscode-remote.remote-ssh/vscode-ssh-host-48a5ecb6-507ce72a4466fbb27b715c3722558bb15afa9f48-0.65.8/data.json"}
    [12:54:26.490] Local server env: {"DISPLAY":":99.0","ELECTRON_RUN_AS_NODE":"1","SSH_ASKPASS":"/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/local-server/askpass.sh","VSCODE_SSH_ASKPASS_NODE":"/app/extra/vscode/code","VSCODE_SSH_ASKPASS_MAIN":"/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/askpass-main.js","VSCODE_SSH_ASKPASS_HANDLE":"/run/user/1000/vscode-ssh-askpass-59f8107e5f8a89dfd1a5728c561edb170e91f293.sock"}
    [12:54:26.497] Spawned 315
    [12:54:26.641] > local-server-1> Spawned ssh, pid=323
    [12:54:26.643] stderr> OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    [12:54:26.971] stderr> Connection closed by 157.230.199.75 port 22
    [12:54:26.974] > local-server-1> ssh child died, shutting down
    [12:54:26.980] Local server exit: 0
    [12:54:26.980] Received install output: local-server-1> Spawned ssh, pid=323
    OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021
    Connection closed by 157.230.199.75 port 22
    local-server-1> ssh child died, shutting down
    
    [12:54:26.982] Failed to parse remote port from server output
    [12:54:26.983] Resolver error: Error: 
    	at Function.Create (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:397041)
    	at Object.t.handleInstallOutput (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:395684)
    	at Object.e [as tryInstallWithLocalServer] (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:435292)
    	at processTicksAndRejections (internal/process/task_queues.js:93:5)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:452665
    	at async Object.t.withShowDetailsEvent (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:456460)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:433816
    	at async C (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:430392)
    	at async Object.t.resolveWithLocalServer (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:433431)
    	at async Object.t.resolve (/var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:454065)
    	at async /var/home/dudleyp/.var/app/com.visualstudio.code/data/vscode/extensions/ms-vscode-remote.remote-ssh-0.65.8/out/extension.js:1:526942
    [12:54:26.990] ------
    

    I do know that there is already a "co-editing" experience called Live Share for Visual Studio and VSCode, but I was having issues with it reverting changes we had made, and syncing improperly.

    opened by FilBot3 2
  • Introduce a better random string generator

    Introduce a better random string generator

    After doing a bit more research, I found https://github.com/dchest/uniuri which does what we do with the following extras:

    • Bias check: https://github.com/dchest/uniuri/blob/master/uniuri_test.go#L87-L102
    • Boundary check: https://github.com/dchest/uniuri/blob/master/uniuri.go#L57-L59

    Besides, adding this cleans up our code a bit.

    opened by owenthereal 1
  • Fix `make vet`

    Fix `make vet`

    make vet is failing: https://travis-ci.org/github/jingweno/upterm/jobs/684808616.

    opened by owenthereal 1
  • Validate client authorized keys at ssh proxy

    Validate client authorized keys at ssh proxy

    This validates client authorized keys at ssh proxy instead of at the host. It rejects "bad" clients on the server before hitting the host. It also moves session id generation to the server to avoid id collision.

    opened by owenthereal 1
  • Adding the ability to specify a session name

    Adding the ability to specify a session name

    Hi!

    This project is amazing!

    I have a very specific use-case for which it's necessary for me to be able to generate session names from the client-side (I work for a university where we're investigating this for peer-programming between first-year students, but I'm going to build some tooling around it). We could just give them upterm, but I'm building in some features specifically for them. For one of these features, I want to have control of the session's name when logging in (so I can login to <session_name>:<b64 ip>@<my_server>).

    I've forked the project (https://github.com/tfpk/upterm/tree/tfpk/named-sessions) to build a draft to make sure it's feasible; but I'd love to discuss how best to upstream the feature. At the moment, I've already got it to support being given a session name. I don't have to worry about name-spacing, since on the server I'll be hosting, I can assume collisions won't happen between people. I can also assume there's only one upstream server behind the proxy.

    I'd like to ask if/how this would be best upstreamed? There are a few main questions:

    • Does there need to be some API key mechanism for namespacing (similar to how tmate does it's named sessions)?
    • How should we deal with the base64 encoded upstream IP? There are two options I have thought of:
      • Alias those IPs to some constant (so you'd have <session_name>:[email protected]<my_server>); and we could distribute that codename, even if the upstream changed. I can't tell from my cursory examination if there is a circumstance where you'd have multiple servers, but if we went this route we'd need to think about how that worked. If there's only one server, maybe we can avoid this altogether with a global?
      • Store the upstream server in some session store? I'm not sure of how much traffic/data this would require, and I don't want to add a bottleneck, but this would likely be the nicest solution.

    Please let me know what you think!

    Thanks again for this amazing project!

    ~Tom

    opened by tfpk 0
  • Support mosh?

    Support mosh?

    Would it be possible to use mosh instead of ssh?

    opened by pvonmoradi 4
  • proposal: please make SSH public keys fingerprints via trusted way visible

    proposal: please make SSH public keys fingerprints via trusted way visible

    Hereby I propose to make uptermd.upterm.dev SSH key fingerprints publicly available. Then we can verify it BEFORE we connect first time. Currnetly we have to just trust blindly and cannot avoid MITM. Looks like https://uptermd.upterm.dev/ works, one option is to show fingerprints there as index page.

    Also noticed, that following command gave empty output: ssh-keyscan uptermd.upterm.dev | ssh-keygen -lf - ... although this is not reliable as it wouldn't avoid MITM. The only trusted way is get fingerprints directly from upterm server admin via reliable public way. To not depend on 3rd party service, then it would not be good to share these keys via GitHub. Certainly this is also one option, if sharing fingerprints directly via web is not suitable for you. The most important is, that you will share these fingerprints so, that we can use them. I use it e.g. so - create a script

    #!/bin/sh
    user=<token>
    server=uptermd.upterm.dev
    serversshport=22
    key=ED25519
    trustedhash=<fingerprint>
    serverhash=<fingerprint>
    # Connecting
    if [ $serverhash = $trustedhash ]; then clear; printf "\nOffered $(echo $key) key fingerprint\n\n$(echo $serverhash)\n\n...CAN be trusted.\n\nLogging in...\n\n"; ssh [email protected]$server -p $serversshport; else clear; printf "\nOffered $(echo $key) key fingerprint\n\n$(echo $serverhash)\n\n...CAN NOT be trusted.\n\nThe $(echo $key) key trusted fingerprint is:\n\n$(echo $trustedhash)\n\nDO NOT log in\n\n"; fi
    

    ... and then run it. For easier run, I will create bash alias (~/.bash_aliases) to run it: alias upterm-connect='sh upterm.connect.sh' Certainly I will edit that script and fulfill with appropriate data. trustedhash would be the fingerprint got from you via reliable way. The serverhash is the fingerprint offered on first connection. I just will answer no on first time, then copy that hash to script and then connect already via script.

    So my proposal - please adopt to your needs (fix the real web server root location) and run that command on your server for i in /etc/ssh/*.pub; do ssh-keygen -lf $i; done | uniq > uptermd.upterm.dev/index.html

    This means, that server key fingerprints (key pair has same fingerprint) will be redirected as front page of uptermd.upterm.dev server. This is just hack, we all know, that there will be plain text file without any HTML syntax and this syntax is not needed - we just need fingerprints and that purpose will be done.

    The output of that proposed command could look like (depending on what keys are available):

    1024 SHA256:pm5g8a021dZsqZzyajgvrdI8YgeBOFTtzoYVS/+m8+s [email protected] (DSA)
    256 SHA256:OWMdutEQ7xpgUnOIxYFcQsZJhW+soeGqok9nzY [email protected] (ECDSA)
    256 SHA256:9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE [email protected] (ED25519)
    3072 SHA256:uFiKe97+ooizk3/pF1IaUCnbqmnd4ablQpHd40 [email protected] (RSA)
    

    Then we can ensure about the fingerprint BEFORE first connection and verify it and THEN connect.

    On first connection there is such a message:

    The authenticity of host 'uptermd.upterm.dev (157.230.199.75)' can't be established.
    ED25519 key fingerprint is SHA256:9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    After accepting it, we can check the accepted fingerprint from ~/.ssh/authorized_keys file:

    ssh-keygen -F uptermd.upterm.dev | ssh-keygen -lf -
    256 SHA256:9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE |1|DAZ5Gxn3yPCHGMM6QtJRyyfRjrk=|cV9vcPY7UrC+koTzNJsgAscPEzw= (ED25519)
    

    ... and we can see, that 9ajV8JqMe6jJE/s3TYjb/9xw7T0pfJ2+gADiBIJWDPE is the fingerprint of Ed25519 key, which was offered also on first SSH-connection.

    The point is: this will avoid MITM on first connection, next connections will be checked anyway via ~/.ssh/authorized_keys file and in case of mismatch connection will not be established. Current idea of fingerprints availability will avoid MITM on first connection. This is actually regular practice, what sysadmins are using in order to be sure about the server they connecting and avoid MITM.

    opened by edmundlaugasson 0
  • Don't terminate when last client leaves

    Don't terminate when last client leaves

    When the last client leaves the upterm session my upterm host session terminates. This is not ideal, as I could be running an editor and have unsaved changes.

    As soon as the last user terminates their session by closing their terminal this is shown:

    [...]
     ~ ▓▒░ Error: EOF
    Usage:
      upterm host [flags]
    
    Examples:
      # Host a terminal session that runs $SHELL with
      # client's input/output attaching to the host's
      upterm host
    
      # Host a terminal session that only allows specified public key(s) to connect
      $ upterm host --authorized-key PATH_TO_PUBLIC_KEY
    
      # Host a session with a custom command.
      upterm host -- docker run --rm -ti ubuntu bash
    
      # Host a session that runs 'tmux new -t pair-programming' and
      # force clients to join with 'tmux attach -t pair-programming'.
      # This is similar to tmate.
      upterm host --force-command 'tmux attach -t pair-programming' -- tmux new -t pair-programming
    
      # Use a different Uptermd server and host a session via WebSocket
      upterm host --server wss://YOUR_UPTERMD_SERVER -- YOUR_COMMAND
    
    Flags:
      -a, --authorized-key string   an authorized_keys file that lists public keys that are permitted to connect.
      -f, --force-command string    force execution of a command and attach its input/output to client's.
      -h, --help                    help for host
          --known-hosts string      a file contains the known keys for remote hosts (required). (default "/home/hexa/.ssh/known_hosts")
      -i, --private-key strings     private key for public key authentication against the upterm server (required). (default [/home/hexa/.ssh/id_ed25519,/home/hexa/.ssh/id_rsa])
      -r, --read-only               host a read-only session. Clients won't be able to interact.
          --server string           upterm server address (required), supported protocols are shh, ws, or wss. (default "ssh://uptermd.upterm.dev:22")
    
    FATA[0031] EOF   
    
    opened by mweinelt 3
  • Systemd socket activation

    Systemd socket activation

    It would be nice if uptermd would accept systemd sockets during process startup. This allows (among other things) running uptermd on priviledged ports (e.g. 22) without providing it extended priviledges.

    There is a good explanation on how this work in this blog post https://vincent.bernat.ch/en/blog/2018-systemd-golang-socket-activation.

    opened by andir 1
  • Foregrounded mode

    Foregrounded mode

    I'd like to suggest adding a foreground mode, similar to TMate's -F option, to allow clients to connect without requiring further interaction on the host side. This would make upterm useful in automated systems/CI environments where it's not always possible to provide input.

    opened by valenvb 1
  • Automatic authorized keys from github/gitlab

    Automatic authorized keys from github/gitlab

    I would like to simplify something like upterm host --authorized-key <(curl https://github.com/rothgar.keys)

    It would be great if this can be a single option like --github-user rothgar. If we want to make it more flexible maybe it could be something like --git-user [email protected] which would automatically fetch https://github.com/rothgar.keys. This could limit the amount of flags and still make it pluggable for things like [email protected]

    opened by rothgar 6
  • Clarification: INFO[0191] dialing sshd

    Clarification: INFO[0191] dialing sshd

    Hello!

    I'm running uptermd on a server and when I connect to it with upterm I see the dialing message above. When people try to connect to the session the get permission denied. I'm guessing this is because upterm is trying to do some pubkey authentication with my locally running sshd? I'm guessing that since if I run upterm on a computer that has no sshd running everything seems to work normally and clients connect with no permission problems. I was just wondering how the dialing sshd part works and how to set it up so that other clients can connect to my machine.

    On uptermd node:

    uptermd --debug --ssh-addr <ip>:<port> --node-addr <ip>:<port>
    

    On upterm host

    upterm host --server ssh://<ip>:<port> -- bash
    

    On upterm client

    <copied ssh command>
    Connection closed by <ip> port <port>
    

    uptdermd logs:

    DEBU[0850] connection establishing failed                addr="ip:port" app=uptermd com=ssh-proxy error="error checking user cert: ssh: principal \"blahblahblabh" not in the set of valid principals for given certificate: [\"host\"]" network=mem network-opt="[]" node-addr="<ip>:<port>" ssh-addr="<ip>:<port>"
    
    opened by thornycrackers 4
  • Reconnect

    Reconnect

    (Translated by Google)

    Hi

    When I disconnect from the remote terminal, doing 'exit', I am actually also closing the process on the server, and I cannot reconnect, since 'upterm' is no longer running.

    Is there any way I can close my remote session, but leave the process running on the server?

    opened by marcoas 1
  • Compliance / Logging Mode

    Compliance / Logging Mode

    In certain conditions it would be useful to have enforced logging available. Especially in cases where logs are required for compliance, having upterm record the session and export logs would be extremely useful.

    This would also position upterm to fulfil a role similar to what sudo_pair does. It lacks the "approve" feature, but engineers who are performing sensitive actions have both another engineer reviewing actions during the session, and exported logs for future audit requirements.

    Expected behaviour

    There are multiple options here, but the first requirement would be that the session is started in "compliance" mode. This would be through a flag --compliance. The user could also specify a log file location.

    One option with the log file generation is to only generate the log file on the host side. Alternatively a client that connects to a host that has --compliance enabled would also start recording logs. The benefit here is that there are two records of the logs and you remove the single party responsibility.

    Actual logging can be added to the stdin, stdout and stderr of the session. This would need to be added to the session.stdin etc, maybe an io.Pipe that does session.stdin --> logger-pipe --> ptx.stdin

    enhancement 
    opened by staaldraad 0
Releases(v0.6.6)
Simple CLI tool for creating gotd sessions.

Simple CLI tool for creating gotd sessions.

tdakkota 1 Nov 24, 2021
Terminal chat with multiroom support over custom protocol.

Terminal Chat Content Content Overview Download Commands Protocol Room URL Platforms Examples Overview It is a multiroom terminal chat. It allows comm

Sergey Kuznetsov 10 Nov 25, 2021
Song lyrics in your terminal via Genius

lyric Song lyrics in your terminal via the Genius API. Usage Search by song name, artist, parts of lyrics, or a combination. lyric "bohemian rhapsody"

Liam Galvin 13 Dec 3, 2021
CLI for Shamir's Secret Sharing and AES key generation, encryption, and decryption.

Shush ?? This simple program will help you run Shamir's Secret Sharing algorithm on any file using the split and merge commands.

null 23 Nov 22, 2021
A personal knowledge management and sharing system for VSCode

Foam ?? This is an early stage project under rapid development. For updates join the Foam community Discord! ?? Foam is a personal knowledge managemen

Foam 10.9k Dec 4, 2021
VSCode Remote-SSH and configuration sharing on WSL.

Wslssh Wslssh forwards SSH command from VSCode Remote-SSH to WSL and enables SSH configuration sharing. Quick Start Guide Download or compile wslssh a

Fadhli Dzil Ikram 0 Dec 2, 2021
Downloader written in golang to download the public data files from RUC Paraguay.

rucpy-downloader Downloader written in golang to download the public data files(RUC Paraguay) from set.gov.py. The downloader will download the public

bitebait 1 Dec 6, 2021
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.

Stonks is a terminal based stock visualizer and tracker. Installation Requirements: golang >= 1.13 Manual Clone the repo Run make && make install Pack

Eric Moynihan 465 Nov 24, 2021
A wrapper around cd and xdg-open to use aliases to directory paths in terminal

CDD - Change directories Dynamically I am a lazy linux user and turns out that basic tab completion wasn't enough for me to navigate through my direct

Navdeep Singh Rathore 13 Nov 21, 2021
Go terminal app listing open pull requests in chosen GitHub repositories

go-pr-watcher About Shows open pull requests on configured GitHub repositories. Getting started Create GitHub personal token with read permissions Cre

Oleg 0 Oct 29, 2021
Source code of a YouTube tutorial about writing terminal applications with Golang

Bubble Tea Demo 00 Source code of a YouTube tutorial about writing terminal applications with Golang by using Bubble Tea. Contains a simple counter ap

Nicolás Parada 1 Nov 29, 2021
An open-source GitLab command line tool bringing GitLab's cool features to your command line

GLab is an open source GitLab CLI tool bringing GitLab to your terminal next to where you are already working with git and your code without switching

Clement Sam 1.6k Dec 4, 2021
Teller - the open-source universal secret manager for developers

A secrets management tool for developers built in Go - never leave your command line for secrets.

null 497 Nov 25, 2021
a Go language free and open-source document for learning from zero level

Go document a GO language free and open-source document for learning from zero level Please publish and collaborate OPEN-SOURCE Sections About go lang

Erfan Hanifezade 8 Nov 19, 2021
Commandline Utility To Create Secure Password Hashes (scrypt / bcrypt / pbkdf2)

passhash Create Secure Password Hashes with different algorithms. I/O format is base64 conforming to RFC 4648 (also known as url safe base64 encoding)

Michael Gebetsroither 14 Jan 22, 2021
Fast, secure, efficient backup program

Introduction restic is a backup program that is fast, efficient and secure. It supports the three major operating systems (Linux, macOS, Windows) and

The restic backup program 14.9k Nov 29, 2021
Secure, private and feature-rich CLI password manager

Kure Kure is a free and open-source password manager for the command-line. This project aims to offer the most secure and private way of operating wit

Gastón Palomeque 112 Nov 30, 2021
linenoise-classic is a command-line tool that generates strings of random characters that can be used as reasonably secure passwords.

linenoise-classic is a command-line tool that generates strings of random characters that can be used as reasonably secure passwords.

Mark Cornick 0 Nov 29, 2021
Go Library to Execute Commands Over SSH at Scale

Go library to handle tens of thousands SSH connections and execute the command(s) with higher-level API for building network device / server automation.

Yahoo 755 Nov 24, 2021