fix(client): verify relay route before TAP activation
The Windows client pinned the relay host route before opening TAP, but only verified that Windows was actually using that host route after TAP activation. If an existing route or pinning failure prevented the host route from becoming the active relay path, the client could discover that only after touching TAP route policy. Verify the pinned host route immediately after installing/reusing it, before opening the TAP adapter. Keep the existing after-activation verification as the runtime guard against TAP route takeover, and document the new expected startup log line in the MVP guide. Test Plan: - cargo fmt --check - cargo test -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo check -p lanparty-client-route --target x86_64-pc-windows-msvc - git diff --check - git diff --cached --check Windows-target check attempted: - cargo check -p lanparty-client-win --target x86_64-pc-windows-msvc With LLVM tools configured, that still stops inside ring on this Linux host because the Windows C headers are unavailable, starting with assert.h. Refs: MVP relay-route protection
This commit is contained in:
@@ -240,10 +240,10 @@ stale connected state from a previous crashed run without letting the TAP
|
|||||||
adapter influence relay DNS or route selection. The client then resolves the
|
adapter influence relay DNS or route selection. The client then resolves the
|
||||||
relay endpoint, completes the control-stream hello/welcome handshake, pins a
|
relay endpoint, completes the control-stream hello/welcome handshake, pins a
|
||||||
host route for the resolved relay IP on the current pre-TAP interface, verifies
|
host route for the resolved relay IP on the current pre-TAP interface, verifies
|
||||||
that the relay route still uses that pinned host route after TAP activation,
|
that Windows is already using that host route, verifies it again after TAP
|
||||||
and bridges Ethernet frames between the relay and the TAP-Windows6 adapter
|
activation, and bridges Ethernet frames between the relay and the TAP-Windows6
|
||||||
until shutdown. `--relay` accepts a DNS name or socket address; bare hosts
|
adapter until shutdown. `--relay` accepts a DNS name or socket address; bare
|
||||||
default to UDP/443.
|
hosts default to UDP/443.
|
||||||
TAP frames whose source MAC does not match that generated tunnel MAC are
|
TAP frames whose source MAC does not match that generated tunnel MAC are
|
||||||
dropped locally before they can consume relay bandwidth; the relay still
|
dropped locally before they can consume relay bandwidth; the relay still
|
||||||
enforces the same source-MAC rule.
|
enforces the same source-MAC rule.
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ prepared TAP adapter ... MAC ... configured and media disconnected before relay
|
|||||||
lanparty-client-win connected as peer ...; LAN gateway connected yes (peer ...)
|
lanparty-client-win connected as peer ...; LAN gateway connected yes (peer ...)
|
||||||
relay event: LAN gateway connected as peer ...
|
relay event: LAN gateway connected as peer ...
|
||||||
relay route pinned before TAP ...
|
relay route pinned before TAP ...
|
||||||
|
relay route verified before TAP activation ...
|
||||||
relay route verified after TAP activation ...
|
relay route verified after TAP activation ...
|
||||||
TAP driver reports MAC ... and MTU ...
|
TAP driver reports MAC ... and MTU ...
|
||||||
client diagnostics: relay reachable yes gateway connected yes route pinned yes ...
|
client diagnostics: relay reachable yes gateway connected yes route pinned yes ...
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ async fn run_client(
|
|||||||
let relay_route =
|
let relay_route =
|
||||||
verify_relay_route_is_pinned(session.config().relay_addr().ip(), relay_route_pin)
|
verify_relay_route_is_pinned(session.config().relay_addr().ip(), relay_route_pin)
|
||||||
.context("relay route changed after TAP activation")?;
|
.context("relay route changed after TAP activation")?;
|
||||||
print_verified_relay_route(&relay_route);
|
print_verified_relay_route("after TAP activation", &relay_route);
|
||||||
print_and_report_client_diagnostics(
|
print_and_report_client_diagnostics(
|
||||||
session,
|
session,
|
||||||
&client_diagnostics_snapshot(
|
&client_diagnostics_snapshot(
|
||||||
@@ -370,6 +370,9 @@ fn pin_relay_route_before_tap(destination: std::net::IpAddr) -> Result<PinnedRel
|
|||||||
let pin = lanparty_client_route::pin_relay_route(&route)
|
let pin = lanparty_client_route::pin_relay_route(&route)
|
||||||
.context("failed to pin relay route before TAP activation")?;
|
.context("failed to pin relay route before TAP activation")?;
|
||||||
print_pinned_relay_route(&pin);
|
print_pinned_relay_route(&pin);
|
||||||
|
let route = verify_relay_route_is_pinned(destination, &pin)
|
||||||
|
.context("relay route did not use pinned host route before TAP activation")?;
|
||||||
|
print_verified_relay_route("before TAP activation", &route);
|
||||||
|
|
||||||
Ok(pin)
|
Ok(pin)
|
||||||
}
|
}
|
||||||
@@ -445,9 +448,9 @@ fn relay_route_matches_pin(route: &RouteSnapshot, pin: &PinnedRelayRoute) -> boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn print_verified_relay_route(route: &RouteSnapshot) {
|
fn print_verified_relay_route(phase: &str, route: &RouteSnapshot) {
|
||||||
println!(
|
println!(
|
||||||
"relay route verified after TAP activation: destination {} next hop {} interface index {} LUID {} prefix {}/{} metric {}",
|
"relay route verified {phase}: destination {} next hop {} interface index {} LUID {} prefix {}/{} metric {}",
|
||||||
route.destination(),
|
route.destination(),
|
||||||
route_next_hop_label(route.next_hop()),
|
route_next_hop_label(route.next_hop()),
|
||||||
route.interface_index(),
|
route.interface_index(),
|
||||||
|
|||||||
Reference in New Issue
Block a user