Add initial support for running a PT in server mode

This commit is contained in:
Saksham Mittal 2023-08-24 17:03:38 +00:00 committed by Ian Jackson
parent 660adb6dc6
commit bbed17ba4a
7 changed files with 676 additions and 321 deletions

View File

@ -0,0 +1,2 @@
ADDED: `proxied::Protocol`
ADDED: `proxied::settings_to_protocol`

View File

@ -5,7 +5,7 @@ use futures::{AsyncRead, AsyncWrite};
use tor_linkspec::OwnedChanTarget;
pub(crate) mod default;
pub(crate) mod proxied;
pub mod proxied;
pub(crate) use default::DefaultTransport;

View File

@ -40,7 +40,7 @@ use tor_linkspec::{ChannelMethod, HasChanMethod, OwnedChanTarget};
/// Information about what proxy protocol to use, and how to use it.
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub(crate) enum Protocol {
pub enum Protocol {
/// Connect via SOCKS 4, SOCKS 4a, or SOCKS 5.
Socks(SocksVersion, SocksAuth),
}
@ -410,7 +410,7 @@ where
/// authentication.
// NOTE(eta): I am very unsure of the logic in here.
#[cfg(feature = "pt-client")]
fn settings_to_protocol(vers: SocksVersion, s: String) -> Result<Protocol, ProxyError> {
pub fn settings_to_protocol(vers: SocksVersion, s: String) -> Result<Protocol, ProxyError> {
let mut bytes: Vec<_> = s.into();
Ok(if bytes.is_empty() {
Protocol::Socks(vers, SocksAuth::NoAuth)

View File

@ -1,19 +1,25 @@
//! Very very very basic soak test that runs obfs4proxy.
use anyhow::Result;
use tor_ptmgr::ipc::{PluggableTransport, PtParameters};
use tor_ptmgr::ipc::{
PluggableClientTransport, PluggableTransport, PtClientParameters, PtCommonParameters,
};
use tor_rtcompat::PreferredRuntime;
use tracing::info;
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let params = PtParameters::builder()
let common_params = PtCommonParameters::builder()
.state_location("/tmp/arti-pt".into())
.build()
.unwrap();
let client_params = PtClientParameters::builder()
.transports(vec!["obfs4".parse().unwrap()])
.build()
.unwrap();
let mut pt = PluggableTransport::new("./obfs4proxy".into(), vec![], params);
let mut pt =
PluggableClientTransport::new("./obfs4proxy".into(), vec![], common_params, client_params);
pt.launch(PreferredRuntime::current()?).await?;
loop {
info!("message: {:?}", pt.next_message().await?);

View File

@ -0,0 +1,6 @@
ADDED: `ipc::PtServerParameters`
ADDED: `trait ipc::PluggableTransport` providing `.transport_methods()` and `.next_message()`
ADDED: `ipc::PtMessage`
ADDED: `ipc::PluggableServerTransport`
BREAKING: Split `ipc::PtParameters` into `ipc::PtCommonParameters` and `ipc::PtClientParameters`
BREAKING: Renamed `ipc::PluggableTransport` struct into `ipc::PluggableClientTransport`; `ipc::PluggableTransport` is a trait now.

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,10 @@ pub mod ipc;
use crate::config::ManagedTransportConfig;
use crate::err::PtError;
use crate::ipc::{PluggableTransport, PtClientMethod, PtParameters};
use crate::ipc::{
sealed::PluggableTransportPrivate, PluggableClientTransport, PluggableTransport,
PtClientMethod, PtClientParameters, PtCommonParameters,
};
use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
use futures::channel::oneshot;
use futures::stream::FuturesUnordered;
@ -94,14 +97,14 @@ enum PtReactorMessage {
}
/// The result of a spawn attempt: the list of transports the spawned binary covers, and the result.
type SpawnResult = (Vec<PtTransportName>, err::Result<PluggableTransport>);
type SpawnResult = (Vec<PtTransportName>, err::Result<PluggableClientTransport>);
/// Background reactor to handle managing pluggable transport binaries.
struct PtReactor<R> {
/// Runtime.
rt: R,
/// Currently running pluggable transport binaries.
running: Vec<PluggableTransport>,
running: Vec<PluggableClientTransport>,
/// A map of asked-for transports.
///
/// If a transport name has an entry, we will append any additional requests for that entry.
@ -148,7 +151,7 @@ impl<R: Runtime> PtReactor<R> {
fn handle_spawned(
&mut self,
covers: Vec<PtTransportName>,
result: err::Result<PluggableTransport>,
result: err::Result<PluggableClientTransport>,
) {
match result {
Err(e) => {
@ -184,7 +187,7 @@ impl<R: Runtime> PtReactor<R> {
}
/// Called to remove a pluggable transport from the shared state.
fn remove_pt(&self, pt: PluggableTransport) {
fn remove_pt(&self, pt: PluggableClientTransport) {
let mut state = self.state.write().expect("ptmgr state poisoned");
for transport in pt.transport_methods().keys() {
state.cmethods.remove(transport);
@ -381,7 +384,7 @@ async fn spawn_from_config<R: Runtime>(
rt: R,
state_dir: PathBuf,
cfg: ManagedTransportConfig,
) -> Result<PluggableTransport, PtError> {
) -> Result<PluggableClientTransport, PtError> {
// FIXME(eta): I really think this expansion should happen at builder validation time...
let binary_path = cfg.path.path().map_err(|e| PtError::PathExpansionFailed {
path: cfg.path,
@ -399,13 +402,22 @@ async fn spawn_from_config<R: Runtime>(
})?;
// FIXME(eta): make the rest of these parameters configurable
let pt_params = PtParameters::builder()
let pt_common_params = PtCommonParameters::builder()
.state_location(new_state_dir)
.build()
.expect("PtCommonParameters constructed incorrectly");
let pt_client_params = PtClientParameters::builder()
.transports(cfg.protocols)
.build()
.expect("PtParameters constructed incorrectly");
.expect("PtClientParameters constructed incorrectly");
let mut pt = PluggableTransport::new(binary_path, cfg.arguments, pt_params);
let mut pt = PluggableClientTransport::new(
binary_path,
cfg.arguments,
pt_common_params,
pt_client_params,
);
pt.launch(rt).await?;
Ok(pt)
}