diff --git a/Cargo.lock b/Cargo.lock index 5c419ed0348..4c12e6fb984 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2874,7 +2874,7 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.45.0" +version = "0.45.1" dependencies = [ "async-std", "asynchronous-codec", diff --git a/Cargo.toml b/Cargo.toml index 587bef4480a..da8d32e1a4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,7 @@ libp2p-dcutr = { version = "0.12.0", path = "protocols/dcutr" } libp2p-dns = { version = "0.42.0", path = "transports/dns" } libp2p-floodsub = { version = "0.45.0", path = "protocols/floodsub" } libp2p-gossipsub = { version = "0.47.1", path = "protocols/gossipsub" } -libp2p-identify = { version = "0.45.0", path = "protocols/identify" } +libp2p-identify = { version = "0.45.1", path = "protocols/identify" } libp2p-identity = { version = "0.2.9" } libp2p-kad = { version = "0.47.0", path = "protocols/kad" } libp2p-mdns = { version = "0.46.0", path = "protocols/mdns" } diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 275f7114b28..c5778ff92ee 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.45.1 + +- Add `hide_listen_addrs` option to prevent leaking (local) listen addresses. + See [PR 5507](https://github.com/libp2p/rust-libp2p/pull/5507). + ## 0.45.0 - Address translation is moved here from `libp2p-core`. diff --git a/protocols/identify/Cargo.toml b/protocols/identify/Cargo.toml index cdc5ce587de..c3fb585c99c 100644 --- a/protocols/identify/Cargo.toml +++ b/protocols/identify/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-identify" edition = "2021" rust-version = { workspace = true } description = "Nodes identification protocol for libp2p" -version = "0.45.0" +version = "0.45.1" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 6590ccd6588..c8672674c1a 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -147,6 +147,12 @@ pub struct Config { /// /// Disabled by default. pub cache_size: usize, + + /// Whether to include our listen addresses in our responses. If enabled, + /// we will effectively only share our external addresses. + /// + /// Disabled by default. + pub hide_listen_addrs: bool, } impl Config { @@ -160,6 +166,7 @@ impl Config { interval: Duration::from_secs(5 * 60), push_listen_addr_updates: false, cache_size: 100, + hide_listen_addrs: false, } } @@ -189,6 +196,12 @@ impl Config { self.cache_size = cache_size; self } + + /// Configures whether we prevent sending out our listen addresses. + pub fn with_hide_listen_addrs(mut self, b: bool) -> Self { + self.hide_listen_addrs = b; + self + } } impl Behaviour { @@ -258,11 +271,11 @@ impl Behaviour { } fn all_addresses(&self) -> HashSet { - self.listen_addresses - .iter() - .chain(self.external_addresses.iter()) - .cloned() - .collect() + let mut addrs = HashSet::from_iter(self.external_addresses.iter().cloned()); + if !self.config.hide_listen_addrs { + addrs.extend(self.listen_addresses.iter().cloned()); + }; + addrs } fn emit_new_external_addr_candidate_event( diff --git a/protocols/identify/tests/smoke.rs b/protocols/identify/tests/smoke.rs index 49ae9f0726f..d624005408e 100644 --- a/protocols/identify/tests/smoke.rs +++ b/protocols/identify/tests/smoke.rs @@ -222,6 +222,77 @@ async fn emits_unique_listen_addresses() { assert!(reported_addrs.contains(&(swarm2_peer_id, swarm2_tcp_listen_addr))); } +#[async_std::test] +async fn hides_listen_addresses() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + let mut swarm1 = Swarm::new_ephemeral(|identity| { + identify::Behaviour::new( + identify::Config::new("a".to_string(), identity.public()) + .with_agent_version("b".to_string()) + .with_interval(Duration::from_secs(1)) + .with_cache_size(10), + ) + }); + let mut swarm2 = Swarm::new_ephemeral(|identity| { + identify::Behaviour::new( + identify::Config::new("c".to_string(), identity.public()) + .with_agent_version("d".to_string()) + .with_hide_listen_addrs(true), + ) + }); + + let (_swarm2_mem_listen_addr, swarm2_tcp_listen_addr) = + swarm2.listen().with_tcp_addr_external().await; + let swarm2_peer_id = *swarm2.local_peer_id(); + swarm1.connect(&mut swarm2).await; + + async_std::task::spawn(swarm2.loop_on_next()); + + let swarm_events = futures::stream::poll_fn(|cx| swarm1.poll_next_unpin(cx)) + .take(8) + .collect::>() + .await; + + let infos = swarm_events + .iter() + .filter_map(|e| match e { + SwarmEvent::Behaviour(identify::Event::Received { info, .. }) => Some(info.clone()), + _ => None, + }) + .collect::>(); + + assert!( + infos.len() > 1, + "should exchange identify payload more than once" + ); + + let listen_addrs = infos + .iter() + .map(|i| i.listen_addrs.clone()) + .collect::>(); + + for addrs in listen_addrs { + assert_eq!(addrs.len(), 1); + assert!(addrs.contains(&swarm2_tcp_listen_addr)); + } + + let reported_addrs = swarm_events + .iter() + .filter_map(|e| match e { + SwarmEvent::NewExternalAddrOfPeer { peer_id, address } => { + Some((*peer_id, address.clone())) + } + _ => None, + }) + .collect::>(); + + assert_eq!(reported_addrs.len(), 1, "To have one TCP address of remote"); + assert!(reported_addrs.contains(&(swarm2_peer_id, swarm2_tcp_listen_addr))); +} + #[async_std::test] async fn identify_push() { let _ = tracing_subscriber::fmt()