Hi, I’ve been struggling to connect to onion services specifically using arti_client. I can connect to domains and IP addresses available on the clearnet just fine.
Dependencies:
arti-client = { version = "0.41", features = ["onion-service-client"] }
tokio = { version = "1", features = ["macros"] }
tor-rtcompat = "0.41"
tor-error = "0.41"
Code I am using:
use arti_client::{
TorClientConfig,
TorClient,
};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tor_error::ErrorReport;
#[tokio::main]
async fn main() {
let mut config_builder = TorClientConfig::builder();
config_builder.address_filter().allow_onion_addrs(true);
let config = config_builder.build().unwrap();
let tor_client = TorClient::create_bootstrapped(config).await.unwrap();
println!("Created client");
// make connection
{
let mut stream = tor_client.connect(("example.com", 80)).await.unwrap();
stream
.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
.await.unwrap();
stream.flush().await.unwrap();
let mut buf = Vec::new();
stream.read_to_end(&mut buf).await.unwrap();
println!("{}", String::from_utf8_lossy(&buf));
}
println!("Got example.com");
// try an onion site
{
let mut stream = match tor_client
.connect(("duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion", 80))
.await {
Ok(s) => s,
Err(e) => panic!("{}", e.report()),
};
if let Err(e) = stream
.write_all(b"GET / HTTP/1.1\r\nHost: duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion\r\n\
Connection: close\r\n")
.await {
panic!("{}", e.report());
};
if let Err(e) = stream.flush().await {
panic!("{}", e.report());
};
let mut buf = Vec::new();
if let Err(e) = stream.read_to_end(&mut buf).await {
panic!("{}", e.report());
};
println!("{}", String::from_utf8_lossy(&buf));
}
println!("Got onion site");
}
I am able to get example.com without problems, but when it gets to trying to connect to duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion, it panics:
error: tor: tor operation timed out: Failed to obtain hidden service circuit to […]zad.onion: Unable to download hidden service descriptor
Debug print is:
Error { detail: ObtainHsCircuit { hsid: HsId([…]zad.onion), cause: Failed(RetryError { doing: "make circuit to hidden service", errors: [(Single(1), IntroductionTimeout { intro_index: IntroPtIndex(9) }, Instant { tv_sec: 15539, tv_nsec: 183277938 }), (Single(2), IntroductionTimeout { intro_index: IntroPtIndex(7) }, Instant { tv_sec: 15540, tv_nsec: 187632683 }), (Single(3), IntroductionTimeout { intro_index: IntroPtIndex(5) }, Instant { tv_sec: 15541, tv_nsec: 219461270 }), (Single(4), IntroductionTimeout { intro_index: IntroPtIndex(2) }, Instant { tv_sec: 15542, tv_nsec: 221975888 }), (Single(5), RendezvousCompletionTimeout { intro_index: IntroPtIndex(0), rend_pt: ed25519:p7… }, Instant { tv_sec: 15543, tv_nsec: 165188671 }), (Single(6), RendezvousCircuitObtain { error: CircTimeout(None) }, Instant { tv_sec: 15544, tv_nsec: 95640953 }), (Single(7), IntroductionTimeout { intro_index: IntroPtIndex(8) }, Instant { tv_sec: 15545, tv_nsec: 272584717 })], n_errors: 7, first_error_at: Some(SystemTime { tv_sec: 1776183479, tv_nsec: 62420130 }) }) } }
I’ve tried various other onion services (that work fine over Tor Browser) and none of them work.
I’ve also tried using TorClientConfig::default() with the same behaviour observed.
Does anyone have an example of using arti_client to make HTTP requests to onion services? It’s only onion services that don’t work for me.