From d3f302d8e2c04ae937398f9433333fa45d37ad95 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 1 Oct 2024 09:12:39 -0700 Subject: [PATCH] cmd/tailscale/cli: make 'tailscale debug ts2021' try twice In prep for a future port 80 MITM fix, make the 'debug ts2021' command retry once after a failure to give it a chance to pick a new strategy. Updates #13597 Change-Id: Icb7bad60cbf0dbec78097df4a00e9795757bc8e4 Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/debug.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index e98a9e078..fdde9ef09 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -844,7 +844,8 @@ func runTS2021(ctx context.Context, args []string) error { if ts2021Args.verbose { logf = log.Printf } - conn, err := (&controlhttp.Dialer{ + + noiseDialer := &controlhttp.Dialer{ Hostname: ts2021Args.host, HTTPPort: "80", HTTPSPort: "443", @@ -853,7 +854,21 @@ func runTS2021(ctx context.Context, args []string) error { ProtocolVersion: uint16(ts2021Args.version), Dialer: dialFunc, Logf: logf, - }).Dial(ctx) + } + const tries = 2 + for i := range tries { + err := tryConnect(ctx, keys.PublicKey, noiseDialer) + if err != nil { + log.Printf("error on attempt %d/%d: %v", i+1, tries, err) + continue + } + break + } + return nil +} + +func tryConnect(ctx context.Context, controlPublic key.MachinePublic, noiseDialer *controlhttp.Dialer) error { + conn, err := noiseDialer.Dial(ctx) log.Printf("controlhttp.Dial = %p, %v", conn, err) if err != nil { return err @@ -861,8 +876,8 @@ func runTS2021(ctx context.Context, args []string) error { log.Printf("did noise handshake") gotPeer := conn.Peer() - if gotPeer != keys.PublicKey { - log.Printf("peer = %v, want %v", gotPeer, keys.PublicKey) + if gotPeer != controlPublic { + log.Printf("peer = %v, want %v", gotPeer, controlPublic) return errors.New("key mismatch") } @@ -894,7 +909,7 @@ func runTS2021(ctx context.Context, args []string) error { // Make a /whoami request to the server to verify that we can actually // communicate over the newly-established connection. whoamiURL := "http://" + ts2021Args.host + "/machine/whoami" - req, err = http.NewRequestWithContext(ctx, "GET", whoamiURL, nil) + req, err := http.NewRequestWithContext(ctx, "GET", whoamiURL, nil) if err != nil { return err }