docs: add comprehensive project wiki for v1.0
CI / cargo fmt (push) Has been cancelled
CI / cargo clippy (macos-latest) (push) Has been cancelled
CI / cargo clippy (ubuntu-latest) (push) Has been cancelled
CI / cargo clippy (windows-latest) (push) Has been cancelled
CI / cargo test (macos-latest) (push) Has been cancelled
CI / cargo test (ubuntu-latest) (push) Has been cancelled
CI / cargo test (windows-latest) (push) Has been cancelled
CI / cargo build (macos-latest) (push) Has been cancelled
CI / cargo build (ubuntu-latest) (push) Has been cancelled
CI / cargo build (windows-latest) (push) Has been cancelled
CI / cargo build --release (macos-latest) (push) Has been cancelled
CI / cargo build --release (ubuntu-latest) (push) Has been cancelled
CI / cargo build --release (windows-latest) (push) Has been cancelled
CI / CLI smoke (macos-latest) (push) Has been cancelled
CI / CLI smoke (ubuntu-latest) (push) Has been cancelled
CI / CLI smoke (windows-latest) (push) Has been cancelled
CI / Minimal E2E (macos-latest) (push) Has been cancelled
CI / Minimal E2E (ubuntu-latest) (push) Has been cancelled
CI / Minimal E2E (windows-latest) (push) Has been cancelled
CI / cargo fmt (push) Has been cancelled
CI / cargo clippy (macos-latest) (push) Has been cancelled
CI / cargo clippy (ubuntu-latest) (push) Has been cancelled
CI / cargo clippy (windows-latest) (push) Has been cancelled
CI / cargo test (macos-latest) (push) Has been cancelled
CI / cargo test (ubuntu-latest) (push) Has been cancelled
CI / cargo test (windows-latest) (push) Has been cancelled
CI / cargo build (macos-latest) (push) Has been cancelled
CI / cargo build (ubuntu-latest) (push) Has been cancelled
CI / cargo build (windows-latest) (push) Has been cancelled
CI / cargo build --release (macos-latest) (push) Has been cancelled
CI / cargo build --release (ubuntu-latest) (push) Has been cancelled
CI / cargo build --release (windows-latest) (push) Has been cancelled
CI / CLI smoke (macos-latest) (push) Has been cancelled
CI / CLI smoke (ubuntu-latest) (push) Has been cancelled
CI / CLI smoke (windows-latest) (push) Has been cancelled
CI / Minimal E2E (macos-latest) (push) Has been cancelled
CI / Minimal E2E (ubuntu-latest) (push) Has been cancelled
CI / Minimal E2E (windows-latest) (push) Has been cancelled
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
parent
a758e8e0bc
commit
0166fb6511
@@ -0,0 +1,86 @@
|
||||
# Architecture
|
||||
|
||||
rustunnel is organized as a single Rust binary crate with a modular source tree. The architecture separates CLI parsing, credential generation, TLS configuration, SOCKS5 handling, binary framing, and the core tunnel engine into distinct modules.
|
||||
|
||||
## Component diagram
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[CLI `src/cli.rs`] --> B[Main dispatch `src/main.rs`]
|
||||
B --> C[Credential generation `src/generate.rs`]
|
||||
B --> D[Tunnel engine `src/tunnel.rs`]
|
||||
B --> E[Connection keys `src/connkey.rs`]
|
||||
D --> F[TLS stack `src/tls.rs`]
|
||||
D --> G[SOCKS5 proxy `src/socks5.rs`]
|
||||
D --> H[Framing protocol `src/framing.rs`]
|
||||
D --> I[Signal handling `src/signal.rs`]
|
||||
F --> J[Rustls + ring]
|
||||
G --> K[Tokio TCP]
|
||||
H --> L[Bytes + tokio-util]
|
||||
C --> M[rcgen]
|
||||
```
|
||||
|
||||
## Data flow
|
||||
|
||||
A typical tunnel session flows like this:
|
||||
|
||||
1. **Listener** binds a TCP socket and wraps it with `tokio_rustls::TlsAcceptor`.
|
||||
2. Connector initiates a TCP connection and upgrades it with `tokio_rustls::TlsConnector`.
|
||||
3. Both sides perform mTLS handshakes: the listener requires a client certificate signed by the shared CA; the connector validates the server certificate against the same CA.
|
||||
4. The connector sends an HTTP POST to `/tunnel` with an `X-Rustunnel-Token` header.
|
||||
5. The listener validates the token with a constant-time comparison (`src/tunnel.rs`).
|
||||
6. On success, both sides switch from HTTP/1.1 to a binary framing protocol (`src/framing.rs`).
|
||||
7. The connector's local SOCKS5 proxy accepts client connections and opens multiplexed streams over the single persistent tunnel.
|
||||
8. The listener decodes each stream's target address, opens a local TCP connection to that target, and forwards data bidirectionally.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as Local app
|
||||
participant Socks as SOCKS5 proxy
|
||||
participant Conn as Connector
|
||||
participant TLS as mTLS tunnel
|
||||
participant List as Listener
|
||||
participant Target as Target server
|
||||
|
||||
Client->>Socks: SOCKS5 CONNECT
|
||||
Socks->>Conn: open stream
|
||||
Conn->>TLS: TLS handshake
|
||||
TLS->>List: accept + verify client cert
|
||||
Conn->>List: POST /tunnel + auth token
|
||||
List->>Conn: 200 OK
|
||||
Conn->>List: binary framing CONNECT frame
|
||||
List->>Target: TCP connect
|
||||
Target->>List: response
|
||||
List->>Conn: DATA frame
|
||||
Conn->>Socks: raw bytes
|
||||
Socks->>Client: response
|
||||
```
|
||||
|
||||
## Module responsibilities
|
||||
|
||||
| Module | Responsibility |
|
||||
| ------ | -------------- |
|
||||
| `src/cli.rs` | clap-based CLI definitions for all subcommands and arguments |
|
||||
| `src/main.rs` | Entry point, crypto provider installation, tracing init, command dispatch |
|
||||
| `src/tunnel.rs` | Core tunnel engine: listener accept loop, connector reconnect loop, SOCKS5 proxy, stream mux, HTTP auth handshake, framing loop |
|
||||
| `src/tls.rs` | rustls server and client config builders, certificate loading, identity validation, insecure verifier |
|
||||
| `src/socks5.rs` | SOCKS5 greeting, auth, CONNECT request parsing, target resolution |
|
||||
| `src/framing.rs` | Binary frame serialization/deserialization, `FrameReader`, `FrameWriter` |
|
||||
| `src/generate.rs` | Self-signed CA, server cert, client cert, and auth token generation with rcgen |
|
||||
| `src/connkey.rs` | `ConnectionKey` struct: encode/decode all material as a base64 string |
|
||||
| `src/redact.rs` | `Redacted` wrapper and helpers to prevent secrets from leaking into logs |
|
||||
| `src/errors.rs` | `thiserror`-based error enums for TLS, auth, tunnel, and host operations |
|
||||
| `src/config.rs` | JSON configuration file format for generated credential sets |
|
||||
| `src/signal.rs` | Cross-platform shutdown signal handler (SIGINT/SIGTERM on Unix, Ctrl+C on Windows) |
|
||||
|
||||
## Threading model
|
||||
|
||||
The project uses Tokio's multi-threaded runtime. Each side (listener and connector) spawns tasks for:
|
||||
|
||||
- Accepting new TCP connections
|
||||
- TLS handshakes
|
||||
- Per-tunnel framing loops
|
||||
- Per-stream target forwarding
|
||||
- SOCKS5 client handling
|
||||
|
||||
The connector's SOCKS5 proxy stays bound permanently while a background reconnect loop maintains the tunnel. When the tunnel drops, existing streams receive EOF and new streams wait for the reconnect loop to re-establish the session.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Getting started
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Rust 1.85+ (the project uses Edition 2024)
|
||||
- A POSIX shell or PowerShell for running commands
|
||||
- curl (for E2E testing)
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
cd rustunnel
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The release binary is produced at `target/release/rustunnel`.
|
||||
|
||||
## Run tests
|
||||
|
||||
```sh
|
||||
cargo fmt --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo check
|
||||
cargo test --all-targets
|
||||
```
|
||||
|
||||
The test suite includes unit tests for framing, SOCKS5 parsing, TLS config building, credential generation, connection key roundtrips, and full end-to-end tunnel flows.
|
||||
|
||||
## Generate credentials
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel generate --out ./creds
|
||||
```
|
||||
|
||||
This creates:
|
||||
|
||||
- `creds/ca.pem` — CA certificate
|
||||
- `creds/ca.key` — CA private key
|
||||
- `creds/server.crt` — server certificate
|
||||
- `creds/server.key` — server private key
|
||||
- `creds/client.crt` — client certificate
|
||||
- `creds/client.key` — client private key
|
||||
- `creds/token.txt` — auth token
|
||||
- `creds/config.json` — configuration file with paths and defaults
|
||||
|
||||
## Run a tunnel
|
||||
|
||||
### Start the listener
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel listen \
|
||||
--listen 127.0.0.1:4180 \
|
||||
--cert ./creds/server.crt \
|
||||
--key ./creds/server.key \
|
||||
--ca-cert ./creds/ca.pem \
|
||||
--auth-token-file ./creds/token.txt
|
||||
```
|
||||
|
||||
### Start the connector
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel connect \
|
||||
--target 127.0.0.1:4180 \
|
||||
--socks 127.0.0.1:1180 \
|
||||
--cert ./creds/client.crt \
|
||||
--key ./creds/client.key \
|
||||
--ca-cert ./creds/ca.pem \
|
||||
--auth-token-file ./creds/token.txt
|
||||
```
|
||||
|
||||
### Use the SOCKS5 proxy
|
||||
|
||||
```sh
|
||||
curl --proxy socks5h://127.0.0.1:1180 http://127.0.0.1:4181/
|
||||
```
|
||||
|
||||
## Using a connection key
|
||||
|
||||
Instead of passing individual certificate paths, you can generate a single connection key:
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel keygen --target 127.0.0.1:4180
|
||||
```
|
||||
|
||||
Then start the listener with the key (it auto-generates credentials):
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel listen --connection-key <key>
|
||||
```
|
||||
|
||||
And connect with the same key:
|
||||
|
||||
```sh
|
||||
./target/release/rustunnel connect <key>
|
||||
```
|
||||
|
||||
## Defaults
|
||||
|
||||
- Listener bind address: `0.0.0.0:4180`
|
||||
- Connector target: required (or taken from connection key)
|
||||
- Connector SOCKS5 proxy: `127.0.0.1:1180`
|
||||
@@ -0,0 +1,19 @@
|
||||
# Glossary
|
||||
|
||||
**Connection key** — a base64-encoded JSON blob (prefix `rtun1.`) that bundles the CA certificate, server certificate, server key, client certificate, client key, target address, auth token, and version. Generated by `rustunnel keygen` and consumed by `rustunnel listen` and `rustunnel connect`.
|
||||
|
||||
**Connector** — the `rustunnel connect` side. Establishes an outbound HTTPS+mTLS connection to the listener, authenticates, then exposes a local SOCKS5 proxy for local applications.
|
||||
|
||||
**Framing protocol** — the binary protocol used after the HTTP auth handshake completes. Frame types: CONNECT, CONNECT_REPLY, DATA, CLOSE, ERROR. All multi-byte integers are big-endian. Max payload per frame is 4 MiB.
|
||||
|
||||
**Listener** — the `rustunnel listen` side. Binds an HTTPS server that accepts mTLS connections, validates the auth token, then upgrades the connection to the binary framing protocol.
|
||||
|
||||
**mTLS** — mutual TLS. Both the listener and connector present certificates and verify the peer's certificate against a shared CA. rustunnel uses rustls with ring as the crypto provider.
|
||||
|
||||
**Security gate** — one of the validation steps that must pass before tunnel forwarding begins: TLS handshake, client certificate verification (listener), server certificate verification (connector), application auth token validation.
|
||||
|
||||
**SOCKS5 proxy** — the local proxy exposed by the connector. Implements RFC 1928 CONNECT with optional username/password auth (RFC 1929). Supports IPv4 and domain name targets.
|
||||
|
||||
**Stream ID** — a monotonically increasing odd integer (1, 3, 5, ...) assigned by the connector for each SOCKS5 connection. Even IDs are reserved for future server-initiated streams.
|
||||
|
||||
**StreamMux** — the connector-side structure that manages multiple concurrent streams over a single tunnel connection. Maps stream IDs to per-stream data channels.
|
||||
@@ -0,0 +1,20 @@
|
||||
# rustunnel
|
||||
|
||||
`rustunnel` is a cross-platform Rust CLI tool for lab and development tunneling over HTTPS with mutual TLS (mTLS) and an application-level auth token. It exposes a local SOCKS5 proxy on the connector side and forwards traffic only after HTTPS, certificate, and auth checks succeed.
|
||||
|
||||
The tool is designed for local labs, development environments, and controlled testing where you own or are authorized to operate both endpoints. It is not a production-grade tunnel or a mechanism for accessing systems without permission.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Listener** (`rustunnel listen`) — binds an HTTPS server that accepts mTLS connections from connectors, validates an auth token, then upgrades the connection to a persistent binary-framed tunnel.
|
||||
- **Connector** (`rustunnel connect`) — connects to the listener over HTTPS with mTLS, authenticates, then exposes a local SOCKS5 proxy that forwards traffic through the tunnel.
|
||||
- **Credential generation** (`rustunnel generate`) — creates a self-signed CA, server certificate, client certificate, and auth token for a local session.
|
||||
- **Connection keys** (`rustunnel keygen`) — bundles all credential material into a single base64-encoded string that can be copy-pasted between machines.
|
||||
|
||||
## Quick links
|
||||
|
||||
- [Architecture](../overview/architecture.md)
|
||||
- [Getting started](../overview/getting-started.md)
|
||||
- [Tunnel engine](../systems/tunnel-engine.md)
|
||||
- [TLS stack](../systems/tls-stack.md)
|
||||
- [Security posture](../security.md)
|
||||
Reference in New Issue
Block a user