fix(client): configure TAP MAC before relay connect
The Windows startup path opened the TAP adapter to clear stale media state before loading the persisted tunnel identity and writing the NetworkAddress registry value. That made the first TAP touch happen with whatever MAC Windows already had loaded from a previous run. Build the client runtime config first so the virtual MAC and resolved relay address are known before TAP activation. The pre-connect TAP preparation now writes the selected adapter's NetworkAddress value before opening the adapter to mark media disconnected. The relay route is still pinned only after the relay handshake, while TAP remains media-disconnected. This reduces the chance of a first-run or post-crash TAP MAC mismatch during the manual Windows MVP test. The client still validates the driver-reported MAC before bridging and still fails closed if Windows has not reloaded the registry value. Test Plan: - cargo test -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo fmt --check - git diff --check - cargo check -p lanparty-client-win --target x86_64-pc-windows-gnu - blocked by missing x86_64-w64-mingw32-gcc for ring on this host Refs: PLAN.md Windows routing / metric handling; TESTING.md MVP guide
This commit is contained in:
@@ -217,17 +217,16 @@ cargo run -p lanparty-client-win -- \
|
|||||||
|
|
||||||
The Windows client binary currently connects to the relay as `role = client`
|
The Windows client binary currently connects to the relay as `role = client`
|
||||||
with a generated locally administered virtual MAC persisted in
|
with a generated locally administered virtual MAC persisted in
|
||||||
`lanparty-client-identity.json`. Before resolving or connecting to the relay,
|
`lanparty-client-identity.json`. It resolves the relay DNS name before TAP
|
||||||
it selects the TAP-Windows6 adapter and marks TAP media disconnected to clear
|
activation, writes the generated tunnel MAC to the selected TAP driver's
|
||||||
stale connected state from a previous crashed run. It then resolves the relay
|
`NetworkAddress` registry setting, and marks TAP media disconnected before
|
||||||
DNS name before TAP activation, completes the control-stream hello/welcome
|
connecting to the relay. That clears stale connected state from a previous
|
||||||
handshake, pins a host route for the resolved relay IP on the current pre-TAP
|
crashed run without letting the TAP adapter influence relay routing. The client
|
||||||
interface, verifies that the relay route still uses that pinned host route
|
then completes the control-stream hello/welcome handshake, pins a host route
|
||||||
after TAP activation, and then bridges Ethernet frames between the relay and
|
for the resolved relay IP on the current pre-TAP interface, verifies that the
|
||||||
the first TAP-Windows6 adapter until shutdown. `--relay` accepts a DNS name or
|
relay route still uses that pinned host route after TAP activation, and bridges
|
||||||
socket address; bare hosts default to UDP/443. Before opening the adapter for
|
Ethernet frames between the relay and the TAP-Windows6 adapter until shutdown.
|
||||||
bridging, it writes the generated tunnel MAC to the TAP driver's
|
`--relay` accepts a DNS name or socket address; bare hosts default to UDP/443.
|
||||||
`NetworkAddress` registry setting.
|
|
||||||
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.
|
||||||
|
|||||||
+1
-1
@@ -119,7 +119,7 @@ one explicitly:
|
|||||||
Expected client output:
|
Expected client output:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
prepared TAP adapter ... media disconnected before relay connect
|
prepared TAP adapter ... MAC ... configured and media disconnected before relay connect
|
||||||
lanparty-client-win connected as peer ...
|
lanparty-client-win connected as peer ...
|
||||||
relay route pinned before TAP ...
|
relay route pinned before TAP ...
|
||||||
relay route verified after TAP activation ...
|
relay route verified after TAP activation ...
|
||||||
|
|||||||
@@ -145,10 +145,12 @@ async fn main() -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
prepare_tap_before_relay_connect(args.tap_instance_id.as_deref())?;
|
|
||||||
|
|
||||||
let config = args.into_config()?;
|
let config = args.into_config()?;
|
||||||
|
#[cfg(windows)]
|
||||||
|
prepare_tap_before_relay_connect(
|
||||||
|
config.tap_instance_id.as_deref(),
|
||||||
|
config.session.virtual_mac(),
|
||||||
|
)?;
|
||||||
println!(
|
println!(
|
||||||
"lanparty-client-win connecting virtual MAC {} to relay {} room {}",
|
"lanparty-client-win connecting virtual MAC {} to relay {} room {}",
|
||||||
config.session.virtual_mac(),
|
config.session.virtual_mac(),
|
||||||
@@ -201,16 +203,27 @@ fn print_available_tap_adapters() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn prepare_tap_before_relay_connect(tap_instance_id: Option<&str>) -> Result<()> {
|
fn prepare_tap_before_relay_connect(
|
||||||
|
tap_instance_id: Option<&str>,
|
||||||
|
virtual_mac: MacAddr,
|
||||||
|
) -> Result<()> {
|
||||||
let adapters = lanparty_client_tap::available_adapters()
|
let adapters = lanparty_client_tap::available_adapters()
|
||||||
.context("failed to list TAP-Windows6 adapters before relay connect")?;
|
.context("failed to list TAP-Windows6 adapters before relay connect")?;
|
||||||
let info = select_tap_adapter(adapters, tap_instance_id)?;
|
let info = select_tap_adapter(adapters, tap_instance_id)?;
|
||||||
|
lanparty_client_tap::configure_adapter_mac(&info, virtual_mac).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to persist TAP MAC {virtual_mac} for adapter {}",
|
||||||
|
info.instance_id()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
let device_path = info.device_path();
|
let device_path = info.device_path();
|
||||||
let tap = TapAdapter::open(info)?;
|
let tap = TapAdapter::open(info)?;
|
||||||
tap.set_media_connected(false)
|
tap.set_media_connected(false)
|
||||||
.with_context(|| format!("failed to mark TAP media disconnected for {device_path}"))?;
|
.with_context(|| format!("failed to mark TAP media disconnected for {device_path}"))?;
|
||||||
|
|
||||||
println!("prepared TAP adapter {device_path}: media disconnected before relay connect");
|
println!(
|
||||||
|
"prepared TAP adapter {device_path}: MAC {virtual_mac} configured and media disconnected before relay connect"
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user