diff --git a/rust/Cargo.lock b/rust/Cargo.lock index a2eeb30ae..6d9cf664a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1222,6 +1222,7 @@ dependencies = [ "url", "uuid", "webrtc", + "windows 0.52.0", "wintun", ] @@ -2064,6 +2065,7 @@ dependencies = [ "tracing-android", "uuid", "webrtc", + "windows 0.52.0", "wintun", ] diff --git a/rust/connlib/shared/Cargo.toml b/rust/connlib/shared/Cargo.toml index 8c95a870b..174850da6 100644 --- a/rust/connlib/shared/Cargo.toml +++ b/rust/connlib/shared/Cargo.toml @@ -53,3 +53,10 @@ rtnetlink = { version = "0.13", default-features = false, features = ["tokio_soc # Windows tunnel dependencies [target.'cfg(target_os = "windows")'.dependencies] wintun = "0.3.2" + +# Windows Win32 API +[target.'cfg(windows)'.dependencies.windows] +version = "0.52.0" +features = [ + "Win32_Foundation", +] diff --git a/rust/connlib/shared/src/error.rs b/rust/connlib/shared/src/error.rs index 86d8bfecd..761edfde6 100644 --- a/rust/connlib/shared/src/error.rs +++ b/rust/connlib/shared/src/error.rs @@ -144,6 +144,9 @@ pub enum ConnlibError { #[error(transparent)] Uuid(#[from] uuid::Error), #[cfg(target_os = "windows")] + #[error("Windows error: {0}")] + WindowsError(#[from] windows::core::Error), + #[cfg(target_os = "windows")] #[error(transparent)] Wintun(#[from] wintun::Error), #[error("Token has expired")] diff --git a/rust/connlib/tunnel/Cargo.toml b/rust/connlib/tunnel/Cargo.toml index 11aef2cec..e479e1aae 100644 --- a/rust/connlib/tunnel/Cargo.toml +++ b/rust/connlib/tunnel/Cargo.toml @@ -50,3 +50,13 @@ tracing-android = "0.2" [target.'cfg(target_os = "windows")'.dependencies] uuid = { version = "1.5.0", features = ["v4"] } wintun = "0.3.2" + +# Windows Win32 API +[target.'cfg(windows)'.dependencies.windows] +version = "0.52.0" +features = [ + "Win32_Foundation", + "Win32_NetworkManagement_IpHelper", + "Win32_NetworkManagement_Ndis", + "Win32_Networking_WinSock", +] diff --git a/rust/connlib/tunnel/src/device_channel/tun_windows.rs b/rust/connlib/tunnel/src/device_channel/tun_windows.rs index de1c7ed3f..5628f3872 100644 --- a/rust/connlib/tunnel/src/device_channel/tun_windows.rs +++ b/rust/connlib/tunnel/src/device_channel/tun_windows.rs @@ -10,6 +10,13 @@ use std::{ task::{ready, Context, Poll}, }; use tokio::sync::mpsc; +use windows::Win32::{ + NetworkManagement::{ + IpHelper::{GetIpInterfaceEntry, SetIpInterfaceEntry, MIB_IPINTERFACE_ROW}, + Ndis::NET_LUID_LH, + }, + Networking::WinSock::AF_INET, +}; // TODO: Double-check that all these get dropped gracefully on disconnect pub struct Tun { @@ -34,6 +41,8 @@ impl Drop for Tun { // Hides Powershell's console on Windows // const CREATE_NO_WINDOW: u32 = 0x08000000; +// Copied from tun_linux.rs +const DEFAULT_MTU: u32 = 1280; impl Tun { pub fn new(config: &InterfaceConfig) -> Result { @@ -86,6 +95,8 @@ impl Tun { .stdout(Stdio::null()) .status()?; + set_iface_config(adapter.get_luid(), DEFAULT_MTU)?; + // Set our DNS IP as the DNS server for our interface // TODO: Lots of issues with this. Windows does seem to use it, but I'm not sure why. And there's a delay before some Firefox windows pick it up. Curl might be picking it up faster because its DNS cache starts cold every time. Command::new("powershell") @@ -199,3 +210,30 @@ fn start_recv_thread( tracing::debug!("recv_task exiting gracefully"); }) } + +/// Sets MTU on the interface +/// TODO: Set IP and other things in here too, so the code is more organized +fn set_iface_config(luid: wintun::NET_LUID_LH, mtu: u32) -> Result<()> { + // Safety: Both NET_LUID_LH unions should be the same. We're just copying out + // the u64 value and re-wrapping it, since wintun doesn't refer to the windows + // crate's version of NET_LUID_LH. + let luid = NET_LUID_LH { + Value: unsafe { luid.Value }, + }; + + let mut row = MIB_IPINTERFACE_ROW { + Family: AF_INET, + InterfaceLuid: luid, + ..Default::default() + }; + + unsafe { GetIpInterfaceEntry(&mut row) }?; + + row.NlMtu = mtu; + // https://stackoverflow.com/questions/54857292/setipinterfaceentry-returns-error-invalid-parameter + row.SitePrefixLength = 0; + + // Ignore error if we can't set everything + unsafe { SetIpInterfaceEntry(&mut row) }?; + Ok(()) +} diff --git a/rust/windows-client/src-tauri/Cargo.toml b/rust/windows-client/src-tauri/Cargo.toml index 6b04071f0..0553e54da 100755 --- a/rust/windows-client/src-tauri/Cargo.toml +++ b/rust/windows-client/src-tauri/Cargo.toml @@ -49,11 +49,10 @@ wintun = "0.3.2" version = "0.52.0" features = [ "Win32_Foundation", + # Needed for deep_link module "Win32_Security", - "Win32_System_LibraryLoader", + # Needed for deep_link module "Win32_System_SystemServices", - "Win32_UI_Shell", - "Win32_UI_WindowsAndMessaging", ] [features]