diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-12-07 14:40:22 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2021-12-07 14:40:22 +0100 |
| commit | 5fa6d87ef42bc3452d13e8149b11fd26386b6a83 (patch) | |
| tree | cd50e7a85952cde802dbc018958305c3e506fb40 | |
| parent | f646fcd1607129e3823acd2ff104f5c8dc001772 (diff) | |
| parent | 1491c9d0462da46caa7250a50c5451bf50659d84 (diff) | |
| download | mullvadvpn-5fa6d87ef42bc3452d13e8149b11fd26386b6a83.tar.xz mullvadvpn-5fa6d87ef42bc3452d13e8149b11fd26386b6a83.zip | |
Merge branch 'wg-nt-update'
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| m--------- | dist-assets/binaries | 0 | ||||
| -rw-r--r-- | dist-assets/windows/installer.nsh | 5 | ||||
| -rw-r--r-- | gui/tasks/distribution.js | 2 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/wireguard_nt.rs | 182 | ||||
| -rw-r--r-- | talpid-core/src/windows.rs | 26 | ||||
| -rw-r--r-- | windows/driverlogic/src/driverlogic.cpp | 16 | ||||
| -rw-r--r-- | windows/driverlogic/src/wireguard.h | 6 |
8 files changed, 70 insertions, 171 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 305c0107f4..595d472ba3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,9 @@ Line wrap the file at 100 chars. Th * Android Background Execution Limits. * The System Settings way of killing apps ("Force Stop"). +#### Windows +- Update wireguard-nt to 0.10.1. + ### Fixed - Always kill `sslocal` if the tunnel monitor fails to start when using bridges. - Show relay location constraint correctly in the CLI when it is set to `any`. @@ -46,6 +49,7 @@ Line wrap the file at 100 chars. Th - Fix app size after changing display scale. - Fix daemon not starting if all excluded app paths reside on non-existent/unmounted volumes. - Remove tray icon of current running app version when upgrading. +- Allow Mullvad wireguard-nt tunnels to work simultaneously with other wg-nt tunnels. #### Android - Fix Quick Settings tile showing wrong state in certain scenarios. diff --git a/dist-assets/binaries b/dist-assets/binaries -Subproject 19a97997b188855d0ba5aedb7419683df45d93b +Subproject 0ce1cdd413319fbbf0756d339113d36391d535c diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh index 402802e1dc..1f8d8823cd 100644 --- a/dist-assets/windows/installer.nsh +++ b/dist-assets/windows/installer.nsh @@ -13,7 +13,6 @@ # !define WINTUN_POOL "Mullvad" -!define WG_NT_POOL "Mullvad" # "sc" exit code !define SERVICE_STARTED 0 @@ -68,7 +67,7 @@ SetOutPath "$TEMP" File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wintun\wintun.dll" - File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wireguard-nt\wireguard.dll" + File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wireguard-nt\mullvad-wireguard.dll" File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-Release\driverlogic.exe" !macroend @@ -234,7 +233,7 @@ log::Log "RemoveWireGuardNt()" - nsExec::ExecToStack '"$TEMP\driverlogic.exe" wg-nt-cleanup ${WG_NT_POOL}' + nsExec::ExecToStack '"$TEMP\driverlogic.exe" wg-nt-cleanup' Pop $0 Pop $1 diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js index 6f74d65eda..f677cc799b 100644 --- a/gui/tasks/distribution.js +++ b/gui/tasks/distribution.js @@ -114,7 +114,7 @@ const config = { { from: distAssets('binaries/x86_64-pc-windows-msvc/sslocal.exe'), to: '.' }, { from: root('build/lib/x86_64-pc-windows-msvc/libwg.dll'), to: '.' }, { from: distAssets('binaries/x86_64-pc-windows-msvc/wintun/wintun.dll'), to: '.' }, - { from: distAssets('binaries/x86_64-pc-windows-msvc/wireguard-nt/wireguard.dll'), to: '.' }, + { from: distAssets('binaries/x86_64-pc-windows-msvc/wireguard-nt/mullvad-wireguard.dll'), to: '.' }, ], }, diff --git a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs index 66b9c086fc..dde1a991fd 100644 --- a/talpid-core/src/tunnel/wireguard/wireguard_nt.rs +++ b/talpid-core/src/tunnel/wireguard/wireguard_nt.rs @@ -40,7 +40,7 @@ use winapi::{ lazy_static! { static ref WG_NT_DLL: Mutex<Option<Arc<WgNtDll>>> = Mutex::new(None); - static ref ADAPTER_POOL: U16CString = U16CString::from_str("Mullvad").unwrap(); + static ref ADAPTER_TYPE: U16CString = U16CString::from_str("Mullvad").unwrap(); static ref ADAPTER_ALIAS: U16CString = U16CString::from_str("Mullvad").unwrap(); } @@ -51,24 +51,14 @@ const ADAPTER_GUID: GUID = GUID { Data4: [0x8b, 0x05, 0x31, 0xda, 0x25, 0xa0, 0x44, 0xa9], }; -/// Longest possible adapter name (in characters), including null terminator -const MAX_ADAPTER_NAME: usize = 128; - -type WireGuardOpenAdapterFn = - unsafe extern "stdcall" fn(pool: *const u16, name: *const u16) -> RawHandle; type WireGuardCreateAdapterFn = unsafe extern "stdcall" fn( - pool: *const u16, name: *const u16, + tunnel_type: *const u16, requested_guid: *const GUID, - reboot_required: *mut BOOL, ) -> RawHandle; -type WireGuardFreeAdapterFn = unsafe extern "stdcall" fn(adapter: RawHandle); -type WireGuardDeleteAdapterFn = - unsafe extern "stdcall" fn(adapter: RawHandle, reboot_required: *mut BOOL) -> BOOL; +type WireGuardCloseAdapterFn = unsafe extern "stdcall" fn(adapter: RawHandle); type WireGuardGetAdapterLuidFn = unsafe extern "stdcall" fn(adapter: RawHandle, luid: *mut NET_LUID); -type WireGuardGetAdapterNameFn = - unsafe extern "stdcall" fn(adapter: RawHandle, name: *mut u16) -> BOOL; type WireGuardSetConfigurationFn = unsafe extern "stdcall" fn( adapter: RawHandle, config: *const MaybeUninit<u8>, @@ -116,29 +106,19 @@ enum WireGuardAdapterLogState { type WireGuardSetAdapterLoggingFn = unsafe extern "stdcall" fn(adapter: RawHandle, state: WireGuardAdapterLogState) -> BOOL; -type RebootRequired = bool; - pub type Result<T> = std::result::Result<T, Error>; #[derive(err_derive::Error, Debug)] #[error(no_from)] pub enum Error { /// Failed to load WireGuardNT - #[error(display = "Failed to load wireguard.dll")] + #[error(display = "Failed to load mullvad-wireguard.dll")] DllError(#[error(source)] io::Error), - /// Failed to remove tunnel interface - #[error(display = "Failed to remove residual tunnel device")] - DeleteExistingTunnelError(#[error(source)] io::Error), - /// Failed to create tunnel interface #[error(display = "Failed to create WireGuard device")] CreateTunnelDeviceError(#[error(source)] io::Error), - /// Failed to delete tunnel interface - #[error(display = "Failed to delete WireGuard device")] - DeleteTunnelDeviceError(#[error(source)] io::Error), - /// Failed to obtain tunnel interface alias #[error(display = "Failed to obtain interface name")] ObtainAliasError(#[error(source)] io::Error), @@ -432,40 +412,20 @@ impl WgNtTunnel { resource_dir: &Path, ) -> Result<Self> { let dll = load_wg_nt_dll(resource_dir)?; - let logger_handle = LoggerHandle::new(dll.clone(), log_path)?; - - { - if let Ok(device) = WgNtAdapter::open(dll.clone(), &*ADAPTER_POOL, &*ADAPTER_ALIAS) { - device.delete().map_err(Error::DeleteExistingTunnelError)?; - } - } - - let (device, reboot_required) = WgNtAdapter::create( + let device = WgNtAdapter::create( dll.clone(), - &*ADAPTER_POOL, &*ADAPTER_ALIAS, + &*ADAPTER_TYPE, Some(ADAPTER_GUID.clone()), ) .map_err(Error::CreateTunnelDeviceError)?; - if reboot_required { - log::warn!("You may need to reboot to finish installing WireGuardNT"); - } - let interface_luid = device.luid(); - let interface_name = match device.name() { - Ok(name) => name.to_string_lossy(), - Err(error) => { - if let Err(error) = device.delete() { - log::error!( - "{}", - error.display_chain_with_msg("Failed to delete tunnel device") - ); - } - return Err(Error::ObtainAliasError(error)); - } - }; + let interface_name = device + .name() + .map_err(Error::ObtainAliasError)? + .to_string_lossy(); let tunnel = WgNtTunnel { device: Some(device), @@ -477,13 +437,8 @@ impl WgNtTunnel { Ok(tunnel) } - fn stop_tunnel(&mut self) -> Result<()> { - if let Some(device) = self.device.take() { - if let Err(error) = device.delete() { - return Err(Error::DeleteTunnelDeviceError(error)); - } - } - Ok(()) + fn stop_tunnel(&mut self) { + let _ = self.device.take(); } fn configure(&self, config: &Config) -> Result<()> { @@ -510,12 +465,7 @@ impl WgNtTunnel { impl Drop for WgNtTunnel { fn drop(&mut self) { - if let Err(error) = self.stop_tunnel() { - log::error!( - "{}", - error.display_chain_with_msg("Failed to stop WireGuardNT tunnel") - ); - } + self.stop_tunnel(); } } @@ -580,27 +530,21 @@ unsafe impl Send for WgNtAdapter {} unsafe impl Sync for WgNtAdapter {} impl WgNtAdapter { - fn open(dll_handle: Arc<WgNtDll>, pool: &U16CStr, name: &U16CStr) -> io::Result<Self> { - let handle = dll_handle.open_adapter(pool, name)?; - Ok(Self { dll_handle, handle }) - } - fn create( dll_handle: Arc<WgNtDll>, - pool: &U16CStr, name: &U16CStr, + tunnel_type: &U16CStr, requested_guid: Option<GUID>, - ) -> io::Result<(Self, RebootRequired)> { - let (handle, restart_required) = dll_handle.create_adapter(pool, name, requested_guid)?; - Ok((Self { dll_handle, handle }, restart_required)) - } - - fn delete(self) -> io::Result<RebootRequired> { - unsafe { self.dll_handle.delete_adapter(self.handle) } + ) -> io::Result<Self> { + let handle = dll_handle.create_adapter(name, tunnel_type, requested_guid)?; + Ok(Self { dll_handle, handle }) } fn name(&self) -> io::Result<U16CString> { - unsafe { self.dll_handle.get_adapter_name(self.handle) } + windows::alias_from_luid(&self.luid()).and_then(|alias| { + U16CString::from_os_str(alias) + .map_err(|_| io::Error::new(io::ErrorKind::Other, "unexpected null char")) + }) } fn luid(&self) -> NET_LUID { @@ -638,18 +582,15 @@ impl WgNtAdapter { impl Drop for WgNtAdapter { fn drop(&mut self) { - unsafe { self.dll_handle.free_adapter(self.handle) }; + unsafe { self.dll_handle.close_adapter(self.handle) }; } } struct WgNtDll { handle: HINSTANCE, - func_open: WireGuardOpenAdapterFn, func_create: WireGuardCreateAdapterFn, - func_delete: WireGuardDeleteAdapterFn, - func_free: WireGuardFreeAdapterFn, + func_close: WireGuardCloseAdapterFn, func_get_adapter_luid: WireGuardGetAdapterLuidFn, - func_get_adapter_name: WireGuardGetAdapterNameFn, func_set_configuration: WireGuardSetConfigurationFn, func_get_configuration: WireGuardGetConfigurationFn, func_set_adapter_state: WireGuardSetStateFn, @@ -662,7 +603,8 @@ unsafe impl Sync for WgNtDll {} impl WgNtDll { pub fn new(resource_dir: &Path) -> io::Result<Self> { - let wg_nt_dll = U16CString::from_os_str_truncate(resource_dir.join("wireguard.dll")); + let wg_nt_dll = + U16CString::from_os_str_truncate(resource_dir.join("mullvad-wireguard.dll")); let handle = unsafe { LoadLibraryExW( @@ -683,28 +625,16 @@ impl WgNtDll { ) -> io::Result<Self> { Ok(WgNtDll { handle, - func_open: unsafe { - *((&get_proc_fn( - handle, - CStr::from_bytes_with_nul(b"WireGuardOpenAdapter\0").unwrap(), - )?) as *const _ as *const _) - }, func_create: unsafe { *((&get_proc_fn( handle, CStr::from_bytes_with_nul(b"WireGuardCreateAdapter\0").unwrap(), )?) as *const _ as *const _) }, - func_delete: unsafe { - *((&get_proc_fn( - handle, - CStr::from_bytes_with_nul(b"WireGuardDeleteAdapter\0").unwrap(), - )?) as *const _ as *const _) - }, - func_free: unsafe { + func_close: unsafe { *((&get_proc_fn( handle, - CStr::from_bytes_with_nul(b"WireGuardFreeAdapter\0").unwrap(), + CStr::from_bytes_with_nul(b"WireGuardCloseAdapter\0").unwrap(), )?) as *const _ as *const _) }, func_get_adapter_luid: unsafe { @@ -713,12 +643,6 @@ impl WgNtDll { CStr::from_bytes_with_nul(b"WireGuardGetAdapterLUID\0").unwrap(), )?) as *const _ as *const _) }, - func_get_adapter_name: unsafe { - *((&get_proc_fn( - handle, - CStr::from_bytes_with_nul(b"WireGuardGetAdapterName\0").unwrap(), - )?) as *const _ as *const _) - }, func_set_configuration: unsafe { *((&get_proc_fn( handle, @@ -760,54 +684,25 @@ impl WgNtDll { Ok(handle) } - pub fn open_adapter(&self, pool: &U16CStr, name: &U16CStr) -> io::Result<RawHandle> { - let handle = unsafe { (self.func_open)(pool.as_ptr(), name.as_ptr()) }; - if handle == ptr::null_mut() { - return Err(io::Error::last_os_error()); - } - Ok(handle) - } - pub fn create_adapter( &self, - pool: &U16CStr, name: &U16CStr, + tunnel_type: &U16CStr, requested_guid: Option<GUID>, - ) -> io::Result<(RawHandle, RebootRequired)> { + ) -> io::Result<RawHandle> { let guid_ptr = match requested_guid.as_ref() { Some(guid) => guid as *const _, None => ptr::null_mut(), }; - let mut reboot_required = 0; - let handle = unsafe { - (self.func_create)(pool.as_ptr(), name.as_ptr(), guid_ptr, &mut reboot_required) - }; + let handle = unsafe { (self.func_create)(name.as_ptr(), tunnel_type.as_ptr(), guid_ptr) }; if handle == ptr::null_mut() { return Err(io::Error::last_os_error()); } - Ok((handle, reboot_required != 0)) - } - - pub unsafe fn delete_adapter(&self, adapter: RawHandle) -> io::Result<RebootRequired> { - let mut reboot_required = 0; - let result = (self.func_delete)(adapter, &mut reboot_required); - if result == 0 { - return Err(io::Error::last_os_error()); - } - Ok(reboot_required != 0) + Ok(handle) } - pub unsafe fn free_adapter(&self, adapter: RawHandle) { - (self.func_free)(adapter); - } - - pub unsafe fn get_adapter_name(&self, adapter: RawHandle) -> io::Result<U16CString> { - let mut alias_buffer = vec![0u16; MAX_ADAPTER_NAME]; - let result = (self.func_get_adapter_name)(adapter, alias_buffer.as_mut_ptr()); - if result == 0 { - return Err(io::Error::last_os_error()); - } - Ok(U16CString::from_vec_truncate(alias_buffer)) + pub unsafe fn close_adapter(&self, adapter: RawHandle) { + (self.func_close)(adapter); } pub unsafe fn get_adapter_luid(&self, adapter: RawHandle) -> NET_LUID { @@ -1051,15 +946,8 @@ impl Tunnel for WgNtTunnel { } fn stop(mut self: Box<Self>) -> std::result::Result<(), super::TunnelError> { - if let Err(error) = self.stop_tunnel() { - log::error!( - "{}", - error.display_chain_with_msg("Failed to stop WireGuardNT tunnel") - ); - Err(super::TunnelError::StopWireguardError { status: 0 }) - } else { - Ok(()) - } + self.stop_tunnel(); + Ok(()) } } diff --git a/talpid-core/src/windows.rs b/talpid-core/src/windows.rs index 7648441a91..1febc5bc21 100644 --- a/talpid-core/src/windows.rs +++ b/talpid-core/src/windows.rs @@ -1,9 +1,12 @@ use socket2::SockAddr; use std::{ - ffi::OsStr, + ffi::{OsStr, OsString}, fmt, io, mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, - os::windows::{ffi::OsStrExt, io::RawHandle}, + os::windows::{ + ffi::{OsStrExt, OsStringExt}, + io::RawHandle, + }, sync::Mutex, time::{Duration, Instant}, }; @@ -12,12 +15,13 @@ use winapi::shared::{ in6addr::IN6_ADDR, inaddr::IN_ADDR, netioapi::{ - CancelMibChangeNotify2, ConvertInterfaceAliasToLuid, FreeMibTable, GetIpInterfaceEntry, - GetUnicastIpAddressEntry, GetUnicastIpAddressTable, MibAddInstance, - NotifyIpInterfaceChange, SetIpInterfaceEntry, MIB_IPINTERFACE_ROW, + CancelMibChangeNotify2, ConvertInterfaceAliasToLuid, ConvertInterfaceLuidToAlias, + FreeMibTable, GetIpInterfaceEntry, GetUnicastIpAddressEntry, GetUnicastIpAddressTable, + MibAddInstance, NotifyIpInterfaceChange, SetIpInterfaceEntry, MIB_IPINTERFACE_ROW, MIB_UNICASTIPADDRESS_ROW, MIB_UNICASTIPADDRESS_TABLE, }, nldef::{IpDadStatePreferred, IpDadStateTentative, NL_DAD_STATE}, + ntddndis::NDIS_IF_MAX_STRING_SIZE, ntdef::FALSE, winerror::{ERROR_NOT_FOUND, NO_ERROR}, ws2def::{ @@ -359,6 +363,18 @@ pub fn luid_from_alias<T: AsRef<OsStr>>(alias: T) -> io::Result<NET_LUID> { Ok(luid) } +/// Returns the alias of an interface given its LUID. +pub fn alias_from_luid(luid: &NET_LUID) -> io::Result<OsString> { + let mut buffer = [0u16; NDIS_IF_MAX_STRING_SIZE + 1]; + let status = + unsafe { ConvertInterfaceLuidToAlias(luid, &mut buffer[0] as *mut _, buffer.len()) }; + if status != NO_ERROR { + return Err(io::Error::from_raw_os_error(status as i32)); + } + let nul = buffer.iter().position(|&c| c == 0u16).unwrap(); + Ok(OsString::from_wide(&buffer[0..nul])) +} + fn af_family_from_family(family: Option<AddressFamily>) -> u16 { family .map(|family| family as u16) diff --git a/windows/driverlogic/src/driverlogic.cpp b/windows/driverlogic/src/driverlogic.cpp index 3cb1739e21..aba746d3e3 100644 --- a/windows/driverlogic/src/driverlogic.cpp +++ b/windows/driverlogic/src/driverlogic.cpp @@ -283,24 +283,16 @@ ReturnCode CommandWireGuardNtCleanup(const std::vector<std::wstring> &args) { ArgumentContext argsContext(args); - argsContext.ensureExactArgumentCount(1); - - const auto poolName = argsContext.next(); + argsContext.ensureExactArgumentCount(0); WireGuardNtDll wgNt; - BOOL rebootRequired; - - if (FALSE == wgNt.deletePoolDriver(poolName.c_str(), &rebootRequired)) + if (FALSE == wgNt.deleteDriver()) { - throw std::runtime_error("Failed to delete WireGuardNT pool"); + throw std::runtime_error("Failed to delete WireGuardNT driver"); } - std::wstringstream ss; - - ss << L"Successfully deleted WireGuardNT pool. Reboot required: " << rebootRequired; - - Log(ss.str()); + Log(L"Successfully deleted WireGuardNT driver"); return ReturnCode::GENERAL_SUCCESS; } diff --git a/windows/driverlogic/src/wireguard.h b/windows/driverlogic/src/wireguard.h index 5892b248f1..e99da56c05 100644 --- a/windows/driverlogic/src/wireguard.h +++ b/windows/driverlogic/src/wireguard.h @@ -10,7 +10,7 @@ public: WireGuardNtDll() : dllHandle(nullptr) { - auto path = GetProcessModulePath().replace_filename(L"wireguard.dll"); + auto path = GetProcessModulePath().replace_filename(L"mullvad-wireguard.dll"); dllHandle = LoadLibraryExW(path.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); if (nullptr == dllHandle) @@ -20,7 +20,7 @@ public: try { - deletePoolDriver = getProcAddressOrThrow<WIREGUARD_DELETE_POOL_DRIVER_FUNC*>("WireGuardDeletePoolDriver"); + deleteDriver = getProcAddressOrThrow<WIREGUARD_DELETE_DRIVER_FUNC*>("WireGuardDeleteDriver"); } catch (...) { @@ -37,7 +37,7 @@ public: } } - WIREGUARD_DELETE_POOL_DRIVER_FUNC *deletePoolDriver; + WIREGUARD_DELETE_DRIVER_FUNC *deleteDriver; private: |
