Start tor from test

This commit is contained in:
Philipp Hoenisch 2020-10-20 16:14:10 +11:00
parent 295216a8ee
commit a73f1fcc6f
No known key found for this signature in database
GPG Key ID: E5F8E74C672BC666
2 changed files with 120 additions and 56 deletions

View File

@ -10,17 +10,37 @@ use torut::{
onion::TorSecretKeyV3,
};
lazy_static! {
/// The default TOR socks5 proxy address, `127.0.0.1:9050`.
pub static ref TOR_PROXY_ADDR: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050);
/// The default TOR Controller Protocol address, `127.0.0.1:9051`.
pub static ref TOR_CP_ADDR: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9051));
// lazy_static! {
// The default TOR socks5 proxy address, `127.0.0.1:9050`.
// pub static ref TOR_PROXY_ADDR: SocketAddrV4 =
// SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050); The default TOR Controller
// Protocol address, `127.0.0.1:9051`. pub static ref TOR_CP_ADDR: SocketAddr =
// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9051)); }
type Handler = fn(AsyncEvent<'_>) -> Box<dyn Future<Output = Result<(), ConnError>> + Unpin>;
#[allow(missing_debug_implementations)]
pub struct AuthenticatedConnection {
tor_proxy_address: SocketAddrV4,
tor_control_port_address: SocketAddr,
authenticated_connection: Option<AuthenticatedConn<TcpStream, Handler>>,
}
impl Default for AuthenticatedConnection {
fn default() -> Self {
Self {
tor_proxy_address: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050),
tor_control_port_address: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9051)),
authenticated_connection: None,
}
}
}
impl AuthenticatedConnection {
/// checks if tor is running
async fn tor_running() -> Result<()> {
async fn tor_running(&self) -> Result<()> {
// Make sure you are running tor and this is your socks port
let proxy = reqwest::Proxy::all(format!("socks5h://{}", *TOR_PROXY_ADDR).as_str())
let proxy = reqwest::Proxy::all(format!("socks5h://{}", self.tor_proxy_address).as_str())
.expect("tor proxy should be there");
let client = reqwest::Client::builder()
.proxy(proxy)
@ -39,24 +59,29 @@ async fn tor_running() -> Result<()> {
}
}
type Handler = fn(AsyncEvent<'_>) -> Box<dyn Future<Output = Result<(), ConnError>> + Unpin>;
#[allow(missing_debug_implementations)]
pub struct AuthenticatedConnection(AuthenticatedConn<TcpStream, Handler>);
impl AuthenticatedConnection {
async fn init_unauthenticated_connection() -> Result<UnauthenticatedConn<TcpStream>> {
async fn init_unauthenticated_connection(&self) -> Result<UnauthenticatedConn<TcpStream>> {
// try to connect to local tor service via control port
let sock = TcpStream::connect(*TOR_CP_ADDR).await?;
let sock = TcpStream::connect(self.tor_control_port_address).await?;
let unauthenticated_connection = UnauthenticatedConn::new(sock);
Ok(unauthenticated_connection)
}
/// Create a new authenticated connection to your local Tor service
pub async fn new() -> Result<Self> {
tor_running().await?;
pub fn with_ports(proxy_port: u16, control_port: u16) -> Self {
Self {
tor_proxy_address: SocketAddrV4::new(Ipv4Addr::LOCALHOST, proxy_port),
tor_control_port_address: SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::LOCALHOST,
control_port,
)),
authenticated_connection: None,
}
}
let mut unauthenticated_connection = match Self::init_unauthenticated_connection().await {
/// Create a new authenticated connection to your local Tor service
pub async fn connect(self) -> Result<Self> {
self.tor_running().await?;
let mut unauthenticated_connection = match self.init_unauthenticated_connection().await {
Err(_) => bail!("Tor instance not running"),
Ok(unauthenticated_connection) => unauthenticated_connection,
};
@ -79,13 +104,18 @@ impl AuthenticatedConnection {
}
let authenticated_connection = unauthenticated_connection.into_authenticated().await;
Ok(AuthenticatedConnection(authenticated_connection))
Ok(AuthenticatedConnection {
authenticated_connection: Some(authenticated_connection),
..self
})
}
/// Add an ephemeral tor service on localhost with the provided key
pub async fn add_service(&mut self, port: u16, tor_key: &TorSecretKeyV3) -> Result<()> {
self.0
.add_onion_v3(
match self.authenticated_connection {
None => bail!("Not connected to local tor instance"),
Some(ref mut aut) => {
aut.add_onion_v3(
tor_key,
false,
false,
@ -99,6 +129,9 @@ impl AuthenticatedConnection {
)
.await
.map_err(|_| anyhow!("Could not add onion service."))?;
}
}
Ok(())
}
}

View File

@ -5,10 +5,13 @@ mod tor_test {
use hyper::service::{make_service_fn, service_fn};
use reqwest::StatusCode;
use spectral::prelude::*;
use std::convert::Infallible;
use std::{convert::Infallible, process::Child};
use tokio::sync::oneshot::Receiver;
use torut::onion::TorSecretKeyV3;
use xmr_btc::tor::{AuthenticatedConnection, TOR_PROXY_ADDR};
use torut::{
onion::TorSecretKeyV3,
utils::{run_tor, AutoKillChild},
};
use xmr_btc::tor::AuthenticatedConnection;
async fn hello_world(
_req: hyper::Request<hyper::Body>,
@ -32,15 +35,43 @@ mod tor_test {
});
}
fn run_tmp_tor() -> (Child, u16, u16) {
let control_port = 9051;
let proxy_port = 9050;
(
run_tor(
"tor",
&mut [
"--CookieAuthentication",
"1",
"--ControlPort",
control_port.to_string().as_str(),
]
.iter(),
)
.expect("Starting tor filed"),
control_port,
proxy_port,
)
}
#[tokio::test]
async fn test_tor_control_port() -> Result<()> {
// start tmp tor
let (child, control_port, proxy_port) = run_tmp_tor();
let _child = AutoKillChild::new(child);
// Setup test HTTP Server
let (tx, rx) = tokio::sync::oneshot::channel::<()>();
let port = 8080;
start_test_service(port, rx);
// Connect to local Tor service
let mut authenticated_connection = AuthenticatedConnection::new().await?;
let mut authenticated_connection =
AuthenticatedConnection::with_ports(proxy_port, control_port)
.connect()
.await?;
// Expose an onion service that re-directs to the echo server.
let tor_secret_key_v3 = TorSecretKeyV3::generate();
@ -50,7 +81,7 @@ mod tor_test {
// Test if Tor service forwards to HTTP Server
let proxy = reqwest::Proxy::all(format!("socks5h://{}", *TOR_PROXY_ADDR).as_str())
let proxy = reqwest::Proxy::all(format!("socks5h://127.0.0.1:{}", proxy_port).as_str())
.expect("tor proxy should be there");
let client = reqwest::Client::builder().proxy(proxy).build().unwrap();
let onion_address = tor_secret_key_v3.public().get_onion_address().to_string();