net/tlsdial: relax self-signed cert health warning

It seems some security software or macOS itself might be MITMing TLS
(for ScreenTime?), so don't warn unless it fails x509 validation
against system roots.

Updates #3198

Change-Id: I6ea381b5bb6385b3d51da4a1468c0d803236b7bf
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-07-31 09:35:52 -07:00 committed by Brad Fitzpatrick
parent 0def4f8e38
commit 004dded0a8

View File

@ -76,17 +76,30 @@ func Config(host string, ht *health.Tracker, base *tls.Config) *tls.Config {
// own cert verification, as do the same work that it'd do // own cert verification, as do the same work that it'd do
// (with the baked-in fallback root) in the VerifyConnection hook. // (with the baked-in fallback root) in the VerifyConnection hook.
conf.InsecureSkipVerify = true conf.InsecureSkipVerify = true
conf.VerifyConnection = func(cs tls.ConnectionState) error { conf.VerifyConnection = func(cs tls.ConnectionState) (retErr error) {
// Perform some health checks on this certificate before we do // Perform some health checks on this certificate before we do
// any verification. // any verification.
var selfSignedIssuer string
if certs := cs.PeerCertificates; len(certs) > 0 && certIsSelfSigned(certs[0]) {
selfSignedIssuer = certs[0].Issuer.String()
}
if ht != nil { if ht != nil {
if certIsSelfSigned(cs.PeerCertificates[0]) { defer func() {
// Self-signed certs are never valid. if retErr != nil && selfSignedIssuer != "" {
ht.SetTLSConnectionError(cs.ServerName, fmt.Errorf("certificate is self-signed")) // Self-signed certs are never valid.
} else { //
// Ensure we clear any error state for this ServerName. // TODO(bradfitz): plumb down the selfSignedIssuer as a
ht.SetTLSConnectionError(cs.ServerName, nil) // structured health warning argument.
} ht.SetTLSConnectionError(cs.ServerName, fmt.Errorf("likely intercepted connection; certificate is self-signed by %v", selfSignedIssuer))
} else {
// Ensure we clear any error state for this ServerName.
ht.SetTLSConnectionError(cs.ServerName, nil)
if selfSignedIssuer != "" {
// Log the self-signed issuer, but don't treat it as an error.
log.Printf("tlsdial: warning: server cert for %q passed x509 validation but is self-signed by %q", host, selfSignedIssuer)
}
}
}()
} }
// First try doing x509 verification with the system's // First try doing x509 verification with the system's