Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
node: Improve Tor configuration flexibility
cloudhead committed 2 years ago
commit ca7db1620c6f8d4e9caed0902b191c5e6def8bc3
parent cb2cbf014a123a1cd0cd0f188f093e014f93647b
5 files changed +47 -58
modified radicle-cli/examples/rad-config.md
@@ -29,7 +29,6 @@ $ rad config
    "db": {
      "journalMode": "rollback"
    },
-
    "tor": null,
    "network": "main",
    "log": "INFO",
    "relay": "auto",
modified radicle-httpd/src/api/v1/profile.rs
@@ -90,7 +90,6 @@ mod routes {
                  "connect": [],
                  "externalAddresses": [],
                  "db": { "journalMode": "rollback" },
-
                  "tor": null,
                  "network": "main",
                  "log": "INFO",
                  "relay": "auto",
modified radicle-node/src/service.rs
@@ -1232,7 +1232,7 @@ where
                }
                Entry::Vacant(e) => {
                    if let HostName::Ip(ip) = addr.host {
-
                        if !ip.is_loopback() && !self.config.is_proxy_ip(ip) {
+
                        if !address::is_local(&ip) {
                            if let Err(e) =
                                self.db
                                    .addresses_mut()
@@ -2335,8 +2335,8 @@ where
                    .map(|ka| (peer.nid, ka))
            })
            .filter(|(_, ka)| match AddressType::from(&ka.addr) {
-
                // Only consider Tor addresses if Tor is configured.
-
                AddressType::Onion => self.config.tor.is_some(),
+
                // Only consider onion addresses if configured.
+
                AddressType::Onion => self.config.onion.is_some(),
                AddressType::Dns | AddressType::Ipv4 | AddressType::Ipv6 => true,
            })
            .take(wanted)
modified radicle-node/src/wire/protocol.rs
@@ -21,7 +21,7 @@ use netservices::{NetConnection, NetReader, NetWriter};
use reactor::{ResourceId, ResourceType, Timestamp};

use radicle::collections::RandomMap;
-
use radicle::node::config::TorConfig;
+
use radicle::node::config::AddressConfig;
use radicle::node::NodeId;
use radicle::storage::WriteStorage;

@@ -1071,42 +1071,37 @@ pub fn dial<G: Signer + Ecdh<Pk = NodeId>>(
    signer: G,
    config: &service::Config,
) -> io::Result<WireSession<G>> {
-
    let inet_addr: NetAddr<InetHost> = match config.tor {
-
        // In Tor proxy mode, simply specify the proxy address for all connections,
-
        // since we'll be routing all connections through the proxy.
-
        Some(TorConfig::Proxy { address: proxy }) => proxy.into(),
-
        // In transparent Tor mode, we treat `.onion` addresses as regular DNS names.
-
        Some(TorConfig::Transparent) => {
-
            let host = match &remote_addr.host {
-
                HostName::Ip(ip) => InetHost::Ip(*ip),
-
                HostName::Dns(dns) => InetHost::Dns(dns.clone()),
-
                HostName::Tor(onion) => InetHost::Dns(onion.to_string()),
-
                _ => {
-
                    return Err(io::Error::new(
-
                        io::ErrorKind::Unsupported,
-
                        "unsupported remote address type",
-
                    ))
-
                }
-
            };
-
            NetAddr::new(host, remote_addr.port)
-
        }
-
        // Without any Tor configuration, refuse to connect to a `.onion` address.
-
        None => {
-
            let host = match &remote_addr.host {
-
                HostName::Ip(ip) => InetHost::Ip(*ip),
-
                HostName::Dns(dns) => InetHost::Dns(dns.clone()),
-
                _ => {
-
                    return Err(io::Error::new(
-
                        io::ErrorKind::Unsupported,
-
                        "unsupported remote address type",
-
                    ))
+
    let inet_addr: NetAddr<InetHost> = match &remote_addr.host {
+
        HostName::Ip(ip) => NetAddr::new(InetHost::Ip(*ip), remote_addr.port),
+
        HostName::Dns(dns) => NetAddr::new(InetHost::Dns(dns.clone()), remote_addr.port),
+
        HostName::Tor(onion) => match config.onion {
+
            // In Tor proxy mode, simply specify the proxy address.
+
            Some(AddressConfig::Proxy { address }) => address.into(),
+
            // In "forward" mode, if a global proxy is set, we use that, otherwise
+
            // we treat `.onion` addresses as regular DNS names.
+
            Some(AddressConfig::Forward) => {
+
                if let Some(proxy) = config.proxy {
+
                    proxy.into()
+
                } else {
+
                    NetAddr::new(InetHost::Dns(onion.to_string()), remote_addr.port)
                }
-
            };
-
            NetAddr::new(host, remote_addr.port)
+
            }
+
            None => {
+
                return Err(io::Error::new(
+
                    io::ErrorKind::Unsupported,
+
                    "no configuration found for .onion addresses",
+
                ));
+
            }
+
        },
+
        _ => {
+
            return Err(io::Error::new(
+
                io::ErrorKind::Unsupported,
+
                "unsupported remote address type",
+
            ))
        }
    };
    // Whether to tunnel regular connections through the proxy.
-
    let force_proxy = matches!(config.tor, Some(TorConfig::Proxy { .. }));
+
    let force_proxy = config.proxy.is_some();
    // Nb. This timeout is currently not used by the underlying library due to the
    // `socket2` library not supporting non-blocking connect with timeout.
    let connection = net::TcpStream::connect_nonblocking(inet_addr, DEFAULT_DIAL_TIMEOUT)?;
modified radicle/src/node/config.rs
@@ -7,7 +7,7 @@ use localtime::LocalDuration;

use crate::node;
use crate::node::policy::{Policy, Scope};
-
use crate::node::{address, db, Address, Alias, NodeId};
+
use crate::node::{db, Address, Alias, NodeId};

/// Target number of peers to maintain connections to.
pub const TARGET_OUTBOUND_PEERS: usize = 8;
@@ -247,17 +247,18 @@ pub enum Relay {
    Auto,
}

-
/// Tor configuration.
+
/// Proxy configuration.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase", tag = "mode")]
-
pub enum TorConfig {
-
    /// Connect via SOCKS5 proxy.
+
pub enum AddressConfig {
+
    /// Proxy connections to this address type.
    Proxy {
-
        /// Tor proxy address.
+
        /// Proxy address.
        address: net::SocketAddr,
    },
-
    /// Treat Tor onion addresses as DNS names.
-
    Transparent,
+
    /// Forward address to the next layer. Either this is the global proxy,
+
    /// or the operating system, via DNS.
+
    Forward,
}

/// Database configuration.
@@ -290,9 +291,12 @@ pub struct Config {
    /// Database config.
    #[serde(default)]
    pub db: DbConfig,
-
    /// Tor configuration.
-
    #[serde(default)]
-
    pub tor: Option<TorConfig>,
+
    /// Global proxy.
+
    #[serde(default, skip_serializing_if = "Option::is_none")]
+
    pub proxy: Option<net::SocketAddr>,
+
    /// Onion address config.
+
    #[serde(default, skip_serializing_if = "Option::is_none")]
+
    pub onion: Option<AddressConfig>,
    /// Peer-to-peer network.
    #[serde(default)]
    pub network: Network,
@@ -334,7 +338,8 @@ impl Config {
            external_addresses: vec![],
            db: DbConfig::default(),
            network: Network::default(),
-
            tor: None,
+
            proxy: None,
+
            onion: None,
            relay: Relay::default(),
            limits: Limits::default(),
            workers: DEFAULT_WORKERS,
@@ -359,15 +364,6 @@ impl Config {
        self.peer(id).is_some()
    }

-
    /// Check if the given IP address is our proxy.
-
    pub fn is_proxy_ip(&self, ip: net::IpAddr) -> bool {
-
        match self.tor {
-
            None => false,
-
            Some(TorConfig::Proxy { address }) => address.ip() == ip,
-
            Some(TorConfig::Transparent) => address::is_local(&ip),
-
        }
-
    }
-

    /// Are we a relay node? This determines what we do with gossip messages from other peers.
    pub fn is_relay(&self) -> bool {
        match self.relay {