diff options
| author | Emīls <emils@mullvad.net> | 2021-11-19 13:53:29 +0000 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2021-12-10 09:58:51 +0000 |
| commit | bb9582cc37d59b8d852f53521cc496d0e55f2d0b (patch) | |
| tree | d78e4d8b4a64f0851c116d4401360ac0ca71d781 | |
| parent | 1ff05fbf885ca0354a0d9709300b84253a74c9bf (diff) | |
| download | mullvadvpn-bb9582cc37d59b8d852f53521cc496d0e55f2d0b.tar.xz mullvadvpn-bb9582cc37d59b8d852f53521cc496d0e55f2d0b.zip | |
Have DNS manager select the best DNS config
| -rw-r--r-- | talpid-core/src/dns/macos.rs | 11 | ||||
| -rw-r--r-- | talpid-core/src/dns/mod.rs | 4 | ||||
| -rw-r--r-- | talpid-core/src/resolver/mod.rs | 36 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/mod.rs | 2 |
4 files changed, 33 insertions, 20 deletions
diff --git a/talpid-core/src/dns/macos.rs b/talpid-core/src/dns/macos.rs index 1f63310449..fe7501d905 100644 --- a/talpid-core/src/dns/macos.rs +++ b/talpid-core/src/dns/macos.rs @@ -72,7 +72,9 @@ impl State { if let Some(tunnel_tx) = self.tunnel_tx.upgrade() { match parse_sc_config(&self.backup) { Ok(config) => { - let _ = tunnel_tx.unbounded_send(TunnelCommand::HostDnsConfig(config)); + // TODO: do better filtering to get the best resolver + let _ = tunnel_tx + .unbounded_send(TunnelCommand::HostDnsConfig(config.into_iter().next())); } Err(err) => { log::error!("Failed to parse host's DNS config: {}", err); @@ -319,7 +321,7 @@ impl DnsMonitor { result_rx.recv().unwrap() } /// Get the system config without our changes - pub fn get_system_config(&self) -> Result<HashMap<String, Vec<IpAddr>>> { + pub fn get_system_config(&self) -> Result<Option<(String, Vec<IpAddr>)>> { self.state .lock() .as_ref() @@ -330,7 +332,7 @@ impl DnsMonitor { fn parse_sc_config( config: &HashMap<String, Option<DnsSettings>>, -) -> Result<HashMap<String, Vec<IpAddr>>> { +) -> Result<Option<(String, Vec<IpAddr>)>> { config .iter() .filter_map(|(path, maybe_config)| { @@ -344,7 +346,8 @@ fn parse_sc_config( let addresses = settings.interface_config(path.as_str())?; Ok((settings.name.clone(), addresses)) }) - .collect::<Result<_>>() + .next() + .transpose() } /// Creates a `SCDynamicStore` that watches all network interfaces for changes to the DNS settings. diff --git a/talpid-core/src/dns/mod.rs b/talpid-core/src/dns/mod.rs index a941cf783e..5a7b5c0dec 100644 --- a/talpid-core/src/dns/mod.rs +++ b/talpid-core/src/dns/mod.rs @@ -1,7 +1,5 @@ #[cfg(target_os = "linux")] use crate::routing::RouteManagerHandle; -#[cfg(target_os = "macos")] -use std::collections::HashMap; use std::net::IpAddr; #[cfg(target_os = "macos")] @@ -54,7 +52,7 @@ impl DnsMonitor { /// Returns a map of interfaces and respective list of resolvers that don't contain our /// changes. #[cfg(target_os = "macos")] - pub fn get_system_config(&self) -> Result<HashMap<String, Vec<IpAddr>>, Error> { + pub fn get_system_config(&self) -> Result<Option<(String, Vec<IpAddr>)>, Error> { self.inner.get_system_config() } diff --git a/talpid-core/src/resolver/mod.rs b/talpid-core/src/resolver/mod.rs index 28ce99c355..fc3509f513 100644 --- a/talpid-core/src/resolver/mod.rs +++ b/talpid-core/src/resolver/mod.rs @@ -1,7 +1,7 @@ use socket2::{Domain, Socket, Type}; use std::{ - collections::{BTreeSet, HashMap}, + collections::BTreeSet, ffi::CString, future::Future, io, @@ -151,7 +151,7 @@ type ExcludedUpstreamResolver = AsyncResolver<GenericConnection, OurConnectionPr #[derive(Debug, PartialEq, Clone)] pub(crate) enum ResolverState { - Active(HashMap<String, Vec<IpAddr>>), + Active(Option<(String, Vec<IpAddr>)>), Inactive, Shutdown, } @@ -208,7 +208,7 @@ impl ResolverHandle { /// Enable the resolver pub async fn set_active( &self, - config: HashMap<String, Vec<IpAddr>>, + config: Option<(String, Vec<IpAddr>)>, ) -> Result<ResolverStateToggleResult, Error> { self.set_state(ResolverState::Active(config)).await } @@ -373,15 +373,13 @@ impl FilteringResolver { fn get_resolver_config(&self) -> (&str, &[IpAddr]) { match &self.resolver_state { - ResolverState::Active(resolvers) => { + ResolverState::Active(ref resolvers) => { // TODO: actually pick the best resolver resolvers - .iter() - // ignore anay config with loopback addresses + .as_ref() .filter(|(_, addresses)| { !addresses.iter().any(|ip| ip.is_loopback()) }) - .next() .map(|(interface_name, addresses)| (interface_name.as_str(), addresses.as_slice())) .unwrap_or(("", &[])) } @@ -658,7 +656,7 @@ impl LookupObject for ForwardLookup { #[cfg(test)] mod test { use super::*; - use std::{fs, net::UdpSocket}; + use std::{fs, net::UdpSocket, process::Command}; use subslice::SubsliceExt; fn random_port() -> u16 { @@ -668,7 +666,7 @@ mod test { const NAMESERVER: &[u8] = b"nameserver"; - fn read_resolvconf() -> HashMap<String, Vec<IpAddr>> { + fn read_resolvconf() -> Option<(String, Vec<IpAddr>)> { let contents = fs::read("/etc/resolv.conf").unwrap(); let nameserver_index = contents .find(NAMESERVER) @@ -681,9 +679,23 @@ mod test { let resolver_ip = IpAddr::from_str(std::str::from_utf8(ip_addr_subslice).unwrap().trim()).unwrap(); - let mut map = HashMap::new(); - map.insert("".to_string(), vec![resolver_ip]); - map + let route_output = String::from_utf8( + Command::new("route") + .arg("get") + .arg(resolver_ip.to_string()) + .output() + .expect("Failed to run 'route get'") + .stdout, + ) + .unwrap(); + + let mut output_parts = route_output.split_whitespace(); + while let Some(part) = output_parts.next() { + if part.trim() == "interface:" { + return Some((output_parts.next().unwrap().to_string(), vec![resolver_ip])); + } + } + panic!("Couldn't deduce interface") } async fn start_resolver() -> ( diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs index 0130a4a42d..a6696117fc 100644 --- a/talpid-core/src/tunnel_state_machine/mod.rs +++ b/talpid-core/src/tunnel_state_machine/mod.rs @@ -192,7 +192,7 @@ pub enum TunnelCommand { SetCustomResolver(bool, oneshot::Sender<Result<(), crate::resolver::Error>>), /// Receive up-to-date system DNS config. It should never contain our changes to the DNS. #[cfg(target_os = "macos")] - HostDnsConfig(HashMap<String, Vec<IpAddr>>), + HostDnsConfig(Option<(String, Vec<IpAddr>)>), } type TunnelCommandReceiver = stream::Fuse<mpsc::UnboundedReceiver<TunnelCommand>>; |
