feat(cli,tunnel,docs): full Windows support — OS routes + wintun audit

Windows is now first-class for client use:

- aura-cli::os_routes Windows path is no longer a stub. Real install via
  `route ADD <net> MASK <mask> <gw> METRIC 1` for DIRECT bypass (rollback:
  `route DELETE ...`) and `netsh interface ipv4 add route <cidr> "Aura"
  <tun_local_ip> store=active` for VPN default/CIDR (rollback: `netsh ...
  delete route ...`). Default-gateway detection by parsing `route print 0`
  output via parse_windows_route_print_default; rejects `On-link` rows. Dry
  run works on every host.
- aura-tunnel::tun wintun audit fixed a real bug: AuraTun was holding only
  Arc<Session> while Session does NOT keep Arc<Adapter> alive (only the
  Wintun DLL handle). On Drop the adapter was being closed under the
  session. Fixed by adding _adapter: Arc<wintun::Adapter> to AuraTun, with
  field order ensuring Session is dropped before Adapter so end-session
  precedes close-adapter. Also wired mtu into write_packet (hard limit) +
  read_packet (warn).
- Cross-compile verified: cargo check --target x86_64-pc-windows-gnu
  --workspace and clippy on the windows target are both clean (added
  mingw-w64 + x86_64-pc-windows-gnu via rustup).
- docs/deployment.md: §6 updated (Windows OS-routes now Done), new §8
  «Windows как клиент» with download wintun.dll, Admin run, [tunnel.os_routes]
  enabled, known no-ops (run_as, [server.nat]).

9 new tests (7 parser/plan/undo unit + 1 windows dry-run integration + 1
existing). Workspace: 293 tests passed (+9), clippy -D warnings clean, fmt
clean. macOS host + windows-gnu cross-target both green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xah30
2026-05-27 21:14:23 +03:00
parent 1893e24174
commit 5ea643a9e5
4 changed files with 809 additions and 37 deletions
+27
View File
@@ -150,3 +150,30 @@ fn os_routes_section_default_values() {
assert!(d.gateway.is_none());
assert!(d.egress_iface.is_none());
}
/// v3.3: a Windows-style client.toml (with the operator's pre-detected gateway already pinned
/// in `[tunnel.os_routes]`) still parses and the dry-run install renders the windows plan in
/// the logs. We do not assert on the log contents here — that is covered by the inner
/// `windows_plan_default_vpn` unit test in `os_routes.rs` — but we *do* verify that the API
/// surface accepts the same hints on every host (no Windows-only fields).
#[test]
fn dry_run_install_windows_style_overrides_succeed_anywhere() {
let split = SplitRoutes {
default: DefaultAction::Vpn,
direct_cidrs: vec!["192.168.0.0/16".parse().unwrap()],
vpn_cidrs: Vec::new(),
direct_hosts: vec!["1.2.3.4".parse().unwrap()],
vpn_hosts: Vec::new(),
};
// On Windows the "egress" hint is the upstream interface IP, not its display name.
// The dry-run path renders this verbatim into the windows plan.
let guard = OsRouteGuard::install(
"Aura",
&split,
Some("192.168.1.1"),
Some("192.168.1.42"),
/* dry_run */ true,
)
.expect("dry_run with Windows-style overrides must succeed on every host");
drop(guard);
}