From 64393a6c5b09738c7e5c70bd4bc40d63169618a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20L=C3=B6nnhager?= Date: Thu, 2 May 2024 10:56:30 +0200 Subject: [PATCH 1/3] Set dummy DNS servers in blocking states This is a fix for DNS leaks in blocking states due to an underlying OS bug where DNS queries leak when no DNS server is configured. Lockdown mode ("Block connections without VPN") would also not help in this case. More information on this issue: https://issuetracker.google.com/issues/337961996 --- talpid-tunnel/src/tun_provider/android/mod.rs | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/talpid-tunnel/src/tun_provider/android/mod.rs b/talpid-tunnel/src/tun_provider/android/mod.rs index 187dd3b4f502..baccd3f3fc3c 100644 --- a/talpid-tunnel/src/tun_provider/android/mod.rs +++ b/talpid-tunnel/src/tun_provider/android/mod.rs @@ -56,6 +56,7 @@ pub struct AndroidTunProvider { object: GlobalRef, last_tun_config: TunConfig, allow_lan: bool, + blocking: bool, custom_dns_servers: Option>, allowed_lan_networks: Vec, } @@ -82,6 +83,7 @@ impl AndroidTunProvider { object: context.vpn_service, last_tun_config: TunConfig::default(), allow_lan, + blocking: false, custom_dns_servers, allowed_lan_networks, } @@ -105,8 +107,15 @@ impl AndroidTunProvider { Ok(()) } + /// Retrieve a tunnel device with the provided configuration. Custom DNS and LAN routes are + /// appended to the provided config. + pub fn get_tun(&mut self, mut config: TunConfig) -> Result { + self.prepare_tun_config(&mut config, false); + self.get_tun_inner(config) + } + /// Retrieve a tunnel device with the provided configuration. - pub fn get_tun(&mut self, config: TunConfig) -> Result { + fn get_tun_inner(&mut self, config: TunConfig) -> Result { let tun_fd = self.get_tun_fd(config.clone())?; self.last_tun_config = config; @@ -122,15 +131,15 @@ impl AndroidTunProvider { }) } - /// Open a tunnel device that routes everything but custom DNS, and - /// (potentially) LAN routes via the tunnel device. + /// Open a tunnel device that routes everything but (potentially) LAN routes via the tunnel + /// device. /// /// Will open a new tunnel if there is already an active tunnel. The previous tunnel will be /// closed. pub fn create_blocking_tun(&mut self) -> Result<(), Error> { let mut config = TunConfig::default(); - self.prepare_tun_config(&mut config); - let _ = self.get_tun(config)?; + self.prepare_tun_config(&mut config, true); + let _ = self.get_tun_inner(config)?; Ok(()) } @@ -176,9 +185,7 @@ impl AndroidTunProvider { } } - fn get_tun_fd(&mut self, mut config: TunConfig) -> Result { - self.prepare_tun_config(&mut config); - + fn get_tun_fd(&mut self, config: TunConfig) -> Result { let env = self.env()?; let java_config = config.into_java(&env); @@ -198,7 +205,7 @@ impl AndroidTunProvider { fn recreate_tun_if_open(&mut self) -> Result<(), Error> { let mut actual_config = self.last_tun_config.clone(); - self.prepare_tun_config(&mut actual_config); + self.prepare_tun_config(&mut actual_config, self.blocking); let env = self.env()?; let java_config = actual_config.into_java(&env); @@ -216,9 +223,13 @@ impl AndroidTunProvider { } } - fn prepare_tun_config(&self, config: &mut TunConfig) { + fn prepare_tun_config(&mut self, config: &mut TunConfig, blocking: bool) { + self.blocking = blocking; self.prepare_tun_config_for_allow_lan(config); - self.prepare_tun_config_for_custom_dns(config); + if !blocking { + self.prepare_tun_config_for_custom_dns(config); + } + maybe_set_dummy_dns_servers(config); } fn prepare_tun_config_for_allow_lan(&self, config: &mut TunConfig) { @@ -324,6 +335,14 @@ impl AndroidTunProvider { } } +/// Add dummy servers if no DNS servers are set. Android may sometimes leak DNS otherwise. +fn maybe_set_dummy_dns_servers(config: &mut TunConfig) { + if !config.dns_servers.is_empty() { + return; + } + config.dns_servers = vec!["192.0.2.1".parse().unwrap()]; +} + /// Handle to a tunnel device on Android. pub struct VpnServiceTun { tunnel: RawFd, From e94535859f15ee855f499574037adff27b9e1cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20G=C3=B6ransson?= Date: Mon, 6 May 2024 14:58:43 +0200 Subject: [PATCH 2/3] Set dummy DNS if none are valid This is a fix for DNS leaks when no DNS server has been configured due to an underlying OS bug. Lockdown mode ("Block connections without VPN") would also not help in this case. More information on this issue: https://issuetracker.google.com/issues/337961996 --- .../net/mullvad/talpid/TalpidVpnService.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt index 94b097fe1310..76abde2a01f1 100644 --- a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt +++ b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt @@ -2,6 +2,7 @@ package net.mullvad.talpid import android.net.VpnService import android.os.ParcelFileDescriptor +import android.util.Log import java.net.Inet4Address import java.net.Inet6Address import java.net.InetAddress @@ -103,6 +104,18 @@ open class TalpidVpnService : VpnService() { } } + // Avoids creating a tunnel with no DNS servers or if all DNS servers was invalid, + // since apps then may leak DNS requests. + // https://issuetracker.google.com/issues/337961996 + if (invalidDnsServerAddresses.size == config.dnsServers.size) { + Log.w( + "mullvad", + "All DNS servers invalid or non set, using fallback DNS server to " + + "minimize leaks, dnsServers.isEmpty(): ${config.dnsServers.isEmpty()}" + ) + addDnsServer(FALLBACK_DUMMY_DNS_SERVER) + } + for (route in config.routes) { addRoute(route.address, route.prefixLength.toInt()) } @@ -148,4 +161,8 @@ open class TalpidVpnService : VpnService() { private external fun defaultTunConfig(): TunConfig private external fun waitForTunnelUp(tunFd: Int, isIpv6Enabled: Boolean) + + companion object { + private const val FALLBACK_DUMMY_DNS_SERVER = "192.0.2.1" + } } From 25bc1977eb86dc8458a5b247fd75e49dda2d3ce4 Mon Sep 17 00:00:00 2001 From: Albin Date: Wed, 8 May 2024 14:26:38 +0200 Subject: [PATCH 3/3] Update changelog --- android/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index e25d01f58d8b..811fc2dcc7f2 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -22,6 +22,9 @@ Line wrap the file at 100 chars. Th * **Security**: in case of vulnerabilities. ## [Unreleased] +### Security +- Fix DNS leaks in blocking states or when no valid DNS has been configured due to an underlying OS + issue. In these cases a dummy DNS will be set to prevent leaks. ## [android/2024.2-beta1] - 2024-04-17