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,53 +10,78 @@ 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));
}
/// checks if tor is running
async fn tor_running() -> 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())
.expect("tor proxy should be there");
let client = reqwest::Client::builder()
.proxy(proxy)
.build()
.expect("should be able to build reqwest client");
let res = client.get("https://check.torproject.org").send().await?;
let text = res.text().await?;
let is_tor = text.contains("Congratulations. This browser is configured to use Tor.");
if is_tor {
Ok(())
} else {
bail!("Tor is currently not running")
}
}
// 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(AuthenticatedConn<TcpStream, Handler>);
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 {
async fn init_unauthenticated_connection() -> Result<UnauthenticatedConn<TcpStream>> {
/// checks if tor is running
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://{}", self.tor_proxy_address).as_str())
.expect("tor proxy should be there");
let client = reqwest::Client::builder()
.proxy(proxy)
.build()
.expect("should be able to build reqwest client");
let res = client.get("https://check.torproject.org").send().await?;
let text = res.text().await?;
let is_tor = text.contains("Congratulations. This browser is configured to use Tor.");
if is_tor {
Ok(())
} else {
bail!("Tor is currently not running")
}
}
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,26 +104,34 @@ 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(
tor_key,
false,
false,
false,
None,
&mut [(
port,
SocketAddr::new(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), port),
)]
.iter(),
)
.await
.map_err(|_| anyhow!("Could not add onion service."))?;
match self.authenticated_connection {
None => bail!("Not connected to local tor instance"),
Some(ref mut aut) => {
aut.add_onion_v3(
tor_key,
false,
false,
false,
None,
&mut [(
port,
SocketAddr::new(IpAddr::from(Ipv4Addr::new(127, 0, 0, 1)), port),
)]
.iter(),
)
.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();