mirror of
https://github.com/tailscale/tailscale.git
synced 2025-09-21 05:31:36 +02:00
control, ipn, tailcfg: enable seamless key renewal by default
Previously, seamless key renewal was an opt-in feature. Customers had to set a `seamless-key-renewal` node attribute in their policy file. This patch enables seamless key renewal by default for all clients. It includes a `disable-seamless-key-renewal` node attribute we can set in Control, so we can manage the rollout and disable the feature for clients with known bugs. This new attribute makes the feature opt-out. Updates tailscale/corp#31479 Signed-off-by: Alex Chan <alexc@tailscale.com>
This commit is contained in:
parent
1c9aaa444d
commit
cd153aa644
@ -62,8 +62,9 @@ type Knobs struct {
|
|||||||
// netfiltering, unless overridden by the user.
|
// netfiltering, unless overridden by the user.
|
||||||
LinuxForceNfTables atomic.Bool
|
LinuxForceNfTables atomic.Bool
|
||||||
|
|
||||||
// SeamlessKeyRenewal is whether to enable the alpha functionality of
|
// SeamlessKeyRenewal is whether to renew node keys without breaking connections.
|
||||||
// renewing node keys without breaking connections.
|
// This is enabled by default in 1.90 and later, but we but we can remotely disable
|
||||||
|
// it from the control plane if there's a problem.
|
||||||
// http://go/seamless-key-renewal
|
// http://go/seamless-key-renewal
|
||||||
SeamlessKeyRenewal atomic.Bool
|
SeamlessKeyRenewal atomic.Bool
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
|
|||||||
forceIPTables = has(tailcfg.NodeAttrLinuxMustUseIPTables)
|
forceIPTables = has(tailcfg.NodeAttrLinuxMustUseIPTables)
|
||||||
forceNfTables = has(tailcfg.NodeAttrLinuxMustUseNfTables)
|
forceNfTables = has(tailcfg.NodeAttrLinuxMustUseNfTables)
|
||||||
seamlessKeyRenewal = has(tailcfg.NodeAttrSeamlessKeyRenewal)
|
seamlessKeyRenewal = has(tailcfg.NodeAttrSeamlessKeyRenewal)
|
||||||
|
disableSeamlessKeyRenewal = has(tailcfg.NodeAttrDisableSeamlessKeyRenewal)
|
||||||
probeUDPLifetime = has(tailcfg.NodeAttrProbeUDPLifetime)
|
probeUDPLifetime = has(tailcfg.NodeAttrProbeUDPLifetime)
|
||||||
appCStoreRoutes = has(tailcfg.NodeAttrStoreAppCRoutes)
|
appCStoreRoutes = has(tailcfg.NodeAttrStoreAppCRoutes)
|
||||||
userDialUseRoutes = has(tailcfg.NodeAttrUserDialUseRoutes)
|
userDialUseRoutes = has(tailcfg.NodeAttrUserDialUseRoutes)
|
||||||
@ -154,7 +156,6 @@ func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
|
|||||||
k.SilentDisco.Store(silentDisco)
|
k.SilentDisco.Store(silentDisco)
|
||||||
k.LinuxForceIPTables.Store(forceIPTables)
|
k.LinuxForceIPTables.Store(forceIPTables)
|
||||||
k.LinuxForceNfTables.Store(forceNfTables)
|
k.LinuxForceNfTables.Store(forceNfTables)
|
||||||
k.SeamlessKeyRenewal.Store(seamlessKeyRenewal)
|
|
||||||
k.ProbeUDPLifetime.Store(probeUDPLifetime)
|
k.ProbeUDPLifetime.Store(probeUDPLifetime)
|
||||||
k.AppCStoreRoutes.Store(appCStoreRoutes)
|
k.AppCStoreRoutes.Store(appCStoreRoutes)
|
||||||
k.UserDialUseRoutes.Store(userDialUseRoutes)
|
k.UserDialUseRoutes.Store(userDialUseRoutes)
|
||||||
@ -162,6 +163,21 @@ func (k *Knobs) UpdateFromNodeAttributes(capMap tailcfg.NodeCapMap) {
|
|||||||
k.DisableLocalDNSOverrideViaNRPT.Store(disableLocalDNSOverrideViaNRPT)
|
k.DisableLocalDNSOverrideViaNRPT.Store(disableLocalDNSOverrideViaNRPT)
|
||||||
k.DisableCaptivePortalDetection.Store(disableCaptivePortalDetection)
|
k.DisableCaptivePortalDetection.Store(disableCaptivePortalDetection)
|
||||||
k.DisableSkipStatusQueue.Store(disableSkipStatusQueue)
|
k.DisableSkipStatusQueue.Store(disableSkipStatusQueue)
|
||||||
|
|
||||||
|
// If both attributes are present, then "enable" should win. This reflects
|
||||||
|
// the history of seamless key renewal.
|
||||||
|
//
|
||||||
|
// Before 1.90, seamless was a private alpha, opt-in feature. Devices would
|
||||||
|
// only seamless do if customers opted in using the seamless renewal attr.
|
||||||
|
//
|
||||||
|
// In 1.90 and later, seamless is the default behaviour, and devices will use
|
||||||
|
// seamless unless explicitly told not to by control (e.g. if we discover
|
||||||
|
// a bug and want clients to use the prior behaviour).
|
||||||
|
//
|
||||||
|
// If a customer has opted in to the pre-1.90 seamless implementation, we
|
||||||
|
// don't want to switch it off for them -- we only want to switch it off for
|
||||||
|
// devices that haven't opted in.
|
||||||
|
k.SeamlessKeyRenewal.Store(seamlessKeyRenewal || !disableSeamlessKeyRenewal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsDebugJSON returns k as something that can be marshalled with json.Marshal
|
// AsDebugJSON returns k as something that can be marshalled with json.Marshal
|
||||||
|
@ -7420,10 +7420,10 @@ func (b *LocalBackend) readRouteInfoLocked() (*appc.RouteInfo, error) {
|
|||||||
return ri, nil
|
return ri, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// seamlessRenewalEnabled reports whether seamless key renewals are enabled
|
// seamlessRenewalEnabled reports whether seamless key renewals are enabled.
|
||||||
// (i.e. we saw our self node with the SeamlessKeyRenewal attr in a netmap).
|
//
|
||||||
// This enables beta functionality of renewing node keys without breaking
|
// As of 2025-09-11, this is the default behaviour unless nodes receive
|
||||||
// connections.
|
// [tailcfg.NodeAttrDisableSeamlessKeyRenewal] in their netmap.
|
||||||
func (b *LocalBackend) seamlessRenewalEnabled() bool {
|
func (b *LocalBackend) seamlessRenewalEnabled() bool {
|
||||||
return b.ControlKnobs().SeamlessKeyRenewal.Load()
|
return b.ControlKnobs().SeamlessKeyRenewal.Load()
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,8 @@ type CapabilityVersion int
|
|||||||
// - 123: 2025-07-28: fix deadlock regression from cryptokey routing change (issue #16651)
|
// - 123: 2025-07-28: fix deadlock regression from cryptokey routing change (issue #16651)
|
||||||
// - 124: 2025-08-08: removed NodeAttrDisableMagicSockCryptoRouting support, crypto routing is now mandatory
|
// - 124: 2025-08-08: removed NodeAttrDisableMagicSockCryptoRouting support, crypto routing is now mandatory
|
||||||
// - 125: 2025-08-11: dnstype.Resolver adds UseWithExitNode field.
|
// - 125: 2025-08-11: dnstype.Resolver adds UseWithExitNode field.
|
||||||
const CurrentCapabilityVersion CapabilityVersion = 125
|
// - 126: 2025-09-17: Client uses seamless key renewal unless disabled by control (tailscale/corp#31479)
|
||||||
|
const CurrentCapabilityVersion CapabilityVersion = 126
|
||||||
|
|
||||||
// ID is an integer ID for a user, node, or login allocated by the
|
// ID is an integer ID for a user, node, or login allocated by the
|
||||||
// control plane.
|
// control plane.
|
||||||
@ -2530,8 +2531,19 @@ const (
|
|||||||
// This cannot be set simultaneously with NodeAttrLinuxMustUseIPTables.
|
// This cannot be set simultaneously with NodeAttrLinuxMustUseIPTables.
|
||||||
NodeAttrLinuxMustUseNfTables NodeCapability = "linux-netfilter?v=nftables"
|
NodeAttrLinuxMustUseNfTables NodeCapability = "linux-netfilter?v=nftables"
|
||||||
|
|
||||||
// NodeAttrSeamlessKeyRenewal makes clients enable beta functionality
|
// NodeAttrDisableSeamlessKeyRenewal disables seamless key renewal, which is
|
||||||
// of renewing node keys without breaking connections.
|
// enabled by default in clients as of 2025-09-17 (1.90 and later).
|
||||||
|
//
|
||||||
|
// We will use this attribute to manage the rollout, and disable seamless in
|
||||||
|
// clients with known bugs.
|
||||||
|
// http://go/seamless-key-renewal
|
||||||
|
NodeAttrDisableSeamlessKeyRenewal NodeCapability = "disable-seamless-key-renewal"
|
||||||
|
|
||||||
|
// NodeAttrSeamlessKeyRenewal was used to opt-in to seamless key renewal
|
||||||
|
// during its private alpha.
|
||||||
|
//
|
||||||
|
// Deprecated: NodeAttrSeamlessKeyRenewal is deprecated as of CapabilityVersion 126,
|
||||||
|
// because seamless key renewal is now enabled by default.
|
||||||
NodeAttrSeamlessKeyRenewal NodeCapability = "seamless-key-renewal"
|
NodeAttrSeamlessKeyRenewal NodeCapability = "seamless-key-renewal"
|
||||||
|
|
||||||
// NodeAttrProbeUDPLifetime makes the client probe UDP path lifetime at the
|
// NodeAttrProbeUDPLifetime makes the client probe UDP path lifetime at the
|
||||||
|
Loading…
x
Reference in New Issue
Block a user