Skip to content

feat(config): add configurable VPN MTU with unified resolution across…#75

Merged
zerox80 merged 3 commits into
mainfrom
Beta
Apr 24, 2026
Merged

feat(config): add configurable VPN MTU with unified resolution across…#75
zerox80 merged 3 commits into
mainfrom
Beta

Conversation

@zerox80

@zerox80 zerox80 commented Apr 24, 2026

Copy link
Copy Markdown
Owner

Add client-side VPN MTU configuration across all platforms

Summary

  • Add user-configurable VPN MTU (vpn_mtu, range 1280–1360, default 1280) to all client platforms
  • QUIC Payload MTU is always derived automatically as vpn_mtu + 80 bytes — never independently settable
  • Consolidate per-platform MTU resolution into a single shared function resolve_tun_mtu() with fallback chain: explicit config → VPN_MTU env var → default 1280

Motivation

The server already supports VPN_MTU via .env. However, clients had no way to set the matching TUN MTU — Android was hardcoded to 1280, and Windows/Linux only read the env var. If the server operator changed VPN_MTU (e.g. to 1360 for PPPoE/DSL paths), clients would mismatch and send out-of-spec QUIC packets.

Changes (20 files, +440 / −133)

Shared (shared/)

  • lib.rs — Added resolve_tun_mtu(vpn_mtu: Option<u16>) -> u16, MIN_TUN_MTU (1280), MAX_TUN_MTU (1360) constants
  • ipc.rs — Added vpn_mtu: Option<u16> field to Config struct (#[serde(default)], backward-compatible)

Android (JNI + Rust + Kotlin)

  • jni.rs — Added vpn_mtu: jint parameter to native init() (0 = use default)
  • connection.rs — Accepts vpn_mtu: Option<u16>, uses resolve_tun_mtu() instead of hardcoded DEFAULT_TUN_MTU
  • NativeLib.kt — Added vpnMtu: Int to external init()
  • MaviVpnService.kt — Passes prefs.savedVpnMtu to both NativeLib.init() and VpnService.Builder.setMtu()
  • PrefsManager.kt — Added savedVpnMtu: Int SharedPreferences field
  • VpnViewModel.kt — Added vpnMtu state flow, updated saveSettings() signature
  • SettingsScreen.kt — Added VPN MTU text input field with validation (1280–1360)
  • MainActivity.kt — Updated settings callback to pass vpnMtu

Linux CLI

  • vpn_core.rs — Removed local read_tun_mtu_from_env(), uses resolve_tun_mtu(config.vpn_mtu)
  • main.rs — Added interactive VPN MTU prompt, displays MTU when loading saved config

Windows CLI

  • vpn_core/mod.rs — Removed CLIENT_TUN_MTU LazyLock and read_tun_mtu_from_env()
  • vpn_core/handshake.rs — Accepts vpn_mtu: Option<u16>, uses resolve_tun_mtu()
  • vpn_core/network.rs — Fixed set_adapter_network_config to actually use its tun_mtu parameter (was previously ignored)
  • main.rs — Added interactive VPN MTU prompt, displays MTU when loading saved config

GUI (Tauri + Web)

  • lib.rs — Added vpn_mtu: Option<u16> to SavedConn struct
  • index.html — Added <input type="number" min="1280" max="1360"> in settings form and connection modal
  • main.js — Wired vpn_mtu through readSettings(), fillSettings(), openModal(), saveModal(), selectConnection()
  • utils.js — Added vpn_mtu to toConfig() helper

Backward Compatibility

  • vpn_mtu is Option<u16> with #[serde(default)] — existing configs without the field load fine and fall back to 1280
  • The VPN_MTU environment variable still works as a secondary fallback (CLI / daemon use)
  • All existing IPC payloads without vpn_mtu continue to work

Testing

  • All 201 workspace tests pass (cargo test --workspace)
  • IPC bincode roundtrip tests updated with vpn_mtu: None
  • GUI SavedConn deserialization test confirms missing field defaults to None
  • Clean compilation, zero warnings

MTU Safety — MIN is always 1280

Guard Location Enforcement
Backend backend/src/config.rs clap value_parser range 1280–1360
Shared constant shared/src/lib.rs MIN_TUN_MTU = 1280
Shared resolver resolve_tun_mtu() Rejects out-of-range, falls back to 1280
Android MaviVpnService.kt in 1280..1360 check, fallback 1280
HTML inputs gui/src/index.html min="1280" max="1360"
CLI prompts Linux/Windows main.rs >= 1280 && <= 1360 check, fallback None

zerox80 added 3 commits April 24, 2026 02:06
… all platforms

Introduce a `resolve_tun_mtu()` helper in the shared crate that centralizes
MTU resolution from an explicit config field, the `VPN_MTU` env var, or the
compiled-in default (1280). This replaces duplicated per-platform env-reading
logic in linux and windows vpn_core.

Plumb `vpn_mtu` through the full stack on every platform:
- **shared**: add `vpn_mtu: Option<u16>` to `Config`, implement
  `resolve_tun_mtu()` with MIN/MAX_TUN_MTU constants
- **android**: settings UI, ViewModel, PrefsManager, NativeLib JNI bridge,
  and Rust connection handshake
- **gui**: HTML inputs, JS read/write/fill, Rust SavedConn struct, config
  mapping in utils.js
- **linux/windows**: CLI prompts, replace local env-reading with shared
  resolver, wire through connect_and_handshake

Valid range is 1280–1360; values outside this range or absent fall through
to env var, then default. Server and client must agree on TUN MTU.
…oid input

Add comprehensive tests covering the `resolve_tun_mtu()` priority chain:
explicit config > env var > default, with out-of-range and non-numeric
values falling through gracefully. Remove unused `DEFAULT_TUN_MTU`
import in linux vpn_core.

Harden android SettingsScreen with a `parseValidatedMtu()` helper that
rejects values outside 1280–1360 with a user-facing Toast instead of
silently passing invalid input through the onBack callback.
…nction

Merge multiple parallel tests that mutate `std::env` into one
sequential test to eliminate race conditions from concurrent
environment variable manipulation.
@zerox80 zerox80 merged commit e0f000c into main Apr 24, 2026
15 checks passed
zerox80 added a commit that referenced this pull request May 11, 2026
feat(config): add configurable VPN MTU with unified resolution across…
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant