Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
Prevent Onion Connections
Merged fintohaps opened 3 months ago

These are further improvements to ensure that when a node is not configured for Tor, it will not connect to .onion addresses.

1 file changed +28 -9 589925e3 91eb6fc0
modified crates/radicle-protocol/src/service.rs
@@ -221,6 +221,8 @@ pub enum ConnectError {
    SelfConnection,
    #[error("outbound connection limit reached when attempting {nid} ({addr})")]
    LimitReached { nid: NodeId, addr: Address },
+
    #[error("attempted connection to {nid}, but the node is not configured to support the address {addr}")]
+
    UnsupportedAddress { nid: NodeId, addr: Address },
}

/// A store for all node data.
@@ -1437,7 +1439,7 @@ where
        });

        // Attempt to re-connect to persistent peers.
-
        if self.config.peer(&remote).is_some() {
+
        if self.config.is_persistent(&remote) {
            let delay = LocalDuration::from_secs(2u64.saturating_pow(session.attempts() as u32))
                .clamp(MIN_RECONNECTION_DELTA, MAX_RECONNECTION_DELTA);

@@ -2254,6 +2256,9 @@ where
        if nid == self.node_id() {
            return Err(ConnectError::SelfConnection);
        }
+
        if !self.is_supported_address(&addr) {
+
            return Err(ConnectError::UnsupportedAddress { nid, addr });
+
        }
        if self.sessions.contains_key(&nid) {
            return Err(ConnectError::SessionExists { nid });
        }
@@ -2492,7 +2497,7 @@ where
                    .filter(|entry| !self.sessions.contains_key(&entry.node))
                    .filter(|entry| !self.config.external_addresses.contains(&entry.address.addr))
                    .filter(|entry| &entry.node != self.nid())
-
                    .filter(|entry| !entry.address.addr.is_onion() || self.config.onion.is_some())
+
                    .filter(|entry| self.is_supported_address(&entry.address.addr))
                    .fold(HashMap::new(), |mut acc, entry| {
                        acc.entry(entry.node)
                            .and_modify(|e: &mut Peer| e.addresses.push(entry.address.clone()))
@@ -2630,11 +2635,7 @@ where
                    })
                    .map(|ka| (peer.nid, ka))
            })
-
            .filter(|(_, ka)| match AddressType::from(&ka.addr) {
-
                // Only consider onion addresses if configured.
-
                AddressType::Onion => self.config.onion.is_some(),
-
                AddressType::Dns | AddressType::Ipv4 | AddressType::Ipv6 => true,
-
            });
+
            .filter(|(_, ka)| self.is_supported_address(&ka.addr));

        // Peers we are going to attempt connections to.
        let connect = available.take(wanted).collect::<Vec<_>>();
@@ -2660,13 +2661,13 @@ where
        let mut reconnect = Vec::new();

        for (nid, session) in self.sessions.iter_mut() {
-
            if let Some(addr) = self.config.peer(nid) {
+
            if self.config.is_persistent(nid) {
                if let session::State::Disconnected { retry_at, .. } = &mut session.state {
                    // TODO: Try to reconnect only if the peer was attempted. A disconnect without
                    // even a successful attempt means that we're unlikely to be able to reconnect.

                    if now >= *retry_at {
-
                        reconnect.push((*nid, addr.clone(), session.attempts()));
+
                        reconnect.push((*nid, session.addr.clone(), session.attempts()));
                    }
                }
            }
@@ -2678,6 +2679,24 @@ where
            }
        }
    }
+

+
    /// Checks if the [`Address`] supported for connecting to.
+
    ///
+
    /// # IPv4/IPv6/DNS
+
    ///
+
    /// Always returns `true`.
+
    ///
+
    /// # Tor
+
    ///
+
    /// If the [`Address`] is an `.onion` address and the service supports onion
+
    /// routing then this will return `true`.
+
    fn is_supported_address(&self, address: &Address) -> bool {
+
        match AddressType::from(address) {
+
            // Only consider onion addresses if configured.
+
            AddressType::Onion => self.config.onion.is_some(),
+
            AddressType::Dns | AddressType::Ipv4 | AddressType::Ipv6 => true,
+
        }
+
    }
}

/// Gives read access to the service state.