summaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2022-01-26 11:58:56 -0800
committerBrad Fitzpatrick <bradfitz@tailscale.com>2022-01-26 11:58:56 -0800
commitf37daace4eb88d3bec0b1bf698a94a7e2f79ec8b (patch)
treefc7400a12974304e29f9eca93d7b70debaed8e8e /cmd
parent2fd82287b6649b87a8095435893820b1b1fb1d9b (diff)
downloadtailscale-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.go46
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()