diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2022-01-26 11:58:56 -0800 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@tailscale.com> | 2022-01-26 11:58:56 -0800 |
| commit | f37daace4eb88d3bec0b1bf698a94a7e2f79ec8b (patch) | |
| tree | fc7400a12974304e29f9eca93d7b70debaed8e8e /cmd | |
| parent | 2fd82287b6649b87a8095435893820b1b1fb1d9b (diff) | |
| download | tailscale-bradfitz/use_netstack_upstream.tar.xz tailscale-bradfitz/use_netstack_upstream.zip | |
cmd/derpprobe: check derper TLS certs toobradfitz/use_netstack_upstream
Change-Id: If8c48e012b294570ebbb1a46bacdc58fafbfbcc5
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/derpprobe/derpprobe.go | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/cmd/derpprobe/derpprobe.go b/cmd/derpprobe/derpprobe.go index 3adde9f81..bc81d6be4 100644 --- a/cmd/derpprobe/derpprobe.go +++ b/cmd/derpprobe/derpprobe.go @@ -9,7 +9,9 @@ import ( "bytes" "context" crand "crypto/rand" + "crypto/x509" "encoding/json" + "errors" "flag" "fmt" "html" @@ -38,6 +40,7 @@ var ( state = map[nodePair]pairStatus{} lastDERPMap *tailcfg.DERPMap lastDERPMapAt time.Time + certs = map[string]*x509.Certificate{} ) func main() { @@ -46,6 +49,13 @@ func main() { log.Fatal(http.ListenAndServe(*listen, http.HandlerFunc(serve))) } +func setCert(name string, cert *x509.Certificate) { + mu.Lock() + defer mu.Unlock() + certs[name] = cert + log.Printf("Cert %q: not before/after: %v, %v", name, cert.NotBefore, cert.NotAfter) +} + type overallStatus struct { good, bad []string } @@ -93,6 +103,27 @@ func getOverallStatus() (o overallStatus) { } } } + + var subjs []string + for k := range certs { + subjs = append(subjs, k) + } + sort.Strings(subjs) + reissueTime := time.Unix(1643226768, 0) // assume certs before this need reissuance by LetsEncrypt due to ALPN bug + soon := time.Now().Add(14 * 24 * time.Hour) // in 2 weeks; autocert does 30 days by default + for _, s := range subjs { + cert := certs[s] + if cert.NotBefore.Before(reissueTime) { + o.addBadf("cert %q needs reissuing; NotBefore=%v", s, cert.NotBefore.Format(time.RFC3339)) + continue + } + if cert.NotAfter.Before(soon) { + o.addBadf("cert %q expiring soon (%v); wasn't auto-refreshed", s, cert.NotAfter.Format(time.RFC3339)) + continue + } + o.addGoodf("cert %q good %v - %v", s, cert.NotBefore.Format(time.RFC3339), cert.NotAfter.Format(time.RFC3339)) + } + return } @@ -359,6 +390,21 @@ func newConn(ctx context.Context, dm *tailcfg.DERPMap, n *tailcfg.DERPNode) (*de if err != nil { return nil, err } + cs, ok := dc.TLSConnectionState() + if !ok { + dc.Close() + return nil, errors.New("no TLS state") + } + if len(cs.PeerCertificates) == 0 { + dc.Close() + return nil, errors.New("no peer certificates") + } + if cs.ServerName != n.HostName { + dc.Close() + return nil, fmt.Errorf("TLS server name %q != derp hostname %q", cs.ServerName, n.HostName) + } + setCert(cs.ServerName, cs.PeerCertificates[0]) + errc := make(chan error, 1) go func() { m, err := dc.Recv() |
