wgengine/magicsock: make endpoint.bestAddr Geneve-aware (#16195)

This commit adds a new type to magicsock, epAddr, which largely ends up
replacing netip.AddrPort in packet I/O paths throughout, enabling
Geneve encapsulation over UDP awareness.

The conn.ReceiveFunc for UDP has been revamped to fix and more clearly
distinguish the different classes of packets we expect to receive: naked
STUN binding messages, naked disco, naked WireGuard, Geneve-encapsulated
disco, and Geneve-encapsulated WireGuard.

Prior to this commit, STUN matching logic in the RX path could swallow
a naked WireGuard packet if the keypair index, which is randomly
generated, happened to overlap with a subset of the STUN magic cookie.

Updates tailscale/corp#27502
Updates tailscale/corp#29326

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited
2025-06-06 09:46:29 -07:00
committed by GitHub
parent 3f7a9f82e3
commit 66ae8737f4
14 changed files with 604 additions and 386 deletions

View File

@@ -740,8 +740,11 @@ func (c *Conn) processDERPReadResult(dm derpReadResult, b []byte) (n int, ep *en
return 0, nil
}
ipp := netip.AddrPortFrom(tailcfg.DerpMagicIPAddr, uint16(regionID))
if c.handleDiscoMessage(b[:n], ipp, dm.src, discoRXPathDERP) {
srcAddr := epAddr{ap: netip.AddrPortFrom(tailcfg.DerpMagicIPAddr, uint16(regionID))}
pt, isGeneveEncap := packetLooksLike(b[:n])
if pt == packetLooksLikeDisco &&
!isGeneveEncap { // We should never receive Geneve-encapsulated disco over DERP.
c.handleDiscoMessage(b[:n], srcAddr, false, dm.src, discoRXPathDERP)
return 0, nil
}
@@ -755,9 +758,9 @@ func (c *Conn) processDERPReadResult(dm derpReadResult, b []byte) (n int, ep *en
return 0, nil
}
ep.noteRecvActivity(ipp, mono.Now())
ep.noteRecvActivity(srcAddr, mono.Now())
if stats := c.stats.Load(); stats != nil {
stats.UpdateRxPhysical(ep.nodeAddr, ipp, 1, dm.n)
stats.UpdateRxPhysical(ep.nodeAddr, srcAddr.ap, 1, dm.n)
}
c.metrics.inboundPacketsDERPTotal.Add(1)