From a81e9a682bf74bf51f6a0bec97f5cc09de0e7e4c Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Wed, 12 Nov 2025 11:00:26 +0100 Subject: [PATCH 01/12] add mtu setting --- src-tauri/src/app_config.rs | 2 + src/i18n/en/index.ts | 5 ++ src/i18n/i18n-types.ts | 20 ++++++++ src/pages/client/clientAPI/types.ts | 1 + .../GlobalSettingsTab/GlobalSettingsTab.tsx | 47 +++++++++++++++++++ 5 files changed, 75 insertions(+) diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index 492d9023..048768d8 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -71,6 +71,7 @@ pub struct AppConfig { pub log_level: LevelFilter, /// In seconds. How much time after last network activity the connection is automatically dropped. pub peer_alive_period: u32, + pub mtu: Option, } // Important: keep in sync with client store default in frontend @@ -82,6 +83,7 @@ impl Default for AppConfig { tray_theme: AppTrayTheme::Color, log_level: LevelFilter::Info, peer_alive_period: 300, + mtu: None, } } } diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 2dca9b4f..854e9ee4 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -161,6 +161,11 @@ If you are an admin/devops - all your customers (instances) and all their tunnel helper: 'If active connection exceeds given time without making an handshake with the server. The connection will be considered invalid and disconnected automatically.', }, + mtu: { + title: 'Maximum Transmission Unit (MTU)', + helper: + 'MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues.', + }, tray: { title: 'System tray', label: 'Tray icon theme', diff --git a/src/i18n/i18n-types.ts b/src/i18n/i18n-types.ts index 088f2ae0..6d4701f4 100644 --- a/src/i18n/i18n-types.ts +++ b/src/i18n/i18n-types.ts @@ -376,6 +376,16 @@ type RootTranslation = { */ helper: string } + mtu: { + /** + * M​a​x​i​m​u​m​ ​T​r​a​n​s​m​i​s​s​i​o​n​ ​U​n​i​t​ ​(​M​T​U​) + */ + title: string + /** + * M​T​U​ ​s​e​t​s​ ​t​h​e​ ​l​a​r​g​e​s​t​ ​p​a​c​k​e​t​ ​s​i​z​e​ ​s​e​n​t​ ​t​h​r​o​u​g​h​ ​t​h​e​ ​n​e​t​w​o​r​k​.​ ​L​o​w​e​r​i​n​g​ ​i​t​ ​c​a​n​ ​i​m​p​r​o​v​e​ ​c​o​n​n​e​c​t​i​o​n​ ​s​t​a​b​i​l​i​t​y​ ​i​n​ ​r​e​s​t​r​i​c​t​i​v​e​ ​o​r​ ​u​n​r​e​l​i​a​b​l​e​ ​I​S​P​ ​n​e​t​w​o​r​k​s​.​ ​T​h​e​ ​d​e​f​a​u​l​t​ ​v​a​l​u​e​ ​o​n​ ​m​o​s​t​ ​s​y​s​t​e​m​s​ ​i​s​ ​1​5​0​0​.​ ​T​r​y​ ​l​o​w​e​r​i​n​g​ ​i​t​ ​t​o​ ​1​3​0​0​-​1​4​0​0​ ​i​f​ ​y​o​u​ ​e​n​c​o​u​n​t​e​r​ ​I​S​P​-​r​e​l​a​t​e​d​ ​i​s​s​u​e​s​. + */ + helper: string + } tray: { /** * S​y​s​t​e​m​ ​t​r​a​y @@ -2066,6 +2076,16 @@ export type TranslationFunctions = { */ helper: () => LocalizedString } + mtu: { + /** + * Maximum Transmission Unit (MTU) + */ + title: () => LocalizedString + /** + * MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues. + */ + helper: () => LocalizedString + } tray: { /** * System tray diff --git a/src/pages/client/clientAPI/types.ts b/src/pages/client/clientAPI/types.ts index 9bb6dce6..b4eeb624 100644 --- a/src/pages/client/clientAPI/types.ts +++ b/src/pages/client/clientAPI/types.ts @@ -80,6 +80,7 @@ export type AppConfig = { tray_theme: TrayIconTheme; check_for_updates: boolean; peer_alive_period: number; + mtu: number; }; export type PlatformInfo = { diff --git a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx index 4d6dea45..10839715 100644 --- a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx +++ b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx @@ -81,6 +81,44 @@ export const GlobalSettingsTab = () => { required_error: LL.form.errors.required(), }) .gte(120, LL.form.errors.minValue({ min: 120 })), + // TODO nullable number + mtu: z.coerce.number(), + // mtu: z + // .coerce + // .number() + // .lte(65535, LL.form.errors.maxValue({ max: 65535 })) + // .transform((val) => val === 0 ? null : val) + // .optional(), + // mtu: z.preprocess( + // (val) => + // val == null || (typeof val === 'string' && val.trim() === '') + // ? null + // : Number(val), + // z.nullable( + // z.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })), + // ), + // ), + // mtu: z + // .union([ + // z.coerce.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })), + // z.null(), + // ]) + // .transform((val) => (val === 0 ? null : val)) + // .optional() + // mtu: z.union([ + // z.literal(""), // 1. Explicitly allow an empty string + // z.coerce // 2. Or, allow a number... + // .number() + // .lte(65535, LL.form.errors.maxValue({ max: 65535 })), + // ]) + // .optional() // 3. Still allow the field to be undefined + // .transform((val) => (val === "" ? null : val)) + // mtu: z.union([ + // z.string().optional(), + // z.coerce.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })) + // ]) + // .transform((val) => (val === 0 || val === null ? null : val)) + // .optional() }), [LL.form.errors], ); @@ -139,6 +177,15 @@ export const GlobalSettingsTab = () => { +
+
+

{localLL.mtu.title()}

+ +

{localLL.mtu.helper()}

+
+
+ +
); }; From 58542f505c4a1ccf1e1061853d93d7ad01a334f8 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Wed, 12 Nov 2025 11:03:48 +0100 Subject: [PATCH 02/12] make AppConfig::mtu optional --- src/pages/client/clientAPI/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/client/clientAPI/types.ts b/src/pages/client/clientAPI/types.ts index b4eeb624..10aa6b17 100644 --- a/src/pages/client/clientAPI/types.ts +++ b/src/pages/client/clientAPI/types.ts @@ -80,7 +80,7 @@ export type AppConfig = { tray_theme: TrayIconTheme; check_for_updates: boolean; peer_alive_period: number; - mtu: number; + mtu?: number; }; export type PlatformInfo = { From 9f0b8dc544dfdb44c8a14f139c46d3b6e73dbbc5 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Wed, 12 Nov 2025 11:39:55 +0100 Subject: [PATCH 03/12] set mtu when connecting to location/tunnel --- src-tauri/src/utils.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index d518655c..6459388d 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -59,6 +59,7 @@ pub(crate) async fn setup_interface( location: &Location, name: &str, preshared_key: Option, + mtu: Option, pool: &DbPool, ) -> Result { debug!("Setting up interface for location: {location}"); @@ -76,9 +77,10 @@ pub(crate) async fn setup_interface( }; debug!("Found free port: {port} for interface {interface_name}."); - let interface_config = location + let mut interface_config = location .interface_configurarion(pool, interface_name.clone(), preshared_key) .await?; + interface_config.mtu = mtu; debug!("Creating interface for location {location} with configuration {interface_config:?}"); let request = CreateInterfaceRequest { config: Some(interface_config.clone().into()), @@ -307,7 +309,7 @@ pub fn get_service_log_dir() -> &'static Path { } /// Setup client interface -pub async fn setup_interface_tunnel(tunnel: &Tunnel, name: &str) -> Result { +pub async fn setup_interface_tunnel(tunnel: &Tunnel, name: &str, mtu: Option) -> Result { debug!("Setting up interface for tunnel {tunnel}"); let interface_name = get_interface_name(name); // prepare peer config @@ -397,7 +399,7 @@ pub async fn setup_interface_tunnel(tunnel: &Tunnel, name: &str) -> Result Result<(), Error> { debug!("Setting up the connection for location {}", location.name); let state = handle.state::(); - let interface_name = setup_interface(location, &location.name, preshared_key, &DB_POOL).await?; + let mtu = state.app_config.lock().unwrap().mtu; + let interface_name = + setup_interface(location, &location.name, preshared_key, mtu, &DB_POOL).await?; state .add_connection(location.id, &interface_name, ConnectionType::Location) .await; @@ -607,7 +611,8 @@ pub(crate) async fn handle_connection_for_tunnel( ) -> Result<(), Error> { debug!("Setting up the connection for tunnel: {}", tunnel.name); let state = handle.state::(); - let interface_name = setup_interface_tunnel(tunnel, &tunnel.name).await?; + let mtu = state.app_config.lock().unwrap().mtu; + let interface_name = setup_interface_tunnel(tunnel, &tunnel.name, mtu).await?; state .add_connection(tunnel.id, &interface_name, ConnectionType::Tunnel) .await; From 5c5a880c8bd3d3e52d83b1a1b85b6ba7db06e298 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Wed, 12 Nov 2025 13:09:07 +0100 Subject: [PATCH 04/12] add mtu to client -> service grpc structs --- src-tauri/proto | 2 +- src-tauri/src/service/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src-tauri/proto b/src-tauri/proto index 96249ebd..db6741ae 160000 --- a/src-tauri/proto +++ b/src-tauri/proto @@ -1 +1 @@ -Subproject commit 96249ebde0556f4ae8c47eebc6015efb04ed0104 +Subproject commit db6741ae29d030d0ffecd2ef52aebfb51e9c7f37 diff --git a/src-tauri/src/service/mod.rs b/src-tauri/src/service/mod.rs index b81a70c1..cb90ebf4 100644 --- a/src-tauri/src/service/mod.rs +++ b/src-tauri/src/service/mod.rs @@ -575,6 +575,7 @@ impl From for proto::InterfaceConfig { .join(","), port: u32::from(config.port), peers: config.peers.into_iter().map(Into::into).collect(), + mtu: config.mtu, } } } @@ -592,7 +593,7 @@ impl From for InterfaceConfiguration { addresses, port: config.port as u16, peers: config.peers.into_iter().map(Into::into).collect(), - mtu: None, + mtu: config.mtu, } } } From 5f7a72284a33d5f42473ae87547db3241409d74c Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Wed, 12 Nov 2025 13:25:06 +0100 Subject: [PATCH 05/12] bump wireguard-rs dependency --- src-tauri/Cargo.lock | 4 ++-- src-tauri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index de98b815..9a42820e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -669,7 +669,7 @@ dependencies = [ [[package]] name = "boringtun" version = "0.6.0" -source = "git+https://github.com/DefGuard/wireguard-rs?rev=886186c1e088e4805ab8049436c28cf3ea26d727#886186c1e088e4805ab8049436c28cf3ea26d727" +source = "git+https://github.com/DefGuard/wireguard-rs?rev=c99c0b209b19d9ce82e0f5d0d727261f8f9916b3#c99c0b209b19d9ce82e0f5d0d727261f8f9916b3" dependencies = [ "aead", "base64 0.22.1", @@ -1478,7 +1478,7 @@ dependencies = [ [[package]] name = "defguard_wireguard_rs" version = "0.9.0" -source = "git+https://github.com/DefGuard/wireguard-rs?rev=886186c1e088e4805ab8049436c28cf3ea26d727#886186c1e088e4805ab8049436c28cf3ea26d727" +source = "git+https://github.com/DefGuard/wireguard-rs?rev=c99c0b209b19d9ce82e0f5d0d727261f8f9916b3#c99c0b209b19d9ce82e0f5d0d727261f8f9916b3" dependencies = [ "base64 0.22.1", "boringtun", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 26774378..ea2930b8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -4,7 +4,7 @@ default-members = [".", "cli"] [workspace.dependencies] clap = { version = "4.5", features = ["cargo", "derive", "env"] } -defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs", rev = "886186c1e088e4805ab8049436c28cf3ea26d727" } +defguard_wireguard_rs = { git = "https://github.com/DefGuard/wireguard-rs", rev = "c99c0b209b19d9ce82e0f5d0d727261f8f9916b3" } dirs-next = "2.0" prost = "0.14" reqwest = { version = "0.12", features = ["cookies", "json"] } From 31b5ddb090d21aecf24d816720cd0d279ec0df57 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 10:41:42 +0100 Subject: [PATCH 06/12] use 0 for default mtu value --- src-tauri/src/app_config.rs | 15 ++++++- src-tauri/src/utils.rs | 4 +- src/pages/client/hooks/useClientStore.tsx | 1 + .../GlobalSettingsTab/GlobalSettingsTab.tsx | 43 +++---------------- src/shared/utils/types.ts | 1 + 5 files changed, 22 insertions(+), 42 deletions(-) create mode 100644 src/shared/utils/types.ts diff --git a/src-tauri/src/app_config.rs b/src-tauri/src/app_config.rs index 048768d8..0fd9fb23 100644 --- a/src-tauri/src/app_config.rs +++ b/src-tauri/src/app_config.rs @@ -71,7 +71,8 @@ pub struct AppConfig { pub log_level: LevelFilter, /// In seconds. How much time after last network activity the connection is automatically dropped. pub peer_alive_period: u32, - pub mtu: Option, + /// Maximal transmission unit. 0 means default value. + pub mtu: u32, } // Important: keep in sync with client store default in frontend @@ -83,7 +84,7 @@ impl Default for AppConfig { tray_theme: AppTrayTheme::Color, log_level: LevelFilter::Info, peer_alive_period: 300, - mtu: None, + mtu: 0, } } } @@ -132,4 +133,14 @@ impl AppConfig { } } } + + /// Wraps MTU in an Option. We don't store Option directly in AppConfig to avoid struct-patch + /// ambiguity when applying updates coming from the frontend. An incoming MTU value of 0 is + /// interpreted as a request to fall back to the default. + pub fn get_mtu(&self) -> Option { + match self.mtu { + 0 => None, + v => Some(v), + } + } } diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 6459388d..1b997058 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -578,7 +578,7 @@ pub(crate) async fn handle_connection_for_location( ) -> Result<(), Error> { debug!("Setting up the connection for location {}", location.name); let state = handle.state::(); - let mtu = state.app_config.lock().unwrap().mtu; + let mtu = state.app_config.lock().unwrap().get_mtu(); let interface_name = setup_interface(location, &location.name, preshared_key, mtu, &DB_POOL).await?; state @@ -611,7 +611,7 @@ pub(crate) async fn handle_connection_for_tunnel( ) -> Result<(), Error> { debug!("Setting up the connection for tunnel: {}", tunnel.name); let state = handle.state::(); - let mtu = state.app_config.lock().unwrap().mtu; + let mtu = state.app_config.lock().unwrap().get_mtu(); let interface_name = setup_interface_tunnel(tunnel, &tunnel.name, mtu).await?; state .add_connection(tunnel.id, &interface_name, ConnectionType::Tunnel) diff --git a/src/pages/client/hooks/useClientStore.tsx b/src/pages/client/hooks/useClientStore.tsx index 52d16890..a722d8c5 100644 --- a/src/pages/client/hooks/useClientStore.tsx +++ b/src/pages/client/hooks/useClientStore.tsx @@ -35,6 +35,7 @@ const defaultValues: StoreValues = { tray_theme: 'color', check_for_updates: true, peer_alive_period: 300, + mtu: 0, }, platformInfo: { client_version: '', diff --git a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx index 10839715..3cd64ad3 100644 --- a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx +++ b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx @@ -81,44 +81,11 @@ export const GlobalSettingsTab = () => { required_error: LL.form.errors.required(), }) .gte(120, LL.form.errors.minValue({ min: 120 })), - // TODO nullable number - mtu: z.coerce.number(), - // mtu: z - // .coerce - // .number() - // .lte(65535, LL.form.errors.maxValue({ max: 65535 })) - // .transform((val) => val === 0 ? null : val) - // .optional(), - // mtu: z.preprocess( - // (val) => - // val == null || (typeof val === 'string' && val.trim() === '') - // ? null - // : Number(val), - // z.nullable( - // z.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })), - // ), - // ), - // mtu: z - // .union([ - // z.coerce.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })), - // z.null(), - // ]) - // .transform((val) => (val === 0 ? null : val)) - // .optional() - // mtu: z.union([ - // z.literal(""), // 1. Explicitly allow an empty string - // z.coerce // 2. Or, allow a number... - // .number() - // .lte(65535, LL.form.errors.maxValue({ max: 65535 })), - // ]) - // .optional() // 3. Still allow the field to be undefined - // .transform((val) => (val === "" ? null : val)) - // mtu: z.union([ - // z.string().optional(), - // z.coerce.number().lte(65535, LL.form.errors.maxValue({ max: 65535 })) - // ]) - // .transform((val) => (val === 0 || val === null ? null : val)) - // .optional() + mtu: z.number({ + invalid_type_error: LL.form.errors.required(), + required_error: LL.form.errors.required(), + }) + .lte(65535, LL.form.errors.maxValue({ max: 65535 })), }), [LL.form.errors], ); diff --git a/src/shared/utils/types.ts b/src/shared/utils/types.ts new file mode 100644 index 00000000..e2da842c --- /dev/null +++ b/src/shared/utils/types.ts @@ -0,0 +1 @@ +type ReplaceField = Omit & { [P in K]: V }; From 9ebc38248b61bc8f9d5a5519def0d2119047380c Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 10:53:09 +0100 Subject: [PATCH 07/12] cargo fmt --- src-tauri/src/utils.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 1b997058..2baa658e 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -309,7 +309,11 @@ pub fn get_service_log_dir() -> &'static Path { } /// Setup client interface -pub async fn setup_interface_tunnel(tunnel: &Tunnel, name: &str, mtu: Option) -> Result { +pub async fn setup_interface_tunnel( + tunnel: &Tunnel, + name: &str, + mtu: Option, +) -> Result { debug!("Setting up interface for tunnel {tunnel}"); let interface_name = get_interface_name(name); // prepare peer config From 3bbf959adc6f78d413583ced23dfa6f0859c797e Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 11:08:23 +0100 Subject: [PATCH 08/12] add mtu default value description, remove unused util --- src/i18n/en/index.ts | 4 ++-- src/i18n/i18n-types.ts | 8 ++++---- src/shared/utils/types.ts | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 src/shared/utils/types.ts diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 854e9ee4..c598695e 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -162,9 +162,9 @@ If you are an admin/devops - all your customers (instances) and all their tunnel 'If active connection exceeds given time without making an handshake with the server. The connection will be considered invalid and disconnected automatically.', }, mtu: { - title: 'Maximum Transmission Unit (MTU)', + title: 'MTU (Maximum Transmission Unit)', helper: - 'MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues.', + 'MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues. 0 = default.', }, tray: { title: 'System tray', diff --git a/src/i18n/i18n-types.ts b/src/i18n/i18n-types.ts index 6d4701f4..7eeaf5be 100644 --- a/src/i18n/i18n-types.ts +++ b/src/i18n/i18n-types.ts @@ -378,11 +378,11 @@ type RootTranslation = { } mtu: { /** - * M​a​x​i​m​u​m​ ​T​r​a​n​s​m​i​s​s​i​o​n​ ​U​n​i​t​ ​(​M​T​U​) + * M​T​U​ ​(​M​a​x​i​m​u​m​ ​T​r​a​n​s​m​i​s​s​i​o​n​ ​U​n​i​t​) */ title: string /** - * M​T​U​ ​s​e​t​s​ ​t​h​e​ ​l​a​r​g​e​s​t​ ​p​a​c​k​e​t​ ​s​i​z​e​ ​s​e​n​t​ ​t​h​r​o​u​g​h​ ​t​h​e​ ​n​e​t​w​o​r​k​.​ ​L​o​w​e​r​i​n​g​ ​i​t​ ​c​a​n​ ​i​m​p​r​o​v​e​ ​c​o​n​n​e​c​t​i​o​n​ ​s​t​a​b​i​l​i​t​y​ ​i​n​ ​r​e​s​t​r​i​c​t​i​v​e​ ​o​r​ ​u​n​r​e​l​i​a​b​l​e​ ​I​S​P​ ​n​e​t​w​o​r​k​s​.​ ​T​h​e​ ​d​e​f​a​u​l​t​ ​v​a​l​u​e​ ​o​n​ ​m​o​s​t​ ​s​y​s​t​e​m​s​ ​i​s​ ​1​5​0​0​.​ ​T​r​y​ ​l​o​w​e​r​i​n​g​ ​i​t​ ​t​o​ ​1​3​0​0​-​1​4​0​0​ ​i​f​ ​y​o​u​ ​e​n​c​o​u​n​t​e​r​ ​I​S​P​-​r​e​l​a​t​e​d​ ​i​s​s​u​e​s​. + * M​T​U​ ​s​e​t​s​ ​t​h​e​ ​l​a​r​g​e​s​t​ ​p​a​c​k​e​t​ ​s​i​z​e​ ​s​e​n​t​ ​t​h​r​o​u​g​h​ ​t​h​e​ ​n​e​t​w​o​r​k​.​ ​L​o​w​e​r​i​n​g​ ​i​t​ ​c​a​n​ ​i​m​p​r​o​v​e​ ​c​o​n​n​e​c​t​i​o​n​ ​s​t​a​b​i​l​i​t​y​ ​i​n​ ​r​e​s​t​r​i​c​t​i​v​e​ ​o​r​ ​u​n​r​e​l​i​a​b​l​e​ ​I​S​P​ ​n​e​t​w​o​r​k​s​.​ ​T​h​e​ ​d​e​f​a​u​l​t​ ​v​a​l​u​e​ ​o​n​ ​m​o​s​t​ ​s​y​s​t​e​m​s​ ​i​s​ ​1​5​0​0​.​ ​T​r​y​ ​l​o​w​e​r​i​n​g​ ​i​t​ ​t​o​ ​1​3​0​0​-​1​4​0​0​ ​i​f​ ​y​o​u​ ​e​n​c​o​u​n​t​e​r​ ​I​S​P​-​r​e​l​a​t​e​d​ ​i​s​s​u​e​s​.​ ​0​ ​=​ ​d​e​f​a​u​l​t​. */ helper: string } @@ -2078,11 +2078,11 @@ export type TranslationFunctions = { } mtu: { /** - * Maximum Transmission Unit (MTU) + * MTU (Maximum Transmission Unit) */ title: () => LocalizedString /** - * MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues. + * MTU sets the largest packet size sent through the network. Lowering it can improve connection stability in restrictive or unreliable ISP networks. The default value on most systems is 1500. Try lowering it to 1300-1400 if you encounter ISP-related issues. 0 = default. */ helper: () => LocalizedString } diff --git a/src/shared/utils/types.ts b/src/shared/utils/types.ts deleted file mode 100644 index e2da842c..00000000 --- a/src/shared/utils/types.ts +++ /dev/null @@ -1 +0,0 @@ -type ReplaceField = Omit & { [P in K]: V }; From 18ab39c046e7f95c1729b91f9988a9c628fb810b Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 11:08:56 +0100 Subject: [PATCH 09/12] fix linting --- .../components/GlobalSettingsTab/GlobalSettingsTab.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx index 3cd64ad3..8f2ff8a5 100644 --- a/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx +++ b/src/pages/client/pages/ClientSettingsPage/components/GlobalSettingsTab/GlobalSettingsTab.tsx @@ -81,7 +81,8 @@ export const GlobalSettingsTab = () => { required_error: LL.form.errors.required(), }) .gte(120, LL.form.errors.minValue({ min: 120 })), - mtu: z.number({ + mtu: z + .number({ invalid_type_error: LL.form.errors.required(), required_error: LL.form.errors.required(), }) From eafec78bd463126c0b4882db0cef72a28fc2164f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 11:12:19 +0100 Subject: [PATCH 10/12] fix typo --- src-tauri/src/database/models/location.rs | 2 +- src-tauri/src/utils.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/database/models/location.rs b/src-tauri/src/database/models/location.rs index 3b092b50..bfaa553d 100644 --- a/src-tauri/src/database/models/location.rs +++ b/src-tauri/src/database/models/location.rs @@ -257,7 +257,7 @@ impl Location { } #[cfg(not(target_os = "macos"))] - pub(crate) async fn interface_configurarion<'e, E>( + pub(crate) async fn interface_configuration<'e, E>( &self, executor: E, interface_name: String, diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 2baa658e..543956ff 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -78,7 +78,7 @@ pub(crate) async fn setup_interface( debug!("Found free port: {port} for interface {interface_name}."); let mut interface_config = location - .interface_configurarion(pool, interface_name.clone(), preshared_key) + .interface_configuration(pool, interface_name.clone(), preshared_key) .await?; interface_config.mtu = mtu; debug!("Creating interface for location {location} with configuration {interface_config:?}"); From 1f65c7638ffb3d54bb95258c3574a3cfaabb4409 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Thu, 13 Nov 2025 11:14:23 +0100 Subject: [PATCH 11/12] AppConfig::mtu non-optional in frontend --- src/pages/client/clientAPI/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/client/clientAPI/types.ts b/src/pages/client/clientAPI/types.ts index 10aa6b17..b4eeb624 100644 --- a/src/pages/client/clientAPI/types.ts +++ b/src/pages/client/clientAPI/types.ts @@ -80,7 +80,7 @@ export type AppConfig = { tray_theme: TrayIconTheme; check_for_updates: boolean; peer_alive_period: number; - mtu?: number; + mtu: number; }; export type PlatformInfo = { From 55f44b2ad190e400658700cb49b83029a58f1e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= Date: Thu, 13 Nov 2025 11:24:46 +0100 Subject: [PATCH 12/12] Fix build on macOS --- src-tauri/src/utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src-tauri/src/utils.rs b/src-tauri/src/utils.rs index 543956ff..7797602a 100644 --- a/src-tauri/src/utils.rs +++ b/src-tauri/src/utils.rs @@ -122,6 +122,7 @@ pub(crate) async fn setup_interface( location: &Location, name: &str, preshared_key: Option, + _mtu: Option, pool: &DbPool, ) -> Result { debug!("Setting up interface for location: {location}");