justfile, AGENTS.md
This commit is contained in:
@@ -82,7 +82,8 @@ Windows route-table boundary:
|
||||
- unicast IP address snapshots for TAP diagnostics
|
||||
- scoped host-route pinning for the relay IP on the pre-TAP interface
|
||||
- host-route pin matching for relay-route verification after TAP activation
|
||||
- reuse of an already-existing matching relay host route without deleting it on exit
|
||||
- reuse of an already-existing matching relay host route without deleting it on
|
||||
exit
|
||||
- non-Windows builds return a clear unsupported-platform error
|
||||
|
||||
### `lanparty-client-tap`
|
||||
@@ -109,9 +110,9 @@ Public relay binary and relay-owned room state:
|
||||
- per-peer egress budget checks against the negotiated datagram size
|
||||
- reliable `PeerJoined`/`PeerLeft` notifications plus gateway identity in
|
||||
welcome messages
|
||||
- L2 safety filters for invalid-source, jumbo, switch-control, remote VLAN
|
||||
tags, remote IPv6 fragments, IPv4/IPv6 DHCP-server, and IPv6-RA frames,
|
||||
including frames behind ordinary IPv6 extension headers
|
||||
- L2 safety filters for invalid-source, jumbo, switch-control, remote VLAN tags,
|
||||
remote IPv6 fragments, IPv4/IPv6 DHCP-server, and IPv6-RA frames, including
|
||||
frames behind ordinary IPv6 extension headers
|
||||
- client broadcast/multicast, unknown-unicast, and total bandwidth limiting
|
||||
- malformed peer datagram disconnect threshold
|
||||
- peer stats control events retained for relay diagnostics
|
||||
@@ -129,9 +130,9 @@ cargo build --release -p lanparty-relay -p lanparty-gateway
|
||||
git diff --check
|
||||
```
|
||||
|
||||
These checks cover the local Rust code and the real client/relay/gateway
|
||||
session paths that can run without Windows TAP or LAN hardware. For the Windows
|
||||
client build and the manual MVP end-to-end proof, see [TESTING.md](TESTING.md).
|
||||
These checks cover the local Rust code and the real client/relay/gateway session
|
||||
paths that can run without Windows TAP or LAN hardware. For the Windows client
|
||||
build and the manual MVP end-to-end proof, see [TESTING.md](TESTING.md).
|
||||
|
||||
## Relay
|
||||
|
||||
@@ -147,24 +148,24 @@ self-signed development certificate; `--dev-cert-der-out` writes that
|
||||
certificate so the gateway and client can pin it in development. Production
|
||||
certificate handling remains future work. Ethernet forwarding decisions are
|
||||
logged with room, peer, MAC, ethertype, action, drop reason, and target count.
|
||||
Safety-policy rejects use the `filtered` action so they are distinguishable
|
||||
from malformed/unknown-destination drops and rate limits.
|
||||
Malformed peer datagrams log their per-peer count before the relay disconnects
|
||||
peers that cross the malformed-datagram threshold.
|
||||
Relay egress skips caused by a target peer's smaller datagram budget are logged
|
||||
with the ingress peer, target peer, encoded length, and target budget.
|
||||
Ingress datagrams larger than the sending peer's negotiated datagram budget are
|
||||
dropped before decode/forwarding and logged with `reason=datagram_budget`.
|
||||
Unknown unicast from a client is forwarded only to the gateway port; unknown
|
||||
unicast from the gateway is dropped instead of flooded to every remote client.
|
||||
When a peer joins or leaves, the relay sends a reliable lifecycle control event
|
||||
to peers that are still present in the room. Newly joined peers also receive
|
||||
`PeerJoined` events for peers that were already present, and catch-up delivery
|
||||
is part of the accepted handshake rather than a best-effort follow-up. When a
|
||||
client joins, the relay notifies existing peers before the client receives its
|
||||
welcome, so gateways can seed client MAC state before that client starts
|
||||
sending frames. When a gateway joins, the relay gives the gateway the current
|
||||
client list before notifying clients that the gateway is available.
|
||||
Safety-policy rejects use the `filtered` action so they are distinguishable from
|
||||
malformed/unknown-destination drops and rate limits. Malformed peer datagrams
|
||||
log their per-peer count before the relay disconnects peers that cross the
|
||||
malformed-datagram threshold. Relay egress skips caused by a target peer's
|
||||
smaller datagram budget are logged with the ingress peer, target peer, encoded
|
||||
length, and target budget. Ingress datagrams larger than the sending peer's
|
||||
negotiated datagram budget are dropped before decode/forwarding and logged with
|
||||
`reason=datagram_budget`. Unknown unicast from a client is forwarded only to the
|
||||
gateway port; unknown unicast from the gateway is dropped instead of flooded to
|
||||
every remote client. When a peer joins or leaves, the relay sends a reliable
|
||||
lifecycle control event to peers that are still present in the room. Newly
|
||||
joined peers also receive `PeerJoined` events for peers that were already
|
||||
present, and catch-up delivery is part of the accepted handshake rather than a
|
||||
best-effort follow-up. When a client joins, the relay notifies existing peers
|
||||
before the client receives its welcome, so gateways can seed client MAC state
|
||||
before that client starts sending frames. When a gateway joins, the relay gives
|
||||
the gateway the current client list before notifying clients that the gateway is
|
||||
available.
|
||||
|
||||
### MVP Trust Model
|
||||
|
||||
@@ -195,41 +196,38 @@ and completes the control-stream hello/welcome handshake. That startup order
|
||||
keeps an invalid, wireless, or unplugged interface from briefly advertising a
|
||||
gateway that cannot bridge. Once both sides are ready, it bridges Ethernet
|
||||
frames between the relay and wired LAN until shutdown. It captures whole LAN
|
||||
frames up to the
|
||||
overlay payload-length ceiling before deciding whether they fit the tunnel. It
|
||||
never fragments Ethernet frames; LAN frames with invalid source MACs, L2
|
||||
control-plane traffic, jumbo frames, frames above the negotiated TAP MTU, or
|
||||
encoded datagrams exceeding the negotiated QUIC budget are counted, dropped,
|
||||
and logged locally instead of stopping the bridge or consuming relay bandwidth.
|
||||
Remote frames received from
|
||||
the relay are safety-checked again before LAN injection and must use the
|
||||
announced virtual MAC for their source peer, so invalid-source, forged-source,
|
||||
L2 control-plane, remote VLAN, DHCP-server, IPv6 Router Advertisement, IPv6
|
||||
fragment, jumbo, and over-TAP-MTU frames cannot cross the gateway's final
|
||||
physical-LAN boundary even if they reached the gateway over QUIC.
|
||||
`--relay` accepts a DNS name or socket address; bare hosts default to UDP/443.
|
||||
The gateway rejects Linux interfaces that sysfs identifies as Wi-Fi, and rejects
|
||||
wired interfaces whose sysfs carrier state reports no link; managed wireless
|
||||
NICs are not supported for the physical LAN bridge.
|
||||
It tracks remote-client MACs from relay lifecycle events and periodically emits
|
||||
small CAM refresh frames, logged with `reason=periodic`, so the physical
|
||||
switch keeps those MACs associated with the gateway port. A newly observed
|
||||
client also triggers an immediate CAM refresh frame logged with
|
||||
`reason=peer_joined` instead of waiting for the first periodic refresh tick.
|
||||
When control events and frame work are both ready, the bridge handles the
|
||||
lifecycle event first so first packets after a client joins use the freshest
|
||||
remote-MAC state available locally. Gateway
|
||||
frame logs include direction, peer id when present, MACs, ethertype/length,
|
||||
frame length, action, and drop reason. The gateway also tracks frame/datagram
|
||||
counters and periodically sends stats snapshots to the relay. Malformed or runt
|
||||
LAN frames are counted and logged as dropped instead of disappearing before
|
||||
accounting. It drops unrelated LAN unicast locally once the destination is known
|
||||
not to be a connected remote client, so busy LAN traffic is not sent to the
|
||||
public relay just to be discarded there. Relay lifecycle events seed and retire
|
||||
remote-client MACs for CAM refresh and LAN-destination filtering even before
|
||||
that client sends traffic. On shutdown, the gateway sends a best-effort
|
||||
disconnect control message before closing QUIC so the relay can report the
|
||||
intended reason.
|
||||
frames up to the overlay payload-length ceiling before deciding whether they fit
|
||||
the tunnel. It never fragments Ethernet frames; LAN frames with invalid source
|
||||
MACs, L2 control-plane traffic, jumbo frames, frames above the negotiated TAP
|
||||
MTU, or encoded datagrams exceeding the negotiated QUIC budget are counted,
|
||||
dropped, and logged locally instead of stopping the bridge or consuming relay
|
||||
bandwidth. Remote frames received from the relay are safety-checked again before
|
||||
LAN injection and must use the announced virtual MAC for their source peer, so
|
||||
invalid-source, forged-source, L2 control-plane, remote VLAN, DHCP-server, IPv6
|
||||
Router Advertisement, IPv6 fragment, jumbo, and over-TAP-MTU frames cannot cross
|
||||
the gateway's final physical-LAN boundary even if they reached the gateway over
|
||||
QUIC. `--relay` accepts a DNS name or socket address; bare hosts default to
|
||||
UDP/443. The gateway rejects Linux interfaces that sysfs identifies as Wi-Fi,
|
||||
and rejects wired interfaces whose sysfs carrier state reports no link; managed
|
||||
wireless NICs are not supported for the physical LAN bridge. It tracks
|
||||
remote-client MACs from relay lifecycle events and periodically emits small CAM
|
||||
refresh frames, logged with `reason=periodic`, so the physical switch keeps
|
||||
those MACs associated with the gateway port. A newly observed client also
|
||||
triggers an immediate CAM refresh frame logged with `reason=peer_joined` instead
|
||||
of waiting for the first periodic refresh tick. When control events and frame
|
||||
work are both ready, the bridge handles the lifecycle event first so first
|
||||
packets after a client joins use the freshest remote-MAC state available
|
||||
locally. Gateway frame logs include direction, peer id when present, MACs,
|
||||
ethertype/length, frame length, action, and drop reason. The gateway also tracks
|
||||
frame/datagram counters and periodically sends stats snapshots to the relay.
|
||||
Malformed or runt LAN frames are counted and logged as dropped instead of
|
||||
disappearing before accounting. It drops unrelated LAN unicast locally once the
|
||||
destination is known not to be a connected remote client, so busy LAN traffic is
|
||||
not sent to the public relay just to be discarded there. Relay lifecycle events
|
||||
seed and retire remote-client MACs for CAM refresh and LAN-destination filtering
|
||||
even before that client sends traffic. On shutdown, the gateway sends a
|
||||
best-effort disconnect control message before closing QUIC so the relay can
|
||||
report the intended reason.
|
||||
|
||||
## Windows Client
|
||||
|
||||
@@ -246,24 +244,21 @@ path depends on TAP-Windows6 and Windows route protection. Non-Windows builds
|
||||
are useful for type checking, but they fail before tunnel setup instead of
|
||||
joining a room without a TAP adapter. On Windows, the binary connects to the
|
||||
relay as `role = client` with a generated locally administered virtual MAC
|
||||
persisted in
|
||||
`lanparty-client-identity.json`. Before resolving or connecting to the relay,
|
||||
it writes the generated tunnel MAC to the selected TAP driver's
|
||||
persisted in `lanparty-client-identity.json`. Before resolving or connecting to
|
||||
the relay, it writes the generated tunnel MAC to the selected TAP driver's
|
||||
`NetworkAddress` registry setting and marks TAP media disconnected. That clears
|
||||
stale connected state from a previous crashed run without letting the TAP
|
||||
adapter influence relay DNS or route selection. The client then resolves the
|
||||
relay endpoint, pins a host route for the resolved relay IP on the current
|
||||
pre-TAP interface, verifies that Windows is using that host route, completes
|
||||
the control-stream hello/welcome handshake, verifies the host route again after
|
||||
TAP activation, and bridges Ethernet frames between the relay and the
|
||||
TAP-Windows6 adapter until shutdown. `--relay` accepts a DNS name or socket
|
||||
address; bare hosts default to UDP/443.
|
||||
TAP frames whose source MAC does not match that generated tunnel MAC are
|
||||
dropped locally before they can consume relay bandwidth; the relay still
|
||||
enforces the same source-MAC rule.
|
||||
If the exact relay host route already exists, the client uses it and leaves it
|
||||
alone on exit. The startup status reports whether the relay already has a LAN
|
||||
gateway for the room.
|
||||
pre-TAP interface, verifies that Windows is using that host route, completes the
|
||||
control-stream hello/welcome handshake, verifies the host route again after TAP
|
||||
activation, and bridges Ethernet frames between the relay and the TAP-Windows6
|
||||
adapter until shutdown. `--relay` accepts a DNS name or socket address; bare
|
||||
hosts default to UDP/443. TAP frames whose source MAC does not match that
|
||||
generated tunnel MAC are dropped locally before they can consume relay
|
||||
bandwidth; the relay still enforces the same source-MAC rule. If the exact relay
|
||||
host route already exists, the client uses it and leaves it alone on exit. The
|
||||
startup status reports whether the relay already has a LAN gateway for the room.
|
||||
`--virtual-mac` can still override the stored identity for manual testing. On
|
||||
Windows it sets the TAP IP interface MTU to the relay-selected MTU, marks the
|
||||
TAP media connected for the scoped client run, and reports the driver MAC/MTU
|
||||
@@ -271,40 +266,37 @@ before forwarding frames, along with the TAP interface index/LUID. The client
|
||||
applies a scoped TAP interface metric and disables TAP default routes while it
|
||||
runs, periodically rechecks that the relay route remains pinned, then restores
|
||||
the previous route policy and TAP media status on exit. Startup prints a warning
|
||||
when TAP default routes were enabled
|
||||
before the scoped protection was applied. Startup still fails before bridging
|
||||
if the driver-reported MAC does not match the tunnel identity, because an
|
||||
already-initialized Windows TAP adapter may need to be disabled/enabled or
|
||||
reinstalled before it reloads the configured `NetworkAddress`.
|
||||
If exactly one TAP-Windows6 adapter is installed, the client opens it
|
||||
automatically. If multiple TAP-Windows6 adapters are installed, startup fails
|
||||
until `--tap-instance-id` selects the intended adapter by NetCfgInstanceId /
|
||||
InterfaceGuid. `--list-tap-adapters` prints the TAP adapter ids and exits
|
||||
without connecting.
|
||||
It prints and reports client diagnostics snapshots with relay reachability,
|
||||
LAN-gateway presence, route-pinning, QUIC datagram budget, relay RTT, TAP
|
||||
status/IP, broadcast frame flow, frame/datagram counters, and drops. The
|
||||
periodic diagnostics refresh the TAP unicast IP so DHCP results that arrive
|
||||
after bridging starts become visible in later status lines, preferring a
|
||||
when TAP default routes were enabled before the scoped protection was applied.
|
||||
Startup still fails before bridging if the driver-reported MAC does not match
|
||||
the tunnel identity, because an already-initialized Windows TAP adapter may need
|
||||
to be disabled/enabled or reinstalled before it reloads the configured
|
||||
`NetworkAddress`. If exactly one TAP-Windows6 adapter is installed, the client
|
||||
opens it automatically. If multiple TAP-Windows6 adapters are installed, startup
|
||||
fails until `--tap-instance-id` selects the intended adapter by NetCfgInstanceId
|
||||
/ InterfaceGuid. `--list-tap-adapters` prints the TAP adapter ids and exits
|
||||
without connecting. It prints and reports client diagnostics snapshots with
|
||||
relay reachability, LAN-gateway presence, route-pinning, QUIC datagram budget,
|
||||
relay RTT, TAP status/IP, broadcast frame flow, frame/datagram counters, and
|
||||
drops. The periodic diagnostics refresh the TAP unicast IP so DHCP results that
|
||||
arrive after bridging starts become visible in later status lines, preferring a
|
||||
non-link-local IPv4 address when Windows reports several TAP addresses. Each
|
||||
snapshot also emits short user-facing lines such as relay/gateway connection status,
|
||||
relay-route and TAP readiness warnings, DHCP address presence, relay RTT, and
|
||||
broadcast-flow confirmation. One-way broadcast diagnostics distinguish frames
|
||||
sent toward the LAN from broadcast frames received back from the LAN. Malformed frames
|
||||
read from TAP, invalid or unauthorized source-MAC frames, L2 control-plane
|
||||
traffic, remote VLAN tags, DHCP server replies, IPv6 Router Advertisements, IPv6
|
||||
fragments, jumbo frames, frames above the negotiated TAP MTU, and TAP frames
|
||||
whose encoded datagrams exceed the negotiated QUIC budget are counted and
|
||||
dropped before relay send without stopping the bridge. Relayed LAN frames are
|
||||
also safety-checked before TAP writes, so switch-control traffic,
|
||||
snapshot also emits short user-facing lines such as relay/gateway connection
|
||||
status, relay-route and TAP readiness warnings, DHCP address presence, relay
|
||||
RTT, and broadcast-flow confirmation. One-way broadcast diagnostics distinguish
|
||||
frames sent toward the LAN from broadcast frames received back from the LAN.
|
||||
Malformed frames read from TAP, invalid or unauthorized source-MAC frames, L2
|
||||
control-plane traffic, remote VLAN tags, DHCP server replies, IPv6 Router
|
||||
Advertisements, IPv6 fragments, jumbo frames, frames above the negotiated TAP
|
||||
MTU, and TAP frames whose encoded datagrams exceed the negotiated QUIC budget
|
||||
are counted and dropped before relay send without stopping the bridge. Relayed
|
||||
LAN frames are also safety-checked before TAP writes, so switch-control traffic,
|
||||
invalid-source frames, jumbo frames, and over-TAP-MTU frames stay out of the
|
||||
Windows adapter even if they reached the client over QUIC.
|
||||
Misdirected unicast frames not addressed to the client's virtual MAC are also
|
||||
counted, skipped, and logged with the drop reason; accepted TAP-to-relay and
|
||||
relay-to-TAP frames are logged with direction, peer id, MACs, ethertype/length,
|
||||
frame length, action, and drop reason. TAP device read/write errors still stop
|
||||
the bridge.
|
||||
Relay lifecycle events are logged as they arrive, including gateway joins and
|
||||
peer leaves. The client remembers peer identities from join and catch-up events
|
||||
and from the initial welcome, so later leave logs can identify a disconnected
|
||||
LAN gateway or client MAC when that peer was known.
|
||||
Windows adapter even if they reached the client over QUIC. Misdirected unicast
|
||||
frames not addressed to the client's virtual MAC are also counted, skipped, and
|
||||
logged with the drop reason; accepted TAP-to-relay and relay-to-TAP frames are
|
||||
logged with direction, peer id, MACs, ethertype/length, frame length, action,
|
||||
and drop reason. TAP device read/write errors still stop the bridge. Relay
|
||||
lifecycle events are logged as they arrive, including gateway joins and peer
|
||||
leaves. The client remembers peer identities from join and catch-up events and
|
||||
from the initial welcome, so later leave logs can identify a disconnected LAN
|
||||
gateway or client MAC when that peer was known.
|
||||
|
||||
Reference in New Issue
Block a user