diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-10-08 15:07:41 +0200 |
|---|---|---|
| committer | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-10-08 15:07:41 +0200 |
| commit | 104d97e2a6504789e5502ffae33991cc22f1357b (patch) | |
| tree | 6a828b3c56677a70b51b6865de31826c57aaa9b9 | |
| parent | 73a47c1458b1601a4a7b48cef3eecc6d2b3eb69b (diff) | |
| parent | 5d60c723a4555f99e1ab238b838f241d2d72f6a7 (diff) | |
| download | mullvadvpn-104d97e2a6504789e5502ffae33991cc22f1357b.tar.xz mullvadvpn-104d97e2a6504789e5502ffae33991cc22f1357b.zip | |
Merge branch 'handle-patch_allowed_ips-block-non-relay-traffic-during-pq-des-2179'
| -rw-r--r-- | talpid-wireguard/src/boringtun/mod.rs | 92 | ||||
| -rw-r--r-- | talpid-wireguard/src/config.rs | 25 | ||||
| -rw-r--r-- | talpid-wireguard/src/lib.rs | 1 | ||||
| -rw-r--r-- | talpid-wireguard/src/wireguard_go/mod.rs | 45 |
4 files changed, 80 insertions, 83 deletions
diff --git a/talpid-wireguard/src/boringtun/mod.rs b/talpid-wireguard/src/boringtun/mod.rs index d1ad0b1587..f687458f0b 100644 --- a/talpid-wireguard/src/boringtun/mod.rs +++ b/talpid-wireguard/src/boringtun/mod.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "android")] +use crate::config::patch_allowed_ips; use crate::{ Tunnel, TunnelError, config::Config, @@ -114,6 +116,24 @@ enum Devices { }, } +impl Devices { + async fn stop(self) { + match self { + Devices::Singlehop { device, .. } => { + device.stop().await; + } + Devices::Multihop { + entry_device, + exit_device, + .. + } => { + exit_device.stop().await; + entry_device.stop().await; + } + } + } +} + #[cfg(target_os = "android")] struct AndroidUdpSocketFactory { pub tun: Arc<Tun>, @@ -144,6 +164,7 @@ pub async fn open_boringtun_tunnel( config: &Config, tun_provider: Arc<Mutex<tun_provider::TunProvider>>, #[cfg(target_os = "android")] route_manager_handle: talpid_routing::RouteManagerHandle, + #[cfg(target_os = "android")] gateway_only: bool, ) -> super::Result<BoringTun> { log::info!("BoringTun::start_tunnel"); let routes = config.get_tunnel_destinations(); @@ -197,11 +218,19 @@ pub async fn open_boringtun_tunnel( log::info!("passing tunnel dev to boringtun"); let async_tun = Arc::new(async_tun); + let config = config.clone(); + #[cfg(target_os = "android")] + let config = match gateway_only { + // See `wireguard_go` module for why this is needed. + true => patch_allowed_ips(config), + false => config, + }; + let boringtun = BoringTun::new( async_tun, #[cfg(target_os = "android")] tun.clone(), - config.clone(), + config, interface_name, ) .await @@ -358,21 +387,12 @@ impl Tunnel for BoringTun { fn stop(mut self: Box<Self>) -> Result<(), TunnelError> { log::info!("BoringTun::stop"); // remove me tokio::runtime::Handle::current().block_on(async { - match self.devices.take().unwrap() { - Devices::Singlehop { device, .. } => { - device.stop().await; - } - Devices::Multihop { - entry_device, - exit_device, - .. - } => { - exit_device.stop().await; - entry_device.stop().await; - } + // TODO: devices should never be None while this BoringTun instance is running. + debug_assert!(self.devices.is_some()); + if let Some(devices) = self.devices.take() { + devices.stop().await; } }); - Ok(()) } @@ -422,34 +442,22 @@ impl Tunnel for BoringTun { config: Config, ) -> std::pin::Pin<Box<dyn Future<Output = Result<(), TunnelError>> + Send + 'a>> { Box::pin(async move { - let old_config = std::mem::replace(&mut self.config, config); - - if old_config.is_multihop() != self.config.is_multihop() { - // TODO: Update existing tunnels? - match self.devices.take().unwrap() { - Devices::Singlehop { device, .. } => { - device.stop().await; - } - Devices::Multihop { - entry_device, - exit_device, - .. - } => { - exit_device.stop().await; - entry_device.stop().await; - } - } - - self.devices = Some( - create_devices( - &self.config, - self.tun.clone(), - #[cfg(target_os = "android")] - self.android_tun.clone(), - ) - .await?, - ); + let _old_config = std::mem::replace(&mut self.config, config); + // TODO: diff with _old_config to see if devices need to be recreated. + // TODO: devices should never be None while this BoringTun instance is running. + debug_assert!(self.devices.is_some()); + if let Some(devices) = self.devices.take() { + devices.stop().await; } + self.devices = Some( + create_devices( + &self.config, + self.tun.clone(), + #[cfg(target_os = "android")] + self.android_tun.clone(), + ) + .await?, + ); Ok(()) }) } @@ -564,7 +572,7 @@ pub fn get_tunnel_for_userspace( tun_config.ipv6_gateway = config.ipv6_gateway; tun_config.mtu = config.mtu; - // Route everything into the tunnel and have wireguard-go act as a firewall when + // Route everything into the tunnel and have WireGuard act as a firewall when // blocking. These will not necessarily be the actual routes used by android. Those will // be generated at a later stage e.g. if Local Network Sharing is enabled. tun_config.routes = vec!["0.0.0.0/0".parse().unwrap(), "::/0".parse().unwrap()]; diff --git a/talpid-wireguard/src/config.rs b/talpid-wireguard/src/config.rs index c8b943e0c1..74d3541142 100644 --- a/talpid-wireguard/src/config.rs +++ b/talpid-wireguard/src/config.rs @@ -262,3 +262,28 @@ fn write_peer_to_config(wg_conf: &mut WgConfigBuffer, peer: &PeerConfig) { wg_conf.add("constant_packet_size", "true"); } } + +/// Replace `0.0.0.0/0`/`::/0` with the gateway IPs. +/// Used to block traffic to other destinations while connecting on Android. +#[cfg(target_os = "android")] +pub(crate) fn patch_allowed_ips(mut config: Config) -> Config { + use ipnetwork::IpNetwork; + use std::net::IpAddr; + + let gateway_net_v4 = IpNetwork::from(IpAddr::from(config.ipv4_gateway)); + let gateway_net_v6 = config + .ipv6_gateway + .map(|net| IpNetwork::from(IpAddr::from(net))); + for peer in config.peers_mut() { + for allowed_ips in &mut peer.allowed_ips { + if allowed_ips.prefix() == 0 { + match (allowed_ips.is_ipv4(), gateway_net_v6) { + (true, _) => *allowed_ips = gateway_net_v4, + (_, Some(net)) => *allowed_ips = net, + _ => continue, + } + } + } + } + config +} diff --git a/talpid-wireguard/src/lib.rs b/talpid-wireguard/src/lib.rs index ce7c256e9f..9531a1066f 100644 --- a/talpid-wireguard/src/lib.rs +++ b/talpid-wireguard/src/lib.rs @@ -472,6 +472,7 @@ impl WireguardMonitor { &config, args.tun_provider.clone(), args.route_manager, + should_negotiate_ephemeral_peer, )) .map(Box::new)? as Box<dyn Tunnel>; diff --git a/talpid-wireguard/src/wireguard_go/mod.rs b/talpid-wireguard/src/wireguard_go/mod.rs index b12afe40b4..55058f2a0c 100644 --- a/talpid-wireguard/src/wireguard_go/mod.rs +++ b/talpid-wireguard/src/wireguard_go/mod.rs @@ -13,8 +13,6 @@ use crate::connectivity; use crate::logging::{clean_up_logging, initialize_logging}; #[cfg(all(unix, not(target_os = "android")))] use ipnetwork::IpNetwork; -#[cfg(target_os = "android")] -use std::borrow::Cow; #[cfg(daita)] use std::ffi::CString; #[cfg(unix)] @@ -114,7 +112,10 @@ pub(crate) async fn open_wireguard_go_tunnel( // // Refer to `docs/architecture.md` for details on how to use multihop + PQ. #[cfg(target_os = "android")] - let config = patch_allowed_ips(config, gateway_only); + let config = match gateway_only { + true => config::patch_allowed_ips(config.clone()), + false => config.clone(), + }; #[cfg(target_os = "android")] let tunnel = if let Some(exit_peer) = &config.exit_peer { @@ -142,44 +143,6 @@ pub(crate) async fn open_wireguard_go_tunnel( Ok(tunnel) } -/// Replace `0.0.0.0/0`/`::/0` with the gateway IPs when `gateway_only` is true. -/// Used to block traffic to other destinations while connecting on Android. -#[cfg(target_os = "android")] -fn patch_allowed_ips(config: &Config, gateway_only: bool) -> Cow<'_, Config> { - use std::net::IpAddr; - - if gateway_only { - let mut patched_config = config.clone(); - let gateway_net_v4 = - ipnetwork::IpNetwork::from(std::net::IpAddr::from(config.ipv4_gateway)); - let gateway_net_v6 = config - .ipv6_gateway - .map(|net| ipnetwork::IpNetwork::from(IpAddr::from(net))); - for peer in patched_config.peers_mut() { - peer.allowed_ips = peer - .allowed_ips - .iter() - .cloned() - .filter_map(|mut allowed_ip| { - if allowed_ip.prefix() == 0 { - if allowed_ip.is_ipv4() { - allowed_ip = gateway_net_v4; - } else if let Some(net) = gateway_net_v6 { - allowed_ip = net; - } else { - return None; - } - } - Some(allowed_ip) - }) - .collect(); - } - Cow::Owned(patched_config) - } else { - Cow::Borrowed(config) - } -} - impl WgGoTunnel { fn handle(&self) -> &WgGoTunnelState { debug_assert!(&self.inner.is_some()); |
