From b7de544cbbf158fa98c1e4233d5f5619a00cfe44 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 09:24:38 +0000 Subject: [PATCH 01/25] config: Add local dialing behavior on the builder Signed-off-by: Alexandru Vasile --- src/config.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/config.rs b/src/config.rs index c29560219..09bf54246 100644 --- a/src/config.rs +++ b/src/config.rs @@ -124,6 +124,9 @@ pub struct ConfigBuilder { /// Close the connection if no substreams are open within this time frame. keep_alive_timeout: Duration, + + /// True if litep2p should attempt to dial local addresses. + local_dialing: bool, } impl Default for ConfigBuilder { @@ -157,6 +160,7 @@ impl ConfigBuilder { known_addresses: Vec::new(), connection_limits: ConnectionLimitsConfig::default(), keep_alive_timeout: KEEP_ALIVE_TIMEOUT, + local_dialing: true, } } @@ -278,6 +282,22 @@ impl ConfigBuilder { self } + /// Set the local dialing behavior. + /// + /// When the local dialing is enabled, litep2p will attempt to dial local addresses. + /// This is useful for testing or when you want to preserve local connections. + /// + /// However, for production use, it is recommended to disable local dialing + /// to avoid unnecessary local traffic. Furthermore, it is not recommended + /// to enable local dialing when running a validator in a cloud provider, as this behavior + /// might be misinterpreted by the cloud provider's network policies as port scanning. + /// + /// By default, local dialing is enabled. + pub fn with_local_dialing(mut self, enable: bool) -> Self { + self.local_dialing = enable; + self + } + /// Build [`Litep2pConfig`]. pub fn build(mut self) -> Litep2pConfig { let keypair = match self.keypair { @@ -307,6 +327,7 @@ impl ConfigBuilder { known_addresses: self.known_addresses, connection_limits: self.connection_limits, keep_alive_timeout: self.keep_alive_timeout, + local_dialing: self.local_dialing, } } } @@ -369,4 +390,7 @@ pub struct Litep2pConfig { /// Close the connection if no substreams are open within this time frame. pub(crate) keep_alive_timeout: Duration, + + /// True if litep2p should attempt to dial local addresses. + pub(crate) local_dialing: bool, } From 37ded8f14392c76813d073e11200c4dab370c6c5 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 09:34:05 +0000 Subject: [PATCH 02/25] manager: Pass the use private IP option to the manager Signed-off-by: Alexandru Vasile --- src/config.rs | 23 +++++++------- src/lib.rs | 1 + src/protocol/libp2p/kademlia/mod.rs | 1 + src/protocol/mdns.rs | 2 ++ src/protocol/notification/tests/mod.rs | 1 + src/protocol/request_response/tests.rs | 1 + src/transport/manager/mod.rs | 44 ++++++++++++++++++++++++++ src/transport/tcp/mod.rs | 1 + 8 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/config.rs b/src/config.rs index 09bf54246..8e2389d70 100644 --- a/src/config.rs +++ b/src/config.rs @@ -126,7 +126,7 @@ pub struct ConfigBuilder { keep_alive_timeout: Duration, /// True if litep2p should attempt to dial local addresses. - local_dialing: bool, + use_private_ip: bool, } impl Default for ConfigBuilder { @@ -160,7 +160,7 @@ impl ConfigBuilder { known_addresses: Vec::new(), connection_limits: ConnectionLimitsConfig::default(), keep_alive_timeout: KEEP_ALIVE_TIMEOUT, - local_dialing: true, + use_private_ip: true, } } @@ -282,19 +282,20 @@ impl ConfigBuilder { self } - /// Set the local dialing behavior. + /// Allow or forbid connecting to private IPv4/IPv6 addresses. /// - /// When the local dialing is enabled, litep2p will attempt to dial local addresses. + /// When the private IP is enabled, litep2p will attempt to dial local addresses. /// This is useful for testing or when you want to preserve local connections. /// - /// However, for production use, it is recommended to disable local dialing + /// However, for production use, it is recommended to disable the private IP dialing /// to avoid unnecessary local traffic. Furthermore, it is not recommended - /// to enable local dialing when running a validator in a cloud provider, as this behavior + /// to enable private IP dialing when running a validator in a cloud provider, as this behavior /// might be misinterpreted by the cloud provider's network policies as port scanning. /// - /// By default, local dialing is enabled. - pub fn with_local_dialing(mut self, enable: bool) -> Self { - self.local_dialing = enable; + /// Address allocation for private networks is specified by + /// [RFC1918](https://tools.ietf.org/html/rfc1918)). + pub fn with_private_ip(mut self, enable: bool) -> Self { + self.use_private_ip = enable; self } @@ -327,7 +328,7 @@ impl ConfigBuilder { known_addresses: self.known_addresses, connection_limits: self.connection_limits, keep_alive_timeout: self.keep_alive_timeout, - local_dialing: self.local_dialing, + use_private_ip: self.use_private_ip, } } } @@ -392,5 +393,5 @@ pub struct Litep2pConfig { pub(crate) keep_alive_timeout: Duration, /// True if litep2p should attempt to dial local addresses. - pub(crate) local_dialing: bool, + pub(crate) use_private_ip: bool, } diff --git a/src/lib.rs b/src/lib.rs index 32f61bf4a..cff4668d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,6 +165,7 @@ impl Litep2p { bandwidth_sink.clone(), litep2p_config.max_parallel_dials, litep2p_config.connection_limits, + litep2p_config.use_private_ip, ); // add known addresses to `TransportManager`, if any exist diff --git a/src/protocol/libp2p/kademlia/mod.rs b/src/protocol/libp2p/kademlia/mod.rs index fcfb6a88a..4a4a1ab68 100644 --- a/src/protocol/libp2p/kademlia/mod.rs +++ b/src/protocol/libp2p/kademlia/mod.rs @@ -1281,6 +1281,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true ); let peer = PeerId::random(); diff --git a/src/protocol/mdns.rs b/src/protocol/mdns.rs index 7ea8f30d3..c5ad2c59c 100644 --- a/src/protocol/mdns.rs +++ b/src/protocol/mdns.rs @@ -355,6 +355,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let mdns1 = Mdns::new( @@ -378,6 +379,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let mdns2 = Mdns::new( diff --git a/src/protocol/notification/tests/mod.rs b/src/protocol/notification/tests/mod.rs index 4aa48aa40..3ca7ceade 100644 --- a/src/protocol/notification/tests/mod.rs +++ b/src/protocol/notification/tests/mod.rs @@ -57,6 +57,7 @@ fn make_notification_protocol() -> ( BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); diff --git a/src/protocol/request_response/tests.rs b/src/protocol/request_response/tests.rs index 32cc65e7c..d67fbcaf6 100644 --- a/src/protocol/request_response/tests.rs +++ b/src/protocol/request_response/tests.rs @@ -55,6 +55,7 @@ fn protocol() -> ( BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index f44a07a6b..19cd0b0bb 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -252,6 +252,9 @@ pub struct TransportManager { /// Opening connections errors. opening_errors: HashMap>, + + /// True if litep2p should attempt to dial local addresses. + use_private_ip: bool, } impl TransportManager { @@ -263,6 +266,7 @@ impl TransportManager { bandwidth_sink: BandwidthSink, max_parallel_dials: usize, connection_limits_config: limits::ConnectionLimitsConfig, + use_private_ip: bool, ) -> (Self, TransportManagerHandle) { let local_peer_id = PeerId::from_public_key(&keypair.public().into()); let peers = Arc::new(RwLock::new(HashMap::new())); @@ -300,6 +304,7 @@ impl TransportManager { next_connection_id: Arc::new(AtomicUsize::new(0usize)), connection_limits: limits::ConnectionLimits::new(connection_limits_config), opening_errors: HashMap::new(), + use_private_ip, }, handle, ) @@ -1534,6 +1539,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_protocol( @@ -1561,6 +1567,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_protocol( @@ -1591,6 +1598,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_protocol( @@ -1624,6 +1632,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1641,6 +1650,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), + true, ); assert!(manager.dial(local_peer_id).await.is_err()); @@ -1654,6 +1664,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1684,6 +1695,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -1746,6 +1758,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1777,6 +1790,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1822,6 +1836,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1841,6 +1856,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1874,6 +1890,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); // ipv6 @@ -1936,6 +1953,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2003,6 +2021,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2090,6 +2109,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2175,6 +2195,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2284,6 +2305,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2380,6 +2402,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2489,6 +2512,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2593,6 +2617,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2737,6 +2762,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.on_dial_failure(ConnectionId::random()).unwrap(); @@ -2756,6 +2782,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.on_connection_closed(PeerId::random(), ConnectionId::random()).unwrap(); } @@ -2774,6 +2801,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager .on_connection_opened( @@ -2798,6 +2826,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -2822,6 +2851,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -2849,6 +2879,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager @@ -2870,6 +2901,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -2890,6 +2922,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); assert!(manager.next().await.is_none()); @@ -2903,6 +2936,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = { @@ -2951,6 +2985,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = { @@ -3014,6 +3049,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = { @@ -3057,6 +3093,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); // transport doesn't start with ip/dns @@ -3123,6 +3160,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); async fn call_manager(manager: &mut TransportManager, address: Multiaddr) { @@ -3177,6 +3215,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3263,6 +3302,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3516,6 +3556,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3569,6 +3610,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3721,6 +3763,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3807,6 +3850,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let peer = PeerId::random(); let connection_id = ConnectionId::from(0); diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index 748e138d5..2fac36a82 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -980,6 +980,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), + true, ); let handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport( From 3efda1df83fe852397213eb71ee217d018f77cb4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 09:54:14 +0000 Subject: [PATCH 03/25] transport: Dial only global IPs if specified Signed-off-by: Alexandru Vasile --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/transport/manager/address.rs | 12 ++++++++++++ src/transport/manager/mod.rs | 33 +++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 7b4ded8f7..e9ee84912 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1452,6 +1452,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + [[package]] name = "ipconfig" version = "0.3.2" @@ -1937,6 +1943,7 @@ dependencies = [ "hex-literal", "hickory-resolver", "indexmap", + "ip_network", "libc", "libp2p", "mockall", diff --git a/Cargo.toml b/Cargo.toml index d11b4837c..c15bdc1f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ x509-parser = "0.17.0" yasna = "0.5.0" zeroize = "1.8.1" yamux = "0.13.5" +ip_network = { version = "0.4.1" } # Websocket related dependencies. tokio-tungstenite = { version = "0.26.2", features = ["rustls-tls-native-roots", "url"], optional = true } diff --git a/src/transport/manager/address.rs b/src/transport/manager/address.rs index 2c3cb5d03..5e6363890 100644 --- a/src/transport/manager/address.rs +++ b/src/transport/manager/address.rs @@ -217,6 +217,11 @@ impl AddressStore { self.addresses.is_empty() } + /// Remove the address record from [`AddressStore`] by its address. + pub fn remove(&mut self, address: &Multiaddr) -> Option { + self.addresses.remove(address) + } + /// Insert the address record into [`AddressStore`] with the provided score. /// /// If the address is not in the store, it will be inserted. @@ -259,6 +264,13 @@ impl AddressStore { records.sort_by(|lhs, rhs| rhs.score.cmp(&lhs.score)); records.into_iter().take(limit).map(|record| record.address).collect() } + + /// Similar to [`Self::addresses`], but returns an iterator over the addresses. + pub fn addresses_iter(&self) -> impl Iterator { + let mut records = self.addresses.values().collect::>(); + records.sort_by(|lhs, rhs| rhs.score.cmp(&lhs.score)); + records.into_iter().map(|record| &record.address) + } } #[cfg(test)] diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 19cd0b0bb..4174a5198 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -461,6 +461,19 @@ impl TransportManager { transports } + /// Check if the IP address in the given `Multiaddr` is global. + fn is_address_global(address: &Multiaddr) -> bool { + let ip = match address.iter().next() { + Some(Protocol::Ip4(ip)) => ip_network::IpNetwork::from(ip), + Some(Protocol::Ip6(ip)) => ip_network::IpNetwork::from(ip), + Some(Protocol::Dns(_)) | Some(Protocol::Dns4(_)) | Some(Protocol::Dns6(_)) => + return true, + _ => return false, + }; + + ip.is_global() + } + /// Dial peer using `PeerId`. /// /// Returns an error if the peer is unknown or the peer is already connected. @@ -487,7 +500,23 @@ impl TransportManager { // The addresses are sorted by score and contain the remote peer ID. // We double checked above that the remote peer is not the local peer. - let dial_addresses = context.addresses.addresses(limit); + let dial_addresses = context + .addresses + .addresses_iter() + .filter_map(|addr| { + if self.use_private_ip { + return Some(addr.clone()); + } + + if Self::is_address_global(addr) { + Some(addr.clone()) + } else { + None + } + }) + .take(limit) + .collect::>(); + if dial_addresses.is_empty() { return Err(Error::NoAddressAvailable(peer)); } @@ -3393,6 +3422,7 @@ mod tests { ConnectionLimitsConfig::default() .max_incoming_connections(Some(3)) .max_outgoing_connections(Some(2)), + true, ); // The connection limit is agnostic of the underlying transports. manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3469,6 +3499,7 @@ mod tests { ConnectionLimitsConfig::default() .max_incoming_connections(Some(3)) .max_outgoing_connections(Some(2)), + true, ); // The connection limit is agnostic of the underlying transports. manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); From d5204630181fded7cf1036b904795e25f3d05881 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 09:57:03 +0000 Subject: [PATCH 04/25] manager: Skip dialing provided address if not global Signed-off-by: Alexandru Vasile --- src/transport/manager/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 4174a5198..47a18019b 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -577,6 +577,11 @@ impl TransportManager { return Err(Error::TriedToDialSelf); } + if !self.use_private_ip && !Self::is_address_global(address_record.address()) { + tracing::debug!(target: LOG_TARGET, address = ?address_record.address(), "dial address is not global, skipping"); + return Err(Error::AddressError(AddressError::AddressNotAvailable)); + } + tracing::debug!(target: LOG_TARGET, address = ?address_record.address(), "dial address"); let mut protocol_stack = address_record.as_ref().iter(); From a13d60216ef509f53582aaaa37624b0a280368d0 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 09:58:34 +0000 Subject: [PATCH 05/25] manager/address: Remove unneeded method Signed-off-by: Alexandru Vasile --- src/transport/manager/address.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/transport/manager/address.rs b/src/transport/manager/address.rs index 5e6363890..b8e535e5a 100644 --- a/src/transport/manager/address.rs +++ b/src/transport/manager/address.rs @@ -217,11 +217,6 @@ impl AddressStore { self.addresses.is_empty() } - /// Remove the address record from [`AddressStore`] by its address. - pub fn remove(&mut self, address: &Multiaddr) -> Option { - self.addresses.remove(address) - } - /// Insert the address record into [`AddressStore`] with the provided score. /// /// If the address is not in the store, it will be inserted. From b2299d89c65dd36053b4bb9e365f1bc7bd21ac10 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 10:58:05 +0000 Subject: [PATCH 06/25] kad: Apply cargo fmt Signed-off-by: Alexandru Vasile --- src/protocol/libp2p/kademlia/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/libp2p/kademlia/mod.rs b/src/protocol/libp2p/kademlia/mod.rs index 4a4a1ab68..237cc1a6c 100644 --- a/src/protocol/libp2p/kademlia/mod.rs +++ b/src/protocol/libp2p/kademlia/mod.rs @@ -1281,7 +1281,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true + true, ); let peer = PeerId::random(); From bef61da8c641834e9f52c65f4a8d56212eee5299 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 12:38:18 +0000 Subject: [PATCH 07/25] cargo: Use plain version format Signed-off-by: Alexandru Vasile --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c15bdc1f6..69f34ac4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ x509-parser = "0.17.0" yasna = "0.5.0" zeroize = "1.8.1" yamux = "0.13.5" -ip_network = { version = "0.4.1" } +ip_network = "0.4.1" # Websocket related dependencies. tokio-tungstenite = { version = "0.26.2", features = ["rustls-tls-native-roots", "url"], optional = true } From 94ceb62980f48acb90817b4d434accbc92755be2 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 12:59:07 +0000 Subject: [PATCH 08/25] manager: Add wrapper for IP dialing mode Signed-off-by: Alexandru Vasile --- src/transport/manager/handle.rs | 7 ++- src/transport/manager/mod.rs | 78 +++++++++++++++++++++------------ 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index 36619e516..308602807 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -28,7 +28,7 @@ use crate::{ address::AddressRecord, peer_state::StateDialResult, types::{PeerContext, SupportedTransport}, - ProtocolContext, TransportManagerEvent, LOG_TARGET, + IpDialingMode, ProtocolContext, TransportManagerEvent, LOG_TARGET, }, types::{protocol::ProtocolName, ConnectionId}, BandwidthSink, PeerId, @@ -87,6 +87,9 @@ pub struct TransportManagerHandle { /// Public addresses. public_addresses: PublicAddresses, + + /// IP dialing mode. + ip_dialing_mode: IpDialingMode, } impl TransportManagerHandle { @@ -98,6 +101,7 @@ impl TransportManagerHandle { supported_transport: HashSet, listen_addresses: Arc>>, public_addresses: PublicAddresses, + ip_dialing_mode: IpDialingMode, ) -> Self { Self { peers, @@ -106,6 +110,7 @@ impl TransportManagerHandle { supported_transport, listen_addresses, public_addresses, + ip_dialing_mode, } } diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 47a18019b..d5738e3d6 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -194,6 +194,44 @@ impl Stream for TransportContext { } } +/// The IP dialing mode determines how the transport manager handles dialing +/// IP addresses. It can either dial only global addresses or all addresses, including private IPs. +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +pub(crate) enum IpDialingMode { + /// Dial only global addresses. + #[default] + GlobalOnly, + + /// Dial all addresses, including private IPs. + /// + /// This setup is not recommended for production use-cases. + All, +} + +impl IpDialingMode { + /// Check if the IP address in the given `Multiaddr` is global. + pub fn is_address_global(address: &Multiaddr) -> bool { + let ip = match address.iter().next() { + Some(Protocol::Ip4(ip)) => ip_network::IpNetwork::from(ip), + Some(Protocol::Ip6(ip)) => ip_network::IpNetwork::from(ip), + Some(Protocol::Dns(_)) | Some(Protocol::Dns4(_)) | Some(Protocol::Dns6(_)) => + return true, + _ => return false, + }; + + ip.is_global() + } + + /// Check if the IP dialing mode allows dialing private IPs. + pub fn allows_address(&self, address: &Multiaddr) -> bool { + match self { + Self::GlobalOnly => Self::is_address_global(address), + // All IP addresses are allowed. + Self::All => true, + } + } +} + /// Litep2p connection manager. pub struct TransportManager { /// Local peer ID. @@ -253,8 +291,8 @@ pub struct TransportManager { /// Opening connections errors. opening_errors: HashMap>, - /// True if litep2p should attempt to dial local addresses. - use_private_ip: bool, + /// IP dialing mode. + ip_dialing_mode: IpDialingMode, } impl TransportManager { @@ -281,8 +319,15 @@ impl TransportManager { supported_transports, listen_addresses.clone(), public_addresses.clone(), + use_private_ip, ); + let ip_dialing_mode = if use_private_ip { + IpDialingMode::All + } else { + IpDialingMode::GlobalOnly + }; + ( Self { peers, @@ -304,7 +349,7 @@ impl TransportManager { next_connection_id: Arc::new(AtomicUsize::new(0usize)), connection_limits: limits::ConnectionLimits::new(connection_limits_config), opening_errors: HashMap::new(), - use_private_ip, + ip_dialing_mode, }, handle, ) @@ -461,19 +506,6 @@ impl TransportManager { transports } - /// Check if the IP address in the given `Multiaddr` is global. - fn is_address_global(address: &Multiaddr) -> bool { - let ip = match address.iter().next() { - Some(Protocol::Ip4(ip)) => ip_network::IpNetwork::from(ip), - Some(Protocol::Ip6(ip)) => ip_network::IpNetwork::from(ip), - Some(Protocol::Dns(_)) | Some(Protocol::Dns4(_)) | Some(Protocol::Dns6(_)) => - return true, - _ => return false, - }; - - ip.is_global() - } - /// Dial peer using `PeerId`. /// /// Returns an error if the peer is unknown or the peer is already connected. @@ -503,17 +535,7 @@ impl TransportManager { let dial_addresses = context .addresses .addresses_iter() - .filter_map(|addr| { - if self.use_private_ip { - return Some(addr.clone()); - } - - if Self::is_address_global(addr) { - Some(addr.clone()) - } else { - None - } - }) + .filter_map(|addr| self.ip_dialing_mode.allows_address(addr).then(|| addr.clone())) .take(limit) .collect::>(); @@ -577,7 +599,7 @@ impl TransportManager { return Err(Error::TriedToDialSelf); } - if !self.use_private_ip && !Self::is_address_global(address_record.address()) { + if !self.ip_dialing_mode.allows_address(address_record.address()) { tracing::debug!(target: LOG_TARGET, address = ?address_record.address(), "dial address is not global, skipping"); return Err(Error::AddressError(AddressError::AddressNotAvailable)); } From 0b007dc903114b2c4e8ba777ed9a53199284ceb4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 13:39:23 +0000 Subject: [PATCH 09/25] manager: Report errors earlier on ip dialing mode from handlers Signed-off-by: Alexandru Vasile --- src/transport/manager/handle.rs | 28 ++++++++++++++++++++++++++-- src/transport/manager/mod.rs | 23 +++++++++++++++-------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index 308602807..9d39cf390 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -253,7 +253,11 @@ impl TransportManagerHandle { { let peers = self.peers.read(); - let Some(PeerContext { state, addresses }) = peers.get(peer) else { + let Some(PeerContext { + state, + addresses: address_store, + }) = peers.get(peer) + else { return Err(ImmediateDialError::NoAddressAvailable); }; @@ -265,7 +269,18 @@ impl TransportManagerHandle { }; // Check if we have enough addresses to dial. - if addresses.is_empty() { + if address_store.is_empty() { + return Err(ImmediateDialError::NoAddressAvailable); + } + + // Check if we can dial at least one address from the store in the current operating + // mode. If the mode is `IpDialingMode::All`, this will always return + // `true` on the first address. + let has_dialable_address = address_store + .addresses + .iter() + .any(|(address, _record)| self.ip_dialing_mode.allows_address(address)); + if !has_dialable_address { return Err(ImmediateDialError::NoAddressAvailable); } } @@ -286,6 +301,15 @@ impl TransportManagerHandle { return Err(ImmediateDialError::PeerIdMissing); } + if self.ip_dialing_mode.allows_address(&address) { + tracing::debug!( + target: LOG_TARGET, + ?address, + "Dialing address is not global, skipping", + ); + return Err(ImmediateDialError::NoAddressAvailable); + } + self.cmd_tx .try_send(InnerTransportManagerCommand::DialAddress { address }) .map_err(|error| match error { diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index d5738e3d6..19e3ea96e 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -312,6 +312,13 @@ impl TransportManager { let (event_tx, event_rx) = channel(256); let listen_addresses = Arc::new(RwLock::new(HashSet::new())); let public_addresses = PublicAddresses::new(local_peer_id); + + let ip_dialing_mode = if use_private_ip { + IpDialingMode::All + } else { + IpDialingMode::GlobalOnly + }; + let handle = TransportManagerHandle::new( local_peer_id, peers.clone(), @@ -319,15 +326,9 @@ impl TransportManager { supported_transports, listen_addresses.clone(), public_addresses.clone(), - use_private_ip, + ip_dialing_mode, ); - let ip_dialing_mode = if use_private_ip { - IpDialingMode::All - } else { - IpDialingMode::GlobalOnly - }; - ( Self { peers, @@ -535,7 +536,13 @@ impl TransportManager { let dial_addresses = context .addresses .addresses_iter() - .filter_map(|addr| self.ip_dialing_mode.allows_address(addr).then(|| addr.clone())) + .filter_map(|addr| { + if self.ip_dialing_mode.allows_address(addr) { + Some(addr.clone()) + } else { + None + } + }) .take(limit) .collect::>(); From c75924f19f5a1cc6acaf5471c20ee05dd0e2f191 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 13:47:30 +0000 Subject: [PATCH 10/25] manager: Use the new ip mode Signed-off-by: Alexandru Vasile --- src/protocol/transport_service.rs | 1 + src/transport/manager/handle.rs | 10 +++++++++- src/transport/manager/mod.rs | 17 ++++++++--------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/protocol/transport_service.rs b/src/protocol/transport_service.rs index b729e9312..498603f7e 100644 --- a/src/protocol/transport_service.rs +++ b/src/protocol/transport_service.rs @@ -662,6 +662,7 @@ mod tests { HashSet::new(), Default::default(), PublicAddresses::new(peer), + true, ); let (service, sender) = TransportService::new( diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index 9d39cf390..be875538e 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -101,8 +101,14 @@ impl TransportManagerHandle { supported_transport: HashSet, listen_addresses: Arc>>, public_addresses: PublicAddresses, - ip_dialing_mode: IpDialingMode, + use_private_ip: bool, ) -> Self { + let ip_dialing_mode = if use_private_ip { + IpDialingMode::All + } else { + IpDialingMode::GlobalOnly + }; + Self { peers, cmd_tx, @@ -397,6 +403,7 @@ mod tests { supported_transport: HashSet::new(), listen_addresses: Default::default(), public_addresses: PublicAddresses::new(local_peer_id), + ip_dialing_mode: IpDialingMode::default(), }, cmd_rx, ) @@ -789,6 +796,7 @@ mod tests { supported_transport: HashSet::new(), listen_addresses, public_addresses: PublicAddresses::new(local_peer_id), + ip_dialing_mode: IpDialingMode::default(), }; // local addresses diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 19e3ea96e..02eac1e77 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -199,12 +199,12 @@ impl Stream for TransportContext { #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] pub(crate) enum IpDialingMode { /// Dial only global addresses. - #[default] GlobalOnly, /// Dial all addresses, including private IPs. /// /// This setup is not recommended for production use-cases. + #[default] All, } @@ -312,13 +312,6 @@ impl TransportManager { let (event_tx, event_rx) = channel(256); let listen_addresses = Arc::new(RwLock::new(HashSet::new())); let public_addresses = PublicAddresses::new(local_peer_id); - - let ip_dialing_mode = if use_private_ip { - IpDialingMode::All - } else { - IpDialingMode::GlobalOnly - }; - let handle = TransportManagerHandle::new( local_peer_id, peers.clone(), @@ -326,9 +319,15 @@ impl TransportManager { supported_transports, listen_addresses.clone(), public_addresses.clone(), - ip_dialing_mode, + use_private_ip, ); + let ip_dialing_mode = if use_private_ip { + IpDialingMode::All + } else { + IpDialingMode::GlobalOnly + }; + ( Self { peers, From 7b895ad543ee4374092651d22663ea53c52711bd Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 8 Jul 2025 14:53:34 +0000 Subject: [PATCH 11/25] manager: Fix ip dialing mode condition and add debug logs Signed-off-by: Alexandru Vasile --- src/transport/manager/handle.rs | 8 +++++++- src/transport/manager/mod.rs | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index be875538e..1d3947296 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -109,6 +109,12 @@ impl TransportManagerHandle { IpDialingMode::GlobalOnly }; + tracing::debug!( + target: LOG_TARGET, + ?ip_dialing_mode, + "Transport manager handle created", + ); + Self { peers, cmd_tx, @@ -307,7 +313,7 @@ impl TransportManagerHandle { return Err(ImmediateDialError::PeerIdMissing); } - if self.ip_dialing_mode.allows_address(&address) { + if !self.ip_dialing_mode.allows_address(&address) { tracing::debug!( target: LOG_TARGET, ?address, diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 02eac1e77..eb46967a3 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -328,6 +328,12 @@ impl TransportManager { IpDialingMode::GlobalOnly }; + tracing::debug!( + target: LOG_TARGET, + ?ip_dialing_mode, + "Transport manager created", + ); + ( Self { peers, From 5ce55c32eb2a4fe36377d2ac21b68a10fff1b1dd Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 14 Oct 2025 07:35:44 +0000 Subject: [PATCH 12/25] error: Remove unneeded error variant Signed-off-by: Alexandru Vasile --- src/error.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/error.rs b/src/error.rs index 448005d08..e87964e94 100644 --- a/src/error.rs +++ b/src/error.rs @@ -78,8 +78,6 @@ pub enum Error { Timeout, #[error("Invalid state transition")] InvalidState, - #[error("DNS address resolution failed")] - DnsAddressResolutionFailed, #[error("Transport error: `{0}`")] TransportError(String), #[cfg(feature = "quic")] From c0785e6123c889193ebb283766f92e6b58abf831 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 14 Oct 2025 07:52:04 +0000 Subject: [PATCH 13/25] manager: Remove addresses_iter fn Signed-off-by: Alexandru Vasile --- src/transport/manager/address.rs | 7 ------- src/transport/manager/mod.rs | 11 +++-------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/transport/manager/address.rs b/src/transport/manager/address.rs index 8c6332f35..68325d7df 100644 --- a/src/transport/manager/address.rs +++ b/src/transport/manager/address.rs @@ -259,13 +259,6 @@ impl AddressStore { records.sort_by(|lhs, rhs| rhs.score.cmp(&lhs.score)); records.into_iter().take(limit).map(|record| record.address).collect() } - - /// Similar to [`Self::addresses`], but returns an iterator over the addresses. - pub fn addresses_iter(&self) -> impl Iterator { - let mut records = self.addresses.values().collect::>(); - records.sort_by(|lhs, rhs| rhs.score.cmp(&lhs.score)); - records.into_iter().map(|record| &record.address) - } } #[cfg(test)] diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 7312a849f..fb9856799 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -540,14 +540,9 @@ impl TransportManager { // We double checked above that the remote peer is not the local peer. let dial_addresses = context .addresses - .addresses_iter() - .filter_map(|addr| { - if self.ip_dialing_mode.allows_address(addr) { - Some(addr.clone()) - } else { - None - } - }) + .addresses(usize::MAX) + .into_iter() + .filter(|addr| self.ip_dialing_mode.allows_address(addr)) .take(limit) .collect::>(); From dc73acce855968d76183eb6c39bbb2e0c4bae71c Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 14 Oct 2025 08:02:35 +0000 Subject: [PATCH 14/25] manager: Deny private IP in DNS resolution Signed-off-by: Alexandru Vasile --- src/transport/manager/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index fb9856799..370d5be7f 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -48,7 +48,9 @@ use tokio::sync::mpsc::{channel, Receiver, Sender}; use std::{ collections::{HashMap, HashSet}, + net::IpAddr, pin::Pin, + str::FromStr, sync::{ atomic::{AtomicUsize, Ordering}, Arc, @@ -214,8 +216,13 @@ impl IpDialingMode { let ip = match address.iter().next() { Some(Protocol::Ip4(ip)) => ip_network::IpNetwork::from(ip), Some(Protocol::Ip6(ip)) => ip_network::IpNetwork::from(ip), - Some(Protocol::Dns(_)) | Some(Protocol::Dns4(_)) | Some(Protocol::Dns6(_)) => - return true, + Some(Protocol::Dns(host)) | Some(Protocol::Dns4(host)) | Some(Protocol::Dns6(host)) => + if let Ok(ip) = IpAddr::from_str(&host) { + ip_network::IpNetwork::from(ip) + } else { + // Allow DNS resolutions for DNS names. + return true; + }, _ => return false, }; From 95b8b30206476b3fa1d9f862b3b119bdb9c21b8f Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 13:13:36 +0000 Subject: [PATCH 15/25] manager: Refactor builder to use ip_dialing_mode Signed-off-by: Alexandru Vasile --- src/config.rs | 21 +++++++++++---------- src/lib.rs | 2 +- src/transport/manager/handle.rs | 8 +------- src/transport/manager/mod.rs | 16 ++++++---------- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/config.rs b/src/config.rs index 314a20f9e..b5d6212e2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,7 +29,8 @@ use crate::{ notification, request_response, UserProtocol, }, transport::{ - manager::limits::ConnectionLimitsConfig, tcp::config::Config as TcpConfig, + manager::{limits::ConnectionLimitsConfig, IpDialingMode}, + tcp::config::Config as TcpConfig, KEEP_ALIVE_TIMEOUT, MAX_PARALLEL_DIALS, }, types::protocol::ProtocolName, @@ -125,8 +126,8 @@ pub struct ConfigBuilder { /// Close the connection if no substreams are open within this time frame. keep_alive_timeout: Duration, - /// True if litep2p should attempt to dial local addresses. - use_private_ip: bool, + /// IP dialing mode. + ip_dialing_mode: IpDialingMode, /// Use system's DNS config. use_system_dns_config: bool, @@ -163,7 +164,7 @@ impl ConfigBuilder { known_addresses: Vec::new(), connection_limits: ConnectionLimitsConfig::default(), keep_alive_timeout: KEEP_ALIVE_TIMEOUT, - use_private_ip: true, + ip_dialing_mode: IpDialingMode::GlobalOnly, use_system_dns_config: false, } } @@ -286,7 +287,7 @@ impl ConfigBuilder { self } - /// Allow or forbid connecting to private IPv4/IPv6 addresses. + /// Set the ip dialing mode. /// /// When the private IP is enabled, litep2p will attempt to dial local addresses. /// This is useful for testing or when you want to preserve local connections. @@ -298,8 +299,8 @@ impl ConfigBuilder { /// /// Address allocation for private networks is specified by /// [RFC1918](https://tools.ietf.org/html/rfc1918)). - pub fn with_private_ip(mut self, enable: bool) -> Self { - self.use_private_ip = enable; + pub fn with_ip_dialing_mode(mut self, mode: IpDialingMode) -> Self { + self.ip_dialing_mode = mode; self } @@ -338,7 +339,7 @@ impl ConfigBuilder { known_addresses: self.known_addresses, connection_limits: self.connection_limits, keep_alive_timeout: self.keep_alive_timeout, - use_private_ip: self.use_private_ip, + ip_dialing_mode: self.ip_dialing_mode, use_system_dns_config: self.use_system_dns_config, } } @@ -403,8 +404,8 @@ pub struct Litep2pConfig { /// Close the connection if no substreams are open within this time frame. pub(crate) keep_alive_timeout: Duration, - /// True if litep2p should attempt to dial local addresses. - pub(crate) use_private_ip: bool, + /// IP dialing mode. + pub(crate) ip_dialing_mode: IpDialingMode, /// Use system's DNS config. pub(crate) use_system_dns_config: bool, diff --git a/src/lib.rs b/src/lib.rs index e62248ab3..5fb046bce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,7 +176,7 @@ impl Litep2p { bandwidth_sink.clone(), litep2p_config.max_parallel_dials, litep2p_config.connection_limits, - litep2p_config.use_private_ip, + litep2p_config.ip_dialing_mode, ); // add known addresses to `TransportManager`, if any exist diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index d03fc82fa..ecf1d1bf4 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -101,14 +101,8 @@ impl TransportManagerHandle { supported_transport: HashSet, listen_addresses: Arc>>, public_addresses: PublicAddresses, - use_private_ip: bool, + ip_dialing_mode: IpDialingMode, ) -> Self { - let ip_dialing_mode = if use_private_ip { - IpDialingMode::All - } else { - IpDialingMode::GlobalOnly - }; - tracing::debug!( target: LOG_TARGET, ?ip_dialing_mode, diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 370d5be7f..c2402be3f 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -197,9 +197,11 @@ impl Stream for TransportContext { } /// The IP dialing mode determines how the transport manager handles dialing -/// IP addresses. It can either dial only global addresses or all addresses, including private IPs. +/// IP addresses. +/// +/// It can either dial only global addresses or all addresses, including private IPs. #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] -pub(crate) enum IpDialingMode { +pub enum IpDialingMode { /// Dial only global addresses. GlobalOnly, @@ -311,7 +313,7 @@ impl TransportManager { bandwidth_sink: BandwidthSink, max_parallel_dials: usize, connection_limits_config: limits::ConnectionLimitsConfig, - use_private_ip: bool, + ip_dialing_mode: IpDialingMode, ) -> (Self, TransportManagerHandle) { let local_peer_id = PeerId::from_public_key(&keypair.public().into()); let peers = Arc::new(RwLock::new(HashMap::new())); @@ -326,15 +328,9 @@ impl TransportManager { supported_transports, listen_addresses.clone(), public_addresses.clone(), - use_private_ip, + ip_dialing_mode, ); - let ip_dialing_mode = if use_private_ip { - IpDialingMode::All - } else { - IpDialingMode::GlobalOnly - }; - tracing::debug!( target: LOG_TARGET, ?ip_dialing_mode, From cea33f062abf1799767217b20b34780b2ff21b78 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 13:33:07 +0000 Subject: [PATCH 16/25] tcp: Propagate ip dialing mode to tcp Signed-off-by: Alexandru Vasile --- src/transport/manager/handle.rs | 1 + src/transport/manager/mod.rs | 1 + src/transport/tcp/mod.rs | 9 ++++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index ecf1d1bf4..2e0c86ae4 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -356,6 +356,7 @@ pub struct TransportHandle { pub next_substream_id: Arc, pub bandwidth_sink: BandwidthSink, pub executor: Arc, + pub ip_dialing_mode: IpDialingMode, } impl TransportHandle { diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index c2402be3f..5a2d02d8c 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -449,6 +449,7 @@ impl TransportManager { bandwidth_sink: self.bandwidth_sink.clone(), next_substream_id: self.next_substream_id.clone(), next_connection_id: self.next_connection_id.clone(), + ip_dialing_mode: self.ip_dialing_mode, } } diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index c3fe09268..99a35cb70 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -26,7 +26,7 @@ use crate::{ error::{DialError, Error}, transport::{ common::listener::{DialAddresses, GetSocketAddr, SocketListener, TcpAddress}, - manager::TransportHandle, + manager::{IpDialingMode, TransportHandle}, tcp::{ config::Config, connection::{NegotiatedConnection, TcpConnection}, @@ -134,6 +134,9 @@ pub(crate) struct TcpTransport { /// DNS resolver. resolver: Arc, + + /// IP dialing mode. + ip_dialing_mode: IpDialingMode, } impl TcpTransport { @@ -281,9 +284,12 @@ impl TransportBuilder for TcpTransport { mut config: Self::Config, resolver: Arc, ) -> crate::Result<(Self, Vec)> { + let ip_dialing_mode = context.ip_dialing_mode; + tracing::debug!( target: LOG_TARGET, listen_addresses = ?config.listen_addresses, + ?ip_dialing_mode, "start tcp transport", ); @@ -308,6 +314,7 @@ impl TransportBuilder for TcpTransport { pending_raw_connections: FuturesStream::new(), cancel_futures: HashMap::new(), resolver, + ip_dialing_mode, }, listen_addresses, )) From 9ff3fe87069a15dfe3d3b2d2bd49a2e073c92f59 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 14:42:44 +0000 Subject: [PATCH 17/25] tcp: Ensure DNS lookups are not dialing forbidden IPs Signed-off-by: Alexandru Vasile --- src/transport/common/listener.rs | 74 +++++++++++++++++++++++--------- src/transport/manager/mod.rs | 11 ++++- src/transport/tcp/connection.rs | 1 + src/transport/tcp/mod.rs | 15 +++++-- 4 files changed, 76 insertions(+), 25 deletions(-) diff --git a/src/transport/common/listener.rs b/src/transport/common/listener.rs index 856b4c19b..d8b9fbced 100644 --- a/src/transport/common/listener.rs +++ b/src/transport/common/listener.rs @@ -22,6 +22,7 @@ use crate::{ error::{AddressError, DnsError}, + transport::manager::IpDialingMode, PeerId, }; @@ -54,6 +55,7 @@ pub enum AddressType { address: String, port: u16, dns_type: DnsType, + ip_dialing_mode: IpDialingMode, }, } @@ -71,14 +73,15 @@ pub enum DnsType { impl AddressType { /// Resolve the address to a concrete IP. pub async fn lookup_ip(self, resolver: Arc) -> Result { - let (url, port, dns_type) = match self { + let (url, port, dns_type, ip_dialing_mode) = match self { // We already have the IP address. AddressType::Socket(address) => return Ok(address), AddressType::Dns { address, port, dns_type, - } => (address, port, dns_type), + ip_dialing_mode, + } => (address, port, dns_type, ip_dialing_mode), }; let lookup = match resolver.lookup_ip(url.clone()).await { @@ -95,10 +98,22 @@ impl AddressType { } }; - let Some(ip) = lookup.iter().find(|ip| match dns_type { - DnsType::Dns => true, - DnsType::Dns4 => ip.is_ipv4(), - DnsType::Dns6 => ip.is_ipv6(), + let Some(ip) = lookup.iter().find(|ip| { + if !ip_dialing_mode.allows_ip(*ip) { + tracing::debug!( + target: LOG_TARGET, + ?ip, + ?ip_dialing_mode, + "IP address not allowed by IP dialing mode during DNS lookup", + ); + return false; + } + + match dns_type { + DnsType::Dns => true, + DnsType::Dns4 => ip.is_ipv4(), + DnsType::Dns6 => ip.is_ipv6(), + } }) else { tracing::debug!( target: LOG_TARGET, @@ -178,6 +193,7 @@ pub trait GetSocketAddr { /// The `PeerId` is optional and may not be present. fn multiaddr_to_socket_address( address: &Multiaddr, + ip_dialing_mode: IpDialingMode, ) -> Result<(AddressType, Option), AddressError>; /// Convert concrete `SocketAddr` to `Multiaddr`. @@ -190,8 +206,9 @@ pub struct TcpAddress; impl GetSocketAddr for TcpAddress { fn multiaddr_to_socket_address( address: &Multiaddr, + ip_dialing_mode: IpDialingMode, ) -> Result<(AddressType, Option), AddressError> { - multiaddr_to_socket_address(address, SocketListenerType::Tcp) + multiaddr_to_socket_address(address, ip_dialing_mode, SocketListenerType::Tcp) } fn socket_address_to_multiaddr(address: &SocketAddr) -> Multiaddr { @@ -209,8 +226,9 @@ pub struct WebSocketAddress; impl GetSocketAddr for WebSocketAddress { fn multiaddr_to_socket_address( address: &Multiaddr, + ip_dialing_mode: IpDialingMode, ) -> Result<(AddressType, Option), AddressError> { - multiaddr_to_socket_address(address, SocketListenerType::WebSocket) + multiaddr_to_socket_address(address, ip_dialing_mode, SocketListenerType::WebSocket) } fn socket_address_to_multiaddr(address: &SocketAddr) -> Multiaddr { @@ -231,19 +249,21 @@ impl SocketListener { let (listeners, listen_addresses): (_, Vec>) = addresses .into_iter() .filter_map(|address| { - let address = match T::multiaddr_to_socket_address(&address).ok()?.0 { - AddressType::Dns { address, port, .. } => { - tracing::debug!( - target: LOG_TARGET, - ?address, - ?port, - "dns not supported as bind address" - ); - - return None; - } - AddressType::Socket(address) => address, - }; + // Allows listening on the specified address. + let address = + match T::multiaddr_to_socket_address(&address, IpDialingMode::All).ok()?.0 { + AddressType::Dns { address, port, .. } => { + tracing::debug!( + target: LOG_TARGET, + ?address, + ?port, + "dns not supported as bind address" + ); + + return None; + } + AddressType::Socket(address) => address, + }; let socket = if address.is_ipv4() { Socket::new(Domain::IPV4, Type::STREAM, Some(socket2::Protocol::TCP)).ok()? @@ -348,10 +368,21 @@ enum SocketListenerType { /// Extract socket address and `PeerId`, if found, from `address`. fn multiaddr_to_socket_address( address: &Multiaddr, + ip_dialing_mode: IpDialingMode, ty: SocketListenerType, ) -> Result<(AddressType, Option), AddressError> { tracing::trace!(target: LOG_TARGET, ?address, "parse multi address"); + if !ip_dialing_mode.allows_address(address) { + tracing::error!( + target: LOG_TARGET, + ?address, + ?ip_dialing_mode, + "address not allowed by IP dialing mode", + ); + return Err(AddressError::AddressNotAvailable); + } + let mut iter = address.iter(); // Small helper to handle DNS types. let handle_dns_type = @@ -360,6 +391,7 @@ fn multiaddr_to_socket_address( address, port, dns_type, + ip_dialing_mode, }), protocol => { tracing::error!( diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 5a2d02d8c..284cb413f 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -231,7 +231,7 @@ impl IpDialingMode { ip.is_global() } - /// Check if the IP dialing mode allows dialing private IPs. + /// Check if the IP dialing mode allows dialing the given address. pub fn allows_address(&self, address: &Multiaddr) -> bool { match self { Self::GlobalOnly => Self::is_address_global(address), @@ -239,6 +239,15 @@ impl IpDialingMode { Self::All => true, } } + + /// Check if the IP dialing mode allows dialing the given IP address. + pub fn allows_ip(&self, ip: IpAddr) -> bool { + match self { + Self::GlobalOnly => ip_network::IpNetwork::from(ip).is_global(), + // All IP addresses are allowed. + Self::All => true, + } + } } /// Litep2p connection manager. diff --git a/src/transport/tcp/connection.rs b/src/transport/tcp/connection.rs index c724dff65..60492af91 100644 --- a/src/transport/tcp/connection.rs +++ b/src/transport/tcp/connection.rs @@ -469,6 +469,7 @@ impl TcpConnection { address, port, dns_type, + .. } => match dns_type { DnsType::Dns => Multiaddr::empty() .with(Protocol::Dns(Cow::Owned(address))) diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index 99a35cb70..73aa676ec 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -185,8 +185,10 @@ impl TcpTransport { connection_open_timeout: Duration, nodelay: bool, resolver: Arc, + ip_dialing_mode: IpDialingMode, ) -> Result<(Multiaddr, TcpStream), DialError> { - let (socket_address, _) = TcpAddress::multiaddr_to_socket_address(&address)?; + let (socket_address, _) = + TcpAddress::multiaddr_to_socket_address(&address, ip_dialing_mode)?; let remote_address = match tokio::time::timeout(connection_open_timeout, socket_address.lookup_ip(resolver)) @@ -325,7 +327,8 @@ impl Transport for TcpTransport { fn dial(&mut self, connection_id: ConnectionId, address: Multiaddr) -> crate::Result<()> { tracing::debug!(target: LOG_TARGET, ?connection_id, ?address, "open connection"); - let (socket_address, peer) = TcpAddress::multiaddr_to_socket_address(&address)?; + let (socket_address, peer) = + TcpAddress::multiaddr_to_socket_address(&address, self.ip_dialing_mode)?; let yamux_config = self.config.yamux_config.clone(); let max_read_ahead_factor = self.config.noise_read_ahead_frame_count; let max_write_buffer_size = self.config.noise_write_buffer_size; @@ -335,6 +338,7 @@ impl Transport for TcpTransport { let keypair = self.context.keypair.clone(); let nodelay = self.config.nodelay; let resolver = self.resolver.clone(); + let ip_dialing_mode = self.ip_dialing_mode; self.pending_dials.insert(connection_id, address.clone()); self.pending_connections.push(Box::pin(async move { @@ -344,6 +348,7 @@ impl Transport for TcpTransport { connection_open_timeout, nodelay, resolver, + ip_dialing_mode, ) .await .map_err(|error| (connection_id, error))?; @@ -450,6 +455,7 @@ impl Transport for TcpTransport { let connection_open_timeout = self.config.connection_open_timeout; let nodelay = self.config.nodelay; let resolver = self.resolver.clone(); + let ip_dialing_mode = self.ip_dialing_mode; async move { TcpTransport::dial_peer( @@ -458,6 +464,7 @@ impl Transport for TcpTransport { connection_open_timeout, nodelay, resolver, + ip_dialing_mode, ) .await .map_err(|error| (address, error)) @@ -508,7 +515,9 @@ impl Transport for TcpTransport { .remove(&connection_id) .ok_or(Error::ConnectionDoesntExist(connection_id))?; - let (socket_address, peer) = TcpAddress::multiaddr_to_socket_address(&address)?; + // Address already validated during the dial process. + let (socket_address, peer) = + TcpAddress::multiaddr_to_socket_address(&address, IpDialingMode::All)?; let yamux_config = self.config.yamux_config.clone(); let max_read_ahead_factor = self.config.noise_read_ahead_frame_count; let max_write_buffer_size = self.config.noise_write_buffer_size; From dd44a837eeb77a44f205da75d341d41925f8aa11 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 14:55:16 +0000 Subject: [PATCH 18/25] websocket: Introduce IP dialing mode Signed-off-by: Alexandru Vasile --- src/transport/tcp/mod.rs | 10 +++++----- src/transport/websocket/mod.rs | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index 73aa676ec..1a4ead49a 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -747,7 +747,6 @@ mod tests { keypair: keypair1.clone(), tx: event_tx1, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -756,6 +755,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let transport_config1 = Config { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], @@ -841,7 +841,6 @@ mod tests { keypair: keypair1.clone(), tx: event_tx1, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -850,6 +849,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let transport_config1 = Config { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], @@ -872,7 +872,6 @@ mod tests { keypair: keypair2.clone(), tx: event_tx2, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -881,6 +880,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let transport_config2 = Config { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], @@ -930,7 +930,6 @@ mod tests { keypair: keypair1.clone(), tx: event_tx1, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -939,6 +938,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); let (mut transport1, _) = @@ -968,7 +968,6 @@ mod tests { keypair: keypair2.clone(), tx: event_tx2, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -977,6 +976,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let (mut transport2, _) = TcpTransport::new(handle2, Default::default(), resolver).unwrap(); diff --git a/src/transport/websocket/mod.rs b/src/transport/websocket/mod.rs index 11013e6c6..f74de6b2e 100644 --- a/src/transport/websocket/mod.rs +++ b/src/transport/websocket/mod.rs @@ -25,7 +25,7 @@ use crate::{ error::{AddressError, Error, NegotiationError}, transport::{ common::listener::{DialAddresses, GetSocketAddr, SocketListener, WebSocketAddress}, - manager::TransportHandle, + manager::{IpDialingMode, TransportHandle}, websocket::{ config::Config, connection::{NegotiatedConnection, WebSocketConnection}, @@ -136,6 +136,9 @@ pub(crate) struct WebSocketTransport { /// DNS resolver. resolver: Arc, + + /// IP dialing mode. + ip_dialing_mode: IpDialingMode, } impl WebSocketTransport { @@ -229,10 +232,12 @@ impl WebSocketTransport { connection_open_timeout: Duration, nodelay: bool, resolver: Arc, + ip_dialing_mode: IpDialingMode, ) -> Result<(Multiaddr, WebSocketStream>), DialError> { let (url, _) = Self::multiaddr_into_url(address.clone())?; - let (socket_address, _) = WebSocketAddress::multiaddr_to_socket_address(&address)?; + let (socket_address, _) = + WebSocketAddress::multiaddr_to_socket_address(&address, ip_dialing_mode)?; let remote_address = match tokio::time::timeout(connection_open_timeout, socket_address.lookup_ip(resolver)) .await @@ -314,9 +319,12 @@ impl TransportBuilder for WebSocketTransport { where Self: Sized, { + let ip_dialing_mode = context.ip_dialing_mode; + tracing::debug!( target: LOG_TARGET, listen_addresses = ?config.listen_addresses, + ?ip_dialing_mode, "start websocket transport", ); let (listener, listen_addresses, dial_addresses) = SocketListener::new::( @@ -339,6 +347,7 @@ impl TransportBuilder for WebSocketTransport { pending_raw_connections: FuturesStream::new(), cancel_futures: HashMap::new(), resolver, + ip_dialing_mode, }, listen_addresses, )) @@ -357,6 +366,7 @@ impl Transport for WebSocketTransport { let dial_addresses = self.dial_addresses.clone(); let nodelay = self.config.nodelay; let resolver = self.resolver.clone(); + let ip_dialing_mode = self.ip_dialing_mode; self.pending_dials.insert(connection_id, address.clone()); @@ -369,6 +379,7 @@ impl Transport for WebSocketTransport { connection_open_timeout, nodelay, resolver, + ip_dialing_mode, ) .await .map_err(|error| (connection_id, error))?; @@ -487,6 +498,7 @@ impl Transport for WebSocketTransport { let dial_addresses = self.dial_addresses.clone(); let nodelay = self.config.nodelay; let resolver = self.resolver.clone(); + let ip_dialing_mode = self.ip_dialing_mode; async move { WebSocketTransport::dial_peer( @@ -495,6 +507,7 @@ impl Transport for WebSocketTransport { connection_open_timeout, nodelay, resolver, + ip_dialing_mode, ) .await .map_err(|error| (address, error)) From 4fc194397b9915004bd451ea6f93dde763e296ee Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 15:21:05 +0000 Subject: [PATCH 19/25] Adjust testing Signed-off-by: Alexandru Vasile --- src/config.rs | 2 +- src/lib.rs | 1 + src/protocol/libp2p/identify.rs | 1 + src/protocol/libp2p/kademlia/mod.rs | 4 +- src/protocol/mdns.rs | 6 +- src/protocol/notification/tests/mod.rs | 4 +- src/protocol/request_response/tests.rs | 4 +- src/protocol/transport_service.rs | 6 +- src/transport/common/listener.rs | 27 +++++++-- src/transport/manager/mod.rs | 83 +++++++++++++------------- src/transport/tcp/connection.rs | 8 ++- src/transport/tcp/mod.rs | 7 ++- src/transport/websocket/connection.rs | 7 ++- 13 files changed, 98 insertions(+), 62 deletions(-) diff --git a/src/config.rs b/src/config.rs index b5d6212e2..3dd368bca 100644 --- a/src/config.rs +++ b/src/config.rs @@ -164,7 +164,7 @@ impl ConfigBuilder { known_addresses: Vec::new(), connection_limits: ConnectionLimitsConfig::default(), keep_alive_timeout: KEEP_ALIVE_TIMEOUT, - ip_dialing_mode: IpDialingMode::GlobalOnly, + ip_dialing_mode: IpDialingMode::All, use_system_dns_config: false, } } diff --git a/src/lib.rs b/src/lib.rs index 5fb046bce..6034c4ff6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -643,6 +643,7 @@ mod tests { .with_notification_protocol(config1) .with_notification_protocol(config2) .with_libp2p_ping(ping_config) + .with_ip_dialing_mode(crate::transport::manager::IpDialingMode::All) .build(); let peer = PeerId::random(); diff --git a/src/protocol/libp2p/identify.rs b/src/protocol/libp2p/identify.rs index 0a969fdaf..db9c24510 100644 --- a/src/protocol/libp2p/identify.rs +++ b/src/protocol/libp2p/identify.rs @@ -474,6 +474,7 @@ mod tests { ..Default::default() }) .with_libp2p_identify(identify_config) + .with_ip_dialing_mode(crate::transport::manager::IpDialingMode::All) .build(); (Litep2p::new(config).unwrap(), identify, peer) diff --git a/src/protocol/libp2p/kademlia/mod.rs b/src/protocol/libp2p/kademlia/mod.rs index 237cc1a6c..bc22c8957 100644 --- a/src/protocol/libp2p/kademlia/mod.rs +++ b/src/protocol/libp2p/kademlia/mod.rs @@ -1257,7 +1257,7 @@ mod tests { codec::ProtocolCodec, crypto::ed25519::Keypair, transport::{ - manager::{limits::ConnectionLimitsConfig, TransportManager}, + manager::{limits::ConnectionLimitsConfig, IpDialingMode, TransportManager}, KEEP_ALIVE_TIMEOUT, }, types::protocol::ProtocolName, @@ -1281,7 +1281,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); diff --git a/src/protocol/mdns.rs b/src/protocol/mdns.rs index f76f0e482..1992fc57b 100644 --- a/src/protocol/mdns.rs +++ b/src/protocol/mdns.rs @@ -365,7 +365,7 @@ mod tests { use super::*; use crate::{ crypto::ed25519::Keypair, - transport::manager::{limits::ConnectionLimitsConfig, TransportManager}, + transport::manager::{limits::ConnectionLimitsConfig, IpDialingMode, TransportManager}, BandwidthSink, }; use futures::StreamExt; @@ -384,7 +384,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let mdns1 = Mdns::new( @@ -407,7 +407,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let mdns2 = Mdns::new( diff --git a/src/protocol/notification/tests/mod.rs b/src/protocol/notification/tests/mod.rs index 3ca7ceade..2c02312fb 100644 --- a/src/protocol/notification/tests/mod.rs +++ b/src/protocol/notification/tests/mod.rs @@ -30,7 +30,7 @@ use crate::{ InnerTransportEvent, ProtocolCommand, TransportService, }, transport::{ - manager::{limits::ConnectionLimitsConfig, TransportManager}, + manager::{limits::ConnectionLimitsConfig, IpDialingMode, TransportManager}, KEEP_ALIVE_TIMEOUT, }, types::protocol::ProtocolName, @@ -57,7 +57,7 @@ fn make_notification_protocol() -> ( BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); diff --git a/src/protocol/request_response/tests.rs b/src/protocol/request_response/tests.rs index d67fbcaf6..00956ebb3 100644 --- a/src/protocol/request_response/tests.rs +++ b/src/protocol/request_response/tests.rs @@ -30,7 +30,7 @@ use crate::{ }, substream::Substream, transport::{ - manager::{limits::ConnectionLimitsConfig, TransportManager}, + manager::{limits::ConnectionLimitsConfig, IpDialingMode, TransportManager}, KEEP_ALIVE_TIMEOUT, }, types::{RequestId, SubstreamId}, @@ -55,7 +55,7 @@ fn protocol() -> ( BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); diff --git a/src/protocol/transport_service.rs b/src/protocol/transport_service.rs index 498603f7e..e648bd76b 100644 --- a/src/protocol/transport_service.rs +++ b/src/protocol/transport_service.rs @@ -638,7 +638,9 @@ mod tests { use crate::{ protocol::{ProtocolCommand, TransportService}, transport::{ - manager::{handle::InnerTransportManagerCommand, TransportManagerHandle}, + manager::{ + handle::InnerTransportManagerCommand, IpDialingMode, TransportManagerHandle, + }, KEEP_ALIVE_TIMEOUT, }, }; @@ -662,7 +664,7 @@ mod tests { HashSet::new(), Default::default(), PublicAddresses::new(peer), - true, + IpDialingMode::All, ); let (service, sender) = TransportService::new( diff --git a/src/transport/common/listener.rs b/src/transport/common/listener.rs index d8b9fbced..ada323ad2 100644 --- a/src/transport/common/listener.rs +++ b/src/transport/common/listener.rs @@ -516,11 +516,13 @@ mod tests { fn parse_multiaddresses_tcp() { assert!(multiaddr_to_socket_address( &"/ip6/::1/tcp/8888".parse().expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_ok()); assert!(multiaddr_to_socket_address( &"/ip4/127.0.0.1/tcp/8888".parse().expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_ok()); @@ -528,6 +530,7 @@ mod tests { &"/ip6/::1/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_ok()); @@ -535,6 +538,7 @@ mod tests { &"/ip4/127.0.0.1/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_ok()); @@ -542,6 +546,7 @@ mod tests { &"/ip6/::1/udp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_err()); @@ -549,6 +554,7 @@ mod tests { &"/ip4/127.0.0.1/udp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::Tcp, ) .is_err()); @@ -559,11 +565,13 @@ mod tests { fn parse_multiaddresses_websocket() { assert!(multiaddr_to_socket_address( &"/ip6/::1/tcp/8888/ws".parse().expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_ok()); assert!(multiaddr_to_socket_address( &"/ip4/127.0.0.1/tcp/8888/ws".parse().expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_ok()); @@ -571,6 +579,7 @@ mod tests { &"/ip6/::1/tcp/8888/ws/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_ok()); @@ -578,6 +587,7 @@ mod tests { &"/ip4/127.0.0.1/tcp/8888/ws/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_ok()); @@ -585,6 +595,7 @@ mod tests { &"/ip6/::1/udp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); @@ -592,11 +603,13 @@ mod tests { &"/ip4/127.0.0.1/udp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); assert!(multiaddr_to_socket_address( &"/ip4/127.0.0.1/tcp/8888/ws/utp".parse().expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); @@ -604,6 +617,7 @@ mod tests { &"/ip6/::1/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); @@ -611,6 +625,7 @@ mod tests { &"/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); @@ -618,28 +633,32 @@ mod tests { &"/dns/hello.world/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), + IpDialingMode::All, SocketListenerType::WebSocket, ) .is_err()); assert!(multiaddr_to_socket_address( &"/dns6/hello.world/tcp/8888/ws/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() - .expect("valid multiaddress") - ,SocketListenerType::WebSocket, + .expect("valid multiaddress"), + IpDialingMode::All, + SocketListenerType::WebSocket, ) .is_ok()); assert!(multiaddr_to_socket_address( &"/dns4/hello.world/tcp/8888/ws/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), - SocketListenerType::WebSocket, + IpDialingMode::All, + SocketListenerType::WebSocket, ) .is_ok()); assert!(multiaddr_to_socket_address( &"/dns6/hello.world/tcp/8888/ws/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" .parse() .expect("valid multiaddress"), - SocketListenerType::WebSocket, + IpDialingMode::All, + SocketListenerType::WebSocket, ) .is_ok()); } diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 284cb413f..ee111bd09 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -1428,6 +1428,7 @@ impl TransportManager { mod tests { use crate::transport::manager::{address::AddressStore, peer_state::SecondaryOrDialing}; use limits::ConnectionLimitsConfig; + use IpDialingMode; use multihash::Multihash; @@ -1620,7 +1621,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_protocol( @@ -1648,7 +1649,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_protocol( @@ -1679,7 +1680,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_protocol( @@ -1713,7 +1714,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1731,7 +1732,7 @@ mod tests { sink, 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); assert!(manager.dial(local_peer_id).await.is_err()); @@ -1745,7 +1746,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1776,7 +1777,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -1839,7 +1840,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1871,7 +1872,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1917,7 +1918,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1937,7 +1938,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -1971,7 +1972,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); // ipv6 @@ -2034,7 +2035,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2102,7 +2103,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2190,7 +2191,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let _handle = manager.transport_handle(Arc::new(DefaultExecutor {})); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2276,7 +2277,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2386,7 +2387,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2483,7 +2484,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2593,7 +2594,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2698,7 +2699,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -2843,7 +2844,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.on_dial_failure(ConnectionId::random()).unwrap(); @@ -2863,7 +2864,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.on_connection_closed(PeerId::random(), ConnectionId::random()).unwrap(); } @@ -2882,7 +2883,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager .on_connection_opened( @@ -2907,7 +2908,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -2932,7 +2933,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -2960,7 +2961,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager @@ -2982,7 +2983,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let connection_id = ConnectionId::random(); let peer = PeerId::random(); @@ -3003,7 +3004,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); assert!(manager.next().await.is_none()); @@ -3017,7 +3018,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = { @@ -3066,7 +3067,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = { @@ -3130,7 +3131,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = { @@ -3174,7 +3175,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); // transport doesn't start with ip/dns @@ -3241,7 +3242,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); async fn call_manager(manager: &mut TransportManager, address: Multiaddr) { @@ -3296,7 +3297,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3383,7 +3384,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3474,7 +3475,7 @@ mod tests { ConnectionLimitsConfig::default() .max_incoming_connections(Some(3)) .max_outgoing_connections(Some(2)), - true, + IpDialingMode::All, ); // The connection limit is agnostic of the underlying transports. manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3551,7 +3552,7 @@ mod tests { ConnectionLimitsConfig::default() .max_incoming_connections(Some(3)) .max_outgoing_connections(Some(2)), - true, + IpDialingMode::All, ); // The connection limit is agnostic of the underlying transports. manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3639,7 +3640,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3693,7 +3694,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); manager.register_transport(SupportedTransport::Tcp, Box::new(DummyTransport::new())); @@ -3846,7 +3847,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); let dial_address = Multiaddr::empty() @@ -3933,7 +3934,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let peer = PeerId::random(); let connection_id = ConnectionId::from(0); diff --git a/src/transport/tcp/connection.rs b/src/transport/tcp/connection.rs index 60492af91..200873b78 100644 --- a/src/transport/tcp/connection.rs +++ b/src/transport/tcp/connection.rs @@ -750,7 +750,7 @@ impl TcpConnection { #[cfg(test)] mod tests { - use crate::transport::tcp::TcpTransport; + use crate::transport::{manager::IpDialingMode, tcp::TcpTransport}; use super::*; use hickory_resolver::{name_server::TokioConnectionProvider, TokioResolver}; @@ -784,6 +784,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); @@ -886,6 +887,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); @@ -1035,6 +1037,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); @@ -1088,6 +1091,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); @@ -1268,6 +1272,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); @@ -1403,6 +1408,7 @@ mod tests { ) .build(), ), + IpDialingMode::All, ) .await .unwrap(); diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index 1a4ead49a..bca1ac270 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -719,7 +719,8 @@ mod tests { crypto::ed25519::Keypair, executor::DefaultExecutor, transport::manager::{ - limits::ConnectionLimitsConfig, ProtocolContext, SupportedTransport, TransportManager, + limits::ConnectionLimitsConfig, IpDialingMode, ProtocolContext, SupportedTransport, + TransportManager, }, types::protocol::ProtocolName, BandwidthSink, PeerId, @@ -778,7 +779,6 @@ mod tests { keypair: keypair2.clone(), tx: event_tx2, bandwidth_sink: bandwidth_sink.clone(), - protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), ProtocolContext { @@ -787,6 +787,7 @@ mod tests { fallback_names: Vec::new(), }, )]), + ip_dialing_mode: IpDialingMode::All, }; let transport_config2 = Config { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], @@ -1018,7 +1019,7 @@ mod tests { BandwidthSink::new(), 8usize, ConnectionLimitsConfig::default(), - true, + IpDialingMode::All, ); let handle = manager.transport_handle(Arc::new(DefaultExecutor {})); let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); diff --git a/src/transport/websocket/connection.rs b/src/transport/websocket/connection.rs index dcfe60e0d..3b0b60668 100644 --- a/src/transport/websocket/connection.rs +++ b/src/transport/websocket/connection.rs @@ -602,7 +602,7 @@ impl WebSocketConnection { #[cfg(test)] mod tests { - use crate::transport::websocket::WebSocketTransport; + use crate::transport::{manager::IpDialingMode, websocket::WebSocketTransport}; use super::*; use futures::AsyncWriteExt; @@ -642,6 +642,7 @@ mod tests { Duration::from_secs(10), false, Arc::new(TokioResolver::builder_tokio().unwrap().build()), + IpDialingMode::All, ) .await .unwrap(); @@ -758,6 +759,7 @@ mod tests { Duration::from_secs(10), false, Arc::new(TokioResolver::builder_tokio().unwrap().build()), + IpDialingMode::All, ) .await .unwrap(); @@ -1030,6 +1032,7 @@ mod tests { Duration::from_secs(10), false, Arc::new(TokioResolver::builder_tokio().unwrap().build()), + IpDialingMode::All, ) .await .unwrap(); @@ -1198,6 +1201,7 @@ mod tests { Duration::from_secs(10), false, Arc::new(TokioResolver::builder_tokio().unwrap().build()), + IpDialingMode::All, ) .await .unwrap(); @@ -1352,6 +1356,7 @@ mod tests { Duration::from_secs(10), false, Arc::new(TokioResolver::builder_tokio().unwrap().build()), + IpDialingMode::All, ) .await .unwrap(); From ed3921ec31d6ffad0861e092fe10db13a7a0cf23 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Tue, 21 Oct 2025 15:37:32 +0000 Subject: [PATCH 20/25] manager/handle: Remove unneeded check Signed-off-by: Alexandru Vasile --- src/protocol/transport_service.rs | 5 +---- src/transport/manager/handle.rs | 28 ---------------------------- src/transport/manager/mod.rs | 1 - 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/protocol/transport_service.rs b/src/protocol/transport_service.rs index e648bd76b..b729e9312 100644 --- a/src/protocol/transport_service.rs +++ b/src/protocol/transport_service.rs @@ -638,9 +638,7 @@ mod tests { use crate::{ protocol::{ProtocolCommand, TransportService}, transport::{ - manager::{ - handle::InnerTransportManagerCommand, IpDialingMode, TransportManagerHandle, - }, + manager::{handle::InnerTransportManagerCommand, TransportManagerHandle}, KEEP_ALIVE_TIMEOUT, }, }; @@ -664,7 +662,6 @@ mod tests { HashSet::new(), Default::default(), PublicAddresses::new(peer), - IpDialingMode::All, ); let (service, sender) = TransportService::new( diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index 2e0c86ae4..3872b660e 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -87,9 +87,6 @@ pub struct TransportManagerHandle { /// Public addresses. public_addresses: PublicAddresses, - - /// IP dialing mode. - ip_dialing_mode: IpDialingMode, } impl TransportManagerHandle { @@ -101,11 +98,9 @@ impl TransportManagerHandle { supported_transport: HashSet, listen_addresses: Arc>>, public_addresses: PublicAddresses, - ip_dialing_mode: IpDialingMode, ) -> Self { tracing::debug!( target: LOG_TARGET, - ?ip_dialing_mode, "Transport manager handle created", ); @@ -116,7 +111,6 @@ impl TransportManagerHandle { supported_transport, listen_addresses, public_addresses, - ip_dialing_mode, } } @@ -278,17 +272,6 @@ impl TransportManagerHandle { if address_store.is_empty() { return Err(ImmediateDialError::NoAddressAvailable); } - - // Check if we can dial at least one address from the store in the current operating - // mode. If the mode is `IpDialingMode::All`, this will always return - // `true` on the first address. - let has_dialable_address = address_store - .addresses - .iter() - .any(|(address, _record)| self.ip_dialing_mode.allows_address(address)); - if !has_dialable_address { - return Err(ImmediateDialError::NoAddressAvailable); - } } self.cmd_tx @@ -307,15 +290,6 @@ impl TransportManagerHandle { return Err(ImmediateDialError::PeerIdMissing); } - if !self.ip_dialing_mode.allows_address(&address) { - tracing::debug!( - target: LOG_TARGET, - ?address, - "Dialing address is not global, skipping", - ); - return Err(ImmediateDialError::NoAddressAvailable); - } - self.cmd_tx .try_send(InnerTransportManagerCommand::DialAddress { address }) .map_err(|error| match error { @@ -404,7 +378,6 @@ mod tests { supported_transport: HashSet::new(), listen_addresses: Default::default(), public_addresses: PublicAddresses::new(local_peer_id), - ip_dialing_mode: IpDialingMode::default(), }, cmd_rx, ) @@ -797,7 +770,6 @@ mod tests { supported_transport: HashSet::new(), listen_addresses, public_addresses: PublicAddresses::new(local_peer_id), - ip_dialing_mode: IpDialingMode::default(), }; // local addresses diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index ee111bd09..307188662 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -337,7 +337,6 @@ impl TransportManager { supported_transports, listen_addresses.clone(), public_addresses.clone(), - ip_dialing_mode, ); tracing::debug!( From 0b45790c9db6b2a2adfc3d9f6446e9706729fc5d Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Oct 2025 10:38:25 +0000 Subject: [PATCH 21/25] tests/quic: Add ip dialing mode Signed-off-by: Alexandru Vasile --- src/transport/quic/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/transport/quic/mod.rs b/src/transport/quic/mod.rs index 2c1536317..219acf731 100644 --- a/src/transport/quic/mod.rs +++ b/src/transport/quic/mod.rs @@ -589,7 +589,7 @@ mod tests { codec::ProtocolCodec, crypto::ed25519::Keypair, executor::DefaultExecutor, - transport::manager::{ProtocolContext, TransportHandle}, + transport::manager::{IpDialingMode::All, ProtocolContext, TransportHandle}, types::protocol::ProtocolName, BandwidthSink, }; @@ -613,6 +613,7 @@ mod tests { keypair: keypair1.clone(), tx: event_tx1, bandwidth_sink: BandwidthSink::new(), + ip_dialing_mode: IpDialingMode::All, protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), @@ -640,6 +641,7 @@ mod tests { keypair: keypair2.clone(), tx: event_tx2, bandwidth_sink: BandwidthSink::new(), + ip_dialing_mode: IpDialingMode::All, protocols: HashMap::from_iter([( ProtocolName::from("/notif/1"), From c314ece53159353992c5be07b8f18682493c8bc4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Oct 2025 11:06:24 +0000 Subject: [PATCH 22/25] tests/quic: Import IpDialingMode Signed-off-by: Alexandru Vasile --- src/transport/quic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport/quic/mod.rs b/src/transport/quic/mod.rs index 219acf731..9f7774784 100644 --- a/src/transport/quic/mod.rs +++ b/src/transport/quic/mod.rs @@ -589,7 +589,7 @@ mod tests { codec::ProtocolCodec, crypto::ed25519::Keypair, executor::DefaultExecutor, - transport::manager::{IpDialingMode::All, ProtocolContext, TransportHandle}, + transport::manager::{IpDialingMode, ProtocolContext, TransportHandle}, types::protocol::ProtocolName, BandwidthSink, }; From 6e0c23581e14d8e230c99ed8be0cbfd95b4e7f59 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Oct 2025 15:09:58 +0000 Subject: [PATCH 23/25] tcp/tests: Add test to ensure we are allowed to dial global IPs Signed-off-by: Alexandru Vasile --- src/transport/tcp/mod.rs | 61 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index bca1ac270..27597ca60 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -727,9 +727,68 @@ mod tests { }; use multiaddr::Protocol; use multihash::Multihash; - use std::{collections::HashSet, sync::Arc}; + use std::{collections::HashSet, str::FromStr, sync::Arc}; use tokio::sync::mpsc::channel; + #[tokio::test] + async fn deny_private_ip_dials() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let keypair1 = Keypair::generate(); + let (tx1, _rx1) = channel(64); + let (event_tx1, _event_rx1) = channel(64); + let bandwidth_sink = BandwidthSink::new(); + + let handle = crate::transport::manager::TransportHandle { + executor: Arc::new(DefaultExecutor {}), + next_substream_id: Default::default(), + next_connection_id: Default::default(), + keypair: keypair1.clone(), + tx: event_tx1, + bandwidth_sink: bandwidth_sink.clone(), + protocols: HashMap::from_iter([( + ProtocolName::from("/notif/1"), + ProtocolContext { + tx: tx1, + codec: ProtocolCodec::Identity(32), + fallback_names: Vec::new(), + }, + )]), + ip_dialing_mode: IpDialingMode::GlobalOnly, + }; + + let transport_config1 = Config { + listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], + ..Default::default() + }; + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + + let (mut transport, listen_addresses) = + TcpTransport::new(handle, transport_config1, resolver.clone()).unwrap(); + let listen_address = listen_addresses[0].clone(); + + // Dialing local addresses is unsupported. + transport.dial(ConnectionId::new(), listen_address).unwrap_err(); + + // DNS with private IP is unsupported. + transport + .dial( + ConnectionId::new(), + Multiaddr::from_str("/dns/127.0.0.1/tcp/30333").unwrap(), + ) + .unwrap_err(); + + // Public DNS is allowed. + transport + .dial( + ConnectionId::new(), + Multiaddr::from_str("/dns/polkadot-bootnode-0.polkadot.io/tcp/30333/p2p/12D3KooWSz8r2WyCdsfWHgPyvD8GKQdJ1UAiRmrcrs8sQB3fe2KU").unwrap(), + ) + .unwrap(); + } + #[tokio::test] async fn connect_and_accept_works() { let _ = tracing_subscriber::fmt() From 25eb211dc3447220d40a18d5c62373f6dae27144 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Oct 2025 15:10:31 +0000 Subject: [PATCH 24/25] listener: Downgrade log to debug Signed-off-by: Alexandru Vasile --- src/transport/common/listener.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transport/common/listener.rs b/src/transport/common/listener.rs index ada323ad2..ecb159da4 100644 --- a/src/transport/common/listener.rs +++ b/src/transport/common/listener.rs @@ -374,7 +374,7 @@ fn multiaddr_to_socket_address( tracing::trace!(target: LOG_TARGET, ?address, "parse multi address"); if !ip_dialing_mode.allows_address(address) { - tracing::error!( + tracing::debug!( target: LOG_TARGET, ?address, ?ip_dialing_mode, From dacc8d98838cd26aad946c8d9a49036fad5131e1 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 27 Oct 2025 16:08:30 +0000 Subject: [PATCH 25/25] transport: Public export for IpDialingMode Signed-off-by: Alexandru Vasile --- src/transport/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/transport/mod.rs b/src/transport/mod.rs index 79c582c03..45e788a49 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -42,7 +42,10 @@ pub(crate) mod dummy; pub(crate) mod manager; -pub use manager::limits::{ConnectionLimitsConfig, ConnectionLimitsError}; +pub use manager::{ + limits::{ConnectionLimitsConfig, ConnectionLimitsError}, + IpDialingMode, +}; /// Timeout for opening a connection. pub(crate) const CONNECTION_OPEN_TIMEOUT: Duration = Duration::from_secs(10);