283 lines
9.5 KiB
Markdown
283 lines
9.5 KiB
Markdown
# Socktop WebTerm
|
|
|
|
A web-based terminal using xterm.js and Rust, part of the Socktop project.
|
|
|
|
This is the repository and CICD for [socktop.io](https://www.socktop.io/)
|
|
|
|

|
|
|
|
## About
|
|
|
|
This is a modern web terminal server that provides browser-based terminal access with WebSocket support. It's built with Rust using the Actix-Web framework and xterm.js for the frontend.
|
|
|
|
## Features
|
|
|
|
- Full-featured terminal emulation via xterm.js
|
|
- WebSocket-based communication using the Terminado protocol
|
|
- High-performance Rust backend
|
|
- Privacy-focused analytics with Umami (self-hosted)
|
|
- Command sanitization for security and privacy
|
|
- Zero-downtime rolling deployments via CI/CD
|
|
- Containerized deployment with Docker
|
|
- Kubernetes/k3s ready with automated deployments
|
|
|
|
## Architecture
|
|
|
|
The application consists of two main components:
|
|
|
|
### Backend (Rust)
|
|
- **Websocket Actor**: Implements WebSocket communication using the [Terminado](https://github.com/jupyter/terminado) protocol
|
|
- **Terminal Actor**: Manages PTY communication with spawned processes using [portable-pty](https://crates.io/crates/portable-pty)
|
|
- **Actix-Web Server**: Serves static files and handles HTTP/WebSocket routing
|
|
|
|
### Frontend
|
|
- **xterm.js**: Provides the terminal UI in the browser
|
|
- **Static Assets**: HTML, CSS, and JavaScript served by Actix-Web
|
|
|
|
## Prerequisites
|
|
|
|
- Rust 1.90+ (2021 edition)
|
|
- Node.js and npm (for xterm.js dependencies)
|
|
- Docker (optional, for containerized deployment)
|
|
- Kubernetes/k3s (optional, for orchestrated deployment)
|
|
|
|
## Local Development
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone https://gt.wittyoneoff.com/jason/socktop-webterm
|
|
cd socktop-webterm
|
|
|
|
# Install npm dependencies
|
|
npm install
|
|
|
|
# Verify setup (optional but recommended)
|
|
./check-setup.sh
|
|
|
|
# Build and run
|
|
cargo build
|
|
cargo run
|
|
```
|
|
|
|
Then head to `http://localhost:8082/` to see it in action!
|
|
|
|
### Setup Verification
|
|
|
|
Before running the server, you can verify that all required files and dependencies are in place:
|
|
|
|
```bash
|
|
./check-setup.sh
|
|
```
|
|
|
|
This will check for:
|
|
- Required directories (static, templates, node_modules)
|
|
- Critical files (templates, JavaScript, CSS)
|
|
- xterm.js installation
|
|
- Build tools (cargo, npm)
|
|
|
|
**Note**: The server must be run from the project root directory, as it expects `./static`, `./templates`, and `./node_modules` to be accessible in the current working directory.
|
|
|
|
### Command Line Options
|
|
|
|
```bash
|
|
webterm-server --help
|
|
```
|
|
|
|
Options:
|
|
- `-p, --port <PORT>` - The port to listen on (default: 8082)
|
|
- `-H, --host <HOST>` - The host or IP to listen on (default: localhost)
|
|
- `-c, --command <COMMAND>` - The command to execute (default: /bin/sh)
|
|
|
|
Example:
|
|
```bash
|
|
cargo run -- --port 8080 --host 0.0.0.0 --command /bin/bash
|
|
```
|
|
|
|
## Production Deployment
|
|
|
|
### Docker
|
|
|
|
```bash
|
|
# Build the image
|
|
docker build -t socktop-webterm:latest .
|
|
|
|
# Run the container
|
|
docker run -d -p 8082:8082 socktop-webterm:latest
|
|
```
|
|
|
|
### Kubernetes/k3s
|
|
|
|
Automated deployment via Gitea Actions CI/CD:
|
|
|
|
1. Push to `main` branch
|
|
2. Workflow automatically builds arm64 image
|
|
3. Image tagged with version from `Cargo.toml`
|
|
4. Deployed to k3s cluster with zero-downtime rolling update
|
|
|
|
See `.gitea/workflows/build-and-deploy.yaml` for the complete workflow.
|
|
|
|
Manual deployment:
|
|
```bash
|
|
kubectl apply -f kubernetes/
|
|
```
|
|
|
|
## CI/CD Pipeline
|
|
|
|
This project includes a complete CI/CD pipeline using Gitea Actions:
|
|
|
|
- **Automatic builds** on every push to main
|
|
- **Version tagging** from Cargo.toml
|
|
- **Container registry** integration
|
|
- **Automated k3s deployment** with rolling updates
|
|
- **Zero downtime** deployments
|
|
|
|
## Technology Stack
|
|
|
|
- **Backend**: Rust 2021, Actix-Web 4.x, Actix 0.13, portable-pty
|
|
- **Frontend**: xterm.js, HTML5, CSS3
|
|
- **Templating**: Handlebars 6.x
|
|
- **CLI**: clap 4.x
|
|
- **Async Runtime**: Tokio 1.x
|
|
- **Containerization**: Docker, Kubernetes/k3s
|
|
- **CI/CD**: Gitea Actions
|
|
|
|
## Security and Limitations
|
|
|
|
### Security Model
|
|
|
|
This application is designed to provide **safe, public terminal access** for demonstration purposes. The security model consists of multiple layers:
|
|
|
|
#### 1. Restricted Shell
|
|
|
|
When deployed in production (e.g., https://www.socktop.io), the application uses a restricted shell (`docker/restricted-shell.sh`) that:
|
|
|
|
- **Allows only 2 commands**: `socktop` and `help`
|
|
- **Blocks all other commands**: Rejects any attempt to run `ls`, `cat`, `bash`, etc.
|
|
- **Validates arguments**: All arguments passed to `socktop` are sanitized to prevent command injection
|
|
- **Prevents shell escapes**: Blocks metacharacters like `;`, `&&`, `|`, `$()`, backticks, etc.
|
|
- **Blocks path traversal**: Prevents attempts like `../../../etc/passwd`
|
|
|
|
**Example validation:**
|
|
```bash
|
|
# Allowed
|
|
socktop -P local
|
|
socktop -P rpi-master
|
|
socktop ws://192.168.1.100:3000
|
|
|
|
# Blocked with error message
|
|
socktop $(whoami) # Command substitution blocked
|
|
socktop ; /bin/bash # Shell metacharacter blocked
|
|
socktop -P ../etc/passwd # Path traversal blocked
|
|
```
|
|
|
|
#### 2. Argument Sanitization
|
|
|
|
The restricted shell validates all input using regex patterns:
|
|
- Profile names: Only `[a-zA-Z0-9_-]+` characters allowed
|
|
- WebSocket URLs: Only `ws://` or `wss://` with safe characters
|
|
- No environment variable expansion
|
|
- No special characters or shell operators
|
|
|
|
**Security testing**: Run `./scripts/test-shell-security.sh` to verify all 35 security checks pass.
|
|
|
|
#### 3. Container Isolation
|
|
|
|
- Runs inside Docker container (cannot access host system)
|
|
- Non-root user (`socktop` user)
|
|
- Limited resources (CPU/memory limits configurable)
|
|
- No privileged operations
|
|
- Read-only configuration mounts
|
|
|
|
#### 4. WebSocket Security
|
|
|
|
The WebSocket endpoint (`/websocket`) is secure by design:
|
|
- Command spawned is **hardcoded at server startup** (via `--command` flag)
|
|
- No way to change which shell is spawned via WebSocket connection
|
|
- No HTTP headers or request parameters influence the spawned command
|
|
- Direct WebSocket connections get the same restricted shell as browser connections
|
|
|
|
**The Terminado protocol only supports:**
|
|
- `stdin` - Send input to terminal (goes through restricted shell)
|
|
- `stdout` - Receive output from terminal
|
|
- `set_size` - Resize terminal (validated to u16 row/col numbers only)
|
|
|
|
There is no protocol message type that can bypass the shell or execute arbitrary commands.
|
|
|
|
### Reporting Security Issues
|
|
|
|
If you discover a security vulnerability that bypasses the restricted shell or container isolation, please report it via:
|
|
- GetTea Issues (for non-critical issues)
|
|
- Direct contact to maintainer (for critical vulnerabilities)
|
|
|
|
## Credits
|
|
|
|
This project was originally forked from [webterm](https://github.com/fubarnetes/webterm) by Fabian Freyer. I chose this as a base because other projects were way too complex. His project was simple and easy to understand, but it was not well maintained. I have updated it to modern packages and heavily customized it to display a working demo for socktop.
|
|
|
|
### Original Author
|
|
This project is a fork of [webterm](https://github.com/fubarnetes/webterm) originally created by:
|
|
- **Fabian Freyer** (fabian.freyer@physik.tu-berlin.de)
|
|
|
|
### Socktop Enhancements
|
|
Modernized and enhanced for the Socktop project by:
|
|
- **Jason Witty** (jasonpwitty+socktop@proton.me)
|
|
|
|
#### Major Changes from Original
|
|
- Updated to Rust 2021 edition
|
|
- Modernized dependencies (Actix-Web 1.x → 4.x, Tokio 0.1 → 1.x)
|
|
- Replaced deprecated `tokio-pty-process` with `portable-pty`
|
|
- Added automated CI/CD pipeline with Gitea Actions
|
|
- Containerized deployment with Docker
|
|
- Kubernetes/k3s orchestration support
|
|
- Added idle session timeout (5 minutes)
|
|
- Improved error handling and logging
|
|
- Modern CLI with clap instead of structopt
|
|
- Updated to latest xterm.js
|
|
|
|
## License
|
|
|
|
This project is licensed under the **BSD 3-Clause License** - see below:
|
|
|
|
```
|
|
Copyright (c) 2019 Fabian Freyer
|
|
Copyright (c) 2024 Jason Witty
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
3. Neither the name of the copyright holder nor the names of its contributors
|
|
may be used to endorse or promote products derived from this software
|
|
without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
```
|
|
|
|
## Contributing
|
|
|
|
Contributions are welcome! Please feel free to submit pull requests or open issues.
|
|
|
|
## Links
|
|
|
|
- **Repository**: https://gt.wittyoneoff.com/jason/socktop-webterm
|
|
- **Original Project**: https://github.com/fubarnetes/webterm
|
|
- **xterm.js**: https://xtermjs.org/
|
|
- **Actix-Web**: https://actix.rs
|
|
- **portable-pty**: https://crates.io/crates/portable-pty
|