Skip to main content
The iroh-tor-transport crate routes iroh connections through Tor hidden services, hiding both peers’ IP addresses from each other and from the network. This is useful when IP address privacy is a hard requirement for your application. For background, see the blog post.
Both iroh’s custom transport API and this crate are experimental. Expect breaking changes.

Installation

Add the dependency:
cargo add iroh-tor-transport
You also need a running Tor daemon with the control port enabled:
tor --ControlPort 9051 --CookieAuthentication 0

Usage

use iroh::{Endpoint, SecretKey, presets};
use iroh_tor_transport::TorCustomTransport;

let secret_key = SecretKey::generate(&mut rand::rng());
let transport = TorCustomTransport::builder()
    .build(secret_key.clone())
    .await?;

let endpoint = Endpoint::builder()
    .secret_key(secret_key)
    .preset(transport.preset())
    .bind(presets::N0)
    .await?;
You can only connect to other endpoints that also have the Tor transport enabled.

How it works

Connections are routed through Tor onion services. Each endpoint creates a hidden service address, which other endpoints dial over the Tor network. Neither side learns the other’s real IP address.

Current limitations

  • Requires a separately installed and running Tor daemon
  • Cookie authentication must be disabled (--CookieAuthentication 0)
  • No automatic recovery if the Tor daemon crashes
  • Limited to TCP streams over Tor

Feature flag

Custom transport support must be enabled:
[dependencies]
iroh = { version = "*", features = ["unstable-custom-transports"] }