diff --git a/rust/Cargo.lock b/rust/Cargo.lock index c531081ab16..e2937a2dfe4 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1618,12 +1618,13 @@ dependencies = [ [[package]] name = "domain" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e853e3f6d4c6e52a4d73a94c1810c66ad71958fbe24934a7119b447f425aed76" +checksum = "5cd50aea158e9a57c9c9075ca7a3dfa4c08d9a468b405832383876f9df85379b" dependencies = [ "bytes", "octseq", + "pin-project-lite", "rand 0.8.5", "serde", "time", @@ -4116,9 +4117,9 @@ dependencies = [ [[package]] name = "octseq" -version = "0.3.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92b38a4aabbacf619b8083841713216e7668178422decfe06bbc70643024c5d" +checksum = "2ed2eaec452d98ccc1c615dd843fd039d9445f2fb4da114ee7e6af5fcb68be98" dependencies = [ "bytes", "serde", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a09b1b7afda..246ae4d8ec4 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -31,7 +31,7 @@ secrecy = "0.8" hickory-resolver = { git = "https://github.com/hickory-dns/hickory-dns", rev="a3669bd80f3f7b97f0c301c15f1cba6368d97b63", features = ["tokio-runtime"] } str0m = { version = "0.5", default-features = false } futures-bounded = "0.2.1" -domain = { version = "0.9", features = ["serde"] } +domain = { version = "0.10", features = ["serde"] } dns-lookup = "2.0" tokio-tungstenite = "0.21" rtnetlink = { version = "0.14.1", default-features = false, features = ["tokio_socket"] } diff --git a/rust/connlib/shared/src/lib.rs b/rust/connlib/shared/src/lib.rs index 9f7130d7bf7..6fbddef5a93 100644 --- a/rust/connlib/shared/src/lib.rs +++ b/rust/connlib/shared/src/lib.rs @@ -31,7 +31,7 @@ pub use phoenix_channel::{LoginUrl, LoginUrlError}; use rand_core::OsRng; -pub type Dname = domain::base::Dname>; +pub type DomainName = domain::base::Name>; /// Bundle ID / App ID that the client uses to distinguish itself from other programs on the system /// diff --git a/rust/connlib/shared/src/messages.rs b/rust/connlib/shared/src/messages.rs index 0d1b725b376..d591a393285 100644 --- a/rust/connlib/shared/src/messages.rs +++ b/rust/connlib/shared/src/messages.rs @@ -13,7 +13,7 @@ mod key; pub use key::{Key, SecretKey}; -use crate::Dname; +use crate::DomainName; #[derive(Hash, Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] pub struct GatewayId(Uuid); @@ -157,7 +157,7 @@ pub struct RequestConnection { #[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] pub struct ClientPayload { pub ice_parameters: Offer, - pub domain: Option, + pub domain: Option, } /// Represent a request to reuse an existing gateway connection from a client to a given resource. @@ -171,7 +171,7 @@ pub struct ReuseConnection { /// Id of the gateway we want to reuse pub gateway_id: GatewayId, /// Payload that the gateway will receive - pub payload: Option, + pub payload: Option, } // Custom implementation of partial eq to ignore client_rtc_sdp @@ -185,7 +185,7 @@ impl Eq for RequestConnection {} #[derive(Debug, Deserialize, Serialize, Clone, Hash, PartialEq, Eq)] pub struct DomainResponse { - pub domain: Dname, + pub domain: DomainName, pub address: Vec, } diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index 0819a03a596..72667826603 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -9,7 +9,7 @@ use connlib_shared::messages::{ Answer, ClientPayload, DnsServer, DomainResponse, GatewayId, Interface as InterfaceConfig, IpDnsServer, Key, Offer, Relay, RelayId, RequestConnection, ResourceId, ReuseConnection, }; -use connlib_shared::{callbacks, Callbacks, Dname, PublicKey, StaticSecret}; +use connlib_shared::{callbacks, Callbacks, DomainName, PublicKey, StaticSecret}; use domain::base::Rtype; use ip_network::{IpNetwork, Ipv4Network, Ipv6Network}; use ip_network_table::IpNetworkTable; @@ -44,11 +44,14 @@ const DNS_REFRESH_INTERVAL: Duration = Duration::from_secs(300); #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DnsResource { pub id: ResourceId, - pub address: Dname, + pub address: DomainName, } impl DnsResource { - pub fn from_description(description: &ResourceDescriptionDns, address: Dname) -> DnsResource { + pub fn from_description( + description: &ResourceDescriptionDns, + address: DomainName, + ) -> DnsResource { DnsResource { id: description.id, address, @@ -297,7 +300,7 @@ pub struct ClientState { #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct AwaitingConnectionDetails { - pub domain: Option, + pub domain: Option, gateways: HashSet, pub last_intent_sent_at: Instant, } @@ -612,7 +615,7 @@ impl ClientState { self.dns_resources_internal_ips .insert(resource_description.clone(), addrs.clone()); - send_dns_answer(self, Rtype::Aaaa, &resource_description, &addrs); + send_dns_answer(self, Rtype::AAAA, &resource_description, &addrs); send_dns_answer(self, Rtype::A, &resource_description, &addrs); Ok(addrs.iter().copied().map(Into::into).collect()) @@ -715,7 +718,7 @@ impl ClientState { fn on_connection_intent_to_resource( &mut self, resource: ResourceId, - domain: Option, + domain: Option, now: Instant, ) { debug_assert!(self.resource_ids.contains_key(&resource)); @@ -771,7 +774,7 @@ impl ClientState { self.dns_mapping.clone() } - fn is_connected_to(&self, resource: ResourceId, domain: &Option) -> bool { + fn is_connected_to(&self, resource: ResourceId, domain: &Option) -> bool { let Some(resource) = self.resource_ids.get(&resource) else { return false; }; @@ -783,7 +786,7 @@ impl ClientState { fn get_resource_ip( &self, resource: &ResourceDescription, - domain: &Option, + domain: &Option, ) -> Vec { match resource { ResourceDescription::Dns(dns_resource) => { diff --git a/rust/connlib/tunnel/src/dns.rs b/rust/connlib/tunnel/src/dns.rs index 9f212fbd164..637ba320831 100644 --- a/rust/connlib/tunnel/src/dns.rs +++ b/rust/connlib/tunnel/src/dns.rs @@ -1,10 +1,10 @@ use crate::client::DnsResource; use connlib_shared::messages::{client::ResourceDescriptionDns, DnsServer}; -use connlib_shared::Dname; -use domain::base::RelativeDname; +use connlib_shared::DomainName; +use domain::base::RelativeName; use domain::base::{ iana::{Class, Rcode, Rtype}, - Message, MessageBuilder, Question, ToDname, + Message, MessageBuilder, Question, ToName, }; use hickory_resolver::lookup::Lookup; use hickory_resolver::proto::error::{ProtoError, ProtoErrorKind}; @@ -151,7 +151,7 @@ pub(crate) fn create_local_answer<'a>( .map(domain::rdata::A::new) .collect(), ), - Rtype::Aaaa => RecordData::Aaaa( + Rtype::AAAA => RecordData::Aaaa( ips.iter() .copied() .filter_map(get_v6) @@ -241,10 +241,10 @@ fn build_response( fn build_dns_with_answer( message: &Message<[u8]>, qname: &N, - resource: &Option>, + resource: &Option>, ) -> Option> where - N: ToDname + ?Sized, + N: ToName + ?Sized, { let msg_buf = Vec::with_capacity(message.as_slice().len() * 2); let msg_builder = MessageBuilder::from_target(msg_buf).expect( @@ -254,13 +254,13 @@ where let Some(resource) = resource else { return Some( msg_builder - .start_answer(message, Rcode::NXDomain) + .start_answer(message, Rcode::NXDOMAIN) .ok()? .finish(), ); }; - let mut answer_builder = msg_builder.start_answer(message, Rcode::NoError).ok()?; + let mut answer_builder = msg_builder.start_answer(message, Rcode::NOERROR).ok()?; answer_builder.header_mut().set_ra(true); // W/O object-safety there's no other way to access the inner type @@ -269,11 +269,11 @@ where match resource { RecordData::A(r) => r .iter() - .try_for_each(|r| answer_builder.push((qname, Class::In, DNS_TTL, r))), + .try_for_each(|r| answer_builder.push((qname, Class::IN, DNS_TTL, r))), RecordData::Aaaa(r) => r .iter() - .try_for_each(|r| answer_builder.push((qname, Class::In, DNS_TTL, r))), - RecordData::Ptr(r) => answer_builder.push((qname, Class::In, DNS_TTL, r)), + .try_for_each(|r| answer_builder.push((qname, Class::IN, DNS_TTL, r))), + RecordData::Ptr(r) => answer_builder.push((qname, Class::IN, DNS_TTL, r)), } .ok()?; @@ -294,9 +294,9 @@ enum RecordData { Ptr(domain::rdata::Ptr), } -pub fn is_subdomain(name: &Dname, resource: &str) -> bool { - let question_mark = RelativeDname::>::from_octets(b"\x01?".as_ref().into()).unwrap(); - let Ok(resource) = Dname::vec_from_str(resource) else { +pub fn is_subdomain(name: &DomainName, resource: &str) -> bool { + let question_mark = RelativeName::>::from_octets(b"\x01?".as_ref().into()).unwrap(); + let Ok(resource) = DomainName::vec_from_str(resource) else { return false; }; @@ -306,7 +306,7 @@ pub fn is_subdomain(name: &Dname, resource: &str) -> bool { .is_some_and(|r| r == name || name.parent().is_some_and(|n| r == n)); } - if resource.starts_with(&RelativeDname::wildcard_vec()) { + if resource.starts_with(&RelativeName::wildcard_vec()) { let Some(resource) = resource.parent() else { return false; }; @@ -317,7 +317,7 @@ pub fn is_subdomain(name: &Dname, resource: &str) -> bool { } fn get_description( - name: &Dname, + name: &DomainName, dns_resources: &HashMap, ) -> Option { if let Some(resource) = dns_resources.get(&name.to_string()) { @@ -325,12 +325,10 @@ fn get_description( } if let Some(resource) = dns_resources.get( - &RelativeDname::>::from_octets(b"\x01?".as_ref().into()) + &RelativeName::>::from_octets(b"\x01?".as_ref().into()) .ok()? .chain(name) .ok()? - .to_dname::>() - .ok()? .to_string(), ) { return Some(resource.clone()); @@ -338,12 +336,10 @@ fn get_description( if let Some(parent) = name.parent() { if let Some(resource) = dns_resources.get( - &RelativeDname::>::from_octets(b"\x01?".as_ref().into()) + &RelativeName::>::from_octets(b"\x01?".as_ref().into()) .ok()? .chain(parent) .ok()? - .to_dname::>() - .ok()? .to_string(), ) { return Some(resource.clone()); @@ -352,14 +348,7 @@ fn get_description( name.iter_suffixes().find_map(|n| { dns_resources - .get( - &RelativeDname::wildcard_vec() - .chain(n) - .ok()? - .to_dname::>() - .ok()? - .to_string(), - ) + .get(&RelativeName::wildcard_vec().chain(n).ok()?.to_string()) .cloned() }) } @@ -372,12 +361,12 @@ fn get_description( /// upstream (or system default) resolver. /// If we are connected to the Resource, the Client should reply immediately with the IP address(es) of the Resource. /// If we are not connected yet, the Client should defer the response and begin connecting. -fn resource_from_question( +fn resource_from_question( dns_resources: &HashMap, dns_resources_internal_ips: &HashMap>, question: &Question, -) -> Option, DnsQueryParams, DnsResource>> { - let name = ToDname::to_vec(question.qname()); +) -> Option, DnsQueryParams, DnsResource>> { + let name = ToName::to_vec(question.qname()); let qtype = question.qtype(); #[allow(clippy::wildcard_enum_match_arm)] @@ -399,7 +388,7 @@ fn resource_from_question( .collect(), ))) } - Rtype::Aaaa => { + Rtype::AAAA => { let Some(description) = get_description(&name, dns_resources) else { return Some(ResolveStrategy::forward(name.to_string(), qtype)); }; @@ -416,7 +405,7 @@ fn resource_from_question( .collect(), ))) } - Rtype::Ptr => { + Rtype::PTR => { let Some(ip) = reverse_dns_addr(&name.to_string()) else { return Some(ResolveStrategy::forward(name.to_string(), qtype)); }; @@ -494,7 +483,7 @@ fn get_v6(ip: IpAddr) -> Option { #[cfg(test)] mod test { - use connlib_shared::{messages::client::ResourceDescriptionDns, Dname}; + use connlib_shared::{messages::client::ResourceDescriptionDns, DomainName}; use crate::dns::is_subdomain; @@ -611,7 +600,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("a.foo.com").unwrap(), + &DomainName::vec_from_str("a.foo.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -620,7 +609,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -629,7 +618,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("a.b.foo.com").unwrap(), + &DomainName::vec_from_str("a.b.foo.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -637,7 +626,7 @@ mod test { ); assert!(get_description( - &Dname::vec_from_str("oo.com").unwrap(), + &DomainName::vec_from_str("oo.com").unwrap(), &dns_resources_fixture, ) .is_none(),); @@ -649,7 +638,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("a.bar.com").unwrap(), + &DomainName::vec_from_str("a.bar.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -658,7 +647,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("bar.com").unwrap(), + &DomainName::vec_from_str("bar.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -666,7 +655,7 @@ mod test { ); assert!(get_description( - &Dname::vec_from_str("a.b.bar.com").unwrap(), + &DomainName::vec_from_str("a.b.bar.com").unwrap(), &dns_resources_fixture, ) .is_none(),); @@ -678,7 +667,7 @@ mod test { assert_eq!( get_description( - &Dname::vec_from_str("baz.com").unwrap(), + &DomainName::vec_from_str("baz.com").unwrap(), &dns_resources_fixture, ) .unwrap(), @@ -686,13 +675,13 @@ mod test { ); assert!(get_description( - &Dname::vec_from_str("a.baz.com").unwrap(), + &DomainName::vec_from_str("a.baz.com").unwrap(), &dns_resources_fixture, ) .is_none()); assert!(get_description( - &Dname::vec_from_str("a.b.baz.com").unwrap(), + &DomainName::vec_from_str("a.b.baz.com").unwrap(), &dns_resources_fixture, ) .is_none(),); @@ -701,22 +690,22 @@ mod test { #[test] fn exact_subdomain_match() { assert!(is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("a.foo.com").unwrap(), + &DomainName::vec_from_str("a.foo.com").unwrap(), "foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("a.b.foo.com").unwrap(), + &DomainName::vec_from_str("a.b.foo.com").unwrap(), "foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "a.foo.com" )); } @@ -724,47 +713,47 @@ mod test { #[test] fn wildcard_subdomain_match() { assert!(is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "*.foo.com" )); assert!(is_subdomain( - &Dname::vec_from_str("a.foo.com").unwrap(), + &DomainName::vec_from_str("a.foo.com").unwrap(), "*.foo.com" )); assert!(is_subdomain( - &Dname::vec_from_str("a.foo.com").unwrap(), + &DomainName::vec_from_str("a.foo.com").unwrap(), "*.a.foo.com" )); assert!(is_subdomain( - &Dname::vec_from_str("b.a.foo.com").unwrap(), + &DomainName::vec_from_str("b.a.foo.com").unwrap(), "*.a.foo.com" )); assert!(is_subdomain( - &Dname::vec_from_str("a.b.foo.com").unwrap(), + &DomainName::vec_from_str("a.b.foo.com").unwrap(), "*.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("afoo.com").unwrap(), + &DomainName::vec_from_str("afoo.com").unwrap(), "*.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("b.afoo.com").unwrap(), + &DomainName::vec_from_str("b.afoo.com").unwrap(), "*.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("bar.com").unwrap(), + &DomainName::vec_from_str("bar.com").unwrap(), "*.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "*.a.foo.com" )); } @@ -772,32 +761,32 @@ mod test { #[test] fn question_mark_subdomain_match() { assert!(is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "?.foo.com" )); assert!(is_subdomain( - &Dname::vec_from_str("a.foo.com").unwrap(), + &DomainName::vec_from_str("a.foo.com").unwrap(), "?.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("a.b.foo.com").unwrap(), + &DomainName::vec_from_str("a.b.foo.com").unwrap(), "?.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("bar.com").unwrap(), + &DomainName::vec_from_str("bar.com").unwrap(), "?.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("foo.com").unwrap(), + &DomainName::vec_from_str("foo.com").unwrap(), "?.a.foo.com" )); assert!(!is_subdomain( - &Dname::vec_from_str("afoo.com").unwrap(), + &DomainName::vec_from_str("afoo.com").unwrap(), "?.foo.com" )); } diff --git a/rust/connlib/tunnel/src/gateway.rs b/rust/connlib/tunnel/src/gateway.rs index 8c9a5cb06eb..b85feba9493 100644 --- a/rust/connlib/tunnel/src/gateway.rs +++ b/rust/connlib/tunnel/src/gateway.rs @@ -9,7 +9,7 @@ use connlib_shared::messages::{ Answer, ClientId, ConnectionAccepted, DomainResponse, Interface as InterfaceConfig, Key, Offer, Relay, RelayId, ResourceId, }; -use connlib_shared::{Callbacks, Dname, Error, Result, StaticSecret}; +use connlib_shared::{Callbacks, DomainName, Error, Result, StaticSecret}; use ip_network::IpNetwork; use ip_packet::{IpPacket, MutableIpPacket}; use secrecy::{ExposeSecret as _, Secret}; @@ -56,7 +56,7 @@ where client: PublicKey, ips: Vec, relays: Vec, - domain: Option, + domain: Option, expires_at: Option>, resource: ResourceDescription, ) -> Result { @@ -119,7 +119,7 @@ where resource: ResourceDescription, client: ClientId, expires_at: Option>, - domain: Option, + domain: Option, ) -> Option { match (&domain, &resource) { (Some(domain), ResourceDescription::Dns(r)) => { diff --git a/rust/gateway/src/eventloop.rs b/rust/gateway/src/eventloop.rs index edb86d0e524..4e5f1468481 100644 --- a/rust/gateway/src/eventloop.rs +++ b/rust/gateway/src/eventloop.rs @@ -8,7 +8,7 @@ use boringtun::x25519::PublicKey; use connlib_shared::messages::RelaysPresence; use connlib_shared::{ messages::{GatewayResponse, ResourceAccepted}, - Dname, + DomainName, }; #[cfg(not(target_os = "windows"))] use dns_lookup::{AddrInfoHints, AddrInfoIter, LookupError}; @@ -278,7 +278,7 @@ impl Eventloop { } } -async fn resolve(domain: Option) -> Vec { +async fn resolve(domain: Option) -> Vec { let Some(domain) = domain.clone() else { return vec![]; }; diff --git a/rust/gateway/src/messages.rs b/rust/gateway/src/messages.rs index 825d374282d..225e17f5ccf 100644 --- a/rust/gateway/src/messages.rs +++ b/rust/gateway/src/messages.rs @@ -4,7 +4,7 @@ use connlib_shared::{ gateway::ResourceDescription, ClientId, ClientPayload, GatewayResponse, Interface, Peer, Relay, RelaysPresence, ResourceId, }, - Dname, + DomainName, }; use serde::{Deserialize, Serialize}; @@ -52,7 +52,7 @@ pub struct AllowAccess { pub resource: ResourceDescription, #[serde(with = "ts_seconds_option")] pub expires_at: Option>, - pub payload: Option, + pub payload: Option, #[serde(rename = "ref")] pub reference: String, }