diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/tunnel.rs | 55 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 34 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 16 | ||||
| -rw-r--r-- | mullvad-daemon/src/settings.rs | 14 | ||||
| -rw-r--r-- | mullvad-management-interface/proto/management_interface.proto | 3 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types.rs | 6 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/config.rs | 5 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/mod.rs | 22 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_nt.rs | 1 | ||||
| -rw-r--r-- | talpid-types/src/net/wireguard.rs | 4 |
11 files changed, 149 insertions, 13 deletions
@@ -436,7 +436,7 @@ echo "org.gradle.jvmargs=-Xmx4608M" >> ~/.gradle/gradle.properties * `"network-manager"`: use `NetworkManager` service through DBus * `TALPID_FORCE_USERSPACE_WIREGUARD` - Forces the daemon to use the userspace implementation of - WireGuard on Linux. + WireGuard on Linux and Windows. * `TALPID_DNS_CACHE_POLICY` - On Windows, this changes how DNS is configured: * `1`: The default. This sets a global list of DNS servers that `dnscache` will use instead of diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs index 08306b70eb..e01d81a9da 100644 --- a/mullvad-cli/src/cmds/tunnel.rs +++ b/mullvad-cli/src/cmds/tunnel.rs @@ -34,11 +34,19 @@ impl Command for Tunnel { } fn create_wireguard_subcommand() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("wireguard") + let subcmd = clap::SubCommand::with_name("wireguard") .about("Manage options for Wireguard tunnels") .setting(clap::AppSettings::SubcommandRequiredElseHelp) .subcommand(create_wireguard_mtu_subcommand()) - .subcommand(create_wireguard_keys_subcommand()) + .subcommand(create_wireguard_keys_subcommand()); + #[cfg(windows)] + { + subcmd.subcommand(create_wireguard_use_wg_nt_subcommand()) + } + #[cfg(not(windows))] + { + subcmd + } } fn create_wireguard_mtu_subcommand() -> clap::App<'static, 'static> { @@ -61,6 +69,22 @@ fn create_wireguard_keys_subcommand() -> clap::App<'static, 'static> { .subcommand(create_wireguard_keys_rotation_interval_subcommand()) } +#[cfg(windows)] +fn create_wireguard_use_wg_nt_subcommand() -> clap::App<'static, 'static> { + clap::SubCommand::with_name("use-wireguard-nt") + .about("Enable or disable wireguard-nt") + .setting(clap::AppSettings::SubcommandRequiredElseHelp) + .subcommand(clap::SubCommand::with_name("get")) + .subcommand( + clap::SubCommand::with_name("set").arg( + clap::Arg::with_name("policy") + .required(true) + .takes_value(true) + .possible_values(&["on", "off"]), + ), + ) +} + fn create_wireguard_keys_rotation_interval_subcommand() -> clap::App<'static, 'static> { clap::SubCommand::with_name("rotation-interval") .about("Manage automatic key rotation (given in hours)") @@ -147,6 +171,13 @@ impl Tunnel { _ => unreachable!("unhandled command"), }, + #[cfg(windows)] + ("use-wireguard-nt", Some(matches)) => match matches.subcommand() { + ("get", _) => Self::process_wireguard_use_wg_nt_get().await, + ("set", Some(matches)) => Self::process_wireguard_use_wg_nt_set(matches).await, + _ => unreachable!("unhandled command"), + }, + _ => unreachable!("unhandled command"), } } @@ -180,6 +211,26 @@ impl Tunnel { Ok(()) } + #[cfg(windows)] + async fn process_wireguard_use_wg_nt_get() -> Result<()> { + let tunnel_options = Self::get_tunnel_options().await?; + if tunnel_options.wireguard.unwrap().use_wireguard_nt { + println!("enabled"); + } else { + println!("disabled"); + } + Ok(()) + } + + #[cfg(windows)] + async fn process_wireguard_use_wg_nt_set(matches: &clap::ArgMatches<'_>) -> Result<()> { + let new_state = matches.value_of("policy").unwrap() == "on"; + let mut rpc = new_rpc_client().await?; + rpc.set_use_wireguard_nt(new_state).await?; + println!("Updated wireguard-nt setting"); + Ok(()) + } + async fn process_wireguard_key_check() -> Result<()> { let mut rpc = new_rpc_client().await?; let key = rpc.get_wireguard_key(()).await; diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 19692d57fa..bde37e85fb 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -281,6 +281,9 @@ pub enum DaemonCommand { /// Disable split tunnel #[cfg(windows)] SetSplitTunnelState(ResponseTx<(), Error>, bool), + /// Toggle wireguard-nt on or off + #[cfg(target_os = "windows")] + UseWireGuardNt(ResponseTx<(), Error>, bool), /// Makes the daemon exit the main loop and quit. Shutdown, /// Saves the target tunnel state and enters a blocking state. The state is restored @@ -1230,6 +1233,8 @@ where ClearSplitTunnelApps(tx) => self.on_clear_split_tunnel_apps(tx).await, #[cfg(windows)] SetSplitTunnelState(tx, enabled) => self.on_set_split_tunnel_state(tx, enabled).await, + #[cfg(target_os = "windows")] + UseWireGuardNt(tx, state) => self.on_use_wireguard_nt(tx, state).await, Shutdown => self.trigger_shutdown_event(), PrepareRestart => self.on_prepare_restart(), #[cfg(target_os = "android")] @@ -1937,6 +1942,35 @@ where } } + #[cfg(windows)] + async fn on_use_wireguard_nt(&mut self, tx: ResponseTx<(), Error>, state: bool) { + let save_result = self + .settings + .set_use_wireguard_nt(state) + .await + .map_err(Error::SettingsError); + match save_result { + Ok(settings_changed) => { + Self::oneshot_send(tx, Ok(()), "use_wireguard_nt response"); + if settings_changed { + self.event_listener + .notify_settings(self.settings.to_settings()); + if let Some(TunnelType::Wireguard) = self.get_connected_tunnel_type() { + info!("Initiating tunnel restart"); + self.reconnect_tunnel(); + } + } + } + Err(error) => { + error!( + "{}", + error.display_chain_with_msg("Unable to save settings") + ); + Self::oneshot_send(tx, Err(error), "use_wireguard_nt response"); + } + } + } + async fn on_update_relay_settings( &mut self, tx: ResponseTx<(), settings::Error>, diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index 0b2f6b463f..cef8d42f78 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -688,6 +688,22 @@ impl ManagementService for ManagementServiceImpl { async fn set_split_tunnel_state(&self, _: Request<bool>) -> ServiceResult<()> { Ok(Response::new(())) } + + #[cfg(windows)] + async fn set_use_wireguard_nt(&self, request: Request<bool>) -> ServiceResult<()> { + log::debug!("set_use_wireguard_nt"); + let state = request.into_inner(); + let (tx, rx) = oneshot::channel(); + self.send_command_to_daemon(DaemonCommand::UseWireGuardNt(tx, state))?; + self.wait_for_result(rx) + .await? + .map_err(map_daemon_error) + .map(Response::new) + } + #[cfg(not(windows))] + async fn set_use_wireguard_nt(&self, _: Request<bool>) -> ServiceResult<()> { + Ok(Response::new(())) + } } impl ManagementServiceImpl { diff --git a/mullvad-daemon/src/settings.rs b/mullvad-daemon/src/settings.rs index 02568e3226..e3cfeb8ddc 100644 --- a/mullvad-daemon/src/settings.rs +++ b/mullvad-daemon/src/settings.rs @@ -330,6 +330,20 @@ impl SettingsPersister { self.update(should_save).await } + #[cfg(windows)] + pub async fn set_use_wireguard_nt(&mut self, state: bool) -> Result<bool, Error> { + let should_save = Self::update_field( + &mut self + .settings + .tunnel_options + .wireguard + .options + .use_wireguard_nt, + state, + ); + self.update(should_save).await + } + fn update_field<T: Eq>(field: &mut T, new_value: T) -> bool { if *field != new_value { *field = new_value; diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 8711ba7b1b..a6d88bb0e0 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -69,6 +69,8 @@ service ManagementService { rpc RemoveSplitTunnelApp(google.protobuf.StringValue) returns (google.protobuf.Empty) {} rpc ClearSplitTunnelApps(google.protobuf.Empty) returns (google.protobuf.Empty) {} rpc SetSplitTunnelState(google.protobuf.BoolValue) returns (google.protobuf.Empty) {} + + rpc SetUseWireguardNt(google.protobuf.BoolValue) returns (google.protobuf.Empty) {} } message RelaySettingsUpdate { @@ -379,6 +381,7 @@ message TunnelOptions { message WireguardOptions { uint32 mtu = 1; google.protobuf.Duration rotation_interval = 2; + bool use_wireguard_nt = 3; } message GenericOptions { bool enable_ipv6 = 1; diff --git a/mullvad-management-interface/src/types.rs b/mullvad-management-interface/src/types.rs index 81fdbb0e87..4e3a7217eb 100644 --- a/mullvad-management-interface/src/types.rs +++ b/mullvad-management-interface/src/types.rs @@ -562,6 +562,10 @@ impl From<&mullvad_types::settings::TunnelOptions> for TunnelOptions { .wireguard .rotation_interval .map(|ivl| Duration::from(std::time::Duration::from(ivl))), + #[cfg(windows)] + use_wireguard_nt: options.wireguard.options.use_wireguard_nt, + #[cfg(not(windows))] + use_wireguard_nt: false, }), generic: Some(tunnel_options::GenericOptions { enable_ipv6: options.generic.enable_ipv6, @@ -1199,6 +1203,8 @@ impl TryFrom<TunnelOptions> for mullvad_types::settings::TunnelOptions { } else { None }, + #[cfg(windows)] + use_wireguard_nt: wireguard_options.use_wireguard_nt, }, rotation_interval: wireguard_options .rotation_interval diff --git a/talpid-core/src/tunnel/wireguard/config.rs b/talpid-core/src/tunnel/wireguard/config.rs index ae82483c66..252bf8418f 100644 --- a/talpid-core/src/tunnel/wireguard/config.rs +++ b/talpid-core/src/tunnel/wireguard/config.rs @@ -23,6 +23,9 @@ pub struct Config { /// Enable IPv6 routing rules #[cfg(target_os = "linux")] pub enable_ipv6: bool, + /// Temporary switch for wireguard-nt + #[cfg(target_os = "windows")] + pub use_wireguard_nt: bool, } const DEFAULT_MTU: u16 = 1380; @@ -109,6 +112,8 @@ impl Config { fwmark: crate::linux::TUNNEL_FW_MARK, #[cfg(target_os = "linux")] enable_ipv6: generic_options.enable_ipv6, + #[cfg(target_os = "windows")] + use_wireguard_nt: wg_options.use_wireguard_nt, }) } diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs index 8ecec51f4d..a3fa426ca2 100644 --- a/talpid-core/src/tunnel/wireguard/mod.rs +++ b/talpid-core/src/tunnel/wireguard/mod.rs @@ -355,16 +355,18 @@ impl WireguardMonitor { } #[cfg(target_os = "windows")] - match wireguard_nt::WgNtTunnel::start_tunnel(config, log_path, resource_dir) { - Ok(tunnel) => { - log::debug!("Using WireGuardNT"); - return Ok(Box::new(tunnel)); - } - Err(error) => { - log::error!( - "{}", - error.display_chain_with_msg("Failed to setup WireGuardNT tunnel") - ); + if config.use_wireguard_nt { + match wireguard_nt::WgNtTunnel::start_tunnel(config, log_path, resource_dir) { + Ok(tunnel) => { + log::debug!("Using WireGuardNT"); + return Ok(Box::new(tunnel)); + } + Err(error) => { + log::error!( + "{}", + error.display_chain_with_msg("Failed to setup WireGuardNT tunnel") + ); + } } } diff --git a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs index 97207eb933..2314ee283f 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs @@ -1058,6 +1058,7 @@ mod tests { ipv4_gateway: "0.0.0.0".parse().unwrap(), ipv6_gateway: None, mtu: 0, + use_wireguard_nt: true, } }; static ref WG_STRUCT_CONFIG: Interface = Interface { diff --git a/talpid-types/src/net/wireguard.rs b/talpid-types/src/net/wireguard.rs index c5bde3547e..beced8357d 100644 --- a/talpid-types/src/net/wireguard.rs +++ b/talpid-types/src/net/wireguard.rs @@ -86,6 +86,10 @@ pub struct TunnelOptions { jnix(map = "|maybe_mtu| maybe_mtu.map(|mtu| mtu as i32)") )] pub mtu: Option<u16>, + /// Temporary switch for wireguard-nt + #[cfg(windows)] + #[serde(default)] + pub use_wireguard_nt: bool, } /// Wireguard x25519 private key |
