WIP - figure out what is not working

debug-remodel-tor
Daniel Karzel 3 years ago committed by Thomas Eizinger
parent 44dddcd6bc
commit 52bdaf2c1d
No known key found for this signature in database
GPG Key ID: 651AC83A6C6C8B96

@ -1,28 +1,27 @@
[package] [package]
name = "libp2p-tor" name = "libp2p-tor"
version = "0.1.0" version = "0.1.0"
authors = ["Thomas Eizinger <thomas@eizinger.io>"] authors = [ "Thomas Eizinger <thomas@eizinger.io>" ]
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1" # TODO: Get rid of anyhow dependency anyhow = "1" # TODO: Get rid of anyhow dependency
torut = { version = "0.1", default-features = false, features = ["v3", "control"] }
tokio-socks = "0.5"
libp2p = { version = "0.37", default-features = false, features = ["tcp-tokio"] }
tokio = { version = "1", features = ["sync"] }
futures = "0.3"
tracing = "0.1"
data-encoding = "2.3"
reqwest = { version = "0.11", features = ["socks", "rustls-tls"], default-features = false }
async-trait = "0.1" async-trait = "0.1"
data-encoding = "2.3"
futures = "0.3"
libp2p = { version = "0.37", default-features = false, features = [ "tcp-tokio" ] }
rand = { version = "0.8", optional = true } rand = { version = "0.8", optional = true }
reqwest = { version = "0.11", features = [ "socks", "rustls-tls" ], default-features = false }
tokio = { version = "1", features = [ "sync" ] }
tokio-socks = "0.5"
torut = { version = "0.1", default-features = false, features = [ "v3", "control" ] }
tracing = "0.1"
[dev-dependencies] [dev-dependencies]
tempfile = "3" libp2p = { version = "0.37", default-features = false, features = [ "yamux", "noise", "ping" ] }
tokio = { version = "1", features = ["full"] }
rand = "0.8" rand = "0.8"
libp2p = { version = "0.37", default-features = false, features = ["yamux", "noise", "ping"] } tempfile = "3"
tracing-subscriber = { version = "0.2", default-features = false, features = ["fmt", "ansi", "env-filter", "chrono", "tracing-log"] }
testcontainers = "0.12" testcontainers = "0.12"
tokio = { version = "1", features = [ "full" ] }
tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "chrono", "tracing-log" ] }

@ -8,15 +8,19 @@ use std::time::Duration;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let addr_to_dial = std::env::args() let arg = std::env::args()
.next() .last()
.unwrap() .unwrap();
let addr_to_dial = arg
.parse::<Multiaddr>() .parse::<Multiaddr>()
.unwrap(); .unwrap();
let mut swarm = new_swarm(); let mut swarm = new_swarm();
println!("Peer-ID: {}", swarm.local_peer_id()); println!("Peer-ID: {}", swarm.local_peer_id());
println!("Dialing {}", addr_to_dial);
swarm.dial_addr(addr_to_dial).unwrap(); swarm.dial_addr(addr_to_dial).unwrap();
loop { loop {
@ -41,7 +45,9 @@ async fn main() {
println!("Failed to ping {}: {}", peer, failure) println!("Failed to ping {}: {}", peer, failure)
} }
}, },
_ => {} event => {
println!("Swarm event: {:?}", event)
}
} }
} }
} }

