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

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
root
2026-06-04 14:07:55 -06:00
co-authored by factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
parent a758e8e0bc
commit 0166fb6511
32 changed files with 1483 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
# Connection keys
A connection key bundles all credential material and the target address into a single copy-pasteable string.
## Purpose
Simplify distribution of tunnel credentials between machines. Instead of transferring eight separate files, a user can generate one key and paste it into the `listen` and `connect` commands.
## Format
Connection keys start with the prefix `rtun1.` followed by base64url-encoded (no padding) JSON:
```json
{
"version": 1,
"target": "198.51.100.10:4180",
"ca_cert_pem": "-----BEGIN CERTIFICATE-----...",
"server_cert_pem": "-----BEGIN CERTIFICATE-----...",
"server_key_pem": "-----BEGIN PRIVATE KEY-----...",
"client_cert_pem": "-----BEGIN CERTIFICATE-----...",
"client_key_pem": "-----BEGIN PRIVATE KEY-----...",
"auth_token": "a1b2c3..."
}
```
## Key abstractions
| Type | File | Description |
| ---- | ---- | ----------- |
| `ConnectionKey` | `src/connkey.rs` | Struct with all fields, version check, validation |
| `ConnectionKey::encode` | `src/connkey.rs` | Serialize to JSON, base64url-encode, prepend prefix |
| `ConnectionKey::decode` | `src/connkey.rs` | Strip prefix, base64url-decode, deserialize, validate |
| `looks_like_connection_key` | `src/connkey.rs` | Quick check if a string starts with `rtun1.` |
## Validation
`decode` validates:
- Prefix must be `rtun1.`
- Base64 decoding must succeed
- JSON deserialization must succeed
- Version must be exactly `1`
- All string fields must be non-empty after trimming
## Integration
`src/main.rs` uses `ConnectionKey::decode` when the `--connection-key` flag or positional argument is provided. The decoded material is passed to `ServerTlsMaterial::Pem` or `ClientTlsMaterial::Pem` variants, which bypass file loading and use the embedded PEM strings directly.
## Entry points for modification
- To change the key format or add versioning: modify `src/connkey.rs`.
- To add compression or encryption: consider extending the encode/decode pipeline in `ConnectionKey`.
## Key source files
| File | Purpose |
| ---- | ------- |
| `src/connkey.rs` | Connection key struct, encoding, decoding, validation |
+7
View File
@@ -0,0 +1,7 @@
# Features
rustunnel's user-visible and developer-visible capabilities:
- [Connection keys](connection-keys.md) — single-string credential bundles
- [Stream multiplexing](stream-multiplexing.md) — multiple SOCKS5 streams over one tunnel
- [Reconnect and shutdown](reconnect-and-shutdown.md) — operational resilience
@@ -0,0 +1,57 @@
# Reconnect and shutdown
The connector is designed to recover from tunnel interruptions without dropping the SOCKS5 proxy.
## Purpose
Lab networks and development environments are unstable. The connector should tolerate listener restarts, network hiccups, and temporary failures without requiring manual intervention.
## Reconnect behavior
`run_reconnect_loop` in `src/tunnel.rs` continuously attempts to maintain a tunnel:
1. Connect to the target address via TCP.
2. Perform TLS handshake and server certificate verification.
3. Send the HTTP auth request and wait for 200 OK.
4. On success, create a `StreamMux`, publish it via the `watch::channel`, and run the framing loop.
5. When the tunnel drops (framing task ends), log the disconnection and retry.
### Backoff
- Initial delay: 1 second
- Exponential doubling up to a maximum of 30 seconds
- Auth failures are terminal (the loop exits rather than retrying with a bad token)
### SOCKS5 proxy during reconnect
The SOCKS5 proxy stays bound. If a client connects while the tunnel is down, the proxy sees `mux_receiver` is `None` and rejects the connection with a warning log. Once the reconnect loop succeeds, new SOCKS5 requests work immediately.
## Shutdown
Both listener and connector handle graceful shutdown:
- Unix: SIGINT or SIGTERM triggers shutdown via `tokio::signal::unix`.
- Windows: Ctrl+C or Ctrl+Break triggers shutdown via `tokio::signal::ctrl_c`.
### Listener shutdown
1. The shutdown signal breaks the `tokio::select!` in `run_listener`.
2. The TCP listener is dropped, releasing the bind port.
3. The SOCKS5 proxy task (if any) is aborted.
4. Active framing sessions end when their streams close.
### Connector shutdown
1. The shutdown signal breaks the `tokio::select!` in `run_socks5_proxy`.
2. The SOCKS5 listener is dropped.
3. The reconnect loop handle is aborted.
4. Existing SOCKS5 connections receive EOF when their streams close.
E2E tests `e2e_graceful_shutdown_listener` and `e2e_graceful_shutdown_connector` verify that ports are released within 3 seconds of abort.
## Key source files
| File | Purpose |
| ---- | ------- |
| `src/tunnel.rs` | `run_reconnect_loop`, `run_socks5_proxy`, `run_listener`, shutdown handling |
| `src/signal.rs` | Cross-platform shutdown signal future |
@@ -0,0 +1,47 @@
# Stream multiplexing
rustunnel carries multiple SOCKS5 connections over a single persistent TLS tunnel using stream IDs.
## Purpose
Avoid the overhead of establishing a new HTTPS connection for every SOCKS5 request. A single mTLS+auth session stays open, and multiple logical streams are interleaved via the binary framing protocol.
## How it works
### Connector side
1. A local SOCKS5 client connects to the connector's SOCKS5 proxy.
2. The connector's `StreamMux::open_stream` allocates the next odd stream ID.
3. It sends a CONNECT frame with the target address encoded in the payload.
4. It waits for a CONNECT_REPLY frame (status 0x00 = OK).
5. On success, it returns a `mpsc::Receiver<Bytes>` for tunnel-to-SOCKS5 data.
6. The connector spawns a task to read from the SOCKS5 client and send DATA frames to the tunnel.
7. Another path reads from the `data_rx` channel and writes raw bytes back to the SOCKS5 client.
### Listener side
1. The listener receives a CONNECT frame with a stream ID and target address.
2. It resolves the target address and opens a TCP connection.
3. It spawns a task to read from the target and send DATA frames back to the tunnel.
4. It sends a CONNECT_REPLY frame to acknowledge the stream.
5. Incoming DATA frames for that stream ID are written to the target connection.
6. CLOSE frames trigger shutdown of the target connection.
### Stream isolation
Each stream has its own ID. Data from one stream never mixes with another. The E2E test `e2e_concurrent_streams_isolation` verifies this by sending unique payloads through two concurrent streams and asserting each echo response matches its original payload.
## Key abstractions
| Type | File | Description |
| ---- | ---- | ----------- |
| `StreamMux` | `src/tunnel.rs` | Connector-side multiplexer |
| `ServerStreamEntry` | `src/tunnel.rs` | Listener-side per-stream target write half |
| `ConnectorStreamEntry` | `src/tunnel.rs` | Connector-side per-stream data channel and reply channel |
## Key source files
| File | Purpose |
| ---- | ------- |
| `src/tunnel.rs` | StreamMux, open_stream, dispatch_frame, framing loops |
| `src/framing.rs` | Frame types, CONNECT/DATA/CLOSE/ERROR encoding |