{"id":13564491,"url":"https://github.com/TimeToogo/tunshell","last_synced_at":"2025-04-03T21:31:00.775Z","repository":{"id":37084006,"uuid":"259289936","full_name":"TimeToogo/tunshell","owner":"TimeToogo","description":"Remote shell into ephemeral environments 🐚 🦀","archived":false,"fork":false,"pushed_at":"2023-08-15T03:34:06.000Z","size":1551,"stargazers_count":781,"open_issues_count":9,"forks_count":59,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-11-04T17:47:37.324Z","etag":null,"topics":["relay-server","remote-shell","rust","shell"],"latest_commit_sha":null,"homepage":"https://tunshell.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TimeToogo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-04-27T11:11:14.000Z","updated_at":"2024-11-01T18:59:02.000Z","dependencies_parsed_at":"2024-01-13T19:53:14.638Z","dependency_job_id":null,"html_url":"https://github.com/TimeToogo/tunshell","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeToogo%2Ftunshell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeToogo%2Ftunshell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeToogo%2Ftunshell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimeToogo%2Ftunshell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimeToogo","download_url":"https://codeload.github.com/TimeToogo/tunshell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247083047,"owners_count":20880764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["relay-server","remote-shell","rust","shell"],"created_at":"2024-08-01T13:01:32.135Z","updated_at":"2025-04-03T21:30:57.381Z","avatar_url":"https://github.com/TimeToogo.png","language":"Rust","readme":"# Tunshell\n\nhttps://tunshell.com\n\nTunshell is a simple and secure method to remote shell into ephemeral environments such as deployment pipelines or serverless functions.\nThe project is predominately written in [Rust](https://www.rust-lang.org/).\n\n## Why?\n\n\u003e Why would I use this over my well-established SSH client?\n\nGood question, you wouldn't! \nThe use case for tunshell is predominantly quick, ad-hoc remote access to hosts which you may not have SSH access to, or even the ability to install an SSH daemon at all. \nThe beauty of tunshell is that its client is a statically-linked, pre-compiled binary which can be installed by downloading it with a one-liner script. \nThis makes it ideal to debug environments you normally wouldn't have shell access to, some examples:\n\n### Debugging Deployment Pipelines\n\nTunshell allows you to remote shell into GitHub Actions, BitBucket Pipelines etc by inserting a one-liner into your build scripts. \nIf you've ever spent hours trying to track down an issue on a deployment pipeline that you couldn't replicate locally because of subtle environmental differences, this could come in handy.\n\n### Serverless Functions\n\nTunshell even supports extremely limited environments such as AWS Lambda or Google Cloud Functions. \nAs these platforms often only allow for execution of code in a configured language, a variety of install scripts among popular languages are provided. \nThis could be helpful to diagnose networking or connectivity issues which are specific to these environments.\n\n### Unsavory Use-cases\n\nTunshell could also be used as an exploitation tool to gain unauthorized access to remote hosts. \nPersonally, I hope that this tool is not misused for nefarious purposes. \nIf it becomes apparent that tunshell is helping malicious actors go about their activities, the free service will be discontinued.\n\n## How does it work?\n\nTunshell is comprised of 3 main components:\n\n- [Relay Server](./tunshell-server): a server which is able to coordinate with clients to establish connectivity\n- [Client Binary](./tunshell-client): a portable binary acting as a shell server or client.\n- [Website](./website): The user interface for configuring a remote shell session with the relay server and providing install scripts for the client.\n\n### Install Script\n\nThe process is kicked off using [tunshell.com](https://tunshell.com). \nOne can generate a \"session\" which represents a remote shell connection from one client to another.\n\nFor each session the website generates one install script for each side of the connection.\nBelow is a diagram illustrating the noteworthy components embedded in each script.\n\n![Install Script](https://app.lucidchart.com/publicSegments/view/8ad48e9c-299b-4d55-8c95-2d1aa07475c6/image.png)\n\n- ![#fcc438](https://via.placeholder.com/15/fcc438/000000?text=+) **Installer script URL:** A url pointing to a script which will install the client binary on the executing machine. These scripts detect the host's OS and CPU architecture to download the correct pre-compiled executable.\n- ![#834187](https://via.placeholder.com/15/834187/000000?text=+) **Mode argument:** can be target mode (T) or local mode (L). These instruct the client to operate as a shell server or client respectively.\n- ![#7ab648](https://via.placeholder.com/15/7ab648/000000?text=+) **Session keys:** a pair of random strings generated by the relay server corresponding to a session. Upon initialisation, these keys are passed back to the relay server. When a pair of clients have sent a corresponding keys, the relay server will begin establishing connectivity between the clients.\n- ![#c92d39](https://via.placeholder.com/15/c92d39/000000?text=+) **Encryption secret:** a random secret which is generated locally using javascript on the website. This secret is used to generate a unique encryption key to secure data transmission between the two clients.\n\n### Establishing Connectivity\n\nAfter the install scripts have executed and the two clients have validated their session keys with the relay server, the following process of attempting to establish a network connection between the two begins.\n\n![Connection Establishment Flow](https://app.lucidchart.com/publicSegments/view/e14f955d-1622-4d34-ba02-3616a1b5b788/image.png)\n\nThere are three networking models supported that are attempted and used in the following priority order:\n\n1. **TCP:** The clients will attempt to connect to the peer over TCP directly. \nIf both clients are behind a firewall or NAT device, this will likely fail.\n\n![TCP](https://app.lucidchart.com/publicSegments/view/26e86773-55e4-4927-8487-525fde329006/image.png?)\n\n2. **UDP:** The implementation also contains thin [TCP-like protocol built on UDP](./tunshell-client/src/p2p/udp). \nIn some cases this can help establish a direct connection if at least of the clients are behind a more permissive NAT device.\n\n![UDP](https://app.lucidchart.com/publicSegments/view/bd4afe42-a282-45d5-8a67-378ae31ad219/image.png?)\n\n3. **Relayed:** In the case where no direct connection succeeds, the clients will fallback to proxying data through the relay server. \nThe relay server will traffic packets between the clients using the existing TLS connections initiated by each client.\n\n![Relayed](https://app.lucidchart.com/publicSegments/view/055838d6-6aeb-4a8c-8196-3eadf4653f53/image.png?)\n\nThe relayed connection is also used for connections where one of the clients is running in a web browser. \nIn which case a Web Socket is used between the client and the relay server on top of TLS.\n\n![Relayed + WS](https://app.lucidchart.com/publicSegments/view/d8f71cde-9585-4811-9fd2-21a81dda061a/image.png?)\n\n### In-built Shell\n\nIn some restricted environments the client will not have permission to allocate a PTY. \nThis means that running the native shell in an interactive session is not going to be possible. \nThe client has a bare-bones (read: incomplete) implementation of a [VT100-style shell](./tunshell-client/src/shell/server/fallback/) which does not require a PTY and is used as a fallback in such cases. \nThis is still WIP.\n\n## Security Considerations\n\nBefore using tunshell is important to understand inherent risks.\nThe nature of the application and installation method should trigger alarm bells in any developer's head given we are exposing shell access over a network.\nAlthough a lot of thought has gone into the limiting the attack surface there are is still a lot of room for improvement.\n\nFirst and foremost, one must always be wary when running scripts from remote sources.\nThe installation method of the tunshell client relies on the execution of a 3rd party script and binary on the host machine.\nIf these were to be compromised so would your host. So it's critical that these are produced and delivered in a secure and transparent process.\nIn summary, the artifacts are generated directly from the source in this repo, stored in AWS S3 and served via CloudFront CDN.\n\n![Artifact Supply Chain](https://app.lucidchart.com/publicSegments/view/fc6f92fa-1b4b-4800-8a2c-2e1c5f72a8ba/image.png)\n\nThe next consideration is the operation of the client binary, which exposes shell access over a network channel. \nIt is important to state that, although the traffic between clients can be passed through the relay server, effort has gone into ensuring that the relay server is not able to inspect, modify or forge traffic between any two clients. \nThis is currently achieved by generating an encryption secret independently of the relay server which is then known to each of the clients.\n\n![Encryption Diagram](https://app.lucidchart.com/publicSegments/view/1a812bff-1780-464e-ba01-ac2913121c77/image.png)\n\nIn addition to the secret, during the connection establishment phase, the relay server will generate a unique nonce for each connection pair and send this nonce to each client. \nThe clients use the encryption secret and nonce to derive an encryption key using PBKDF2-SHA256. \nThe resulting key is unique to this connection and only known to the both clients. The traffic between the clients is then end-to-end encrypted and authenticated using AES-GCM-256.\n\nIt is important that the session and encryption keys remain secret. \nExposing these parameters could allow attackers who obtain these keys to takeover hosts which have an active tunshell client.\n\n## Supported Targets for Client\n\nThe following is list of the supported platforms and architectures for the tunshell client:\n\n| Target | Builds | Tested |\n|--------|--------|--------|\n| x86_64-unknown-linux-musl | Y | Y |\n| armv7-unknown-linux-musleabihf | Y | N |\n| arm-unknown-linux-musleabi | Y | Y |\n| aarch64-unknown-linux-musl | Y | Y |\n| arm-linux-androideabi | Y | N |\n| i686-unknown-linux-musl | Y | Y |\n| i586-unknown-linux-musl | Y | Y |\n| x86_64-apple-darwin | Y | Y |\n| x86_64-apple-ios | Y | N |\n| x86_64-pc-windows-msvc | Y | Y |\n| i686-pc-windows-msvc | Y | N |\n\n - *Builds:* indicates whether the client successfully built for the target\n - *Tested:* indicates whether the test suites succeeds for the target, clients with _N_ listed may be inoperable\n\n These targets are managed by [the build pipeline](.github/workflows/deploy-client-binaries.yml).\n\n## Self-hosted relay server\n\nFor additional security or customisation it is possible to self-host the relay server on your own infrastructure. The details of doing so can be found [here](./aws/README.md).\n","funding_links":[],"categories":["Rust","Rust (42)","shell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimeToogo%2Ftunshell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTimeToogo%2Ftunshell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimeToogo%2Ftunshell/lists"}