TUN-10525: Add prechecks kill switch

Instead of having the  --precheck flag in cloudflared, we allow controlling prechecks via a DNS flag, so we can short-circuit this behavior in case anything goes wrong. Although we don't expect pre-checks to add that much traffic, we should still guarantee that we can stop pre-checks in case something goes wrong.
This commit is contained in:
Miguel da Costa Martins Marcelino
2026-05-13 18:05:11 +00:00
parent fbfd76089f
commit 31de04f858
5 changed files with 20 additions and 23 deletions
-3
View File
@@ -126,9 +126,6 @@ const (
// NoPrechecks is the command line flag to skip connectivity pre-checks at startup.
NoPrechecks = "no-prechecks"
// Prechecks is the command line flag to run connectivity pre-checks at startup.
Prechecks = "prechecks"
// LogLevel is the command line flag for the cloudflared logging level
LogLevel = "loglevel"
+7 -18
View File
@@ -375,17 +375,6 @@ func StartServer(
info.Log(log)
logClientOptions(c, log)
// Run connectivity pre-checks for cloudflared. This runs in a separate
// goroutine, as we want to keep initializing cloudflared while prechecks
// are running.
if c.Bool(cfdflags.Prechecks) && !c.Bool(cfdflags.NoPrechecks) {
resolvedRegion := c.String(cfdflags.Region)
if resolvedRegion == "" && namedTunnel != nil {
resolvedRegion = namedTunnel.Credentials.Endpoint
}
go runPrechecks(c, log, resolvedRegion)
}
// this context drives the server, when it's canceled tunnel and all other components (origins, dns, etc...) should stop
ctx, cancel := context.WithCancel(c.Context)
defer cancel()
@@ -428,6 +417,13 @@ func StartServer(
}
connectorID := tunnelConfig.ClientConfig.ConnectorID
// Run connectivity pre-checks for cloudflared. This runs in a separate
// goroutine, as we want to keep initializing cloudflared while prechecks
// are running. Prechecks are controlled via DNS flag for remote kill-switch capability.
if !tunnelConfig.ClientConfig.ConnectionFeaturesSnapshot().SkipPrechecks && !c.Bool(cfdflags.NoPrechecks) {
go runPrechecks(c, log, tunnelConfig.Region)
}
// Disable ICMP packet routing for quick tunnels
if quickTunnelURL != "" {
tunnelConfig.ICMPRouterServer = nil
@@ -946,13 +942,6 @@ func configureCloudflaredFlags(shouldHide bool) []cli.Flag {
Value: false,
Hidden: shouldHide,
}),
altsrc.NewBoolFlag(&cli.BoolFlag{
Name: cfdflags.Prechecks,
Usage: "Run connectivity pre-checks at startup.",
EnvVars: []string{"TUNNEL_PRECHECKS"},
Value: false,
Hidden: shouldHide,
}),
altsrc.NewStringFlag(&cli.StringFlag{
Name: cfdflags.Metrics,
Value: metrics.GetMetricsDefaultAddress(metrics.Runtime),
-1
View File
@@ -252,7 +252,6 @@ func prepareTunnelConfig(
QUICConnectionLevelFlowControlLimit: c.Uint64(flags.QuicConnLevelFlowControlLimit),
QUICStreamLevelFlowControlLimit: c.Uint64(flags.QuicStreamLevelFlowControlLimit),
NoPrechecks: c.Bool(flags.NoPrechecks),
Prechecks: c.Bool(flags.Prechecks),
OriginDNSService: dnsService,
OriginDialerService: originDialerService,
}
+4
View File
@@ -42,6 +42,10 @@ type FeatureSnapshot struct {
// We provide the list of features since we need it to send in the ConnectionOptions during connection
// registrations.
FeaturesList []string
// SkipPrechecks indicates when to skip connectivity pre-checks at startup.
// Controlled via DNS TXT record to allow remote kill-switch in case of issues.
SkipPrechecks bool
}
type PostQuantumMode uint8
+9 -1
View File
@@ -24,6 +24,7 @@ const (
type featuresRecord struct {
DatagramV3Percentage uint32 `json:"dv3_2"`
SkipPrechecks bool `json:"skip_prechecks"`
// DatagramV3Percentage int32 `json:"dv3"` // Removed in TUN-9291
// DatagramV3Percentage uint32 `json:"dv3_1"` // Removed in TUN-9883
@@ -89,6 +90,7 @@ func (fs *featureSelector) Snapshot() FeatureSnapshot {
PostQuantum: fs.postQuantumMode(),
DatagramVersion: fs.datagramVersion(),
FeaturesList: fs.clientFeatures(),
SkipPrechecks: fs.prechecksSkip(),
}
}
@@ -121,6 +123,12 @@ func (fs *featureSelector) datagramVersion() DatagramVersion {
return DatagramV2
}
// prechecksSkip returns whether prechecks are enabled via DNS flag.
// Defaults to false if not set in the DNS TXT record.
func (fs *featureSelector) prechecksSkip() bool {
return fs.remoteFeatures.SkipPrechecks
}
// clientFeatures will return the list of currently available features that cloudflared should provide to the edge.
func (fs *featureSelector) clientFeatures() []string {
// Evaluate any remote features along with static feature list to construct the list of features
@@ -186,7 +194,7 @@ func (dr *dnsResolver) lookupRecord(ctx context.Context) ([]byte, error) {
}
if len(records) == 0 {
return nil, fmt.Errorf("No TXT record found for %s to determine which features to opt-in", featureSelectorHostname)
return nil, fmt.Errorf("no TXT record found for %s to determine which features to opt-in", featureSelectorHostname)
}
return []byte(records[0]), nil