tsd, all: add Sys.ExtraRootCAs, plumb through TLS dial paths

Add ExtraRootCAs *x509.CertPool to tsd.System and plumb it through
the control client, noise transport, DERP, and wgengine layers so
that platforms like Android can inject user-installed CA certificates
into Go's TLS verification.

tlsdial.Config now honors base.RootCAs as additional trusted roots,
tried after system roots and before the baked-in LetsEncrypt fallback.
SetConfigExpectedCert gets the same treatment for domain-fronted DERP.

The Android client will set sys.ExtraRootCAs with a pool built from
x509.SystemCertPool + user-installed certs obtained via the Android
KeyStore API, replacing the current SSL_CERT_DIR environment variable
approach.

Updates #8085

Change-Id: Iecce0fd140cd5aa0331b124e55a7045e24d8e0c2
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-04-07 19:09:19 +00:00
committed by Brad Fitzpatrick
parent c4cb5eb809
commit a182b864ac
13 changed files with 108 additions and 4 deletions
+7
View File
@@ -18,6 +18,7 @@
package tsd
import (
"crypto/x509"
"fmt"
"reflect"
@@ -63,6 +64,12 @@ type System struct {
PolicyClient SubSystem[policyclient.Client]
HealthTracker SubSystem[*health.Tracker]
// ExtraRootCAs, if non-nil, specifies additional trusted root CAs
// beyond the system roots. On Android, this includes user-installed
// CA certificates that Go's crypto/x509 does not see.
// It is plumbed through to tlsdial.Config via tls.Config.RootCAs.
ExtraRootCAs *x509.CertPool
// InitialConfig is initial server config, if any.
// It is nil if the node is not in declarative mode.
// This value is never updated after startup.