mirror of
https://github.com/cloudflare/cloudflared.git
synced 2026-06-23 04:10:20 +00:00
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:
@@ -126,9 +126,6 @@ const (
|
|||||||
// NoPrechecks is the command line flag to skip connectivity pre-checks at startup.
|
// NoPrechecks is the command line flag to skip connectivity pre-checks at startup.
|
||||||
NoPrechecks = "no-prechecks"
|
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 is the command line flag for the cloudflared logging level
|
||||||
LogLevel = "loglevel"
|
LogLevel = "loglevel"
|
||||||
|
|
||||||
|
|||||||
@@ -375,17 +375,6 @@ func StartServer(
|
|||||||
info.Log(log)
|
info.Log(log)
|
||||||
logClientOptions(c, 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
|
// 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)
|
ctx, cancel := context.WithCancel(c.Context)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -428,6 +417,13 @@ func StartServer(
|
|||||||
}
|
}
|
||||||
connectorID := tunnelConfig.ClientConfig.ConnectorID
|
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
|
// Disable ICMP packet routing for quick tunnels
|
||||||
if quickTunnelURL != "" {
|
if quickTunnelURL != "" {
|
||||||
tunnelConfig.ICMPRouterServer = nil
|
tunnelConfig.ICMPRouterServer = nil
|
||||||
@@ -946,13 +942,6 @@ func configureCloudflaredFlags(shouldHide bool) []cli.Flag {
|
|||||||
Value: false,
|
Value: false,
|
||||||
Hidden: shouldHide,
|
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{
|
altsrc.NewStringFlag(&cli.StringFlag{
|
||||||
Name: cfdflags.Metrics,
|
Name: cfdflags.Metrics,
|
||||||
Value: metrics.GetMetricsDefaultAddress(metrics.Runtime),
|
Value: metrics.GetMetricsDefaultAddress(metrics.Runtime),
|
||||||
|
|||||||
@@ -252,7 +252,6 @@ func prepareTunnelConfig(
|
|||||||
QUICConnectionLevelFlowControlLimit: c.Uint64(flags.QuicConnLevelFlowControlLimit),
|
QUICConnectionLevelFlowControlLimit: c.Uint64(flags.QuicConnLevelFlowControlLimit),
|
||||||
QUICStreamLevelFlowControlLimit: c.Uint64(flags.QuicStreamLevelFlowControlLimit),
|
QUICStreamLevelFlowControlLimit: c.Uint64(flags.QuicStreamLevelFlowControlLimit),
|
||||||
NoPrechecks: c.Bool(flags.NoPrechecks),
|
NoPrechecks: c.Bool(flags.NoPrechecks),
|
||||||
Prechecks: c.Bool(flags.Prechecks),
|
|
||||||
OriginDNSService: dnsService,
|
OriginDNSService: dnsService,
|
||||||
OriginDialerService: originDialerService,
|
OriginDialerService: originDialerService,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ type FeatureSnapshot struct {
|
|||||||
// We provide the list of features since we need it to send in the ConnectionOptions during connection
|
// We provide the list of features since we need it to send in the ConnectionOptions during connection
|
||||||
// registrations.
|
// registrations.
|
||||||
FeaturesList []string
|
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
|
type PostQuantumMode uint8
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const (
|
|||||||
|
|
||||||
type featuresRecord struct {
|
type featuresRecord struct {
|
||||||
DatagramV3Percentage uint32 `json:"dv3_2"`
|
DatagramV3Percentage uint32 `json:"dv3_2"`
|
||||||
|
SkipPrechecks bool `json:"skip_prechecks"`
|
||||||
|
|
||||||
// DatagramV3Percentage int32 `json:"dv3"` // Removed in TUN-9291
|
// DatagramV3Percentage int32 `json:"dv3"` // Removed in TUN-9291
|
||||||
// DatagramV3Percentage uint32 `json:"dv3_1"` // Removed in TUN-9883
|
// DatagramV3Percentage uint32 `json:"dv3_1"` // Removed in TUN-9883
|
||||||
@@ -89,6 +90,7 @@ func (fs *featureSelector) Snapshot() FeatureSnapshot {
|
|||||||
PostQuantum: fs.postQuantumMode(),
|
PostQuantum: fs.postQuantumMode(),
|
||||||
DatagramVersion: fs.datagramVersion(),
|
DatagramVersion: fs.datagramVersion(),
|
||||||
FeaturesList: fs.clientFeatures(),
|
FeaturesList: fs.clientFeatures(),
|
||||||
|
SkipPrechecks: fs.prechecksSkip(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +123,12 @@ func (fs *featureSelector) datagramVersion() DatagramVersion {
|
|||||||
return DatagramV2
|
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.
|
// clientFeatures will return the list of currently available features that cloudflared should provide to the edge.
|
||||||
func (fs *featureSelector) clientFeatures() []string {
|
func (fs *featureSelector) clientFeatures() []string {
|
||||||
// Evaluate any remote features along with static feature list to construct the list of features
|
// 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 {
|
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
|
return []byte(records[0]), nil
|
||||||
|
|||||||
Reference in New Issue
Block a user