@ -2,7 +2,7 @@ use libp2p::core::muxing::StreamMuxerBox;
use libp2p::core::upgrade::Version; use libp2p::core::upgrade::Version;
use libp2p::ping::{Ping, PingEvent, PingSuccess}; use libp2p::ping::{Ping, PingEvent, PingSuccess};
use libp2p::swarm::{SwarmBuilder, SwarmEvent}; use libp2p::swarm::{SwarmBuilder, SwarmEvent};
use libp2p::{identity, noise, yamux, Swarm, Transport}; use libp2p::{identity, noise, yamux, Swarm, Transport, Multiaddr};
use libp2p_tor::duplex; use libp2p_tor::duplex;
use libp2p_tor::torut_ext::AuthenticatedConnectionExt; use libp2p_tor::torut_ext::AuthenticatedConnectionExt;
use noise::NoiseConfig; use noise::NoiseConfig;
@ -10,23 +10,27 @@ use rand::Rng;
use std::time::Duration; use std::time::Duration;
use torut::control::AuthenticatedConn; use torut::control::AuthenticatedConn;
use torut::onion::TorSecretKeyV3; use torut::onion::TorSecretKeyV3;
use std::str::FromStr;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let wildcard_multiaddr =
"/onion3/WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW:8080"
.parse()
.unwrap();
let mut swarm = new_swarm().await; let key = random_onion_identity();
let onion_address = key.public().get_onion_address().get_address_without_dot_onion();
let onion_port = 7654;
println!("Peer-ID: {}", swarm.local_peer_id()); let mut swarm = new_swarm(key).await;
swarm.listen_on(wildcard_multiaddr).unwrap(); let peer_id = *swarm.local_peer_id();
println!("Peer-ID: {}", peer_id);
// TODO: Figure out what to with the port, we could also set it to 0 and then imply it from the assigned port
swarm.listen_on(Multiaddr::from_str(format!("/onion3/{}:{}", onion_address, onion_port).as_str()).unwrap()).unwrap();
loop { loop {
match swarm.next_event().await { match swarm.next_event().await {
SwarmEvent::NewListenAddr(addr) => { SwarmEvent::NewListenAddr(addr) => {
println!("Listening on {}", addr); println!("Listening on {}", addr);
println!("Connection string: {}/p2p/{}", addr, peer_id)
} }
SwarmEvent::ConnectionEstablished { SwarmEvent::ConnectionEstablished {
peer_id, endpoint, .. peer_id, endpoint, ..
@ -48,7 +52,9 @@ async fn main() {
println!("Failed to ping {}: {}", peer, failure) println!("Failed to ping {}: {}", peer, failure)
} }
}, },
_ => {} event => {
println!("Swarm event: {:?}", event)
}
} }
} }
} }
@ -58,13 +64,13 @@ async fn main() {
/// ///
/// In particular, this swarm can create ephemeral hidden services on the /// In particular, this swarm can create ephemeral hidden services on the
/// configured Tor node. /// configured Tor node.
async fn new_swarm() -> Swarm<Ping> { async fn new_swarm(key: TorSecretKeyV3) -> Swarm<Ping> {
let identity = identity::Keypair::generate_ed25519(); let identity = identity::Keypair::generate_ed25519();
SwarmBuilder::new( SwarmBuilder::new(
duplex::TorConfig::new( duplex::TorConfig::new(
AuthenticatedConn::new(9051).await.unwrap(), AuthenticatedConn::new(9051).await.unwrap(),
random_onion_identity, key,
) )
.await .await
.unwrap() .unwrap()

@ -15,13 +15,6 @@ use tokio::sync::Mutex;
use torut::control::{AsyncEvent, AuthenticatedConn}; use torut::control::{AsyncEvent, AuthenticatedConn};
use torut::onion::TorSecretKeyV3; use torut::onion::TorSecretKeyV3;
/// This is the hash of
/// `/onion3/WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW`.
const WILDCARD_ONION_ADDR_HASH: [u8; 35] = [
181, 173, 107, 90, 214, 181, 173, 107, 90, 214, 181, 173, 107, 90, 214, 181, 173, 107, 90, 214,
181, 173, 107, 90, 214, 181, 173, 107, 90, 214, 181, 173, 107, 90, 214,
];
type TorutAsyncEventHandler = type TorutAsyncEventHandler =
fn( fn(
AsyncEvent<'_>, AsyncEvent<'_>,
@ -31,32 +24,33 @@ type TorutAsyncEventHandler =
pub struct TorConfig { pub struct TorConfig {
inner: MapErr<GenTcpConfig<libp2p::tcp::tokio::Tcp>, fn(std::io::Error) -> Error>, /* TODO: Make generic over async-std / tokio */ inner: MapErr<GenTcpConfig<libp2p::tcp::tokio::Tcp>, fn(std::io::Error) -> Error>, /* TODO: Make generic over async-std / tokio */
tor_client: Arc<Mutex<AuthenticatedConn<tokio::net::TcpStream, TorutAsyncEventHandler>>>, tor_client: Arc<Mutex<AuthenticatedConn<tokio::net::TcpStream, TorutAsyncEventHandler>>>,
onion_key_generator: Arc<dyn (Fn() -> TorSecretKeyV3) + Send + Sync>, key: TorSecretKeyV3,
socks_port: u16, socks_port: u16,
} }
impl TorConfig { impl TorConfig {
pub async fn new( pub async fn new(
mut client: AuthenticatedConn<tokio::net::TcpStream, TorutAsyncEventHandler>, mut client: AuthenticatedConn<tokio::net::TcpStream, TorutAsyncEventHandler>,
onion_key_generator: impl (Fn() -> TorSecretKeyV3) + Send + Sync + 'static, // TODO: change to key directly
key: TorSecretKeyV3,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let socks_port = client.get_socks_port().await?; let socks_port = client.get_socks_port().await?;
Ok(Self { Ok(Self {
inner: TokioTcpConfig::new().map_err(Error::InnerTransprot), inner: TokioTcpConfig::new().map_err(Error::InnerTransprot),
tor_client: Arc::new(Mutex::new(client)), tor_client: Arc::new(Mutex::new(client)),
onion_key_generator: Arc::new(onion_key_generator), key,
socks_port, socks_port,
}) })
} }
pub async fn from_control_port( pub async fn from_control_port(
control_port: u16, control_port: u16,
key_generator: impl (Fn() -> TorSecretKeyV3) + Send + Sync + 'static, key: TorSecretKeyV3,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let client = AuthenticatedConn::new(control_port).await?; let client = AuthenticatedConn::new(control_port).await?;
Self::new(client, key_generator).await Self::new(client, key).await
} }
} }
@ -80,9 +74,9 @@ impl Transport for TorConfig {
return Err(TransportError::MultiaddrNotSupported(addr)); return Err(TransportError::MultiaddrNotSupported(addr));
}; };
if onion.hash() != &WILDCARD_ONION_ADDR_HASH { let key: TorSecretKeyV3 = self.key;
return Err(TransportError::Other(Error::OnlyWildcardAllowed)); let onion_bytes = key.public().get_onion_address().get_raw_bytes();
} let onion_port = onion.port();
let localhost_tcp_random_port_addr = "/ip4/127.0.0.1/tcp/0" let localhost_tcp_random_port_addr = "/ip4/127.0.0.1/tcp/0"
.parse() .parse()
@ -90,10 +84,6 @@ impl Transport for TorConfig {
let listener = self.inner.listen_on(localhost_tcp_random_port_addr)?; let listener = self.inner.listen_on(localhost_tcp_random_port_addr)?;
let key: TorSecretKeyV3 = (self.onion_key_generator)();
let onion_bytes = key.public().get_onion_address().get_raw_bytes();
let onion_port = onion.port();
let tor_client = self.tor_client; let tor_client = self.tor_client;
let listener = listener let listener = listener
@ -115,6 +105,7 @@ impl Transport for TorConfig {
}) })
.expect("TODO: Error handling"); .expect("TODO: Error handling");
// TODO: Don't fully understand this part, why would we have two different multiaddresses here? the actual onion address and the multiaddress would make more sense...?
tracing::debug!( tracing::debug!(
"Setting up hidden service at {} to forward to {}", "Setting up hidden service at {} to forward to {}",
onion_multiaddress, onion_multiaddress,
@ -125,6 +116,7 @@ impl Transport for TorConfig {
.clone() .clone()
.lock() .lock()
.await .await
// TODO: Potentially simplify this, in our setup the onion port is always equal to the local port. Otherwise we would have the user provide an additional port for the oion service.
.add_ephemeral_service(&key, onion_port, local_port) .add_ephemeral_service(&key, onion_port, local_port)
.await .await
{ {
@ -141,7 +133,9 @@ impl Transport for TorConfig {
local_addr, local_addr,
remote_addr, remote_addr,
}, },
ListenerEvent::AddressExpired(_) => { // TODO: why was the constructed multiaddr used here?
ListenerEvent::AddressExpired(adr) => {
// TODO: even if so, why would we ignore it? Far more logical to just use it...
// can ignore address because we only ever listened on one and we // can ignore address because we only ever listened on one and we
// know which one that was // know which one that was
@ -156,7 +150,7 @@ impl Transport for TorConfig {
.del_onion(&onion_address_without_dot_onion) .del_onion(&onion_address_without_dot_onion)
.await .await
{ {
Ok(()) => ListenerEvent::AddressExpired(onion_multiaddress), Ok(()) => ListenerEvent::AddressExpired(adr),
Err(e) => ListenerEvent::Error(Error::Torut( Err(e) => ListenerEvent::Error(Error::Torut(
torut_ext::Error::Connection(e), torut_ext::Error::Connection(e),
)), )),

@ -42,7 +42,7 @@ async fn create_ephemeral_service() {
AuthenticatedConn::with_password(9051, "supersecret") AuthenticatedConn::with_password(9051, "supersecret")
.await .await
.unwrap(), .unwrap(),
move || onion_key_bytes.into(), onion_key_bytes.into(),
) )
.await .await
.unwrap() .unwrap()
@ -149,17 +149,16 @@ impl IntoIterator for TorArgs {
let mut args = Vec::new(); let mut args = Vec::new();
if let Some(port) = self.socks_port { if let Some(port) = self.socks_port {
args.push(format!("SocksPort")); args.push("SocksPort".to_string());
args.push(format!("0.0.0.0:{}", port)); args.push(format!("0.0.0.0:{}", port));
} }
if let Some(port) = self.control_port { if let Some(port) = self.control_port {
args.push(format!("ControlPort")); args.push("ControlPort".to_string());
args.push(format!("0.0.0.0:{}", port)); args.push(format!("0.0.0.0:{}", port));
args.push(format!("HashedControlPassword")); args.push("HashedControlPassword".to_string());
args.push(format!( args.push("16:436B425404AA332A60B4F341C2023146C4B3A80548D757F0BB10DE81B4"
"16:436B425404AA332A60B4F341C2023146C4B3A80548D757F0BB10DE81B4" .to_string())
))
} }
args.into_iter() args.into_iter()
@ -186,7 +185,7 @@ impl Image for TorImage {
} }
fn args(&self) -> Self::Args { fn args(&self) -> Self::Args {
self.args.clone() self.args
} }
fn env_vars(&self) -> Self::EnvVars { fn env_vars(&self) -> Self::EnvVars {

Loading…
Cancel
Save