Skip to content

Commit

Permalink
feat: add control over autonat (#176)
Browse files Browse the repository at this point in the history
Prior to this change autonat would always be enabled. Now it can be
disabled in cases where NAT is not being used.

Additionally previously an unbounded number of probes would be running
concurrently for all observed addresses. When an dynamic outbound NAT is
used this results in many probes. Now we limit to one active probe at a
time and also track failed external address so we do not repeatedly
attempt to probe them.
  • Loading branch information
nathanielc authored Nov 13, 2023
1 parent fe91d40 commit 75e2137
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
13 changes: 9 additions & 4 deletions one/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct DaemonOpts {
#[arg(
short,
long,
default_value = "127.0.0.1:9090",
default_value = "127.0.0.1:9464",
env = "CERAMIC_ONE_METRICS_BIND_ADDRESS"
)]
metrics_bind_address: String,
Expand All @@ -99,14 +99,19 @@ struct DaemonOpts {
#[arg(long, env = "CERAMIC_ONE_LOCAL_NETWORK_ID")]
local_network_id: Option<u32>,

/// When true mdns will be used to discover peers.
/// When set mdns will be used to discover peers.
#[arg(long, default_value_t = false, env = "CERAMIC_ONE_MDNS")]
mdns: bool,

/// When true Recon will be used to synchronized events with peers.
/// When set Recon will be used to synchronized events with peers.
#[arg(long, default_value_t = false, env = "CERAMIC_ONE_RECON")]
recon: bool,

/// When set autonat will not be used to discover external address or allow other peers
/// to directly dial the local peer.
#[arg(long, default_value_t = false, env = "CERAMIC_ONE_DISABLE_AUTONAT")]
disable_autonat: bool,

/// Specify the format of log events.
#[arg(long, default_value = "multi-line", env = "CERAMIC_ONE_LOG_FORMAT")]
log_format: LogFormat,
Expand Down Expand Up @@ -348,7 +353,7 @@ impl Daemon {
bitswap_server: true,
bitswap_client: true,
kademlia: true,
autonat: true,
autonat: !opts.disable_autonat,
relay_server: true,
relay_client: true,
gossipsub: true,
Expand Down
38 changes: 30 additions & 8 deletions p2p/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ where
listen_addrs: Vec<Multiaddr>,

trust_observed_addrs: bool,
failed_external_addresses: HashSet<Multiaddr>,
active_address_probe: Option<Multiaddr>,
}

impl<I, M> fmt::Debug for Node<I, M>
Expand Down Expand Up @@ -194,6 +196,8 @@ where
providers: Providers::new(4),
listen_addrs,
trust_observed_addrs: libp2p_config.trust_observed_addrs,
failed_external_addresses: Default::default(),
active_address_probe: Default::default(),
})
}

Expand Down Expand Up @@ -629,6 +633,7 @@ where
.swarm
.external_addresses()
.any(|addr| addr == &info.observed_addr)
&& !self.failed_external_addresses.contains(&info.observed_addr)
{
if self.trust_observed_addrs {
debug!(
Expand All @@ -640,14 +645,26 @@ where
self.swarm.add_external_address(info.observed_addr.clone());
} else if let Some(autonat) = self.swarm.behaviour_mut().autonat.as_mut() {
// Probe the observed addr for external connectivity.
// See OutboundProbeEvent case for

debug!(
address=%info.observed_addr,
%peer_id,
"probing observed address from peer for external connectivity",
);
autonat.probe_address(info.observed_addr.clone());
// Only probe one address at a time.
//
// This logic is run very frequently because any new peer connection
// for a new observed address triggers this path. Its typical to have
// only a few external addresses, in which cases its likely that the
// in-progress address probe is one that will succeed.
//
// In cases where there are lots of different observed addresses its
// likely that NAT hasn't been setup and so the peer doesn't have an
// external address. Therefore we do not want to waste resources on
// probing many different addresses that are likely to fail.
if self.active_address_probe.is_none() {
self.active_address_probe = Some(info.observed_addr.clone());
debug!(
address=%info.observed_addr,
%peer_id,
"probing observed address from peer for external connectivity",
);
autonat.probe_address(info.observed_addr.clone());
}
};
};

Expand Down Expand Up @@ -765,6 +782,11 @@ where
self.swarm.add_external_address(address);
}
}
Event::Autonat(autonat::Event::OutboundProbe(OutboundProbeEvent::Error { .. })) => {
if let Some(addr) = self.active_address_probe.take() {
self.failed_external_addresses.insert(addr);
}
}
_ => {
// TODO: check all important events are handled
}
Expand Down

0 comments on commit 75e2137

Please sign in to comment.