Remove tor module

This commit is contained in:
Daniel Karzel 2020-12-17 18:50:15 +11:00
parent 6ef6fc894f
commit 43d05935e7
5 changed files with 257 additions and 610 deletions

623
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,6 @@ structopt = "0.3"
tempfile = "3" tempfile = "3"
time = "0.2" time = "0.2"
tokio = { version = "0.2", features = ["rt-threaded", "time", "macros", "sync"] } tokio = { version = "0.2", features = ["rt-threaded", "time", "macros", "sync"] }
torut = { version = "0.1" }
tracing = { version = "0.1", features = ["attributes"] } tracing = { version = "0.1", features = ["attributes"] }
tracing-core = "0.1" tracing-core = "0.1"
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] } tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }

View File

@ -12,7 +12,6 @@ pub mod network;
pub mod serde; pub mod serde;
pub mod state; pub mod state;
pub mod storage; pub mod storage;
pub mod tor;
pub mod trace; pub mod trace;
pub type Never = std::convert::Infallible; pub type Never = std::convert::Infallible;

View File

@ -1,117 +0,0 @@
use anyhow::{anyhow, bail, Result};
use std::{
future::Future,
net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
};
use tokio::net::TcpStream;
use torut::{
control::{AsyncEvent, AuthenticatedConn, ConnError, UnauthenticatedConn},
onion::TorSecretKeyV3,
};
#[derive(Debug, Clone, Copy)]
pub struct UnauthenticatedConnection {
tor_proxy_address: SocketAddrV4,
tor_control_port_address: SocketAddr,
}
impl Default for UnauthenticatedConnection {
fn default() -> Self {
Self {
tor_proxy_address: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050),
tor_control_port_address: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9051)),
}
}
}
impl UnauthenticatedConnection {
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,
)),
}
}
/// checks if tor is running
async fn assert_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())
.map_err(|_| anyhow!("tor proxy should be there"))?;
let client = reqwest::Client::builder().proxy(proxy).build()?;
let res = client.get("https://check.torproject.org").send().await?;
let text = res.text().await?;
if !text.contains("Congratulations. This browser is configured to use Tor.") {
bail!("Tor is currently not running")
}
Ok(())
}
async fn init_unauthenticated_connection(&self) -> Result<UnauthenticatedConn<TcpStream>> {
// Connect to local tor service via control port
let sock = TcpStream::connect(self.tor_control_port_address).await?;
let uc = UnauthenticatedConn::new(sock);
Ok(uc)
}
/// Create a new authenticated connection to your local Tor service
pub async fn init_authenticated_connection(self) -> Result<AuthenticatedConnection> {
self.assert_tor_running().await?;
let mut uc = self
.init_unauthenticated_connection()
.await
.map_err(|_| anyhow!("Tor instance not running."))?;
let tor_info = uc
.load_protocol_info()
.await
.map_err(|_| anyhow!("Failed to load protocol info from Tor."))?;
let tor_auth_data = tor_info
.make_auth_data()?
.ok_or_else(|| anyhow!("Failed to make auth data."))?;
// Get an authenticated connection to the Tor via the Tor Controller protocol.
uc.authenticate(&tor_auth_data)
.await
.map_err(|_| anyhow!("Failed to authenticate with Tor"))?;
Ok(AuthenticatedConnection {
authenticated_connection: uc.into_authenticated().await,
})
}
}
type Handler = fn(AsyncEvent<'_>) -> Box<dyn Future<Output = Result<(), ConnError>> + Unpin>;
#[allow(missing_debug_implementations)]
pub struct AuthenticatedConnection {
authenticated_connection: AuthenticatedConn<TcpStream, Handler>,
}
impl AuthenticatedConnection {
/// 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.authenticated_connection
.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(|e| anyhow!("Could not add onion service.: {:#?}", e))
}
}

View File

@ -1,125 +0,0 @@
#[cfg(feature = "tor")]
mod tor_test {
use anyhow::Result;
use hyper::service::{make_service_fn, service_fn};
use reqwest::StatusCode;
use spectral::prelude::*;
use std::{convert::Infallible, fs};
use swap::tor::UnauthenticatedConnection;
use tempfile::{Builder, NamedTempFile};
use tokio::sync::oneshot::Receiver;
use torut::{
onion::TorSecretKeyV3,
utils::{run_tor, AutoKillChild},
};
async fn hello_world(
_req: hyper::Request<hyper::Body>,
) -> Result<hyper::Response<hyper::Body>, Infallible> {
Ok(hyper::Response::new("Hello World".into()))
}
fn start_test_service(port: u16, rx: Receiver<()>) {
let make_svc =
make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(hello_world)) });
let addr = ([127, 0, 0, 1], port).into();
let server = hyper::Server::bind(&addr).serve(make_svc);
let graceful = server.with_graceful_shutdown(async {
rx.await.ok();
});
tokio::spawn(async {
if let Err(e) = graceful.await {
eprintln!("server error: {}", e);
}
});
tracing::info!("Test server started at port: {}", port);
}
fn run_tmp_tor() -> Result<(AutoKillChild, u16, u16, NamedTempFile)> {
// we create an empty torrc file to not use the system one
let temp_torrc = Builder::new().tempfile()?;
let torrc_file = format!("{}", fs::canonicalize(temp_torrc.path())?.display());
tracing::info!("Temp torrc file created at: {}", torrc_file);
let control_port = if port_check::is_local_port_free(9051) {
9051
} else {
port_check::free_local_port().unwrap()
};
let proxy_port = if port_check::is_local_port_free(9050) {
9050
} else {
port_check::free_local_port().unwrap()
};
let child = run_tor(
"tor",
&mut [
"--CookieAuthentication",
"1",
"--ControlPort",
control_port.to_string().as_str(),
"--SocksPort",
proxy_port.to_string().as_str(),
"-f",
&torrc_file,
]
.iter(),
)?;
tracing::info!("Tor running with pid: {}", child.id());
let child = AutoKillChild::new(child);
Ok((child, control_port, proxy_port, temp_torrc))
}
#[tokio::test]
async fn test_tor_control_port() -> Result<()> {
// start tmp tor
let (_child, control_port, proxy_port, _tmp_torrc) = run_tmp_tor()?;
// 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 =
UnauthenticatedConnection::with_ports(proxy_port, control_port)
.init_authenticated_connection()
.await?;
tracing::info!("Tor authenticated.");
// Expose an onion service that re-directs to the echo server.
let tor_secret_key_v3 = TorSecretKeyV3::generate();
authenticated_connection
.add_service(port, &tor_secret_key_v3)
.await?;
// Test if Tor service forwards to HTTP Server
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()?;
let onion_address = tor_secret_key_v3.public().get_onion_address().to_string();
let onion_url = format!("http://{}:8080", onion_address);
tracing::info!("Tor service added: {}", onion_url);
let res = client.get(&onion_url).send().await?;
assert_that(&res.status()).is_equal_to(StatusCode::OK);
let text = res.text().await?;
assert_that!(text).contains("Hello World");
tracing::info!(
"Local server called via Tor proxy. Its response is: {}",
text
);
// gracefully shut down server
let _ = tx.send(());
Ok(())
}
}