wgengine/magicsock: remove DERP routes on peer gone even if there's a conn change

The derp client connection pointer address is not related at all to
whether a peer is present on a DERP. If the peer is not present at that
DERP, the route should be removed unconditionally regardless of
connection state.

Updates tailscale/support-escalations#48

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker 2024-07-12 15:11:17 -07:00
parent 114d1caf55
commit 74cf11c4a2
No known key found for this signature in database

View File

@ -63,11 +63,10 @@ type derpRoute struct {
} }
// removeDerpPeerRoute removes a DERP route entry previously added by addDerpPeerRoute. // removeDerpPeerRoute removes a DERP route entry previously added by addDerpPeerRoute.
func (c *Conn) removeDerpPeerRoute(peer key.NodePublic, derpID int, dc *derphttp.Client) { func (c *Conn) removeDerpPeerRoute(peer key.NodePublic, derpID int) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
r2 := derpRoute{derpID, dc} if r, ok := c.derpRoute[peer]; ok && r.derpID == derpID {
if r, ok := c.derpRoute[peer]; ok && r == r2 {
delete(c.derpRoute, peer) delete(c.derpRoute, peer)
} }
} }
@ -553,7 +552,7 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
// Forget that all these peers have routes. // Forget that all these peers have routes.
for peer := range peerPresent { for peer := range peerPresent {
delete(peerPresent, peer) delete(peerPresent, peer)
c.removeDerpPeerRoute(peer, regionID, dc) c.removeDerpPeerRoute(peer, regionID)
} }
if err == derphttp.ErrClientClosed { if err == derphttp.ErrClientClosed {
return return
@ -649,7 +648,7 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netip.AddrPort, d
c.logf("[unexpected] magicsock: derp-%d peer %s gone, reason %v, removing route", c.logf("[unexpected] magicsock: derp-%d peer %s gone, reason %v, removing route",
regionID, key.NodePublic(m.Peer).ShortString(), m.Reason) regionID, key.NodePublic(m.Peer).ShortString(), m.Reason)
} }
c.removeDerpPeerRoute(key.NodePublic(m.Peer), regionID, dc) c.removeDerpPeerRoute(key.NodePublic(m.Peer), regionID)
continue continue
default: default:
// Ignore. // Ignore.