From 8eb15d3d2d4f7397663f6e8ae55674dcae9cc8a6 Mon Sep 17 00:00:00 2001 From: Andrea Gottardo Date: Tue, 18 Jun 2024 15:04:43 -0700 Subject: [PATCH] cli/netcheck: fail with output if we time out fetching a derpmap (#12528) Updates tailscale/corp#20969 Right now, when netcheck starts, it asks tailscaled for a copy of the DERPMap. If it doesn't have one, it makes a HTTPS request to controlplane.tailscale.com to fetch one. This will always fail if you're on a network with a captive portal actively blocking HTTPS traffic. The code appears to hang entirely because the http.Client doesn't have a Timeout set. It just sits there waiting until the request succeeds or fails. This adds a timeout of 10 seconds, and logs more details about the status of the HTTPS request. Signed-off-by: Andrea Gottardo --- cmd/tailscale/cli/netcheck.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/tailscale/cli/netcheck.go b/cmd/tailscale/cli/netcheck.go index f8bb906ef..2fbc9d919 100644 --- a/cmd/tailscale/cli/netcheck.go +++ b/cmd/tailscale/cli/netcheck.go @@ -78,9 +78,13 @@ func runNetcheck(ctx context.Context, args []string) error { log.Printf("No DERP map from tailscaled; using default.") } if err != nil || noRegions { - hc := &http.Client{Transport: tlsdial.NewTransport()} + hc := &http.Client{ + Transport: tlsdial.NewTransport(), + Timeout: 10 * time.Second, + } dm, err = prodDERPMap(ctx, hc) if err != nil { + log.Println("Failed to fetch a DERP map, so netcheck cannot continue. Check your Internet connection.") return err } } @@ -209,6 +213,7 @@ func portMapping(r *netcheck.Report) string { } func prodDERPMap(ctx context.Context, httpc *http.Client) (*tailcfg.DERPMap, error) { + log.Printf("attempting to fetch a DERPMap from %s", ipn.DefaultControlURL) req, err := http.NewRequestWithContext(ctx, "GET", ipn.DefaultControlURL+"/derpmap/default", nil) if err != nil { return nil, fmt.Errorf("create prodDERPMap request: %w", err)