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
+6
View File
@@ -7,6 +7,7 @@ import (
"bufio"
"context"
crand "crypto/rand"
"crypto/x509"
"errors"
"fmt"
"io"
@@ -236,6 +237,10 @@ type Config struct {
// If nil, a new Dialer is created.
Dialer *tsdial.Dialer
// ExtraRootCAs, if non-nil, specifies additional trusted root CAs for TLS
// connections (e.g. DERP). Passed through to magicsock.
ExtraRootCAs *x509.CertPool
// ControlKnobs is the set of control plane-provied knobs
// to use.
// If nil, defaults are used.
@@ -450,6 +455,7 @@ func NewUserspaceEngine(logf logger.Logf, conf Config) (_ Engine, reterr error)
IdleFunc: e.tundev.IdleDuration,
NetMon: e.netMon,
HealthTracker: e.health,
ExtraRootCAs: conf.ExtraRootCAs,
Metrics: conf.Metrics,
ControlKnobs: conf.ControlKnobs,
PeerByKeyFunc: e.PeerByKey,