fix: redesign direct address allocation and membership authority - #24
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
The direction is right, and better than what I was doing: making signed Genesis the allocation authority and signed membership the only Two things it doesn't fix, both still present in the branch and both on main today:
Two questions rather than objections:
Also: what's the migration story for networks that already exist? Removing collision indexes and overrides changes allocation, so I assume existing Direct networks renumber. Worth stating explicitly in the PR. One heads-up: main got rebased and dropped the 8 datapath commits, so all my open PRs picked them up and look enormous. Rebasing them now, ignore the diffs until I've pushed. |
Captures the reproduction and what the evidence did and did not support, including that the originally reported no_route figure was disproven (it was multicast discovery noise) and that the anti-spoof drops were later confirmed causally with a TCP probe against a live peer. Notes that tunnetio#24 supersedes the proposal section, and which two defects it does not address.
075e70d to
a00f700
Compare
tunnetio#24 moved Direct addressing to exact /32s and `build_tun_multi` passes a hardcoded prefix of 32. The Android app derived its route from that prefix, so `networkAddress(ipv4, 32)` produced a host route to the node itself: the tunnel captured no peer traffic at all while still reporting connected. The Kotlin comment still described the old model ("Direct mode uses a /10, so the route must be the truncated network"). Addresses and routes are separate facts, so `TunRequest` now carries them as separate lists rather than one address plus a prefix the app has to interpret. A node holds one /32 per joined network; the traffic that must enter the tunnel is each network's peer range, taken from the signed genesis address plan and threaded through `DataPlaneActorConfig`. The JNI signature becomes `([Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;I)I`, passing addresses, routes and resolvers in canonical text form so the contract does not change shape again as the lists grow. `establishTun` applies each address as a /32, each supplied route, and each resolver, and refuses to establish with no routes rather than producing a tunnel that silently carries nothing. The resolver list is deliberately empty for now. PeerDNS binds host loopback, which Android cannot use: port 53 is privileged for an unprivileged app, and `netd` resolves per app so 127.0.0.1 would name the app rather than the agent. Making names work needs PeerDNS to answer on an in-tunnel address, which is a feature rather than plumbing; the field is in place for when it exists.
This PR addresses #18 by replacing Direct's hardcoded addressing model with a proper network-level architecture.
The root problem was broader than the
100.64.0.0/10collision with Tailscale: Direct addressing was spread across hardcoded CIDRs, local derivation logic, DNS fake IPs, join-order precedence, and manual overrides, with no single authenticated source of truth.The new design makes signed Genesis the authority for the network's peer allocation range, makes the coordinator the only peer-IP allocator, and makes signed membership the only
EndpointId -> IPauthority.It also removes the broad connected subnet model in favor of exact
/32addresses/routes, removes legacy collision indexes and IP overrides, makes overlapping Direct networks fail explicitly instead of relying on precedence, and keeps PeerDNS/MagicDNS host-local rather than part of the Direct protocol.The goal is a simpler zero-config model: users keep using
tunnet create/invite/join, while address selection, validation, conflict detection, allocation, and routing are handled automatically.