From 333e9e75d40dd1787e69ac281f393f8cd151e451 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 15 Jun 2021 12:28:34 -0700 Subject: [PATCH] tailcfg, control/controlclient: clarify more, enforce PingRequest.URL is unique Updates #2079 Signed-off-by: Brad Fitzpatrick --- control/controlclient/direct.go | 20 +++++++++++++++++++- tailcfg/tailcfg.go | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 05d4086ea..d1cfdf62b 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -80,6 +80,7 @@ type Direct struct { endpoints []tailcfg.Endpoint everEndpoints bool // whether we've ever had non-empty endpoints localPort uint16 // or zero to mean auto + lastPingURL string // last PingRequest.URL received, for dup suppresion } type Options struct { @@ -775,7 +776,7 @@ func (c *Direct) sendMapRequest(ctx context.Context, maxPolls int, cb func(*netm health.GotStreamedMapResponse() } - if pr := resp.PingRequest; pr != nil { + if pr := resp.PingRequest; pr != nil && c.isUniquePingRequest(pr) { go answerPing(c.logf, c.httpc, pr) } @@ -1170,6 +1171,23 @@ func ipForwardingBroken(routes []netaddr.IPPrefix, state *interfaces.State) bool return false } +// isUniquePingRequest reports whether pr contains a new PingRequest.URL +// not already handled, noting its value when returning true. +func (c *Direct) isUniquePingRequest(pr *tailcfg.PingRequest) bool { + if pr == nil || pr.URL == "" { + // Bogus. + return false + } + + c.mu.Lock() + defer c.mu.Unlock() + if pr.URL == c.lastPingURL { + return false + } + c.lastPingURL = pr.URL + return true +} + func answerPing(logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest) { if pr.URL == "" { logf("invalid PingRequest with no URL") diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index a4ec682dd..d57a72e8a 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -880,6 +880,9 @@ type DNSConfig struct { type PingRequest struct { // URL is the URL to send a HEAD request to. // It will be a unique URL each time. No auth headers are necessary. + // + // If the client sees multiple PingRequests with the same URL, + // subsequent ones should be ignored. URL string // Log is whether to log about this ping in the success case.