From 6f36f8842c3ee0908e1d4e50f9d0d9a387c9d980 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 6 Oct 2023 20:39:23 -0700 Subject: [PATCH] cmd/tailscale, magicsock: add debug command to flip DERP homes For testing netmap patchification server-side. Updates #1909 Change-Id: Ib1d784bd97b8d4a31e48374b4567404aae5280cc Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/debug.go | 5 +++++ ipn/ipnlocal/local.go | 6 ++++++ ipn/localapi/localapi.go | 2 ++ wgengine/magicsock/magicsock.go | 27 +++++++++++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 3dc821c10..3a429a82a 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -139,6 +139,11 @@ var debugCmd = &ffcli.Command{ Exec: localAPIAction("break-derp-conns"), ShortHelp: "break any open DERP connections from the daemon", }, + { + Name: "pick-new-derp", + Exec: localAPIAction("pick-new-derp"), + ShortHelp: "switch to some other random DERP home region for a short time", + }, { Name: "force-netmap-update", Exec: localAPIAction("force-netmap-update"), diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 6d9d21e5a..e948ba953 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -2156,6 +2156,12 @@ func (b *LocalBackend) DebugForceNetmapUpdate() { b.setNetMapLocked(nm) } +// DebugPickNewDERP forwards to magicsock.Conn.DebugPickNewDERP. +// See its docs. +func (b *LocalBackend) DebugPickNewDERP() error { + return b.sys.MagicSock.Get().DebugPickNewDERP() +} + // send delivers n to the connected frontend and any API watchers from // LocalBackend.WatchNotifications (via the LocalAPI). // diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index e68e6adaf..a25c8e717 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -566,6 +566,8 @@ func (h *Handler) serveDebug(w http.ResponseWriter, r *http.Request) { if err == nil { return } + case "pick-new-derp": + err = h.b.DebugPickNewDERP() case "": err = fmt.Errorf("missing parameter 'action'") default: diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 016061c21..4e03f014a 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -2715,6 +2715,33 @@ func (c *Conn) getPinger() *ping.Pinger { }) } +// DebugPickNewDERP picks a new DERP random home temporarily (even if just for +// seconds) and reports it to control. It exists to test DERP home changes and +// netmap deltas, etc. It serves no useful user purpose. +func (c *Conn) DebugPickNewDERP() error { + c.mu.Lock() + defer c.mu.Unlock() + dm := c.derpMap + if dm == nil { + return errors.New("no derpmap") + } + if c.netInfoLast == nil { + return errors.New("no netinfo") + } + for _, r := range dm.Regions { + if r.RegionID == c.myDerp { + continue + } + c.logf("magicsock: [debug] switching derp home to random %v (%v)", r.RegionID, r.RegionCode) + go c.setNearestDERP(r.RegionID) + ni2 := c.netInfoLast.Clone() + ni2.PreferredDERP = r.RegionID + c.callNetInfoCallbackLocked(ni2) + return nil + } + return errors.New("too few regions") +} + // portableTrySetSocketBuffer sets SO_SNDBUF and SO_RECVBUF on pconn to socketBufferSize, // logging an error if it occurs. func portableTrySetSocketBuffer(pconn nettype.PacketConn, logf logger.Logf) {