diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-01-08 14:53:31 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2021-01-08 14:53:31 +0100 |
| commit | 63835d9ab54688c00aa8c87ebd628bfa91c16385 (patch) | |
| tree | 831784de081a1d7f3c0cd56e8c84f2cfaf02c7d4 | |
| parent | 44929b7bc51428985f7f0508d65abee43b0ee1d3 (diff) | |
| parent | 49391a28ff00ae8efd452be664ca66d134517f2a (diff) | |
| download | mullvadvpn-63835d9ab54688c00aa8c87ebd628bfa91c16385.tar.xz mullvadvpn-63835d9ab54688c00aa8c87ebd628bfa91c16385.zip | |
Merge branch 'netbios-fallback'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | talpid-core/src/dns/windows/mod.rs | 56 |
3 files changed, 47 insertions, 18 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index b72ba378c4..ac7303ff09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ Line wrap the file at 100 chars. Th #### Linux - Fix missing app window icon in Xfce. +#### Windows +- Resolve single-label hostnames correctly. + ### Security #### Linux - Prevent the private tunnel IPv6 address from being detectable on a local network when using @@ -369,6 +369,12 @@ echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties * `TALPID_FORCE_USERSPACE_WIREGUARD` - Forces the daemon to use the userspace implementation of WireGuard on Linux. +* `TALPID_DNS_CACHE_POLICY` - On Windows, this changes how DNS is configured: + * `1`: The default. This sets a global list of DNS servers that `dnscache` will use instead of + the servers specified on each interface. + * `0`: Only set DNS servers on the tunnel interface. This will misbehave if local custom DNS + servers are used. + ## Building and running the desktop Electron GUI app diff --git a/talpid-core/src/dns/windows/mod.rs b/talpid-core/src/dns/windows/mod.rs index 66a361e9be..17165c2364 100644 --- a/talpid-core/src/dns/windows/mod.rs +++ b/talpid-core/src/dns/windows/mod.rs @@ -1,7 +1,10 @@ use crate::logging::windows::{log_sink, LogSink}; +use lazy_static::lazy_static; use log::{error, trace, warn}; -use std::{ffi::OsString, io, iter, mem, net::IpAddr, os::windows::ffi::OsStrExt, path::Path, ptr}; +use std::{ + env, ffi::OsString, io, iter, mem, net::IpAddr, os::windows::ffi::OsStrExt, path::Path, ptr, +}; use talpid_types::ErrorExt; use widestring::WideCString; use winapi::um::{ @@ -21,6 +24,13 @@ use self::system_state::SystemStateWriter; const DNS_STATE_FILENAME: &'static str = "dns-state-backup"; const DNS_CACHE_POLICY_GUID: &str = "{d57d2750-f971-408e-8e55-cfddb37e60ae}"; +lazy_static! { + /// Specifies whether to override per-interface DNS resolvers with a global DNS policy. + static ref GLOBAL_DNS_CACHE_POLICY: bool = env::var("TALPID_DNS_CACHE_POLICY") + .map(|v| v != "0") + .unwrap_or(true); +} + /// Errors that can happen when configuring DNS on Windows. #[derive(err_derive::Error, Debug)] pub enum Error { @@ -49,15 +59,6 @@ impl super::DnsMonitorT for DnsMonitor { fn new(cache_dir: impl AsRef<Path>) -> Result<Self, Error> { unsafe { WinDns_Initialize(Some(log_sink), b"WinDns\0".as_ptr()).into_result()? }; - if is_minimum_windows10() { - if let Err(error) = reset_dns_cache_policy() { - error!( - "{}", - error.display_chain_with_msg("Failed to reset DNS cache policy") - ); - } - } - let backup_writer = SystemStateWriter::new( cache_dir .as_ref() @@ -65,7 +66,11 @@ impl super::DnsMonitorT for DnsMonitor { .into_boxed_path(), ); let _ = backup_writer.remove_backup(); - Ok(DnsMonitor {}) + + let mut monitor = DnsMonitor {}; + monitor.reset()?; + + Ok(monitor) } fn set(&mut self, interface: &str, servers: &[IpAddr]) -> Result<(), Error> { @@ -103,7 +108,7 @@ impl super::DnsMonitorT for DnsMonitor { .into_result() }?; - if is_minimum_windows10() { + if *GLOBAL_DNS_CACHE_POLICY && is_minimum_windows10() { if let Err(error) = set_dns_cache_policy(servers) { error!("{}", error.display_chain()); warn!("DNS resolution may be slowed down"); @@ -114,7 +119,7 @@ impl super::DnsMonitorT for DnsMonitor { } fn reset(&mut self) -> Result<(), Error> { - if is_minimum_windows10() { + if *GLOBAL_DNS_CACHE_POLICY && is_minimum_windows10() { reset_dns_cache_policy() } else { Ok(()) @@ -128,7 +133,7 @@ fn ip_to_widestring(ip: &IpAddr) -> WideCString { impl Drop for DnsMonitor { fn drop(&mut self) { - if is_minimum_windows10() { + if *GLOBAL_DNS_CACHE_POLICY && is_minimum_windows10() { if let Err(error) = reset_dns_cache_policy() { warn!( "{}", @@ -160,8 +165,13 @@ fn set_dns_cache_policy(servers: &[IpAddr]) -> Result<(), Error> { } fn set_dns_cache_policy_inner(transaction: &Transaction, servers: &[IpAddr]) -> Result<(), Error> { - let dns_cache_parameters = RegKey::predef(HKEY_LOCAL_MACHINE) - .open_subkey(r#"SYSTEM\CurrentControlSet\Services\DnsCache\Parameters"#)?; + let (dns_cache_parameters, _) = RegKey::predef(HKEY_LOCAL_MACHINE).create_subkey_transacted( + r#"SYSTEM\CurrentControlSet\Services\DnsCache\Parameters"#, + transaction, + )?; + + // Fall back on LLMNR and NetBIOS if DNS resolution fails + dns_cache_parameters.set_value("DnsSecureNameQueryFallback", &1u32)?; let policy_path = Path::new("DnsPolicyConfig").join(DNS_CACHE_POLICY_GUID); let (policy_config, _) = @@ -186,8 +196,18 @@ fn set_dns_cache_policy_inner(transaction: &Transaction, servers: &[IpAddr]) -> } fn reset_dns_cache_policy() -> Result<(), Error> { - let dns_cache_parameters = RegKey::predef(HKEY_LOCAL_MACHINE) - .open_subkey(r#"SYSTEM\CurrentControlSet\Services\DnsCache\Parameters"#)?; + let (dns_cache_parameters, _) = RegKey::predef(HKEY_LOCAL_MACHINE) + .create_subkey(r#"SYSTEM\CurrentControlSet\Services\DnsCache\Parameters"#)?; + match dns_cache_parameters.delete_value("DnsSecureNameQueryFallback") { + Ok(()) => Ok(()), + Err(error) => { + if error.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(Error::UpdateDnsCachePolicy(error)) + } + } + }?; let policy_path = Path::new("DnsPolicyConfig").join(DNS_CACHE_POLICY_GUID); match dns_cache_parameters.delete_subkey_all(policy_path) { Ok(()) => Ok(()), |
