Files
rootandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 0166fb6511
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
docs: add comprehensive project wiki for v1.0
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-06-04 14:07:55 -06:00

87 lines
4.0 KiB
Markdown

# 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.