Add webtunnel pluggable transport crate#111
Open
PHPCraftdream wants to merge 1 commit into
Open
Conversation
WebTunnel is a Tor pluggable transport that disguises Tor connections as legitimate HTTPS/WebSocket traffic. The client opens a TLS connection to the bridge, issues an HTTP/1.1 `Upgrade: websocket` handshake, and after a `101 Switching Protocols` response the underlying TCP stream carries raw Tor cell bytes (no WebSocket framing — the Upgrade dance is purely camouflage). Crate contents (`crates/webtunnel/`): - `WebTunnelBuilder` / `WebTunnelClient` implementing `ptrs::ClientBuilder` and `ptrs::ClientTransport` over `tokio::net::TcpStream`. - `WebTunnelConfig` parsing the standard webtunnel bridge-line parameters (`url`, `ver`, `servername`, `addr`, with `utls` accepted and ignored — TLS fingerprint emulation deferred). - TLS via `tokio-rustls` (`webpki-roots` for trust anchors, no ALPN to match the Go reference implementation). - HTTP Upgrade request built without `obs-fold` whitespace (RFC 7230 §3.2.4). `Sec-WebSocket-Key` is 16 cryptographically random bytes from `getrandom`. - 101 response parser via `httparse`, lenient about the optional `Sec-WebSocket-Accept` header. - A `PrefixStream<S>` wrapper preserves any bytes the server fused into the same read as the 101 response (previously a silent data loss vector — the first Tor cell could be discarded). 32 unit tests cover the config parser, HTTP request shape (path, Host, headers, no obs-fold), key generation (length, base64 validity, randomness), 101 response parsing (with and without trailing bytes, non-101 rejection), the prefix stream (transparent on empty prefix, write passthrough), and edge cases (HTTP vs HTTPS scheme, query strings, addr= overriding URL host). Dependencies: tokio-rustls 0.26, webpki-roots 0.26, httparse 1, url 2, base64 0.22, getrandom 0.2. Workspace Cargo.toml updated to include the new crate. Protocol details cross-checked against the Go reference implementation at gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel (via pkg.go.dev and the github mirror at blackyblack/webtunnel).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new
webtunnelcrate implementing the WebTunnel pluggable transport: TLS + HTTP/1.1Upgrade: websockethandshake, after which the TCP stream carries raw Tor cell bytes. No WebSocket framing — the Upgrade dance is purely traffic-shape camouflage.The crate slots in alongside
obfs4/o5as anotherptrs::ClientBuilder/ptrs::ClientTransportimplementation; nothing inlyrebird,ptrs, or any other existing crate is touched. OnlyCargo.tomlgains one new workspace member.What the crate provides
WebTunnelBuilder/WebTunnelClientovertokio::net::TcpStream.WebTunnelConfig: parser for the standard webtunnel bridge-line params (url,ver,servername,addr).utls=is accepted but ignored — TLS fingerprint emulation is deferred (would needboringor a custom ClientHello).tokio-rustlswithwebpki-rootstrust anchors. No ALPN — matches the Go client (NextProtosis nil).Upgraderequest built without obs-fold whitespace (RFC 7230 §3.2.4).Sec-WebSocket-Keyis 16 cryptographically random bytes fromgetrandom.httparse, lenient about the optionalSec-WebSocket-Acceptheader (the Go server doesn't return it; NGINX fronts that add it must not break clients).PrefixStream<S>wrapper preserves any bytes the server fused into the same read as the 101 response (otherwise the first Tor cell can silently disappear).Tests
32 unit tests covering:
PrefixStream: trailing bytes preserved, prefix→inner stream transition, empty-prefix transparent, write passthrough.Cross-referenced sources
Protocol details verified against the Go reference implementation:
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel(viapkg.go.dev)github.com/blackyblack/webtunnelmirror —transport/httpupgrade/httpupgrade.go,transport/tls/tls.goConfirmed: server returns no
Sec-WebSocket-Accept, no ALPN, noSec-WebSocket-Keyvalidation, TCP target isurl=(oraddr=override) — the bridge-line<addr>:<port>is cosmetic.Dependencies added (workspace-relative)
Known follow-ups (out of scope for this PR)
utls=TLS fingerprint emulation (requiresboringor hand-rolled ClientHello).http://URL support is in code but untested against a real server.🤖 Generated with Claude Code