justfile, AGENTS.md
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
# Agent Instructions
|
||||||
|
|
||||||
|
## Commit Policy
|
||||||
|
|
||||||
|
Automatically commit changes once a full feature, bugfix, refactor, or other
|
||||||
|
coherent unit of work is finished. Do not wait for the user to ask for a commit.
|
||||||
|
|
||||||
|
## Versioning Policy
|
||||||
|
|
||||||
|
Only update the version, when the user explicitly asks for it.
|
||||||
|
|
||||||
|
### Guidelines for how to update the version
|
||||||
|
|
||||||
|
1. Use `cargo set-version` to bump the version. Decide, based on the actual
|
||||||
|
changes, based on semver semantics, if major, minor or patch needs to be
|
||||||
|
bumped.
|
||||||
|
2. Update the CHANGELOG.md file accordingly.
|
||||||
|
3. Create a release commit.
|
||||||
|
4. Tag the release commit in the style of previous versioning tags.
|
||||||
@@ -1,14 +1,23 @@
|
|||||||
|
# PLAN
|
||||||
|
|
||||||
What I want to do:
|
What I want to do:
|
||||||
|
|
||||||
A simple one-click Layer 2 tunnel software (Windows 11 client) to bridge people who cannot participate in person at a LAN party to the LAN party. And a simple server endpoint (Linux) software that runs physically at the LAN party and bridges the tunneled traffic and the real LAN network.
|
A simple one-click Layer 2 tunnel software (Windows 11 client) to bridge people
|
||||||
|
who cannot participate in person at a LAN party to the LAN party. And a simple
|
||||||
|
server endpoint (Linux) software that runs physically at the LAN party and
|
||||||
|
bridges the tunneled traffic and the real LAN network.
|
||||||
|
|
||||||
I already talked a bit with different AIs about how to do this, here's the current plan:
|
I already talked a bit with different AIs about how to do this, here's the
|
||||||
|
current plan:
|
||||||
|
|
||||||
# LAN Party Tunnel Plan
|
## LAN Party Tunnel Plan
|
||||||
|
|
||||||
Build a **TAP-based L2-over-QUIC tunnel**.
|
Build a **TAP-based L2-over-QUIC tunnel**.
|
||||||
|
|
||||||
The remote Windows client gets a real virtual Ethernet adapter. Ethernet frames from that adapter are sent over QUIC to a public relay. The relay forwards them to a Linux gateway at the LAN party. The Linux gateway injects those frames onto the physical LAN and captures replies.
|
The remote Windows client gets a real virtual Ethernet adapter. Ethernet frames
|
||||||
|
from that adapter are sent over QUIC to a public relay. The relay forwards them
|
||||||
|
to a Linux gateway at the LAN party. The Linux gateway injects those frames onto
|
||||||
|
the physical LAN and captures replies.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Windows game
|
Windows game
|
||||||
@@ -21,13 +30,10 @@ Windows game
|
|||||||
⇄ physical Ethernet LAN
|
⇄ physical Ethernet LAN
|
||||||
```
|
```
|
||||||
|
|
||||||
No WireGuard.
|
No WireGuard. No Npcap. No Windows bridge. No packet rewriting from the user’s
|
||||||
No Npcap.
|
real NIC. No tunnel fragmentation for MVP.
|
||||||
No Windows bridge.
|
|
||||||
No packet rewriting from the user’s real NIC.
|
|
||||||
No tunnel fragmentation for MVP.
|
|
||||||
|
|
||||||
## Goal
|
### Goal
|
||||||
|
|
||||||
The remote player should do this:
|
The remote player should do this:
|
||||||
|
|
||||||
@@ -53,11 +59,12 @@ The public server does this:
|
|||||||
lanparty-relay --listen 443/udp
|
lanparty-relay --listen 443/udp
|
||||||
```
|
```
|
||||||
|
|
||||||
UDP/443 is a good default, but the port must be configurable because some networks block QUIC/UDP.
|
UDP/443 is a good default, but the port must be configurable because some
|
||||||
|
networks block QUIC/UDP.
|
||||||
|
|
||||||
## Components
|
### Components
|
||||||
|
|
||||||
### 1. Windows client: `lanparty-client.exe`
|
#### 1. Windows client: `lanparty-client.exe`
|
||||||
|
|
||||||
Written in Rust.
|
Written in Rust.
|
||||||
|
|
||||||
@@ -75,9 +82,13 @@ Responsibilities:
|
|||||||
- keep the relay connection routed through the real internet NIC
|
- keep the relay connection routed through the real internet NIC
|
||||||
```
|
```
|
||||||
|
|
||||||
Use a real TAP/Ethernet adapter. `tap-windows6` is an NDIS TAP-Windows driver used by OpenVPN and other apps, which is the right class of device here because we need Ethernet frames, not just IP packets. ([GitHub][1])
|
Use a real TAP/Ethernet adapter. `tap-windows6` is an NDIS TAP-Windows driver
|
||||||
|
used by OpenVPN and other apps, which is the right class of device here because
|
||||||
|
we need Ethernet frames, not just IP packets. ([GitHub][1])
|
||||||
|
|
||||||
Do **not** use Wintun for this design. Wintun is L3/TUN-style and does not give you the Ethernet/L2 behavior needed for ARP, DHCP, broadcast discovery, and old LAN games.
|
Do **not** use Wintun for this design. Wintun is L3/TUN-style and does not give
|
||||||
|
you the Ethernet/L2 behavior needed for ARP, DHCP, broadcast discovery, and old
|
||||||
|
LAN games.
|
||||||
|
|
||||||
The TAP adapter is the remote player’s LAN-party identity.
|
The TAP adapter is the remote player’s LAN-party identity.
|
||||||
|
|
||||||
@@ -88,7 +99,7 @@ Game sends ARP/broadcast/multicast through TAP
|
|||||||
Client tunnels the Ethernet frames
|
Client tunnels the Ethernet frames
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Linux gateway: `lanparty-gateway`
|
#### 2. Linux gateway: `lanparty-gateway`
|
||||||
|
|
||||||
Runs on the physical LAN party machine.
|
Runs on the physical LAN party machine.
|
||||||
|
|
||||||
@@ -104,15 +115,23 @@ Responsibilities:
|
|||||||
- periodically refresh switch CAM table entries
|
- periodically refresh switch CAM table entries
|
||||||
```
|
```
|
||||||
|
|
||||||
Use Linux `AF_PACKET` / `SOCK_RAW` on the real wired NIC. Packet sockets operate at device-driver / OSI Layer 2 level, and `SOCK_RAW` includes the link-layer header, which is exactly what we need for Ethernet frames. ([man7.org][2])
|
Use Linux `AF_PACKET` / `SOCK_RAW` on the real wired NIC. Packet sockets operate
|
||||||
|
at device-driver / OSI Layer 2 level, and `SOCK_RAW` includes the link-layer
|
||||||
|
header, which is exactly what we need for Ethernet frames. ([man7.org][2])
|
||||||
|
|
||||||
For MVP, run as root. Later, reduce privileges. Opening raw sockets and changing/promiscuous network behavior needs elevated networking privileges; `CAP_NET_ADMIN` covers things like setting promiscuous mode, and `CAP_NET_RAW` covers raw packet access. ([man7.org][3])
|
For MVP, run as root. Later, reduce privileges. Opening raw sockets and
|
||||||
|
changing/promiscuous network behavior needs elevated networking privileges;
|
||||||
|
`CAP_NET_ADMIN` covers things like setting promiscuous mode, and `CAP_NET_RAW`
|
||||||
|
covers raw packet access. ([man7.org][3])
|
||||||
|
|
||||||
No Linux bridge is needed for MVP. No `br0`. No moving the host’s IP from `eth0` to a bridge. The gateway daemon directly captures and injects frames on the physical NIC.
|
No Linux bridge is needed for MVP. No `br0`. No moving the host’s IP from `eth0`
|
||||||
|
to a bridge. The gateway daemon directly captures and injects frames on the
|
||||||
|
physical NIC.
|
||||||
|
|
||||||
Wired Ethernet only. No Wi-Fi gateway mode for MVP. Managed Wi-Fi NICs are not reliable for arbitrary source-MAC injection.
|
Wired Ethernet only. No Wi-Fi gateway mode for MVP. Managed Wi-Fi NICs are not
|
||||||
|
reliable for arbitrary source-MAC injection.
|
||||||
|
|
||||||
### 3. Public relay: `lanparty-relay`
|
#### 3. Public relay: `lanparty-relay`
|
||||||
|
|
||||||
Runs on VPS/public server.
|
Runs on VPS/public server.
|
||||||
|
|
||||||
@@ -139,7 +158,7 @@ gateway → outbound QUIC → relay
|
|||||||
|
|
||||||
No port forwarding. No NAT traversal pain. Direct P2P can come later.
|
No port forwarding. No NAT traversal pain. Direct P2P can come later.
|
||||||
|
|
||||||
## Transport
|
### Transport
|
||||||
|
|
||||||
Use QUIC.
|
Use QUIC.
|
||||||
|
|
||||||
@@ -158,11 +177,16 @@ disconnect reason
|
|||||||
future auth
|
future auth
|
||||||
```
|
```
|
||||||
|
|
||||||
Use QUIC DATAGRAM for Ethernet frames. QUIC DATAGRAM is specifically the unreliable datagram extension for QUIC, which fits Ethernet/game traffic better than reliable streams because old frames should not block newer frames. ([IETF Datatracker][4])
|
Use QUIC DATAGRAM for Ethernet frames. QUIC DATAGRAM is specifically the
|
||||||
|
unreliable datagram extension for QUIC, which fits Ethernet/game traffic better
|
||||||
|
than reliable streams because old frames should not block newer frames. ([IETF
|
||||||
|
Datatracker][4])
|
||||||
|
|
||||||
Rust QUIC implementation: start with `quinn`. It exposes `Connection::max_datagram_size()`, which returns the maximum datagram payload size or `None` if datagrams are unsupported/disabled. ([Docs.rs][5])
|
Rust QUIC implementation: start with `quinn`. It exposes
|
||||||
|
`Connection::max_datagram_size()`, which returns the maximum datagram payload
|
||||||
|
size or `None` if datagrams are unsupported/disabled. ([Docs.rs][5])
|
||||||
|
|
||||||
## No fragmentation for MVP
|
### No fragmentation for MVP
|
||||||
|
|
||||||
Do **not** fragment Ethernet frames inside the overlay.
|
Do **not** fragment Ethernet frames inside the overlay.
|
||||||
|
|
||||||
@@ -200,9 +224,10 @@ tap_mtu <= quic_max_datagram_size
|
|||||||
- safety_margin
|
- safety_margin
|
||||||
```
|
```
|
||||||
|
|
||||||
No fragment table. No reassembly timeout. No “one lost fragment kills the whole Ethernet frame.” Add fragmentation later only if testing proves it is necessary.
|
No fragment table. No reassembly timeout. No “one lost fragment kills the whole
|
||||||
|
Ethernet frame.” Add fragmentation later only if testing proves it is necessary.
|
||||||
|
|
||||||
## Overlay frame format
|
### Overlay frame format
|
||||||
|
|
||||||
Keep the outer routing header small and stable.
|
Keep the outer routing header small and stable.
|
||||||
|
|
||||||
@@ -226,13 +251,16 @@ clear routing header
|
|||||||
encrypted Ethernet payload
|
encrypted Ethernet payload
|
||||||
```
|
```
|
||||||
|
|
||||||
MVP can skip payload encryption beyond QUIC, but the wire format should not make later E2E encryption painful.
|
MVP can skip payload encryption beyond QUIC, but the wire format should not make
|
||||||
|
later E2E encryption painful.
|
||||||
|
|
||||||
## Trust model
|
### Trust model
|
||||||
|
|
||||||
MVP relay sees plaintext Ethernet frames.
|
MVP relay sees plaintext Ethernet frames.
|
||||||
|
|
||||||
QUIC encrypts traffic on the wire, but because the relay terminates QUIC connections, it decrypts frames from clients and re-encrypts them to the gateway.
|
QUIC encrypts traffic on the wire, but because the relay terminates QUIC
|
||||||
|
connections, it decrypts frames from clients and re-encrypts them to the
|
||||||
|
gateway.
|
||||||
|
|
||||||
That is acceptable for a LAN-party MVP, but it should be explicitly documented.
|
That is acceptable for a LAN-party MVP, but it should be explicitly documented.
|
||||||
|
|
||||||
@@ -246,7 +274,7 @@ relay only sees room id, peer id, size, timing
|
|||||||
|
|
||||||
Do not retrofit this into a bad packet format later. Reserve the shape now.
|
Do not retrofit this into a bad packet format later. Reserve the shape now.
|
||||||
|
|
||||||
## Switching model
|
### Switching model
|
||||||
|
|
||||||
Treat the whole thing as a tiny user-space Ethernet switch.
|
Treat the whole thing as a tiny user-space Ethernet switch.
|
||||||
|
|
||||||
@@ -285,7 +313,7 @@ LAN frames go to matching remote client or all clients if broadcast/multicast
|
|||||||
|
|
||||||
But MAC learning belongs in the real design.
|
But MAC learning belongs in the real design.
|
||||||
|
|
||||||
## MAC identity
|
### MAC identity
|
||||||
|
|
||||||
Each Windows client needs a unique locally administered unicast MAC.
|
Each Windows client needs a unique locally administered unicast MAC.
|
||||||
|
|
||||||
@@ -295,7 +323,8 @@ Example range:
|
|||||||
02:xx:xx:xx:xx:xx
|
02:xx:xx:xx:xx:xx
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate once per install or per profile. Store it. Configure TAP with it. Announce it during join.
|
Generate once per install or per profile. Store it. Configure TAP with it.
|
||||||
|
Announce it during join.
|
||||||
|
|
||||||
Relay must reject:
|
Relay must reject:
|
||||||
|
|
||||||
@@ -315,11 +344,13 @@ maybe 2 later for weird cases
|
|||||||
|
|
||||||
This is your responsibility, not the user’s.
|
This is your responsibility, not the user’s.
|
||||||
|
|
||||||
## Linux gateway CAM-table refresh
|
### Linux gateway CAM-table refresh
|
||||||
|
|
||||||
The physical LAN switch must learn that remote clients’ MACs live behind the gateway port.
|
The physical LAN switch must learn that remote clients’ MACs live behind the
|
||||||
|
gateway port.
|
||||||
|
|
||||||
That happens when the gateway injects frames onto the LAN using the remote client’s source MAC.
|
That happens when the gateway injects frames onto the LAN using the remote
|
||||||
|
client’s source MAC.
|
||||||
|
|
||||||
But switch CAM entries age out. So the gateway should periodically refresh them.
|
But switch CAM entries age out. So the gateway should periodically refresh them.
|
||||||
|
|
||||||
@@ -330,7 +361,8 @@ for each connected remote MAC:
|
|||||||
inject a tiny harmless Ethernet frame with that MAC as source
|
inject a tiny harmless Ethernet frame with that MAC as source
|
||||||
```
|
```
|
||||||
|
|
||||||
The exact frame can be decided during implementation, but the goal is simple: keep the LAN switch mapping the remote MAC to the gateway’s physical port.
|
The exact frame can be decided during implementation, but the goal is simple:
|
||||||
|
keep the LAN switch mapping the remote MAC to the gateway’s physical port.
|
||||||
|
|
||||||
Phase 1 success criterion:
|
Phase 1 success criterion:
|
||||||
|
|
||||||
@@ -340,9 +372,10 @@ remote client MAC appears in the LAN switch MAC table on the gateway port
|
|||||||
|
|
||||||
If that is false, the L2 illusion is broken.
|
If that is false, the L2 illusion is broken.
|
||||||
|
|
||||||
## Safety filters
|
### Safety filters
|
||||||
|
|
||||||
Remote clients must not be allowed to spray arbitrary L2 control-plane junk onto the real LAN.
|
Remote clients must not be allowed to spray arbitrary L2 control-plane junk onto
|
||||||
|
the real LAN.
|
||||||
|
|
||||||
Drop remote → LAN unconditionally:
|
Drop remote → LAN unconditionally:
|
||||||
|
|
||||||
@@ -368,7 +401,8 @@ Also drop LAN → remote:
|
|||||||
|
|
||||||
No remote Windows client needs to see switch/control-plane traffic.
|
No remote Windows client needs to see switch/control-plane traffic.
|
||||||
|
|
||||||
EAPOL is especially important: remote clients should never be able to interfere with 802.1X or port authentication behavior on the physical switch.
|
EAPOL is especially important: remote clients should never be able to interfere
|
||||||
|
with 802.1X or port authentication behavior on the physical switch.
|
||||||
|
|
||||||
Add rate limits:
|
Add rate limits:
|
||||||
|
|
||||||
@@ -379,11 +413,12 @@ Add rate limits:
|
|||||||
- malformed packet disconnect threshold
|
- malformed packet disconnect threshold
|
||||||
```
|
```
|
||||||
|
|
||||||
## Windows routing / metric handling
|
### Windows routing / metric handling
|
||||||
|
|
||||||
The TAP adapter may receive DHCP from the party LAN. That is good.
|
The TAP adapter may receive DHCP from the party LAN. That is good.
|
||||||
|
|
||||||
But if DHCP gives it a default gateway, Windows might try to route the relay connection through the tunnel itself. That would break the tunnel.
|
But if DHCP gives it a default gateway, Windows might try to route the relay
|
||||||
|
connection through the tunnel itself. That would break the tunnel.
|
||||||
|
|
||||||
Client startup should:
|
Client startup should:
|
||||||
|
|
||||||
@@ -396,7 +431,8 @@ Client startup should:
|
|||||||
6. detect and neutralize TAP default-route takeover
|
6. detect and neutralize TAP default-route takeover
|
||||||
```
|
```
|
||||||
|
|
||||||
The TAP should be preferred for the party LAN subnet, but it must not steal general internet traffic.
|
The TAP should be preferred for the party LAN subnet, but it must not steal
|
||||||
|
general internet traffic.
|
||||||
|
|
||||||
Also strongly recommend uncommon LAN party subnets:
|
Also strongly recommend uncommon LAN party subnets:
|
||||||
|
|
||||||
@@ -409,9 +445,10 @@ bad: 192.168.178.0/24
|
|||||||
|
|
||||||
Duplicate subnet with a remote user’s home LAN will be painful.
|
Duplicate subnet with a remote user’s home LAN will be painful.
|
||||||
|
|
||||||
## Relay placement / latency
|
### Relay placement / latency
|
||||||
|
|
||||||
Relay-as-data-path is the right MVP. It makes the product work through NAT immediately.
|
Relay-as-data-path is the right MVP. It makes the product work through NAT
|
||||||
|
immediately.
|
||||||
|
|
||||||
But latency becomes:
|
But latency becomes:
|
||||||
|
|
||||||
@@ -421,7 +458,10 @@ client → relay → gateway
|
|||||||
|
|
||||||
So relay location matters.
|
So relay location matters.
|
||||||
|
|
||||||
For Europe/Germany-focused usage, put the relay near the expected players and LAN site, e.g. Frankfurt/Nuremberg/Amsterdam depending on hosting. Later, add direct QUIC path attempts with relay fallback, but do not block MVP on NAT traversal.
|
For Europe/Germany-focused usage, put the relay near the expected players and
|
||||||
|
LAN site, e.g. Frankfurt/Nuremberg/Amsterdam depending on hosting. Later, add
|
||||||
|
direct QUIC path attempts with relay fallback, but do not block MVP on NAT
|
||||||
|
traversal.
|
||||||
|
|
||||||
Design the room protocol so future modes are possible:
|
Design the room protocol so future modes are possible:
|
||||||
|
|
||||||
@@ -431,7 +471,7 @@ mode = direct-p2p
|
|||||||
mode = direct-failed-relay-fallback
|
mode = direct-failed-relay-fallback
|
||||||
```
|
```
|
||||||
|
|
||||||
## Logging / diagnostics
|
### Logging / diagnostics
|
||||||
|
|
||||||
Phase 1 should log heavily.
|
Phase 1 should log heavily.
|
||||||
|
|
||||||
@@ -473,9 +513,9 @@ Broadcast traffic flowing
|
|||||||
Warning: TAP received default route, adjusted metric
|
Warning: TAP received default route, adjusted metric
|
||||||
```
|
```
|
||||||
|
|
||||||
## Phase plan
|
### Phase plan
|
||||||
|
|
||||||
### Phase 1: prove the illusion
|
#### Phase 1: prove the illusion
|
||||||
|
|
||||||
Manual, ugly, real.
|
Manual, ugly, real.
|
||||||
|
|
||||||
@@ -500,7 +540,7 @@ Success criteria:
|
|||||||
- one real LAN game discovers or joins a LAN server
|
- one real LAN game discovers or joins a LAN server
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 2: multi-client
|
#### Phase 2: multi-client
|
||||||
|
|
||||||
```text
|
```text
|
||||||
- multiple Windows clients
|
- multiple Windows clients
|
||||||
@@ -512,7 +552,7 @@ Success criteria:
|
|||||||
- reconnect handling
|
- reconnect handling
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 3: safety and correctness
|
#### Phase 3: safety and correctness
|
||||||
|
|
||||||
```text
|
```text
|
||||||
- L2 control-plane filters
|
- L2 control-plane filters
|
||||||
@@ -524,7 +564,7 @@ Success criteria:
|
|||||||
- better malformed-frame handling
|
- better malformed-frame handling
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 4: product UX
|
#### Phase 4: product UX
|
||||||
|
|
||||||
```text
|
```text
|
||||||
- Windows installer
|
- Windows installer
|
||||||
@@ -536,9 +576,11 @@ Success criteria:
|
|||||||
- logs export button
|
- logs export button
|
||||||
```
|
```
|
||||||
|
|
||||||
Driver signing and TAP bundling must be validated early. `tap-windows6` is the right kind of driver, but Windows driver installation/signing is a product risk, not something to handwave. ([GitHub][1])
|
Driver signing and TAP bundling must be validated early. `tap-windows6` is the
|
||||||
|
right kind of driver, but Windows driver installation/signing is a product risk,
|
||||||
|
not something to handwave. ([GitHub][1])
|
||||||
|
|
||||||
### Phase 5: better security and latency
|
#### Phase 5: better security and latency
|
||||||
|
|
||||||
```text
|
```text
|
||||||
- invite tokens / auth
|
- invite tokens / auth
|
||||||
@@ -549,7 +591,7 @@ Driver signing and TAP bundling must be validated early. `tap-windows6` is the r
|
|||||||
- regional relay selection
|
- regional relay selection
|
||||||
```
|
```
|
||||||
|
|
||||||
## Explicit non-goals
|
### Explicit non-goals
|
||||||
|
|
||||||
For MVP, do not build:
|
For MVP, do not build:
|
||||||
|
|
||||||
@@ -565,14 +607,29 @@ For MVP, do not build:
|
|||||||
- full internet VPN mode
|
- full internet VPN mode
|
||||||
```
|
```
|
||||||
|
|
||||||
## One-sentence version
|
### One-sentence version
|
||||||
|
|
||||||
Build a **Rust Windows TAP client + public QUIC relay + Linux AF_PACKET gateway** that carries one small-MTU Ethernet frame per QUIC datagram, gives each remote player a unique virtual MAC on the real LAN, filters dangerous L2 control traffic, and keeps the physical LAN gateway as the only machine touching the real LAN.
|
Build a **Rust Windows TAP client + public QUIC relay + Linux AF_PACKET
|
||||||
|
gateway** that carries one small-MTU Ethernet frame per QUIC datagram, gives
|
||||||
|
each remote player a unique virtual MAC on the real LAN, filters dangerous L2
|
||||||
|
control traffic, and keeps the physical LAN gateway as the only machine touching
|
||||||
|
the real LAN.
|
||||||
|
|
||||||
[1]: https://github.com/OpenVPN/tap-windows6?utm_source=chatgpt.com "OpenVPN/tap-windows6: Windows TAP driver (NDIS 6)"
|
[1]:
|
||||||
[2]: https://man7.org/linux/man-pages/man7/packet.7.html?utm_source=chatgpt.com "packet(7) - Linux manual page"
|
<https://github.com/OpenVPN/tap-windows6?utm_source=chatgpt.com>
|
||||||
[3]: https://man7.org/linux/man-pages/man7/capabilities.7.html?utm_source=chatgpt.com "capabilities(7) - Linux manual page"
|
"OpenVPN/tap-windows6: Windows TAP driver (NDIS 6)"
|
||||||
[4]: https://datatracker.ietf.org/doc/html/rfc9221?utm_source=chatgpt.com "RFC 9221 - An Unreliable Datagram Extension to QUIC"
|
[2]:
|
||||||
[5]: https://docs.rs/quinn/latest/quinn/struct.Connection.html?utm_source=chatgpt.com "Connection in quinn - Rust"
|
<https://man7.org/linux/man-pages/man7/packet.7.html?utm_source=chatgpt.com>
|
||||||
|
"packet(7) - Linux manual page"
|
||||||
|
[3]:
|
||||||
|
<https://man7.org/linux/man-pages/man7/capabilities.7.html?utm_source=chatgpt.com>
|
||||||
|
"capabilities(7) - Linux manual page"
|
||||||
|
[4]:
|
||||||
|
<https://datatracker.ietf.org/doc/html/rfc9221?utm_source=chatgpt.com>
|
||||||
|
"RFC 9221 - An Unreliable Datagram Extension to QUIC"
|
||||||
|
[5]:
|
||||||
|
<https://docs.rs/quinn/latest/quinn/struct.Connection.html?utm_source=chatgpt.com>
|
||||||
|
"Connection in quinn - Rust"
|
||||||
|
|
||||||
I want a mono-repo, Rust code, crates into a "crates" folder, one cargo workspace.
|
I want a mono-repo, Rust code, crates into a "crates" folder, one cargo
|
||||||
|
workspace.
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ Windows route-table boundary:
|
|||||||
- unicast IP address snapshots for TAP diagnostics
|
- unicast IP address snapshots for TAP diagnostics
|
||||||
- scoped host-route pinning for the relay IP on the pre-TAP interface
|
- scoped host-route pinning for the relay IP on the pre-TAP interface
|
||||||
- host-route pin matching for relay-route verification after TAP activation
|
- 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
|
- non-Windows builds return a clear unsupported-platform error
|
||||||
|
|
||||||
### `lanparty-client-tap`
|
### `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
|
- per-peer egress budget checks against the negotiated datagram size
|
||||||
- reliable `PeerJoined`/`PeerLeft` notifications plus gateway identity in
|
- reliable `PeerJoined`/`PeerLeft` notifications plus gateway identity in
|
||||||
welcome messages
|
welcome messages
|
||||||
- L2 safety filters for invalid-source, jumbo, switch-control, remote VLAN
|
- L2 safety filters for invalid-source, jumbo, switch-control, remote VLAN tags,
|
||||||
tags, remote IPv6 fragments, IPv4/IPv6 DHCP-server, and IPv6-RA frames,
|
remote IPv6 fragments, IPv4/IPv6 DHCP-server, and IPv6-RA frames, including
|
||||||
including frames behind ordinary IPv6 extension headers
|
frames behind ordinary IPv6 extension headers
|
||||||
- client broadcast/multicast, unknown-unicast, and total bandwidth limiting
|
- client broadcast/multicast, unknown-unicast, and total bandwidth limiting
|
||||||
- malformed peer datagram disconnect threshold
|
- malformed peer datagram disconnect threshold
|
||||||
- peer stats control events retained for relay diagnostics
|
- peer stats control events retained for relay diagnostics
|
||||||
@@ -129,9 +130,9 @@ cargo build --release -p lanparty-relay -p lanparty-gateway
|
|||||||
git diff --check
|
git diff --check
|
||||||
```
|
```
|
||||||
|
|
||||||
These checks cover the local Rust code and the real client/relay/gateway
|
These checks cover the local Rust code and the real client/relay/gateway session
|
||||||
session paths that can run without Windows TAP or LAN hardware. For the Windows
|
paths that can run without Windows TAP or LAN hardware. For the Windows client
|
||||||
client build and the manual MVP end-to-end proof, see [TESTING.md](TESTING.md).
|
build and the manual MVP end-to-end proof, see [TESTING.md](TESTING.md).
|
||||||
|
|
||||||
## Relay
|
## 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 so the gateway and client can pin it in development. Production
|
||||||
certificate handling remains future work. Ethernet forwarding decisions are
|
certificate handling remains future work. Ethernet forwarding decisions are
|
||||||
logged with room, peer, MAC, ethertype, action, drop reason, and target count.
|
logged with room, peer, MAC, ethertype, action, drop reason, and target count.
|
||||||
Safety-policy rejects use the `filtered` action so they are distinguishable
|
Safety-policy rejects use the `filtered` action so they are distinguishable from
|
||||||
from malformed/unknown-destination drops and rate limits.
|
malformed/unknown-destination drops and rate limits. Malformed peer datagrams
|
||||||
Malformed peer datagrams log their per-peer count before the relay disconnects
|
log their per-peer count before the relay disconnects peers that cross the
|
||||||
peers that cross the malformed-datagram threshold.
|
malformed-datagram threshold. Relay egress skips caused by a target peer's
|
||||||
Relay egress skips caused by a target peer's smaller datagram budget are logged
|
smaller datagram budget are logged with the ingress peer, target peer, encoded
|
||||||
with the ingress peer, target peer, encoded length, and target budget.
|
length, and target budget. Ingress datagrams larger than the sending peer's
|
||||||
Ingress datagrams larger than the sending peer's negotiated datagram budget are
|
negotiated datagram budget are dropped before decode/forwarding and logged with
|
||||||
dropped before decode/forwarding and logged with `reason=datagram_budget`.
|
`reason=datagram_budget`. Unknown unicast from a client is forwarded only to the
|
||||||
Unknown unicast from a client is forwarded only to the gateway port; unknown
|
gateway port; unknown unicast from the gateway is dropped instead of flooded to
|
||||||
unicast from the gateway is dropped instead of flooded to every remote client.
|
every remote client. When a peer joins or leaves, the relay sends a reliable
|
||||||
When a peer joins or leaves, the relay sends a reliable lifecycle control event
|
lifecycle control event to peers that are still present in the room. Newly
|
||||||
to peers that are still present in the room. Newly joined peers also receive
|
joined peers also receive `PeerJoined` events for peers that were already
|
||||||
`PeerJoined` events for peers that were already present, and catch-up delivery
|
present, and catch-up delivery is part of the accepted handshake rather than a
|
||||||
is part of the accepted handshake rather than a best-effort follow-up. When a
|
best-effort follow-up. When a client joins, the relay notifies existing peers
|
||||||
client joins, the relay notifies existing peers before the client receives its
|
before the client receives its welcome, so gateways can seed client MAC state
|
||||||
welcome, so gateways can seed client MAC state before that client starts
|
before that client starts sending frames. When a gateway joins, the relay gives
|
||||||
sending frames. When a gateway joins, the relay gives the gateway the current
|
the gateway the current client list before notifying clients that the gateway is
|
||||||
client list before notifying clients that the gateway is available.
|
available.
|
||||||
|
|
||||||
### MVP Trust Model
|
### 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
|
keeps an invalid, wireless, or unplugged interface from briefly advertising a
|
||||||
gateway that cannot bridge. Once both sides are ready, it bridges Ethernet
|
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 between the relay and wired LAN until shutdown. It captures whole LAN
|
||||||
frames up to the
|
frames up to the overlay payload-length ceiling before deciding whether they fit
|
||||||
overlay payload-length ceiling before deciding whether they fit the tunnel. It
|
the tunnel. It never fragments Ethernet frames; LAN frames with invalid source
|
||||||
never fragments Ethernet frames; LAN frames with invalid source MACs, L2
|
MACs, L2 control-plane traffic, jumbo frames, frames above the negotiated TAP
|
||||||
control-plane traffic, jumbo frames, frames above the negotiated TAP MTU, or
|
MTU, or encoded datagrams exceeding the negotiated QUIC budget are counted,
|
||||||
encoded datagrams exceeding the negotiated QUIC budget are counted, dropped,
|
dropped, and logged locally instead of stopping the bridge or consuming relay
|
||||||
and logged locally instead of stopping the bridge or consuming relay bandwidth.
|
bandwidth. Remote frames received from the relay are safety-checked again before
|
||||||
Remote frames received from
|
LAN injection and must use the announced virtual MAC for their source peer, so
|
||||||
the relay are safety-checked again before LAN injection and must use the
|
invalid-source, forged-source, L2 control-plane, remote VLAN, DHCP-server, IPv6
|
||||||
announced virtual MAC for their source peer, so invalid-source, forged-source,
|
Router Advertisement, IPv6 fragment, jumbo, and over-TAP-MTU frames cannot cross
|
||||||
L2 control-plane, remote VLAN, DHCP-server, IPv6 Router Advertisement, IPv6
|
the gateway's final physical-LAN boundary even if they reached the gateway over
|
||||||
fragment, jumbo, and over-TAP-MTU frames cannot cross the gateway's final
|
QUIC. `--relay` accepts a DNS name or socket address; bare hosts default to
|
||||||
physical-LAN boundary even if they reached the gateway over QUIC.
|
UDP/443. The gateway rejects Linux interfaces that sysfs identifies as Wi-Fi,
|
||||||
`--relay` accepts a DNS name or socket address; bare hosts default to UDP/443.
|
and rejects wired interfaces whose sysfs carrier state reports no link; managed
|
||||||
The gateway rejects Linux interfaces that sysfs identifies as Wi-Fi, and rejects
|
wireless NICs are not supported for the physical LAN bridge. It tracks
|
||||||
wired interfaces whose sysfs carrier state reports no link; managed wireless
|
remote-client MACs from relay lifecycle events and periodically emits small CAM
|
||||||
NICs are not supported for the physical LAN bridge.
|
refresh frames, logged with `reason=periodic`, so the physical switch keeps
|
||||||
It tracks remote-client MACs from relay lifecycle events and periodically emits
|
those MACs associated with the gateway port. A newly observed client also
|
||||||
small CAM refresh frames, logged with `reason=periodic`, so the physical
|
triggers an immediate CAM refresh frame logged with `reason=peer_joined` instead
|
||||||
switch keeps those MACs associated with the gateway port. A newly observed
|
of waiting for the first periodic refresh tick. When control events and frame
|
||||||
client also triggers an immediate CAM refresh frame logged with
|
work are both ready, the bridge handles the lifecycle event first so first
|
||||||
`reason=peer_joined` instead of waiting for the first periodic refresh tick.
|
packets after a client joins use the freshest remote-MAC state available
|
||||||
When control events and frame work are both ready, the bridge handles the
|
locally. Gateway frame logs include direction, peer id when present, MACs,
|
||||||
lifecycle event first so first packets after a client joins use the freshest
|
ethertype/length, frame length, action, and drop reason. The gateway also tracks
|
||||||
remote-MAC state available locally. Gateway
|
frame/datagram counters and periodically sends stats snapshots to the relay.
|
||||||
frame logs include direction, peer id when present, MACs, ethertype/length,
|
Malformed or runt LAN frames are counted and logged as dropped instead of
|
||||||
frame length, action, and drop reason. The gateway also tracks frame/datagram
|
disappearing before accounting. It drops unrelated LAN unicast locally once the
|
||||||
counters and periodically sends stats snapshots to the relay. Malformed or runt
|
destination is known not to be a connected remote client, so busy LAN traffic is
|
||||||
LAN frames are counted and logged as dropped instead of disappearing before
|
not sent to the public relay just to be discarded there. Relay lifecycle events
|
||||||
accounting. It drops unrelated LAN unicast locally once the destination is known
|
seed and retire remote-client MACs for CAM refresh and LAN-destination filtering
|
||||||
not to be a connected remote client, so busy LAN traffic is not sent to the
|
even before that client sends traffic. On shutdown, the gateway sends a
|
||||||
public relay just to be discarded there. Relay lifecycle events seed and retire
|
best-effort disconnect control message before closing QUIC so the relay can
|
||||||
remote-client MACs for CAM refresh and LAN-destination filtering even before
|
report the intended reason.
|
||||||
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
|
## 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
|
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
|
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
|
relay as `role = client` with a generated locally administered virtual MAC
|
||||||
persisted in
|
persisted in `lanparty-client-identity.json`. Before resolving or connecting to
|
||||||
`lanparty-client-identity.json`. Before resolving or connecting to the relay,
|
the relay, it writes the generated tunnel MAC to the selected TAP driver's
|
||||||
it writes the generated tunnel MAC to the selected TAP driver's
|
|
||||||
`NetworkAddress` registry setting and marks TAP media disconnected. That clears
|
`NetworkAddress` registry setting and marks TAP media disconnected. That clears
|
||||||
stale connected state from a previous crashed run without letting the TAP
|
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, pins a host route for the resolved relay IP on the current
|
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
|
pre-TAP interface, verifies that Windows is using that host route, completes the
|
||||||
the control-stream hello/welcome handshake, verifies the host route again after
|
control-stream hello/welcome handshake, verifies the host route again after TAP
|
||||||
TAP activation, and bridges Ethernet frames between the relay and the
|
activation, and bridges Ethernet frames between the relay and the TAP-Windows6
|
||||||
TAP-Windows6 adapter until shutdown. `--relay` accepts a DNS name or socket
|
adapter until shutdown. `--relay` accepts a DNS name or socket address; bare
|
||||||
address; bare hosts default to UDP/443.
|
hosts default to UDP/443. TAP frames whose source MAC does not match that
|
||||||
TAP frames whose source MAC does not match that generated tunnel MAC are
|
generated tunnel MAC are dropped locally before they can consume relay
|
||||||
dropped locally before they can consume relay bandwidth; the relay still
|
bandwidth; the relay still enforces the same source-MAC rule. If the exact relay
|
||||||
enforces the same source-MAC rule.
|
host route already exists, the client uses it and leaves it alone on exit. The
|
||||||
If the exact relay host route already exists, the client uses it and leaves it
|
startup status reports whether the relay already has a LAN gateway for the room.
|
||||||
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
|
`--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
|
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
|
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
|
applies a scoped TAP interface metric and disables TAP default routes while it
|
||||||
runs, periodically rechecks that the relay route remains pinned, then restores
|
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
|
the previous route policy and TAP media status on exit. Startup prints a warning
|
||||||
when TAP default routes were enabled
|
when TAP default routes were enabled before the scoped protection was applied.
|
||||||
before the scoped protection was applied. Startup still fails before bridging
|
Startup still fails before bridging if the driver-reported MAC does not match
|
||||||
if the driver-reported MAC does not match the tunnel identity, because an
|
the tunnel identity, because an already-initialized Windows TAP adapter may need
|
||||||
already-initialized Windows TAP adapter may need to be disabled/enabled or
|
to be disabled/enabled or reinstalled before it reloads the configured
|
||||||
reinstalled before it reloads the configured `NetworkAddress`.
|
`NetworkAddress`. If exactly one TAP-Windows6 adapter is installed, the client
|
||||||
If exactly one TAP-Windows6 adapter is installed, the client opens it
|
opens it automatically. If multiple TAP-Windows6 adapters are installed, startup
|
||||||
automatically. If multiple TAP-Windows6 adapters are installed, startup fails
|
fails until `--tap-instance-id` selects the intended adapter by NetCfgInstanceId
|
||||||
until `--tap-instance-id` selects the intended adapter by NetCfgInstanceId /
|
/ InterfaceGuid. `--list-tap-adapters` prints the TAP adapter ids and exits
|
||||||
InterfaceGuid. `--list-tap-adapters` prints the TAP adapter ids and exits
|
without connecting. It prints and reports client diagnostics snapshots with
|
||||||
without connecting.
|
relay reachability, LAN-gateway presence, route-pinning, QUIC datagram budget,
|
||||||
It prints and reports client diagnostics snapshots with relay reachability,
|
relay RTT, TAP status/IP, broadcast frame flow, frame/datagram counters, and
|
||||||
LAN-gateway presence, route-pinning, QUIC datagram budget, relay RTT, TAP
|
drops. The periodic diagnostics refresh the TAP unicast IP so DHCP results that
|
||||||
status/IP, broadcast frame flow, frame/datagram counters, and drops. The
|
arrive after bridging starts become visible in later status lines, preferring a
|
||||||
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
|
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,
|
snapshot also emits short user-facing lines such as relay/gateway connection
|
||||||
relay-route and TAP readiness warnings, DHCP address presence, relay RTT, and
|
status, relay-route and TAP readiness warnings, DHCP address presence, relay
|
||||||
broadcast-flow confirmation. One-way broadcast diagnostics distinguish frames
|
RTT, and broadcast-flow confirmation. One-way broadcast diagnostics distinguish
|
||||||
sent toward the LAN from broadcast frames received back from the LAN. Malformed frames
|
frames sent toward the LAN from broadcast frames received back from the LAN.
|
||||||
read from TAP, invalid or unauthorized source-MAC frames, L2 control-plane
|
Malformed frames read from TAP, invalid or unauthorized source-MAC frames, L2
|
||||||
traffic, remote VLAN tags, DHCP server replies, IPv6 Router Advertisements, IPv6
|
control-plane traffic, remote VLAN tags, DHCP server replies, IPv6 Router
|
||||||
fragments, jumbo frames, frames above the negotiated TAP MTU, and TAP frames
|
Advertisements, IPv6 fragments, jumbo frames, frames above the negotiated TAP
|
||||||
whose encoded datagrams exceed the negotiated QUIC budget are counted and
|
MTU, and TAP frames whose encoded datagrams exceed the negotiated QUIC budget
|
||||||
dropped before relay send without stopping the bridge. Relayed LAN frames are
|
are counted and dropped before relay send without stopping the bridge. Relayed
|
||||||
also safety-checked before TAP writes, so switch-control traffic,
|
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
|
invalid-source frames, jumbo frames, and over-TAP-MTU frames stay out of the
|
||||||
Windows adapter even if they reached the client over QUIC.
|
Windows adapter even if they reached the client over QUIC. Misdirected unicast
|
||||||
Misdirected unicast frames not addressed to the client's virtual MAC are also
|
frames not addressed to the client's virtual MAC are also counted, skipped, and
|
||||||
counted, skipped, and logged with the drop reason; accepted TAP-to-relay and
|
logged with the drop reason; accepted TAP-to-relay and relay-to-TAP frames are
|
||||||
relay-to-TAP frames are logged with direction, peer id, MACs, ethertype/length,
|
logged with direction, peer id, MACs, ethertype/length, frame length, action,
|
||||||
frame length, action, and drop reason. TAP device read/write errors still stop
|
and drop reason. TAP device read/write errors still stop the bridge. Relay
|
||||||
the bridge.
|
lifecycle events are logged as they arrive, including gateway joins and peer
|
||||||
Relay lifecycle events are logged as they arrive, including gateway joins and
|
leaves. The client remembers peer identities from join and catch-up events and
|
||||||
peer leaves. The client remembers peer identities from join and catch-up events
|
from the initial welcome, so later leave logs can identify a disconnected LAN
|
||||||
and from the initial welcome, so later leave logs can identify a disconnected
|
gateway or client MAC when that peer was known.
|
||||||
LAN gateway or client MAC when that peer was known.
|
|
||||||
|
|||||||
+24
-25
@@ -58,8 +58,8 @@ Windows TAP IPv4:
|
|||||||
- Gateway: Linux machine plugged into the LAN party switch with wired Ethernet.
|
- Gateway: Linux machine plugged into the LAN party switch with wired Ethernet.
|
||||||
- Client: Windows 11 machine with TAP-Windows6 installed.
|
- Client: Windows 11 machine with TAP-Windows6 installed.
|
||||||
|
|
||||||
Use the same room code everywhere, for example `ROOM1`.
|
Use the same room code everywhere, for example `ROOM1`. Start order is relay
|
||||||
Start order is relay first, gateway second, Windows client last.
|
first, gateway second, Windows client last.
|
||||||
|
|
||||||
## Log Capture
|
## Log Capture
|
||||||
|
|
||||||
@@ -153,8 +153,8 @@ Linux: ./target/release/lanparty-gateway
|
|||||||
Windows: .\target\release\lanparty-client-win.exe
|
Windows: .\target\release\lanparty-client-win.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
The Windows client must run elevated because it opens TAP and edits routes.
|
The Windows client must run elevated because it opens TAP and edits routes. The
|
||||||
The gateway usually needs root because it opens an AF_PACKET raw socket.
|
gateway usually needs root because it opens an AF_PACKET raw socket.
|
||||||
|
|
||||||
## Start The Relay
|
## Start The Relay
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@ sudo ./target/release/lanparty-gateway \
|
|||||||
```
|
```
|
||||||
|
|
||||||
Use the real wired LAN interface name for `--interface`. `--iface` is accepted
|
Use the real wired LAN interface name for `--interface`. `--iface` is accepted
|
||||||
as a shorter alias. Do not use Wi-Fi. The gateway fails before joining the
|
as a shorter alias. Do not use Wi-Fi. The gateway fails before joining the relay
|
||||||
relay if sysfs reports no Ethernet carrier.
|
if sysfs reports no Ethernet carrier.
|
||||||
|
|
||||||
Expected gateway output:
|
Expected gateway output:
|
||||||
|
|
||||||
@@ -245,7 +245,8 @@ one explicitly:
|
|||||||
Expected client output:
|
Expected client output:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
prepared TAP adapter ... MAC ... configured and media disconnected before relay connect
|
prepared TAP adapter ... MAC ... configured and media disconnected before relay
|
||||||
|
connect
|
||||||
relay route pinned before TAP ...
|
relay route pinned before TAP ...
|
||||||
relay route verified before TAP activation ...
|
relay route verified before TAP activation ...
|
||||||
lanparty-client-win connecting virtual MAC ... to relay ... room ROOM1
|
lanparty-client-win connecting virtual MAC ... to relay ... room ROOM1
|
||||||
@@ -261,11 +262,10 @@ relay event: LAN gateway connected as peer ...
|
|||||||
|
|
||||||
The route pin line ends with `(created)` or `(already existed)`. Either is OK.
|
The route pin line ends with `(created)` or `(already existed)`. Either is OK.
|
||||||
`already existed` usually means a matching relay host route was already present,
|
`already existed` usually means a matching relay host route was already present,
|
||||||
for example after a previous crashed test run.
|
for example after a previous crashed test run. You may also see TAP IPv4/IPv6
|
||||||
You may also see TAP IPv4/IPv6 MTU, metric, and default-route protection lines
|
MTU, metric, and default-route protection lines between the connect and TAP-open
|
||||||
between the connect and TAP-open lines. Those are expected.
|
lines. Those are expected. The lifecycle event may appear after the bridge
|
||||||
The lifecycle event may appear after the bridge starts because event logging
|
starts because event logging begins once TAP and route protection are ready.
|
||||||
begins once TAP and route protection are ready.
|
|
||||||
|
|
||||||
The first diagnostics line may show `IP unknown`. After DHCP succeeds, a later
|
The first diagnostics line may show `IP unknown`. After DHCP succeeds, a later
|
||||||
line should show:
|
line should show:
|
||||||
@@ -274,8 +274,8 @@ line should show:
|
|||||||
DHCP received: 10.x.x.x
|
DHCP received: 10.x.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
If Windows reports both a `169.254.x.x` TAP address and a real LAN IPv4
|
If Windows reports both a `169.254.x.x` TAP address and a real LAN IPv4 address,
|
||||||
address, the client diagnostics should prefer the real LAN address.
|
the client diagnostics should prefer the real LAN address.
|
||||||
|
|
||||||
## Verify The Tunnel
|
## Verify The Tunnel
|
||||||
|
|
||||||
@@ -395,10 +395,9 @@ drop_reason=RateLimit
|
|||||||
|
|
||||||
On gateway `LanToRemote` logs, `UnknownDestination` usually means the gateway
|
On gateway `LanToRemote` logs, `UnknownDestination` usually means the gateway
|
||||||
captured unrelated LAN unicast and dropped it locally instead of sending it to
|
captured unrelated LAN unicast and dropped it locally instead of sending it to
|
||||||
the relay.
|
the relay. `TapMtuExceeded` means a host emitted an Ethernet frame larger than
|
||||||
`TapMtuExceeded` means a host emitted an Ethernet frame larger than the
|
the negotiated tunnel MTU; occasional drops can happen while testing software
|
||||||
negotiated tunnel MTU; occasional drops can happen while testing software that
|
that does not honor the smaller adapter MTU yet.
|
||||||
does not honor the smaller adapter MTU yet.
|
|
||||||
|
|
||||||
Drops that should be investigated if they dominate:
|
Drops that should be investigated if they dominate:
|
||||||
|
|
||||||
@@ -414,8 +413,8 @@ drop_reason=Ipv6Fragment
|
|||||||
```
|
```
|
||||||
|
|
||||||
On gateway `RemoteToLan` logs, `UnauthorizedSourceMac` means the relayed peer id
|
On gateway `RemoteToLan` logs, `UnauthorizedSourceMac` means the relayed peer id
|
||||||
did not match the client MAC announced by lifecycle events. If it repeats,
|
did not match the client MAC announced by lifecycle events. If it repeats, check
|
||||||
check relay lifecycle logs and duplicate-MAC rejection first.
|
relay lifecycle logs and duplicate-MAC rejection first.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
@@ -454,11 +453,11 @@ If ping fails but DHCP worked, check Windows firewall, the target LAN host
|
|||||||
firewall, and whether the LAN subnet conflicts with the client's home LAN.
|
firewall, and whether the LAN subnet conflicts with the client's home LAN.
|
||||||
Uncommon LAN subnets such as `10.73.42.0/24` are safer than `192.168.0.0/24`.
|
Uncommon LAN subnets such as `10.73.42.0/24` are safer than `192.168.0.0/24`.
|
||||||
|
|
||||||
If switch MAC learning does not show the Windows client MAC on the gateway
|
If switch MAC learning does not show the Windows client MAC on the gateway port,
|
||||||
port, look for `gateway CAM refresh ... reason=peer_joined` immediately after
|
look for `gateway CAM refresh ... reason=peer_joined` immediately after join and
|
||||||
join and `gateway CAM refresh ... reason=periodic` about once per minute after
|
`gateway CAM refresh ... reason=periodic` about once per minute after that. If
|
||||||
that. If those lines are present but the switch still does not learn it, check
|
those lines are present but the switch still does not learn it, check the
|
||||||
the selected gateway interface and switch port first.
|
selected gateway interface and switch port first.
|
||||||
|
|
||||||
## Cleanup
|
## Cleanup
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ edition.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
windows-sys = { workspace = true, features = [
|
windows-sys = {
|
||||||
"Win32_Foundation",
|
workspace = true,
|
||||||
"Win32_NetworkManagement_IpHelper",
|
features = [
|
||||||
"Win32_NetworkManagement_Ndis",
|
"Win32_Foundation",
|
||||||
"Win32_Networking_WinSock",
|
"Win32_NetworkManagement_IpHelper",
|
||||||
] }
|
"Win32_NetworkManagement_Ndis",
|
||||||
|
"Win32_Networking_WinSock",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ edition.workspace = true
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
lanparty-proto = { path = "../lanparty-proto" }
|
lanparty-proto = { path = "../lanparty-proto" }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
windows-sys = { workspace = true, features = [
|
windows-sys = {
|
||||||
"Win32_Foundation",
|
workspace = true,
|
||||||
"Win32_Security",
|
features = [
|
||||||
"Win32_Storage_FileSystem",
|
"Win32_Foundation",
|
||||||
"Win32_System_IO",
|
"Win32_Security",
|
||||||
"Win32_System_Registry",
|
"Win32_Storage_FileSystem",
|
||||||
] }
|
"Win32_System_IO",
|
||||||
|
"Win32_System_Registry",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ lanparty-obs = { path = "../lanparty-obs" }
|
|||||||
lanparty-proto = { path = "../lanparty-proto" }
|
lanparty-proto = { path = "../lanparty-proto" }
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
lanparty-client-route = { path = "../lanparty-client-route" }
|
lanparty-client-route = { path = "../lanparty-client-route" }
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
set positional-arguments
|
||||||
|
|
||||||
|
run *args:
|
||||||
|
cargo run -- "$@"
|
||||||
|
|
||||||
|
build:
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
build-release:
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
build-production:
|
||||||
|
cargo build --profile production
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
cargo +nightly fmt
|
||||||
|
tombi format
|
||||||
|
fd -tf -e md -x prettier --write --prose-wrap always --print-width 80
|
||||||
|
rumdl check --flavor commonmark --fix
|
||||||
|
just --fmt
|
||||||
|
|
||||||
|
_fix:
|
||||||
|
cargo fix --workspace --all-targets --all-features
|
||||||
|
cargo clippy --fix --workspace --all-targets --all-features
|
||||||
|
|
||||||
|
fix: _fix fmt
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
|
||||||
|
test:
|
||||||
|
cargo test --workspace --all-targets --all-features
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
Reference in New Issue
Block a user