diff --git a/protocols/autonat/src/behaviour.rs b/protocols/autonat/src/behaviour.rs index a1a8bb6ff21..31f658d5222 100644 --- a/protocols/autonat/src/behaviour.rs +++ b/protocols/autonat/src/behaviour.rs @@ -52,6 +52,9 @@ pub struct Config { /// Timeout for requests. pub timeout: Duration, + /// Whether to consider only global IP addresses for NAT. + pub use_only_global_ips: bool, + // Client Config /// Delay on init before starting the fist probe. pub boot_delay: Duration, @@ -83,6 +86,7 @@ impl Default for Config { fn default() -> Self { Config { timeout: Duration::from_secs(30), + use_only_global_ips: false, boot_delay: Duration::from_secs(15), retry_interval: Duration::from_secs(90), refresh_interval: Duration::from_secs(15 * 60), @@ -510,3 +514,18 @@ trait HandleInnerEvent { event: RequestResponseEvent, ) -> (VecDeque, Option); } + +// Test for global IP address implemented on MultiAddr +trait GlobalAddress { + fn contains_global_address(&self) -> bool; +} + +impl GlobalAddress for Multiaddr { + fn contains_global_address(&self) -> bool { + self.into_iter().any(|proto| match proto { + libp2p_core::multiaddr::Protocol::Ip4(addr) => addr.is_global(), + libp2p_core::multiaddr::Protocol::Ip6(addr) => addr.is_global(), + _ => false, + }) + } +} diff --git a/protocols/autonat/src/behaviour/as_client.rs b/protocols/autonat/src/behaviour/as_client.rs index de6a00d5629..0a5c282eeb0 100644 --- a/protocols/autonat/src/behaviour/as_client.rs +++ b/protocols/autonat/src/behaviour/as_client.rs @@ -21,8 +21,8 @@ use crate::ResponseError; use super::{ - Action, AutoNatCodec, Config, DialRequest, DialResponse, Event, HandleInnerEvent, NatStatus, - ProbeId, + Action, AutoNatCodec, Config, DialRequest, DialResponse, Event, GlobalAddress, + HandleInnerEvent, NatStatus, ProbeId, }; use futures::FutureExt; use futures_timer::Delay; @@ -201,6 +201,12 @@ impl<'a> AsClient<'a> { let mut addresses: Vec<_> = params.external_addresses().map(|r| r.addr).collect(); addresses.extend(params.listened_addresses()); + if self.config.use_only_global_ips { + addresses = addresses + .into_iter() + .filter(|a| a.contains_global_address()) + .collect::>(); + }; let probe_id = self.probe_id.next(); let event = match self.do_probe(probe_id, addresses) { diff --git a/protocols/autonat/src/behaviour/as_server.rs b/protocols/autonat/src/behaviour/as_server.rs index 24ffb443deb..007640c7416 100644 --- a/protocols/autonat/src/behaviour/as_server.rs +++ b/protocols/autonat/src/behaviour/as_server.rs @@ -19,8 +19,8 @@ // DEALINGS IN THE SOFTWARE. use super::{ - Action, AutoNatCodec, Config, DialRequest, DialResponse, Event, HandleInnerEvent, ProbeId, - ResponseError, + Action, AutoNatCodec, Config, DialRequest, DialResponse, Event, GlobalAddress, + HandleInnerEvent, ProbeId, ResponseError, }; use instant::Instant; use libp2p_core::{connection::ConnectionId, multiaddr::Protocol, Multiaddr, PeerId}; @@ -114,13 +114,22 @@ impl<'a> HandleInnerEvent for AsServer<'a> { } => { let probe_id = self.probe_id.next(); match self.resolve_inbound_request(peer, request) { - Ok(addrs) => { + Ok(mut addrs) => { log::debug!( "Inbound dial request from Peer {} with dial-back addresses {:?}.", peer, addrs ); + if self.config.use_only_global_ips { + addrs = addrs + .into_iter() + .filter(|a| { + !self.config.use_only_global_ips || a.contains_global_address() + }) + .collect(); + } + self.ongoing_inbound .insert(peer, (probe_id, request_id, addrs.clone(), channel)); self.throttled_clients.push((peer, Instant::now())); diff --git a/protocols/autonat/src/lib.rs b/protocols/autonat/src/lib.rs index d55ab3acc14..1d5697ae465 100644 --- a/protocols/autonat/src/lib.rs +++ b/protocols/autonat/src/lib.rs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. //! Implementation of the AutoNAT protocol. +#![feature(ip)] mod behaviour; mod protocol;