diff options
Diffstat (limited to 'mullvad-daemon/src/tunnel.rs')
| -rw-r--r-- | mullvad-daemon/src/tunnel.rs | 225 |
1 files changed, 115 insertions, 110 deletions
diff --git a/mullvad-daemon/src/tunnel.rs b/mullvad-daemon/src/tunnel.rs index 2094838173..f230a3c4b2 100644 --- a/mullvad-daemon/src/tunnel.rs +++ b/mullvad-daemon/src/tunnel.rs @@ -8,20 +8,22 @@ use std::{ use tokio::sync::Mutex; -use mullvad_relay_selector::{RelaySelector, SelectedBridge, SelectedObfuscator, SelectedRelay}; +use mullvad_relay_selector::{GetRelay, RelaySelector, RuntimeParameters, WireguardConfig}; use mullvad_types::{ - endpoint::MullvadEndpoint, location::GeoIpLocation, relay_list::Relay, settings::TunnelOptions, + endpoint::MullvadWireguardEndpoint, location::GeoIpLocation, relay_list::Relay, + settings::TunnelOptions, }; use once_cell::sync::Lazy; use talpid_core::tunnel_state_machine::TunnelParametersGenerator; -use talpid_types::{ - net::{wireguard, TunnelParameters}, - tunnel::ParameterGenerationError, - ErrorExt, +#[cfg(not(target_os = "android"))] +use talpid_types::net::{ + obfuscation::ObfuscatorConfig, openvpn, proxy::CustomProxy, wireguard, Endpoint, + TunnelParameters, }; +#[cfg(target_os = "android")] +use talpid_types::net::{obfuscation::ObfuscatorConfig, wireguard, TunnelParameters}; -#[cfg(not(target_os = "android"))] -use talpid_types::net::openvpn; +use talpid_types::{tunnel::ParameterGenerationError, ErrorExt}; use crate::device::{AccountManagerHandle, PrivateAccountAndDevice}; @@ -138,127 +140,129 @@ impl ParametersGenerator { } impl InnerParametersGenerator { - async fn generate(&mut self, retry_attempt: u32) -> Result<TunnelParameters, Error> { - let _data = self.device().await?; - match self.relay_selector.get_relay(retry_attempt) { - Ok((SelectedRelay::Custom(custom_relay), _bridge, _obfsucator)) => { - self.last_generated_relays = None; - custom_relay - // TODO: generate proxy settings for custom tunnels - .to_tunnel_parameters(self.tunnel_options.clone(), None) - .map_err(|e| { - log::error!("Failed to resolve hostname for custom tunnel config: {}", e); - Error::ResolveCustomHostname - }) - } - Ok((SelectedRelay::Normal(constraints), bridge, obfuscator)) => { - self.create_tunnel_parameters( - &constraints.exit_relay, - &constraints.entry_relay, - constraints.endpoint, - bridge, - obfuscator, - ) - .await - } - Err(mullvad_relay_selector::Error::NoBridge) => Err(Error::NoBridgeAvailable), - Err(_error) => Err(Error::NoRelayAvailable), - } - } - - #[cfg_attr(target_os = "android", allow(unused_variables))] - async fn create_tunnel_parameters( + async fn generate( &mut self, - relay: &Relay, - entry_relay: &Option<Relay>, - endpoint: MullvadEndpoint, - bridge: Option<SelectedBridge>, - obfuscator: Option<SelectedObfuscator>, + retry_attempt: u32, + ipv6: bool, ) -> Result<TunnelParameters, Error> { let data = self.device().await?; - match endpoint { - #[cfg(not(target_os = "android"))] - MullvadEndpoint::OpenVpn(endpoint) => { - let (bridge_settings, bridge_relay) = match bridge { - Some(SelectedBridge::Normal(bridge)) => { - (Some(bridge.settings), Some(bridge.relay)) - } - Some(SelectedBridge::Custom(settings)) => (Some(settings), None), - None => (None, None), - }; + let selected_relay = self + .relay_selector + .get_relay(retry_attempt as usize, RuntimeParameters { ipv6 }) + .map_err(|err| match err { + mullvad_relay_selector::Error::NoBridge => Error::NoBridgeAvailable, + _ => Error::NoRelayAvailable, + })?; + match selected_relay { + #[cfg(not(target_os = "android"))] + GetRelay::OpenVpn { + endpoint, + exit, + bridge, + } => { + let bridge_relay = bridge.as_ref().and_then(|bridge| bridge.relay()); self.last_generated_relays = Some(LastSelectedRelays::OpenVpn { - relay: relay.clone(), - bridge: bridge_relay, + relay: exit.clone(), + bridge: bridge_relay.cloned(), }); - - Ok(openvpn::TunnelParameters { - config: openvpn::ConnectionConfig::new( - endpoint, - data.account_token, - "-".to_string(), - ), - options: self.tunnel_options.openvpn.clone(), - generic_options: self.tunnel_options.generic.clone(), - proxy: bridge_settings, - #[cfg(target_os = "linux")] - fwmark: mullvad_types::TUNNEL_FWMARK, - } - .into()) + let bridge_settings = bridge.as_ref().map(|bridge| bridge.settings()); + Ok(self.create_openvpn_tunnel_parameters(endpoint, data, bridge_settings.cloned())) } - #[cfg(target_os = "android")] - MullvadEndpoint::OpenVpn(endpoint) => { - unreachable!("OpenVPN is not supported on Android"); - } - MullvadEndpoint::Wireguard(endpoint) => { - let tunnel_ipv4 = data.device.wg_data.addresses.ipv4_address.ip(); - let tunnel_ipv6 = data.device.wg_data.addresses.ipv6_address.ip(); - let tunnel = wireguard::TunnelConfig { - private_key: data.device.wg_data.private_key, - addresses: vec![IpAddr::from(tunnel_ipv4), IpAddr::from(tunnel_ipv6)], - }; - // FIXME: Used for debugging purposes during the migration to same IP. Remove when - // the migration is over. - if tunnel_ipv4 == *SAME_IP_V4 || tunnel_ipv6 == *SAME_IP_V6 { - log::debug!("Same IP is being used"); - } else { - log::debug!("Same IP is NOT being used"); - } - + GetRelay::Wireguard { + endpoint, + obfuscator, + inner, + } => { let (obfuscator_relay, obfuscator_config) = match obfuscator { Some(obfuscator) => (Some(obfuscator.relay), Some(obfuscator.config)), None => (None, None), }; + let (wg_entry, wg_exit) = match inner { + WireguardConfig::Singlehop { exit } => (None, exit), + WireguardConfig::Multihop { exit, entry } => (Some(entry), exit), + }; self.last_generated_relays = Some(LastSelectedRelays::WireGuard { - wg_entry: entry_relay.clone(), - wg_exit: relay.clone(), + wg_entry, + wg_exit, obfuscator: obfuscator_relay, }); - Ok(wireguard::TunnelParameters { - connection: wireguard::ConnectionConfig { - tunnel, - peer: endpoint.peer, - exit_peer: endpoint.exit_peer, - ipv4_gateway: endpoint.ipv4_gateway, - ipv6_gateway: Some(endpoint.ipv6_gateway), - #[cfg(target_os = "linux")] - fwmark: Some(mullvad_types::TUNNEL_FWMARK), - }, - options: self - .tunnel_options - .wireguard - .clone() - .into_talpid_tunnel_options(), - generic_options: self.tunnel_options.generic.clone(), - obfuscation: obfuscator_config, - } - .into()) + Ok(self.create_wireguard_tunnel_parameters(endpoint, data, obfuscator_config)) + } + GetRelay::Custom(custom_relay) => { + self.last_generated_relays = None; + custom_relay + // TODO: generate proxy settings for custom tunnels + .to_tunnel_parameters(self.tunnel_options.clone(), None) + .map_err(|e| { + log::error!("Failed to resolve hostname for custom tunnel config: {}", e); + Error::ResolveCustomHostname + }) } } } + #[cfg(not(target_os = "android"))] + fn create_openvpn_tunnel_parameters( + &self, + endpoint: Endpoint, + data: PrivateAccountAndDevice, + bridge_settings: Option<CustomProxy>, + ) -> TunnelParameters { + openvpn::TunnelParameters { + config: openvpn::ConnectionConfig::new(endpoint, data.account_token, "-".to_string()), + options: self.tunnel_options.openvpn.clone(), + generic_options: self.tunnel_options.generic.clone(), + proxy: bridge_settings, + #[cfg(target_os = "linux")] + fwmark: mullvad_types::TUNNEL_FWMARK, + } + .into() + } + + fn create_wireguard_tunnel_parameters( + &self, + endpoint: MullvadWireguardEndpoint, + data: PrivateAccountAndDevice, + obfuscator_config: Option<ObfuscatorConfig>, + ) -> TunnelParameters { + let tunnel_ipv4 = data.device.wg_data.addresses.ipv4_address.ip(); + let tunnel_ipv6 = data.device.wg_data.addresses.ipv6_address.ip(); + let tunnel = wireguard::TunnelConfig { + private_key: data.device.wg_data.private_key, + addresses: vec![IpAddr::from(tunnel_ipv4), IpAddr::from(tunnel_ipv6)], + }; + // FIXME: Used for debugging purposes during the migration to same IP. Remove when + // the migration is over. + if tunnel_ipv4 == *SAME_IP_V4 || tunnel_ipv6 == *SAME_IP_V6 { + log::debug!("Same IP is being used"); + } else { + log::debug!("Same IP is NOT being used"); + } + + wireguard::TunnelParameters { + connection: wireguard::ConnectionConfig { + tunnel, + peer: endpoint.peer, + exit_peer: endpoint.exit_peer, + ipv4_gateway: endpoint.ipv4_gateway, + ipv6_gateway: Some(endpoint.ipv6_gateway), + #[cfg(target_os = "linux")] + fwmark: Some(mullvad_types::TUNNEL_FWMARK), + }, + options: self + .tunnel_options + .wireguard + .clone() + .into_talpid_tunnel_options(), + generic_options: self.tunnel_options.generic.clone(), + obfuscation: obfuscator_config, + } + .into() + } + async fn device(&self) -> Result<PrivateAccountAndDevice, Error> { self.account_manager .data() @@ -274,12 +278,13 @@ impl TunnelParametersGenerator for ParametersGenerator { fn generate( &mut self, retry_attempt: u32, + ipv6: bool, ) -> Pin<Box<dyn Future<Output = Result<TunnelParameters, ParameterGenerationError>>>> { let generator = self.0.clone(); Box::pin(async move { let mut inner = generator.lock().await; inner - .generate(retry_attempt) + .generate(retry_attempt, ipv6) .await .map_err(|error| match error { Error::NoBridgeAvailable => ParameterGenerationError::NoMatchingBridgeRelay, |
