summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2024-05-08 15:10:46 +0200
committerAlbin <albin@mullvad.net>2024-05-08 15:10:46 +0200
commit9869614e08caa819a36877633ccc0bf981f29c76 (patch)
tree92fc83e33a2d36e9d9e2cb4ba2758dd9fa531252
parent44dcda5625ddbbc2bceb4689de28d837f6526ced (diff)
parent25bc1977eb86dc8458a5b247fd75e49dda2d3ce4 (diff)
downloadmullvadvpn-9869614e08caa819a36877633ccc0bf981f29c76.tar.xz
mullvadvpn-9869614e08caa819a36877633ccc0bf981f29c76.zip
Merge branch 'prevent-dns-leaks-in-blocking-states-droid-950'
-rw-r--r--android/CHANGELOG.md3
-rw-r--r--android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt17
-rw-r--r--talpid-tunnel/src/tun_provider/android/mod.rs41
3 files changed, 50 insertions, 11 deletions
diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md
index e25d01f58d..811fc2dcc7 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
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 94b097fe13..76abde2a01 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"
+ }
}
diff --git a/talpid-tunnel/src/tun_provider/android/mod.rs b/talpid-tunnel/src/tun_provider/android/mod.rs
index 187dd3b4f5..baccd3f3fc 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<Vec<IpAddr>>,
allowed_lan_networks: Vec<IpNetwork>,
}
@@ -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<VpnServiceTun, Error> {
+ 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<VpnServiceTun, Error> {
+ fn get_tun_inner(&mut self, config: TunConfig) -> Result<VpnServiceTun, Error> {
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<RawFd, Error> {
- self.prepare_tun_config(&mut config);
-
+ fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> {
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,