# How webtor-rs Enables Anonymous HTTP/HTTPS Connections Over Tor

> Discover how webtor-rs uses Rust to build Tor circuits for anonymous HTTP/HTTPS connections. Learn about stream isolation and TLS wrapping for enhanced privacy.

- Repository: [igor53627/webtor-rs](https://github.com/igor53627/webtor-rs)
- Tags: deep-dive
- Published: 2026-03-04

---

**webtor-rs enables anonymous HTTP/HTTPS connections by constructing Tor circuits in pure Rust, applying stream isolation policies to prevent correlation attacks, and wrapping TCP streams with TLS—using rustls for native targets and subtle-tls for WebAssembly.**

The `igor53627/webtor-rs` repository implements a complete Tor client in Rust that compiles to both native binaries and WebAssembly. Unlike proxy-based solutions, this library embeds the full circuit construction logic, allowing applications to make HTTP requests without revealing the client IP address or linking separate requests to the same identity.

## How webtor-rs Routes Traffic Through Tor

Anonymous connections in webtor-rs follow a three-stage pipeline: circuit construction with isolation, stream creation, and HTTP/TLS handling. Each stage is designed to prevent IP leakage and correlation attacks while supporting both desktop and browser environments.

### Circuit Construction and Stream Isolation

The `CircuitManager` in [`webtor/src/client.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/client.rs) assembles Tor circuits consisting of a guard, middle, and exit relay. When a new HTTP request is initiated, the client derives an `IsolationKey` from the target URL via `IsolationKey::from_url` in [`webtor/src/isolation.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/isolation.rs).

This isolation key ensures that distinct domains never share the same circuit, preventing exit nodes from correlating traffic across different destinations. The policy defaults to `StreamIsolationPolicy::PerDomain`, though applications can configure alternative strategies for session-based or request-based isolation.

### Opening Anonymous Streams

Once a circuit is selected, the client opens a raw TCP stream to the destination host and port through the exit relay. The `Circuit::begin_stream` method in [`webtor/src/circuit.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/circuit.rs) handles this negotiation, establishing the end-to-end connection without exposing the client's actual IP address.

This stream serves as the underlying transport for the HTTP payload, ensuring that all network-level communication appears to originate from the Tor exit node rather than the originating device.

### HTTP Request Handling and TLS Encryption

The `TorHttpClient` in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) orchestrates the final request phase. For each request, it constructs the HTTP byte buffer using `HttpRequest::build_request`, then determines whether TLS is required based on the URL scheme.

For native targets, the stream is wrapped using `wrap_with_tls` in [`webtor/src/tls.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/tls.rs), which utilizes **rustls** for TLS 1.2/1.3 encryption. For WebAssembly builds, the client automatically switches to **subtle-tls** (located in the `subtle-tls` crate), which implements TLS using the WebCrypto API available in browsers.

After establishing the secure tunnel, the client writes the HTTP request bytes, reads the response, and handles chunked transfer-encoding and Content-Length validation before returning the parsed `HttpResponse`.

## Anonymous HTTP/HTTPS Request Flow in Code

The following example demonstrates how to configure a `TorHttpClient` with per-domain isolation and execute anonymous GET and POST requests:

```rust
use std::sync::Arc;
use tokio::sync::RwLock;
use webtor::{
    client::TorClient,
    http::{TorHttpClient, HttpRequest},
    relay::RelayManager,
    circuit::CircuitManager,
    isolation::StreamIsolationPolicy,
};

#[tokio::main]
async fn main() -> webtor::Result<()> {
    // Initialize relay list (normally populated from Tor consensus)
    let relays = vec![
        webtor::relay::Relay::new(
            "fingerprint1".into(),
            "guard1".into(),
            "1.1.1.1".into(),
            9001,
            vec!["Fast".into(), "Guard".into()],
            "0000...".into(),
        ),
        // ... middle and exit relays
    ];

    // Build core Tor client components
    let relay_manager = RelayManager::new(relays);
    let circuit_manager = Arc::new(RwLock::new(CircuitManager::new(
        Arc::new(RwLock::new(relay_manager)),
        Arc::new(RwLock::new(None)),
    )));
    let tor_client = TorClient::new(circuit_manager.clone());

    // Create HTTP client with per-domain stream isolation
    let http = TorHttpClient::new(circuit_manager, StreamIsolationPolicy::PerDomain);

    // Anonymous GET request
    let resp = http.get("https://httpbin.org/ip").await?;
    println!("Status: {}", resp.status);
    println!("Body: {}", resp.text()?);

    // Anonymous POST request with JSON payload
    let json = br#"{"msg":"hello"}"#.to_vec();
    let resp = http.post("https://httpbin.org/post", json).await?;
    println!("POST response: {}", resp.text()?);

    Ok(())
}

```

When compiled for WebAssembly, the same code automatically uses the `subtle-tls` implementation for TLS handshakes via the WebCrypto API, requiring no API changes.

## Key Implementation Files

The anonymous connection capability is distributed across these core modules:

- **[`webtor/src/client.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/client.rs)** – `TorClient` initialization and circuit management entry points
- **[`webtor/src/circuit.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/circuit.rs)** – `Circuit::begin_stream` for opening TCP streams through exit relays
- **[`webtor/src/isolation.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/isolation.rs)** – `IsolationKey::from_url` and stream isolation policies
- **[`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs)** – `TorHttpClient`, `HttpRequest::build_request`, and response parsing
- **[`webtor/src/tls.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/tls.rs)** – Native TLS wrapping using `rustls` via `wrap_with_tls`
- **`subtle-tls/`** – WebAssembly-specific TLS implementation using WebCrypto

## Summary

- **webtor-rs** implements a complete Tor client in Rust that supports both native and WebAssembly targets for anonymous HTTP/HTTPS connections.
- **Stream isolation** via `IsolationKey::from_url` ensures distinct domains use separate Tor circuits, preventing traffic correlation.
- **Circuit construction** in `CircuitManager` and `Circuit::begin_stream` routes TCP streams through guard, middle, and exit relays without exposing the client IP.
- **TLS abstraction** automatically selects `rustls` for native builds and `subtle-tls` (WebCrypto) for WASM, enabling secure HTTPS requests in browsers without native code.
- All traffic exits through Tor exit nodes, ensuring the destination server sees only the exit relay's IP address.

## Frequently Asked Questions

### How does webtor-rs prevent different websites from correlating my requests?

webtor-rs implements **stream isolation** through the `IsolationKey` struct in [`webtor/src/isolation.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/isolation.rs). By default, it uses `StreamIsolationPolicy::PerDomain`, which derives a unique isolation key from each URL's host component. The `CircuitManager` ensures that requests with different isolation keys are routed through separate Tor circuits (distinct guard, middle, and exit relays), preventing exit nodes from linking traffic across different destinations.

### Can I use webtor-rs in a web browser?

Yes. webtor-rs compiles to **WebAssembly** using the `wasm32-unknown-unknown` target. When running in a browser, the library automatically switches from the native `rustls` TLS implementation to **subtle-tls**, which performs TLS handshakes using the WebCrypto API. This allows the Tor client to establish secure HTTPS connections within the browser sandbox without requiring native code or browser extensions.

### What happens if a TLS 1.3 connection fails in webtor-rs?

The `TorHttpClient` in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs) includes automatic fallback logic for TLS handshake failures. If a TLS 1.3 connection attempt fails (common with older servers or certain exit relays), the client automatically retries the connection using **TLS 1.2**. This fallback ensures maximum connectivity while maintaining the anonymity guarantees of the underlying Tor circuit, as the retry occurs over the same isolated circuit without exposing the client identity.

### Does webtor-rs support HTTP/2 or only HTTP/1.1?

Based on the current implementation in [`webtor/src/http.rs`](https://github.com/igor53627/webtor-rs/blob/main/webtor/src/http.rs), webtor-rs primarily targets **HTTP/1.1** through its `HttpRequest::build_request` method and manual response parsing (handling chunked transfer-encoding and Content-Length). The library focuses on compatibility and anonymity rather than advanced protocol features. HTTP/2 support would require additional implementation of the HTTP/2 framing layer atop the existing Tor stream infrastructure.