summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2025-10-08 15:07:41 +0200
committerMarkus Pettersson <markus.pettersson@mullvad.net>2025-10-08 15:07:41 +0200
commit104d97e2a6504789e5502ffae33991cc22f1357b (patch)
tree6a828b3c56677a70b51b6865de31826c57aaa9b9
parent73a47c1458b1601a4a7b48cef3eecc6d2b3eb69b (diff)
parent5d60c723a4555f99e1ab238b838f241d2d72f6a7 (diff)
downloadmullvadvpn-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.rs92
-rw-r--r--talpid-wireguard/src/config.rs25
-rw-r--r--talpid-wireguard/src/lib.rs1
-rw-r--r--talpid-wireguard/src/wireguard_go/mod.rs45
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());