summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJonathan <jonathan@mullvad.net>2022-08-15 10:29:55 +0200
committerJonathan <jonathan@mullvad.net>2022-08-15 10:29:55 +0200
commit844714165375e3a8ec45dcc7a97e4907ccda8e27 (patch)
tree6d7147d32c610ba16711b8435dbf0374c21e6817
parent3cd0deb3e2fb35eceaf217100deed8737d1500c1 (diff)
parentaf8776538d411cbc8d1619881382ce3c9c707c01 (diff)
downloadmullvadvpn-844714165375e3a8ec45dcc7a97e4907ccda8e27.tar.xz
mullvadvpn-844714165375e3a8ec45dcc7a97e4907ccda8e27.zip
Merge branch 'migrate-windows-users-to-wireguard'
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.lock1
-rw-r--r--docs/relay-selector.md5
-rw-r--r--mullvad-api/src/lib.rs10
-rw-r--r--mullvad-daemon/src/lib.rs41
-rw-r--r--mullvad-daemon/src/settings.rs11
-rw-r--r--mullvad-daemon/src/version_check.rs13
-rw-r--r--mullvad-relay-selector/src/lib.rs205
-rw-r--r--mullvad-types/Cargo.toml1
-rw-r--r--mullvad-types/src/settings/mod.rs14
-rw-r--r--mullvad-types/src/version.rs7
11 files changed, 239 insertions, 71 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b7c8c4fc0..aad8dd68b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,8 @@ Line wrap the file at 100 chars. Th
- Windows daemon now looks up the MTU on the default interface and uses this MTU instead of the
default 1500. The 1500 is still the fallback if this for some reason fails. This may stop
fragmentation.
+- The default VPN protocol is slowly being changed from OpenVPN to WireGuard.
+ The app fetches the ratio between the protocols from the API.
#### Linux
- GUI: Add electron flags to run Wayland native if in a compositor/desktop known to work well
diff --git a/Cargo.lock b/Cargo.lock
index 161335a35d..d0658e6d98 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1727,6 +1727,7 @@ dependencies = [
"jnix",
"lazy_static",
"log",
+ "rand 0.8.5",
"regex",
"serde",
"talpid-types",
diff --git a/docs/relay-selector.md b/docs/relay-selector.md
index 1c6525d5cf..4f7dc31ea7 100644
--- a/docs/relay-selector.md
+++ b/docs/relay-selector.md
@@ -45,10 +45,13 @@ constraints, following default ones will take effect:
- If no tunnel protocol is specified for tunnel endpoints, then the behavior is different on Windows
and other platforms.
- - On Windows, OpenVPN is used.
- On MacOS and Linux, first two connection attempts will use WireGuard, over a random port at
first and then port 53. From the third attempt onwards, OpenVPN will be used, alternating
between UDP on any port and TCP on port 443.
+ - On Windows, a migration to WireGuard is ongoing and a percentage value provided by the API tells
+ clients to randomly decide if they will use WireGuard as a default or OpenVPN as a default.
+ The client's decision will persist over time.
+ If the client decides to use WireGuard it will have the same behavior as MacOS and Linux.
- If the tunnel protocol is specified as WireGuard without any other protocol constraints, then the
transport protocol is not applicable as only UDP endpoints exist and any port will be matched.
diff --git a/mullvad-api/src/lib.rs b/mullvad-api/src/lib.rs
index d967791192..b0222ca244 100644
--- a/mullvad-api/src/lib.rs
+++ b/mullvad-api/src/lib.rs
@@ -477,6 +477,16 @@ pub struct AppVersionResponse {
pub latest: AppVersion,
pub latest_stable: Option<AppVersion>,
pub latest_beta: AppVersion,
+ #[serde(default = "default_wg_threshold")]
+ pub x_threshold_wg_default: f32,
+}
+
+/// Temporary function that will be removed later. Used to generate default wg_threshold.
+/// In case there is no `x_threshold_wg_default` returned by the API result we interpret that to
+/// mean that the migration is done and WireGuard should be the default. In that case the threshold
+/// value should be 1.0
+fn default_wg_threshold() -> f32 {
+ 1.0
}
impl AppVersionProxy {
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index 2a7799b15c..770a231013 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -586,8 +586,9 @@ where
None
});
let settings = SettingsPersister::load(&settings_dir).await;
+ let app_version_info = version_check::load_cache(&cache_dir).await;
- let initial_selector_config = new_selector_config(&settings);
+ let initial_selector_config = new_selector_config(&settings, &app_version_info);
let relay_selector = RelaySelector::new(initial_selector_config, &resource_dir, &cache_dir);
let proxy_provider =
@@ -697,7 +698,6 @@ where
on_relay_list_update,
);
- let app_version_info = version_check::load_cache(&cache_dir).await;
let (version_updater, version_updater_handle) = version_check::VersionUpdater::new(
api_handle.clone(),
api_availability.clone(),
@@ -822,7 +822,7 @@ where
Command(command) => self.handle_command(command).await,
TriggerShutdown => self.trigger_shutdown_event(),
NewAppVersionInfo(app_version_info) => {
- self.handle_new_app_version_info(app_version_info)
+ self.handle_new_app_version_info(app_version_info);
}
DeviceEvent(event) => self.handle_device_event(event).await,
DeviceMigrationEvent(event) => self.handle_device_migration_event(event).await,
@@ -1032,6 +1032,8 @@ where
fn handle_new_app_version_info(&mut self, app_version_info: AppVersionInfo) {
self.app_version_info = Some(app_version_info.clone());
+ self.relay_selector
+ .set_config(new_selector_config(&self.settings, &self.app_version_info));
self.event_listener.notify_app_version(app_version_info);
}
@@ -1742,7 +1744,7 @@ where
self.event_listener
.notify_settings(self.settings.to_settings());
self.relay_selector
- .set_config(new_selector_config(&self.settings));
+ .set_config(new_selector_config(&self.settings, &self.app_version_info));
log::info!("Initiating tunnel restart because the relay settings changed");
self.reconnect_tunnel();
}
@@ -1884,7 +1886,7 @@ where
self.event_listener
.notify_settings(self.settings.to_settings());
self.relay_selector
- .set_config(new_selector_config(&self.settings));
+ .set_config(new_selector_config(&self.settings, &self.app_version_info));
if let Err(error) = self.api_handle.service().next_api_endpoint().await {
log::error!("Failed to rotate API endpoint: {}", error);
}
@@ -1914,7 +1916,7 @@ where
self.event_listener
.notify_settings(self.settings.to_settings());
self.relay_selector
- .set_config(new_selector_config(&self.settings));
+ .set_config(new_selector_config(&self.settings, &self.app_version_info));
self.reconnect_tunnel();
}
Self::oneshot_send(tx, Ok(()), "set_obfuscation_settings");
@@ -1940,7 +1942,7 @@ where
self.event_listener
.notify_settings(self.settings.to_settings());
self.relay_selector
- .set_config(new_selector_config(&self.settings));
+ .set_config(new_selector_config(&self.settings, &self.app_version_info));
log::info!("Initiating tunnel restart because bridge state changed");
self.reconnect_tunnel();
}
@@ -2253,11 +2255,34 @@ impl DaemonShutdownHandle {
}
}
-fn new_selector_config(settings: &Settings) -> SelectorConfig {
+fn new_selector_config(
+ settings: &Settings,
+ app_version_info: &Option<AppVersionInfo>,
+) -> SelectorConfig {
+ // In case of the app not having a version we safety default to OpenVPN to guard against the
+ // case where some error causes users to not recieve a version and in that case all going to
+ // wireguard. Magic number 0.0 implies that 0% of users should use Wireguard.
+ // This will be removed in the future when we the migration is done.
+ let wg_migration_threshold = app_version_info
+ .as_ref()
+ .map(|f| f.wg_migration_threshold)
+ .unwrap_or(0.0);
+
+ let default_tunnel_type = if cfg!(target_os = "windows") {
+ if wg_migration_threshold >= settings.wg_migration_rand_num {
+ TunnelType::Wireguard
+ } else {
+ TunnelType::OpenVpn
+ }
+ } else {
+ TunnelType::Wireguard
+ };
+
SelectorConfig {
relay_settings: settings.get_relay_settings(),
bridge_state: settings.get_bridge_state(),
bridge_settings: settings.bridge_settings.clone(),
obfuscation_settings: settings.obfuscation_settings.clone(),
+ default_tunnel_type,
}
}
diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs
index e69ca8316f..5ca3ff8908 100644
--- a/mullvad-daemon/src/settings.rs
+++ b/mullvad-daemon/src/settings.rs
@@ -5,6 +5,7 @@ use mullvad_types::{
settings::{DnsOptions, Settings},
wireguard::RotationInterval,
};
+use rand::Rng;
#[cfg(target_os = "windows")]
use std::collections::HashSet;
use std::{
@@ -69,6 +70,15 @@ impl SettingsPersister {
}
};
+ // If the settings file did not contain a wg_migration_rand_num then it will be initialized
+ // to -1.0 by serde. This block ensures that this value is correctly intitialzed to a
+ // percentage.
+ if settings.wg_migration_rand_num < 0.0 || settings.wg_migration_rand_num > 1.0 {
+ let mut rng = rand::thread_rng();
+ settings.wg_migration_rand_num = rng.gen_range(0.0..=1.0);
+ should_save |= true
+ }
+
// Force IPv6 to be enabled on Android
if cfg!(target_os = "android") {
should_save |=
@@ -185,6 +195,7 @@ impl SettingsPersister {
/// is being run or not.
fn default_settings() -> Settings {
let mut settings = Settings::default();
+
if crate::version::is_beta_version() {
settings.show_beta_releases = true;
}
diff --git a/mullvad-daemon/src/version_check.rs b/mullvad-daemon/src/version_check.rs
index 6e1a9bc568..72126b7862 100644
--- a/mullvad-daemon/src/version_check.rs
+++ b/mullvad-daemon/src/version_check.rs
@@ -47,7 +47,7 @@ const PLATFORM: &str = "windows";
#[cfg(target_os = "android")]
const PLATFORM: &str = "android";
-#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct CachedAppVersionInfo {
#[serde(flatten)]
pub version_info: AppVersionInfo,
@@ -281,11 +281,20 @@ impl VersionUpdater {
self.show_beta_releases || is_beta_version(),
);
+ let wg_migration_threshold = if response.x_threshold_wg_default.is_nan() {
+ // If the value should for some strange reason be NaN then safe default to 0.0
+ 0.0
+ } else {
+ // Make sure that the returned value is between 0% and 100%
+ response.x_threshold_wg_default.clamp(0.0, 1.0)
+ };
+
AppVersionInfo {
supported: response.supported,
latest_stable: response.latest_stable.unwrap_or_else(|| "".to_owned()),
latest_beta: response.latest_beta,
suggested_upgrade,
+ wg_migration_threshold,
}
}
@@ -375,6 +384,7 @@ impl VersionUpdater {
latest_stable: last_app_version_info.latest_stable,
latest_beta: last_app_version_info.latest_beta,
suggested_upgrade,
+ wg_migration_threshold: last_app_version_info.wg_migration_threshold,
}).await;
}
}
@@ -468,6 +478,7 @@ fn dev_version_cache() -> AppVersionInfo {
latest_stable: PRODUCT_VERSION.to_owned(),
latest_beta: PRODUCT_VERSION.to_owned(),
suggested_upgrade: None,
+ wg_migration_threshold: 1.0,
}
}
diff --git a/mullvad-relay-selector/src/lib.rs b/mullvad-relay-selector/src/lib.rs
index d9a16ff748..961357abf2 100644
--- a/mullvad-relay-selector/src/lib.rs
+++ b/mullvad-relay-selector/src/lib.rs
@@ -169,6 +169,7 @@ pub struct SelectorConfig {
pub bridge_state: BridgeState,
pub bridge_settings: BridgeSettings,
pub obfuscation_settings: ObfuscationSettings,
+ pub default_tunnel_type: TunnelType,
}
#[derive(Clone)]
@@ -231,8 +232,12 @@ impl RelaySelector {
Ok((SelectedRelay::Custom(custom_relay.clone()), None, None))
}
RelaySettings::Normal(constraints) => {
- let relay =
- self.get_tunnel_endpoint(constraints, config.bridge_state, retry_attempt)?;
+ let relay = self.get_tunnel_endpoint(
+ constraints,
+ config.bridge_state,
+ retry_attempt,
+ config.default_tunnel_type,
+ )?;
let bridge = match relay.endpoint {
MullvadEndpoint::OpenVpn(endpoint)
if endpoint.protocol == TransportProtocol::Tcp =>
@@ -271,6 +276,7 @@ impl RelaySelector {
relay_constraints: &RelayConstraints,
bridge_state: BridgeState,
retry_attempt: u32,
+ default_tunnel_type: TunnelType,
) -> Result<NormalSelectedRelay, Error> {
match relay_constraints.tunnel_protocol {
Constraint::Only(TunnelType::OpenVpn) => self.get_openvpn_endpoint(
@@ -289,9 +295,12 @@ impl RelaySelector {
&relay_constraints.wireguard_constraints,
retry_attempt,
),
- Constraint::Any => {
- self.get_any_tunnel_endpoint(relay_constraints, bridge_state, retry_attempt)
- }
+ Constraint::Any => self.get_any_tunnel_endpoint(
+ relay_constraints,
+ bridge_state,
+ retry_attempt,
+ default_tunnel_type,
+ ),
}
}
@@ -576,9 +585,14 @@ impl RelaySelector {
relay_constraints: &RelayConstraints,
bridge_state: BridgeState,
retry_attempt: u32,
+ default_tunnel_type: TunnelType,
) -> Result<NormalSelectedRelay, Error> {
- let preferred_constraints =
- self.preferred_constraints(relay_constraints, bridge_state, retry_attempt);
+ let preferred_constraints = self.preferred_constraints(
+ relay_constraints,
+ bridge_state,
+ retry_attempt,
+ default_tunnel_type,
+ );
if let Ok(result) = self.get_multihop_tunnel_endpoint_internal(&preferred_constraints) {
log::debug!(
@@ -604,10 +618,12 @@ impl RelaySelector {
original_constraints: &RelayConstraints,
bridge_state: BridgeState,
retry_attempt: u32,
+ default_tunnel_type: TunnelType,
) -> RelayConstraints {
let (preferred_port, preferred_protocol, preferred_tunnel) = self
.preferred_tunnel_constraints(
retry_attempt,
+ default_tunnel_type,
&original_constraints.location,
&original_constraints.providers,
&original_constraints.ownership,
@@ -929,40 +945,46 @@ impl RelaySelector {
fn preferred_tunnel_constraints(
&self,
retry_attempt: u32,
+ default_tunnel_type: TunnelType,
location_constraint: &Constraint<LocationConstraint>,
providers_constraint: &Constraint<Providers>,
ownership_constraint: &Constraint<Ownership>,
) -> (Constraint<u16>, TransportProtocol, TunnelType) {
- #[cfg(target_os = "windows")]
- {
- let location_supports_openvpn =
- self.parsed_relays.lock().relays().iter().any(|relay| {
- relay.active
- && relay.endpoint_data == RelayEndpointData::Openvpn
- && location_constraint.matches(relay)
- && providers_constraint.matches(relay)
- && ownership_constraint.matches(relay)
- });
- if location_supports_openvpn {
- let (preferred_port, preferred_protocol) =
- Self::preferred_openvpn_constraints(retry_attempt);
- return (preferred_port, preferred_protocol, TunnelType::OpenVpn);
+ match default_tunnel_type {
+ TunnelType::OpenVpn => {
+ let location_supports_openvpn =
+ self.parsed_relays.lock().relays().iter().any(|relay| {
+ relay.active
+ && relay.endpoint_data == RelayEndpointData::Openvpn
+ && location_constraint.matches(relay)
+ && providers_constraint.matches(relay)
+ && ownership_constraint.matches(relay)
+ });
+
+ if location_supports_openvpn {
+ let (preferred_port, preferred_protocol) =
+ Self::preferred_openvpn_constraints(retry_attempt);
+ return (preferred_port, preferred_protocol, TunnelType::OpenVpn);
+ }
}
- }
+ TunnelType::Wireguard => {
+ let location_supports_wireguard =
+ self.parsed_relays.lock().relays().iter().any(|relay| {
+ relay.active
+ && matches!(relay.endpoint_data, RelayEndpointData::Wireguard(_))
+ && location_constraint.matches(relay)
+ && providers_constraint.matches(relay)
+ && ownership_constraint.matches(relay)
+ });
- let location_supports_wireguard = self.parsed_relays.lock().relays().iter().any(|relay| {
- relay.active
- && matches!(relay.endpoint_data, RelayEndpointData::Wireguard(_))
- && location_constraint.matches(relay)
- && providers_constraint.matches(relay)
- && ownership_constraint.matches(relay)
- });
- // If location does not support WireGuard, defer to preferred OpenVPN tunnel
- // constraints
- if !location_supports_wireguard {
- let (preferred_port, preferred_protocol) =
- Self::preferred_openvpn_constraints(retry_attempt);
- return (preferred_port, preferred_protocol, TunnelType::OpenVpn);
+ // If location does not support WireGuard, defer to preferred OpenVPN tunnel
+ // constraints
+ if !location_supports_wireguard {
+ let (preferred_port, preferred_protocol) =
+ Self::preferred_openvpn_constraints(retry_attempt);
+ return (preferred_port, preferred_protocol, TunnelType::OpenVpn);
+ }
+ }
}
// Try out WireGuard in the first two connection attempts, first with any port,
@@ -1318,6 +1340,7 @@ mod test {
..Default::default()
},
bridge_state: BridgeState::Auto,
+ default_tunnel_type: TunnelType::Wireguard,
})),
}
}
@@ -1338,8 +1361,12 @@ mod test {
..RelayConstraints::default()
};
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::Off, 0);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::Off,
+ 0,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::Wireguard)
@@ -1347,7 +1374,12 @@ mod test {
for attempt in 0..10 {
assert!(relay_selector
- .get_any_tunnel_endpoint(&relay_constraints, BridgeState::Off, attempt)
+ .get_any_tunnel_endpoint(
+ &relay_constraints,
+ BridgeState::Off,
+ attempt,
+ TunnelType::Wireguard,
+ )
.is_ok());
}
@@ -1363,8 +1395,12 @@ mod test {
..RelayConstraints::default()
};
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::Off, 0);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::Off,
+ 0,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::OpenVpn)
@@ -1372,7 +1408,12 @@ mod test {
for attempt in 0..10 {
assert!(relay_selector
- .get_any_tunnel_endpoint(&relay_constraints, BridgeState::Off, attempt)
+ .get_any_tunnel_endpoint(
+ &relay_constraints,
+ BridgeState::Off,
+ attempt,
+ TunnelType::Wireguard,
+ )
.is_ok());
}
@@ -1385,6 +1426,7 @@ mod test {
&relay_constraints,
BridgeState::Off,
attempt,
+ TunnelType::OpenVpn,
);
assert_eq!(
preferred.tunnel_protocol,
@@ -1394,6 +1436,7 @@ mod test {
&relay_constraints,
BridgeState::Off,
attempt,
+ TunnelType::OpenVpn,
) {
Ok(result) if matches!(result.endpoint, MullvadEndpoint::OpenVpn(_)) => (),
_ => panic!("OpenVPN endpoint was not selected"),
@@ -1428,14 +1471,24 @@ mod test {
// The same host cannot be used for entry and exit
assert!(relay_selector
- .get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0)
+ .get_tunnel_endpoint(
+ &relay_constraints,
+ BridgeState::Off,
+ 0,
+ TunnelType::Wireguard,
+ )
.is_err());
relay_constraints.wireguard_constraints.entry_location = Constraint::Only(location2);
// If the entry and exit differ, this should succeed
assert!(relay_selector
- .get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0)
+ .get_tunnel_endpoint(
+ &relay_constraints,
+ BridgeState::Off,
+ 0,
+ TunnelType::Wireguard,
+ )
.is_ok());
}
@@ -1464,7 +1517,7 @@ mod test {
// The exit must not equal the entry
let exit_relay = relay_selector
- .get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0)
+ .get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0, TunnelType::OpenVpn)
.map_err(|error| error.to_string())?
.exit_relay;
@@ -1479,7 +1532,12 @@ mod test {
endpoint,
..
} = relay_selector
- .get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0)
+ .get_tunnel_endpoint(
+ &relay_constraints,
+ BridgeState::Off,
+ 0,
+ TunnelType::Wireguard,
+ )
.map_err(|error| error.to_string())?;
assert_eq!(exit_relay.hostname, specific_hostname);
@@ -1513,8 +1571,12 @@ mod test {
port: Constraint::Any,
});
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::On, 0);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::On,
+ 0,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::OpenVpn)
@@ -1539,8 +1601,12 @@ mod test {
tunnel_protocol: Constraint::Any,
..RelayConstraints::default()
};
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::On, 0);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::On,
+ 0,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::Wireguard)
@@ -1558,15 +1624,23 @@ mod test {
});
#[cfg(all(unix, not(target_os = "android")))]
{
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::On, 0);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::On,
+ 0,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::Wireguard)
);
}
- let preferred =
- relay_selector.preferred_constraints(&relay_constraints, BridgeState::On, 2);
+ let preferred = relay_selector.preferred_constraints(
+ &relay_constraints,
+ BridgeState::On,
+ 2,
+ TunnelType::Wireguard,
+ );
assert_eq!(
preferred.tunnel_protocol,
Constraint::Only(TunnelType::OpenVpn)
@@ -1597,7 +1671,13 @@ mod test {
let relay_selector = new_relay_selector();
- let result = relay_selector.get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0)
+ let default_tunnel_type = if cfg!(target_os = "windows") {
+ TunnelType::OpenVpn
+ } else {
+ TunnelType::Wireguard
+ };
+
+ let result = relay_selector.get_tunnel_endpoint(&relay_constraints, BridgeState::Off, 0, default_tunnel_type)
.expect("Failed to get relay when tunnel constraints are set to Any and retrying the selection");
// Windows will ignore WireGuard until WireGuard is supported well enough
// TODO: Remove this caveat once Windows defaults to using WireGuard
@@ -1649,7 +1729,7 @@ mod test {
fn test_selecting_wireguard_location_will_consider_multihop() {
let relay_selector = new_relay_selector();
- let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_MULTIHOP_CONSTRAINTS, BridgeState::Off, 0)
+ let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_MULTIHOP_CONSTRAINTS, BridgeState::Off, 0, TunnelType::Wireguard)
.expect("Failed to get relay when tunnel constraints are set to default WireGuard multihop constraints");
assert!(result.entry_relay.is_some());
@@ -1660,7 +1740,7 @@ mod test {
fn test_selecting_wg_endpoint_with_udp2tcp_obfuscation() {
let relay_selector = new_relay_selector();
- let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_SINGLEHOP_CONSTRAINTS, BridgeState::Off, 0)
+ let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_SINGLEHOP_CONSTRAINTS, BridgeState::Off, 0, TunnelType::Wireguard)
.expect("Failed to get relay when tunnel constraints are set to default WireGuard constraints");
assert!(result.entry_relay.is_none());
@@ -1689,7 +1769,7 @@ mod test {
fn test_selecting_wg_endpoint_with_auto_obfuscation() {
let relay_selector = new_relay_selector();
- let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_SINGLEHOP_CONSTRAINTS, BridgeState::Off, 0)
+ let result = relay_selector.get_tunnel_endpoint(&WIREGUARD_SINGLEHOP_CONSTRAINTS, BridgeState::Off, 0, TunnelType::Wireguard)
.expect("Failed to get relay when tunnel constraints are set to default WireGuard constraints");
assert!(result.entry_relay.is_none());
@@ -1729,7 +1809,12 @@ mod test {
for attempt in 0..1000 {
let result = relay_selector
- .get_tunnel_endpoint(&WIREGUARD_SINGLEHOP_CONSTRAINTS, BridgeState::Off, attempt)
+ .get_tunnel_endpoint(
+ &WIREGUARD_SINGLEHOP_CONSTRAINTS,
+ BridgeState::Off,
+ attempt,
+ TunnelType::Wireguard,
+ )
.expect("Failed to select a WireGuard relay");
assert!(result.entry_relay.is_none());
@@ -1765,7 +1850,7 @@ mod test {
for i in 0..10 {
constraints.ownership = Constraint::Only(Ownership::MullvadOwned);
let relay = relay_selector
- .get_tunnel_endpoint(&constraints, BridgeState::Auto, i)
+ .get_tunnel_endpoint(&constraints, BridgeState::Auto, i, TunnelType::Wireguard)
.unwrap();
assert!(matches!(
relay,
@@ -1777,7 +1862,7 @@ mod test {
constraints.ownership = Constraint::Only(Ownership::Rented);
let relay = relay_selector
- .get_tunnel_endpoint(&constraints, BridgeState::Auto, i)
+ .get_tunnel_endpoint(&constraints, BridgeState::Auto, i, TunnelType::Wireguard)
.unwrap();
assert!(matches!(
relay,
diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml
index 94a48c5538..c450e4e353 100644
--- a/mullvad-types/Cargo.toml
+++ b/mullvad-types/Cargo.toml
@@ -15,6 +15,7 @@ lazy_static = "1.1.0"
log = "0.4"
regex = "1"
serde = { version = "1.0", features = ["derive"] }
+rand = "0.8"
talpid-types = { path = "../talpid-types" }
diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs
index 7bfff42824..d7cc62e605 100644
--- a/mullvad-types/src/settings/mod.rs
+++ b/mullvad-types/src/settings/mod.rs
@@ -8,6 +8,7 @@ use crate::{
};
#[cfg(target_os = "android")]
use jnix::IntoJava;
+use rand::Rng;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(target_os = "windows")]
use std::{collections::HashSet, path::PathBuf};
@@ -88,11 +89,23 @@ pub struct Settings {
/// Split tunneling settings
#[cfg(windows)]
pub split_tunnel: SplitTunnelSettings,
+ /// Temporary variable for a random number between 0 and 1 that determines if the user should
+ /// use wireguard or openvpn when the automatic feature is set. This variable will be removed
+ /// in future versions.
+ /// A value of -1.0 implies that the variable should be initialized to a random number.
+ /// NOTE: This field will be removed completely in future versions.
+ #[serde(default = "out_of_range_wg_migration_rand_num")]
+ #[cfg_attr(target_os = "android", jnix(skip))]
+ pub wg_migration_rand_num: f32,
/// Specifies settings schema version
#[cfg_attr(target_os = "android", jnix(skip))]
settings_version: SettingsVersion,
}
+fn out_of_range_wg_migration_rand_num() -> f32 {
+ -1.0
+}
+
#[cfg(windows)]
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
pub struct SplitTunnelSettings {
@@ -120,6 +133,7 @@ impl Default for Settings {
auto_connect: false,
tunnel_options: TunnelOptions::default(),
show_beta_releases: false,
+ wg_migration_rand_num: rand::thread_rng().gen_range(0.0..=1.0),
#[cfg(windows)]
split_tunnel: SplitTunnelSettings::default(),
settings_version: CURRENT_SETTINGS_VERSION,
diff --git a/mullvad-types/src/version.rs b/mullvad-types/src/version.rs
index 8040b181b0..0bcb6ce7da 100644
--- a/mullvad-types/src/version.rs
+++ b/mullvad-types/src/version.rs
@@ -15,7 +15,7 @@ lazy_static::lazy_static! {
/// AppVersionInfo represents the current stable and the current latest release versions of the
/// Mullvad VPN app.
-#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[cfg_attr(target_os = "android", derive(IntoJava))]
#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))]
pub struct AppVersionInfo {
@@ -35,6 +35,11 @@ pub struct AppVersionInfo {
pub latest_beta: AppVersion,
/// Whether should update to newer version
pub suggested_upgrade: Option<AppVersion>,
+ /// Temporary field provided by the API used to decide if a user should default to Wireguard or
+ /// OpenVpn. Represents the percentage of users which should use Wireguard.
+ /// NOTE: This field will be removed completely in future versions.
+ #[cfg_attr(target_os = "android", jnix(skip))]
+ pub wg_migration_threshold: f32,
}
pub type AppVersion = String;