wgengine/magicsock: use wireguard-go/conn.PeerAwareEndpoint

If we get an non-disco presumably-wireguard-encrypted UDP packet from
an IP:port we don't recognize, rather than drop the packet, give it to
WireGuard anyway and let WireGuard try to figure out who it's from and
tell us.

This uses the new hook added in https://github.com/tailscale/wireguard-go/pull/27

Updates tailscale/corp#20732

Change-Id: I5c61a40143810592f9efac6c12808a87f924ecf2
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-07-08 20:31:16 -07:00
committed by Brad Fitzpatrick
parent 49bf63cdd0
commit 808b4139ee
3 changed files with 51 additions and 3 deletions

View File

@@ -1276,7 +1276,8 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu
//
// ok is whether this read should be reported up to wireguard-go (our
// caller).
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (ep *endpoint, ok bool) {
func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache) (_ conn.Endpoint, ok bool) {
var ep *endpoint
if stun.Is(b) {
c.netChecker.ReceiveSTUNPacket(b, ipp)
return nil, false
@@ -1297,7 +1298,10 @@ func (c *Conn) receiveIP(b []byte, ipp netip.AddrPort, cache *ippEndpointCache)
de, ok := c.peerMap.endpointForIPPort(ipp)
c.mu.Unlock()
if !ok {
return nil, false
if c.controlKnobs != nil && c.controlKnobs.DisableCryptorouting.Load() {
return nil, false
}
return &lazyEndpoint{c: c, src: ipp}, true
}
cache.ipp = ipp
cache.de = de
@@ -3114,3 +3118,35 @@ func (c *Conn) GetLastNetcheckReport(ctx context.Context) *netcheck.Report {
func (c *Conn) SetLastNetcheckReportForTest(ctx context.Context, report *netcheck.Report) {
c.lastNetCheckReport.Store(report)
}
// lazyEndpoint is a wireguard conn.Endpoint for when magicsock received a
// non-disco (presumably WireGuard) packet from a UDP address from which we
// can't map to a Tailscale peer. But Wireguard most likely can, once it
// decrypts it. So we implement the conn.PeerAwareEndpoint interface
// from https://github.com/tailscale/wireguard-go/pull/27 to allow WireGuard
// to tell us who it is later and get the correct conn.Endpoint.
type lazyEndpoint struct {
c *Conn
src netip.AddrPort
}
var _ conn.PeerAwareEndpoint = (*lazyEndpoint)(nil)
var _ conn.Endpoint = (*lazyEndpoint)(nil)
func (le *lazyEndpoint) ClearSrc() {}
func (le *lazyEndpoint) SrcIP() netip.Addr { return le.src.Addr() }
func (le *lazyEndpoint) DstIP() netip.Addr { return netip.Addr{} }
func (le *lazyEndpoint) SrcToString() string { return le.src.String() }
func (le *lazyEndpoint) DstToString() string { return "dst" }
func (le *lazyEndpoint) DstToBytes() []byte { return nil }
func (le *lazyEndpoint) GetPeerEndpoint(peerPublicKey [32]byte) conn.Endpoint {
pubKey := key.NodePublicFromRaw32(mem.B(peerPublicKey[:]))
le.c.mu.Lock()
defer le.c.mu.Unlock()
ep, ok := le.c.peerMap.endpointForNodeKey(pubKey)
if !ok {
return nil
}
le.c.logf("magicsock: lazyEndpoint.GetPeerEndpoint(%v) found: %v", pubKey.ShortString(), ep.nodeAddr)
return ep
}