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>
48 lines
2.1 KiB
Markdown
48 lines
2.1 KiB
Markdown
# 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 |
|