From 7392838b6ada21f1d3d4d8dca1ba8e90faa755ce Mon Sep 17 00:00:00 2001 From: conectado Date: Mon, 18 Mar 2024 16:26:17 -0300 Subject: [PATCH 1/3] fix(connlib): exclude sentinel dns range for resources ips --- rust/connlib/shared/src/lib.rs | 19 ++++++++++++++++--- rust/connlib/tunnel/src/client.rs | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/rust/connlib/shared/src/lib.rs b/rust/connlib/shared/src/lib.rs index 653ce869132..94810ede182 100644 --- a/rust/connlib/shared/src/lib.rs +++ b/rust/connlib/shared/src/lib.rs @@ -25,6 +25,7 @@ pub use callbacks::{Callbacks, Cidrv4, Cidrv6}; pub use callbacks_error_facade::CallbackErrorFacade; pub use error::ConnlibError as Error; pub use error::Result; +use ip_network::IpNetwork; pub use phoenix_channel::{LoginUrl, LoginUrlError}; use ip_network::Ipv4Network; @@ -67,10 +68,22 @@ pub struct IpProvider { } impl IpProvider { - pub fn new(ipv4: Ipv4Network, ipv6: Ipv6Network) -> Self { + pub fn new( + ipv4: Ipv4Network, + ipv6: Ipv6Network, + exclusion_v4: Option, + exclusion_v6: Option, + ) -> Self { Self { - ipv4: Box::new(ipv4.hosts()), - ipv6: Box::new(ipv6.subnets_with_prefix(128).map(|ip| ip.network_address())), + ipv4: Box::new( + ipv4.hosts() + .filter(move |ip| !exclusion_v4.is_some_and(|e| e.contains(*ip))), + ), + ipv6: Box::new( + ipv6.subnets_with_prefix(128) + .map(|ip| ip.network_address()) + .filter(move |ip| !exclusion_v6.is_some_and(|e| e.contains(*ip))), + ), } } diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index 0b5f48eaffd..efa33004903 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -511,6 +511,8 @@ impl ClientState { ip_provider: IpProvider::new( IPV4_RESOURCES.parse().unwrap(), IPV6_RESOURCES.parse().unwrap(), + Some(DNS_SENTINELS_V4.parse().unwrap()), + Some(DNS_SENTINELS_V6.parse().unwrap()), ), dns_resources_internal_ips: Default::default(), dns_resources: Default::default(), @@ -969,6 +971,8 @@ fn sentinel_dns_mapping(dns: &[DnsServer]) -> BiMap { let mut ip_provider = IpProvider::new( DNS_SENTINELS_V4.parse().unwrap(), DNS_SENTINELS_V6.parse().unwrap(), + None, + None, ); dns.iter() From a69c334b19f6ba13731a6b30eca758dc488ab441 Mon Sep 17 00:00:00 2001 From: conectado Date: Mon, 18 Mar 2024 16:52:32 -0300 Subject: [PATCH 2/3] remove unused import --- rust/connlib/shared/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/connlib/shared/src/lib.rs b/rust/connlib/shared/src/lib.rs index 94810ede182..314c992a391 100644 --- a/rust/connlib/shared/src/lib.rs +++ b/rust/connlib/shared/src/lib.rs @@ -25,7 +25,6 @@ pub use callbacks::{Callbacks, Cidrv4, Cidrv6}; pub use callbacks_error_facade::CallbackErrorFacade; pub use error::ConnlibError as Error; pub use error::Result; -use ip_network::IpNetwork; pub use phoenix_channel::{LoginUrl, LoginUrlError}; use ip_network::Ipv4Network; From 61aafc76b09e40ea82127176e0b0625f3fbcf2ae Mon Sep 17 00:00:00 2001 From: conectado Date: Mon, 18 Mar 2024 19:47:44 -0300 Subject: [PATCH 3/3] chore(connlib): move IpProvider to tunnel --- rust/connlib/shared/src/lib.rs | 46 ------------------------------- rust/connlib/tunnel/src/client.rs | 45 ++++++++++++++++++++++++++++-- rust/connlib/tunnel/src/peer.rs | 2 +- 3 files changed, 44 insertions(+), 49 deletions(-) diff --git a/rust/connlib/shared/src/lib.rs b/rust/connlib/shared/src/lib.rs index 314c992a391..37ec6fbf642 100644 --- a/rust/connlib/shared/src/lib.rs +++ b/rust/connlib/shared/src/lib.rs @@ -27,12 +27,7 @@ pub use error::ConnlibError as Error; pub use error::Result; pub use phoenix_channel::{LoginUrl, LoginUrlError}; -use ip_network::Ipv4Network; -use ip_network::Ipv6Network; use rand_core::OsRng; -use std::net::IpAddr; -use std::net::Ipv4Addr; -use std::net::Ipv6Addr; pub type Dname = domain::base::Dname>; @@ -61,47 +56,6 @@ pub fn keypair() -> (StaticSecret, PublicKey) { (private_key, public_key) } -pub struct IpProvider { - ipv4: Box + Send + Sync>, - ipv6: Box + Send + Sync>, -} - -impl IpProvider { - pub fn new( - ipv4: Ipv4Network, - ipv6: Ipv6Network, - exclusion_v4: Option, - exclusion_v6: Option, - ) -> Self { - Self { - ipv4: Box::new( - ipv4.hosts() - .filter(move |ip| !exclusion_v4.is_some_and(|e| e.contains(*ip))), - ), - ipv6: Box::new( - ipv6.subnets_with_prefix(128) - .map(|ip| ip.network_address()) - .filter(move |ip| !exclusion_v6.is_some_and(|e| e.contains(*ip))), - ), - } - } - - pub fn get_proxy_ip_for(&mut self, ip: &IpAddr) -> Option { - let proxy_ip = match ip { - IpAddr::V4(_) => self.ipv4.next().map(Into::into), - IpAddr::V6(_) => self.ipv6.next().map(Into::into), - }; - - if proxy_ip.is_none() { - // TODO: we might want to make the iterator cyclic or another strategy to prevent ip exhaustion - // this might happen in ipv4 if tokens are too long lived. - tracing::error!("IP exhaustion: Please reset your client"); - } - - proxy_ip - } -} - pub fn get_user_agent(os_version_override: Option) -> String { // Note: we could switch to sys-info and get the hostname // but we lose the arch diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index efa33004903..9502c1b059d 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -9,9 +9,9 @@ use connlib_shared::messages::{ IpDnsServer, Key, Offer, Relay, RequestConnection, ResourceDescription, ResourceDescriptionCidr, ResourceDescriptionDns, ResourceId, ReuseConnection, }; -use connlib_shared::{Callbacks, Dname, IpProvider, PublicKey, StaticSecret}; +use connlib_shared::{Callbacks, Dname, PublicKey, StaticSecret}; use domain::base::Rtype; -use ip_network::IpNetwork; +use ip_network::{IpNetwork, Ipv4Network, Ipv6Network}; use ip_network_table::IpNetworkTable; use itertools::Itertools; @@ -1011,6 +1011,47 @@ fn is_definitely_not_a_resource(ip: IpAddr) -> bool { false } +pub struct IpProvider { + ipv4: Box + Send + Sync>, + ipv6: Box + Send + Sync>, +} + +impl IpProvider { + pub fn new( + ipv4: Ipv4Network, + ipv6: Ipv6Network, + exclusion_v4: Option, + exclusion_v6: Option, + ) -> Self { + Self { + ipv4: Box::new( + ipv4.hosts() + .filter(move |ip| !exclusion_v4.is_some_and(|e| e.contains(*ip))), + ), + ipv6: Box::new( + ipv6.subnets_with_prefix(128) + .map(|ip| ip.network_address()) + .filter(move |ip| !exclusion_v6.is_some_and(|e| e.contains(*ip))), + ), + } + } + + pub fn get_proxy_ip_for(&mut self, ip: &IpAddr) -> Option { + let proxy_ip = match ip { + IpAddr::V4(_) => self.ipv4.next().map(Into::into), + IpAddr::V6(_) => self.ipv6.next().map(Into::into), + }; + + if proxy_ip.is_none() { + // TODO: we might want to make the iterator cyclic or another strategy to prevent ip exhaustion + // this might happen in ipv4 if tokens are too long lived. + tracing::error!("IP exhaustion: Please reset your client"); + } + + proxy_ip + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/rust/connlib/tunnel/src/peer.rs b/rust/connlib/tunnel/src/peer.rs index 3fe38d006ca..6f8b03239fa 100644 --- a/rust/connlib/tunnel/src/peer.rs +++ b/rust/connlib/tunnel/src/peer.rs @@ -5,12 +5,12 @@ use std::time::Instant; use bimap::BiMap; use chrono::{DateTime, Utc}; use connlib_shared::messages::{DnsServer, ResourceId}; -use connlib_shared::IpProvider; use connlib_shared::{Error, Result}; use ip_network::IpNetwork; use ip_network_table::IpNetworkTable; use pnet_packet::Packet; +use crate::client::IpProvider; use crate::ip_packet::MutableIpPacket; type ExpiryingResource = (ResourceId, Option>);