Introduce ClientConfig for is_localhost config parameter
This commit is contained in:
parent
f4caae3569
commit
e76988738a
|
@ -116,7 +116,9 @@ name = "arti-tor-client"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"derive_builder",
|
||||
"futures",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tor-chanmgr",
|
||||
"tor-circmgr",
|
||||
|
|
|
@ -104,3 +104,9 @@ request_max_retries = 32
|
|||
# request is still waiting for its own circuits to complete, the request
|
||||
# will wait this long before using the unexpectedly available circuit.
|
||||
request_loyalty = "50 msec"
|
||||
|
||||
# Rules for client configuration
|
||||
[client_config]
|
||||
|
||||
# Are we running as localhost (e.g. on chutney)?
|
||||
is_localhost = false
|
||||
|
|
|
@ -91,6 +91,7 @@ mod proxy;
|
|||
use std::sync::Arc;
|
||||
|
||||
use tor_circmgr::CircMgrConfig;
|
||||
use tor_client::ClientConfig;
|
||||
use tor_client::TorClient;
|
||||
use tor_config::CfgPath;
|
||||
use tor_dirmgr::{DirMgrConfig, DownloadScheduleConfig, NetworkConfig};
|
||||
|
@ -175,6 +176,9 @@ pub struct ArtiConfig {
|
|||
|
||||
/// Information about how to expire circuits.
|
||||
circuit_timing: tor_circmgr::CircuitTiming,
|
||||
|
||||
/// Information about client configuration parameters.
|
||||
client_config: tor_client::ClientConfig,
|
||||
}
|
||||
|
||||
/// Configuration for where information should be stored on disk.
|
||||
|
@ -222,13 +226,14 @@ async fn run<R: Runtime>(
|
|||
statecfg: PathBuf,
|
||||
dircfg: DirMgrConfig,
|
||||
circcfg: CircMgrConfig,
|
||||
clientcfg: ClientConfig,
|
||||
) -> Result<()> {
|
||||
use futures::FutureExt;
|
||||
futures::select!(
|
||||
r = exit::wait_for_ctrl_c().fuse() => r,
|
||||
r = async {
|
||||
let client =
|
||||
Arc::new(TorClient::bootstrap(runtime.clone(), statecfg, dircfg, circcfg).await?);
|
||||
Arc::new(TorClient::bootstrap(runtime.clone(), statecfg, dircfg, circcfg, clientcfg).await?);
|
||||
proxy::run_socks_proxy(runtime, client, socks_port).await
|
||||
}.fuse() => r,
|
||||
)
|
||||
|
@ -272,6 +277,7 @@ fn main() -> Result<()> {
|
|||
let statecfg = config.storage.state_dir.path()?;
|
||||
let dircfg = config.get_dir_config()?;
|
||||
let circcfg = config.get_circ_config()?;
|
||||
let clientcfg = config.client_config;
|
||||
|
||||
let socks_port = match config.socks_port {
|
||||
Some(s) => s,
|
||||
|
@ -287,7 +293,7 @@ fn main() -> Result<()> {
|
|||
let runtime = tor_rtcompat::async_std::create_runtime()?;
|
||||
|
||||
let rt_copy = runtime.clone();
|
||||
rt_copy.block_on(run(runtime, socks_port, statecfg, dircfg, circcfg))?;
|
||||
rt_copy.block_on(run(runtime, socks_port, statecfg, dircfg, circcfg, clientcfg))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@ tor-proto = { path="../tor-proto", version="0.0.0" }
|
|||
tor-rtcompat = { path="../tor-rtcompat", version="0.0.0" }
|
||||
|
||||
anyhow = "1.0.38"
|
||||
derive_builder = "0.10.2"
|
||||
futures = "0.3.13"
|
||||
tracing = "0.1.26"
|
||||
serde = { version = "1.0.124", features = ["derive"] }
|
||||
thiserror = "1.0.24"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//! Once the client is bootstrapped, you can make anonymous
|
||||
//! connections ("streams") over the Tor network using
|
||||
//! `TorClient::connect()`.
|
||||
use crate::config::ClientConfig;
|
||||
use tor_circmgr::{CircMgrConfig, IsolationToken, TargetPort};
|
||||
use tor_dirmgr::{DirEvent, DirMgrConfig};
|
||||
use tor_proto::circuit::{ClientCirc, IpVersionPreference};
|
||||
|
@ -38,6 +39,8 @@ pub struct TorClient<R: Runtime> {
|
|||
circmgr: Arc<tor_circmgr::CircMgr<R>>,
|
||||
/// Directory manager for keeping our directory material up to date.
|
||||
dirmgr: Arc<tor_dirmgr::DirMgr<R>>,
|
||||
/// Client configuration
|
||||
clientcfg: ClientConfig
|
||||
}
|
||||
|
||||
/// Preferences for how to route a stream over the Tor network.
|
||||
|
@ -136,13 +139,14 @@ impl<R: Runtime> TorClient<R> {
|
|||
///
|
||||
/// Return a client once there is enough directory material to
|
||||
/// connect safely over the Tor network.
|
||||
// TODO: Make a ClientConfig to combine DirMgrConfig and circ_cfg
|
||||
// TODO: Expand ClientConfig to combine DirMgrConfig and circ_cfg
|
||||
// and state_cfg.
|
||||
pub async fn bootstrap(
|
||||
runtime: R,
|
||||
state_cfg: PathBuf,
|
||||
dir_cfg: DirMgrConfig,
|
||||
circ_cfg: CircMgrConfig,
|
||||
client_cfg: ClientConfig,
|
||||
) -> Result<TorClient<R>> {
|
||||
let statemgr = tor_persist::FsStateMgr::from_path(state_cfg)?;
|
||||
let chanmgr = Arc::new(tor_chanmgr::ChanMgr::new(runtime.clone()));
|
||||
|
@ -154,6 +158,7 @@ impl<R: Runtime> TorClient<R> {
|
|||
Arc::clone(&circmgr),
|
||||
)
|
||||
.await?;
|
||||
let clientcfg = client_cfg;
|
||||
|
||||
circmgr.update_network_parameters(dirmgr.netdir().params());
|
||||
|
||||
|
@ -180,11 +185,12 @@ impl<R: Runtime> TorClient<R> {
|
|||
runtime,
|
||||
circmgr,
|
||||
dirmgr,
|
||||
clientcfg,
|
||||
})
|
||||
}
|
||||
|
||||
/// Validate if we are an valid hostname or not
|
||||
fn is_valid_hostname(hostname: &str) -> bool {
|
||||
fn is_valid_hostname(&self, hostname: &str) -> bool {
|
||||
/// Check if we have the valid characters for a hostname
|
||||
fn is_valid_char(byte: u8) -> bool {
|
||||
((b'a'..=b'z').contains(&byte))
|
||||
|
@ -208,7 +214,7 @@ impl<R: Runtime> TorClient<R> {
|
|||
|| hostname.ends_with('.')
|
||||
|| hostname.starts_with('.')
|
||||
|| hostname.is_empty()
|
||||
|| hostname.to_lowercase().eq("localhost"))
|
||||
|| (hostname.to_lowercase().eq("localhost") && !self.clientcfg.is_localhost))
|
||||
|| is_ipv6_str(hostname)
|
||||
}
|
||||
|
||||
|
@ -235,7 +241,7 @@ impl<R: Runtime> TorClient<R> {
|
|||
if addr.to_lowercase().ends_with(".onion") {
|
||||
return Err(anyhow!("Rejecting .onion address as unsupported."));
|
||||
}
|
||||
if !Self::is_valid_hostname(addr) {
|
||||
if !Self::is_valid_hostname(self, addr) {
|
||||
return Err(anyhow!("Rejecting hostname as invalid."));
|
||||
}
|
||||
if let Ok(ip) = IpAddr::from_str(addr) {
|
||||
|
@ -272,7 +278,7 @@ impl<R: Runtime> TorClient<R> {
|
|||
if hostname.to_lowercase().ends_with(".onion") {
|
||||
return Err(anyhow!("Rejecting .onion address as unsupported."));
|
||||
}
|
||||
if !Self::is_valid_hostname(hostname) {
|
||||
if !Self::is_valid_hostname(self, hostname) {
|
||||
return Err(anyhow!("Rejecting hostname as invalid."));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
//! Configuration logic for launching a circuit manager.
|
||||
|
||||
use derive_builder::Builder;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Configuration for clients
|
||||
///
|
||||
/// This type is immutable once constructed. To create an object of this type,
|
||||
/// use [`ClientConfigBuilder`].
|
||||
#[derive(Debug, Clone, Builder, Deserialize)]
|
||||
#[builder]
|
||||
pub struct ClientConfig {
|
||||
/// Are we running as localhost?
|
||||
#[builder(default)]
|
||||
pub(crate) is_localhost: bool,
|
||||
}
|
||||
|
||||
// NOTE: it seems that `unwrap` may be safe because of builder defaults
|
||||
// check `derive_builder` documentation for details
|
||||
// https://docs.rs/derive_builder/0.10.2/derive_builder/#default-values
|
||||
#[allow(clippy::unwrap_used)]
|
||||
impl Default for ClientConfig {
|
||||
fn default() -> Self {
|
||||
ClientConfigBuilder::default().build().unwrap()
|
||||
}
|
||||
}
|
|
@ -94,10 +94,14 @@
|
|||
#![warn(clippy::unseparated_literal_suffix)]
|
||||
#![deny(clippy::unwrap_used)]
|
||||
|
||||
mod config;
|
||||
|
||||
mod client;
|
||||
|
||||
pub use client::{ConnectPrefs, TorClient};
|
||||
|
||||
pub use config::{ClientConfig, ClientConfigBuilder};
|
||||
|
||||
pub use tor_circmgr::IsolationToken;
|
||||
/// An anonymized stream over the Tor network.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue