Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
node: Ignore non-routable addresses
cloudhead committed 2 years ago
commit dc7d67c1e2da5d32227ef4788af885c4b9298f19
parent e88839851919c731b6d0d0eaf361bafc2b7e34ec
3 files changed +67 -2
modified radicle-node/src/service.rs
@@ -828,6 +828,7 @@ where
    pub fn handle_announcement(
        &mut self,
        relayer: &NodeId,
+
        relayer_addr: &Address,
        announcement: &Announcement,
    ) -> Result<bool, session::Error> {
        if !announcement.verify() {
@@ -1023,6 +1024,7 @@ where
                    timestamp,
                    addresses
                        .iter()
+
                        .filter(|a| a.is_routable() || relayer_addr.is_local())
                        .map(|a| KnownAddress::new(a.clone(), address::Source::Peer)),
                ) {
                    Ok(updated) => {
@@ -1100,12 +1102,13 @@ where

        match (&mut peer.state, message) {
            // Process a peer announcement.
-
            (session::State::Connected { .. }, Message::Announcement(ann)) => {
+
            (session::State::Connected { addr, .. }, Message::Announcement(ann)) => {
                let relayer = peer.id;
+
                let relayer_addr = addr.clone();
                let announcer = ann.node;

                // Returning true here means that the message should be relayed.
-
                if self.handle_announcement(&relayer, &ann)? {
+
                if self.handle_announcement(&relayer, &relayer_addr, &ann)? {
                    // Choose peers we should relay this message to.
                    // 1. Don't relay to the peer who sent us this message.
                    // 2. Don't relay to the peer who signed this announcement.
modified radicle/src/node.rs
@@ -262,6 +262,24 @@ impl From<CommandResult> for Result<bool, Error> {
#[wrapper_mut(DerefMut)]
pub struct Address(#[serde(with = "crate::serde_ext::string")] NetAddr<HostName>);

+
impl Address {
+
    /// Check whether this address is local.
+
    pub fn is_local(&self) -> bool {
+
        match self.0.host {
+
            HostName::Ip(ip) => address::is_local(&ip),
+
            _ => false,
+
        }
+
    }
+

+
    /// Check whether this address is globally routable.
+
    pub fn is_routable(&self) -> bool {
+
        match self.0.host {
+
            HostName::Ip(ip) => address::is_routable(&ip),
+
            _ => true,
+
        }
+
    }
+
}
+

impl cyphernet::addr::Host for Address {
    fn requires_proxy(&self) -> bool {
        self.0.requires_proxy()
modified radicle/src/node/address.rs
@@ -50,3 +50,47 @@ impl TryFrom<u8> for AddressType {
        }
    }
}
+
/// Check whether an IP address is globally routable.
+
pub fn is_routable(addr: &net::IpAddr) -> bool {
+
    match addr {
+
        net::IpAddr::V4(addr) => ipv4_is_routable(addr),
+
        net::IpAddr::V6(addr) => ipv6_is_routable(addr),
+
    }
+
}
+

+
/// Check whether an IP address is locally routable.
+
pub fn is_local(addr: &net::IpAddr) -> bool {
+
    match addr {
+
        net::IpAddr::V4(addr) => {
+
            addr.is_private() || addr.is_loopback() || addr.is_link_local() || addr.is_unspecified()
+
        }
+
        net::IpAddr::V6(_) => false,
+
    }
+
}
+

+
/// Check whether an IPv4 address is globally routable.
+
///
+
/// This code is adapted from the Rust standard library's `net::Ipv4Addr::is_global`. It can be
+
/// replaced once that function is stabilized.
+
fn ipv4_is_routable(addr: &net::Ipv4Addr) -> bool {
+
    // Check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
+
    // globally routable addresses in the 192.0.0.0/24 range.
+
    if u32::from(*addr) == 0xc0000009 || u32::from(*addr) == 0xc000000a {
+
        return true;
+
    }
+
    !addr.is_private()
+
        && !addr.is_loopback()
+
        && !addr.is_link_local()
+
        && !addr.is_broadcast()
+
        && !addr.is_documentation()
+
        // Make sure the address is not in 0.0.0.0/8.
+
        && addr.octets()[0] != 0
+
}
+

+
/// Check whether an IPv6 address is globally routable.
+
///
+
/// For now, this always returns `true`, as IPv6 addresses
+
/// are not fully supported.
+
fn ipv6_is_routable(_addr: &net::Ipv6Addr) -> bool {
+
    true
+
}