net/tlsdial: call out firewalls blocking Tailscale in health warnings (#13840)
Updates tailscale/tailscale#13839 Adds a new blockblame package which can detect common MITM SSL certificates used by network appliances. We use this in `tlsdial` to display a dedicated health warning when we cannot connect to control, and a network appliance MITM attack is detected. Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
This commit is contained in:
+30
-2
@@ -27,6 +27,7 @@ import (
|
||||
"tailscale.com/envknob"
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/hostinfo"
|
||||
"tailscale.com/net/tlsdial/blockblame"
|
||||
)
|
||||
|
||||
var counterFallbackOK int32 // atomic
|
||||
@@ -44,6 +45,16 @@ var debug = envknob.RegisterBool("TS_DEBUG_TLS_DIAL")
|
||||
// Headscale, etc.
|
||||
var tlsdialWarningPrinted sync.Map // map[string]bool
|
||||
|
||||
var mitmBlockWarnable = health.Register(&health.Warnable{
|
||||
Code: "blockblame-mitm-detected",
|
||||
Title: "Network may be blocking Tailscale",
|
||||
Text: func(args health.Args) string {
|
||||
return fmt.Sprintf("Network equipment from %q may be blocking Tailscale traffic on this network. Connect to another network, or contact your network administrator for assistance.", args["manufacturer"])
|
||||
},
|
||||
Severity: health.SeverityMedium,
|
||||
ImpactsConnectivity: true,
|
||||
})
|
||||
|
||||
// Config returns a tls.Config for connecting to a server.
|
||||
// If base is non-nil, it's cloned as the base config before
|
||||
// being configured and returned.
|
||||
@@ -86,12 +97,29 @@ func Config(host string, ht *health.Tracker, base *tls.Config) *tls.Config {
|
||||
|
||||
// Perform some health checks on this certificate before we do
|
||||
// any verification.
|
||||
var cert *x509.Certificate
|
||||
var selfSignedIssuer string
|
||||
if certs := cs.PeerCertificates; len(certs) > 0 && certIsSelfSigned(certs[0]) {
|
||||
selfSignedIssuer = certs[0].Issuer.String()
|
||||
if certs := cs.PeerCertificates; len(certs) > 0 {
|
||||
cert = certs[0]
|
||||
if certIsSelfSigned(cert) {
|
||||
selfSignedIssuer = cert.Issuer.String()
|
||||
}
|
||||
}
|
||||
if ht != nil {
|
||||
defer func() {
|
||||
if retErr != nil && cert != nil {
|
||||
// Is it a MITM SSL certificate from a well-known network appliance manufacturer?
|
||||
// Show a dedicated warning.
|
||||
m, ok := blockblame.VerifyCertificate(cert)
|
||||
if ok {
|
||||
log.Printf("tlsdial: server cert for %q looks like %q equipment (could be blocking Tailscale)", host, m.Name)
|
||||
ht.SetUnhealthy(mitmBlockWarnable, health.Args{"manufacturer": m.Name})
|
||||
} else {
|
||||
ht.SetHealthy(mitmBlockWarnable)
|
||||
}
|
||||
} else {
|
||||
ht.SetHealthy(mitmBlockWarnable)
|
||||
}
|
||||
if retErr != nil && selfSignedIssuer != "" {
|
||||
// Self-signed certs are never valid.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user