Compare commits

...

10 Commits

Author SHA1 Message Date
Nick Khyl c50fe71822
VERSION.txt: this is v1.90.3
Signed-off-by: Nick Khyl <nickk@tailscale.com>
1 month ago
M. J. Fromberger 597acd8663
logtail: avoid racing eventbus subscriptions with Shutdown (#17639)
When the eventbus is enabled, set up the subscription for change deltas at the
beginning when the client is created, rather than waiting for the first
awaitInternetUp check.

Otherwise, it is possible for a check to race with the client close in
Shutdown, which triggers a panic.

Updates #17638

Change-Id: I461c07939eca46699072b14b1814ecf28eec750c
Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
(cherry picked from commit 4346615d77)
1 month ago
Claus Lensbøl e6a3669277
net/tsdial: do not panic if setting the same eventbus twice (#17640)
Updates #17638

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
(cherry picked from commit fd0e541e5d)
1 month ago
Nick Khyl 8bcd44ecf0
VERSION.txt: this is v1.90.2
Signed-off-by: Nick Khyl <nickk@tailscale.com>
1 month ago
Claus Lensbøl b0f0bce928 health: compare warnable codes to avoid errors on release branch (#17637)
This compares the warnings we actually care about and skips the unstable
warnings and the changes with no warnings.

Fixes #17635

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
(cherry picked from commit 7418583e47)
1 month ago
Brad Fitzpatrick c81ef9055b util/linuxfw: fix 32-bit arm regression with iptables
This fixes a regression from dd615c8fdd that moved the
newIPTablesRunner constructor from a any-Linux-GOARCH file to one that
was only amd64 and arm64, thus breaking iptables on other platforms
(notably 32-bit "arm", as seen on older Pis running Buster with
iptables)

Tested by hand on a Raspberry Pi 2 w/ Buster + iptables for now, for
lack of automated 32-bit arm tests at the moment. But filed #17629.

Fixes #17623
Updates #17629

Change-Id: Iac1a3d78f35d8428821b46f0fed3f3717891c1bd
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
(cherry picked from commit 8576a802ca)
1 month ago
Patrick O'Doherty 9fe44b3718 feature/tpm: use withSRK to probe TPM availability (#17627)
On some platforms e.g. ChromeOS the owner hierarchy might not always be
available to us. To avoid stale sealing exceptions later we probe to
confirm it's working rather than rely solely on family indicator status.

Updates #17622

Signed-off-by: Patrick O'Doherty <patrick@tailscale.com>
(cherry picked from commit 672b1f0e76)
1 month ago
Patrick O'Doherty a8ae316858 feature/tpm: check TPM family data for compatibility (#17624)
Check that the TPM we have opened is advertised as a 2.0 family device
before using it for state sealing / hardware attestation.

Updates #17622

Signed-off-by: Patrick O'Doherty <patrick@tailscale.com>
(cherry picked from commit 36ad24b20f)
1 month ago
Nick Khyl 75b0c6f164 VERSION.txt: this is v1.90.1
Signed-off-by: Nick Khyl <nickk@tailscale.com>
1 month ago
Nick Khyl 3c78146ece VERSION.txt: this is v1.90.0
Signed-off-by: Nick Khyl <nickk@tailscale.com>
2 months ago

@ -1 +1 @@
1.89.0 1.90.3

@ -116,7 +116,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
tailscale.com/syncs from tailscale.com/cmd/derper+ tailscale.com/syncs from tailscale.com/cmd/derper+
tailscale.com/tailcfg from tailscale.com/client/local+ tailscale.com/tailcfg from tailscale.com/client/local+
tailscale.com/tka from tailscale.com/client/local+ tailscale.com/tka from tailscale.com/client/local+
LW tailscale.com/tsconst from tailscale.com/net/netmon+ tailscale.com/tsconst from tailscale.com/net/netmon+
tailscale.com/tstime from tailscale.com/derp+ tailscale.com/tstime from tailscale.com/derp+
tailscale.com/tstime/mono from tailscale.com/tstime/rate tailscale.com/tstime/mono from tailscale.com/tstime/rate
tailscale.com/tstime/rate from tailscale.com/derp/derpserver tailscale.com/tstime/rate from tailscale.com/derp/derpserver

@ -116,7 +116,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/tailcfg from tailscale.com/client/tailscale/apitype+ tailscale.com/tailcfg from tailscale.com/client/tailscale/apitype+
tailscale.com/tempfork/heap from tailscale.com/wgengine/magicsock tailscale.com/tempfork/heap from tailscale.com/wgengine/magicsock
tailscale.com/tka from tailscale.com/control/controlclient+ tailscale.com/tka from tailscale.com/control/controlclient+
tailscale.com/tsconst from tailscale.com/net/netns tailscale.com/tsconst from tailscale.com/net/netns+
tailscale.com/tsd from tailscale.com/cmd/tailscaled+ tailscale.com/tsd from tailscale.com/cmd/tailscaled+
tailscale.com/tstime from tailscale.com/control/controlclient+ tailscale.com/tstime from tailscale.com/control/controlclient+
tailscale.com/tstime/mono from tailscale.com/net/tstun+ tailscale.com/tstime/mono from tailscale.com/net/tstun+

@ -55,11 +55,25 @@ func init() {
} }
func tpmSupported() bool { func tpmSupported() bool {
hi := infoOnce()
if hi == nil {
return false
}
if hi.FamilyIndicator != "2.0" {
return false
}
tpm, err := open() tpm, err := open()
if err != nil { if err != nil {
return false return false
} }
tpm.Close() defer tpm.Close()
if err := withSRK(logger.Discard, tpm, func(srk tpm2.AuthHandle) error {
return nil
}); err != nil {
return false
}
return true return true
} }
@ -104,6 +118,7 @@ func info() *tailcfg.TPMInfo {
{tpm2.TPMPTVendorTPMType, func(info *tailcfg.TPMInfo, value uint32) { info.Model = int(value) }}, {tpm2.TPMPTVendorTPMType, func(info *tailcfg.TPMInfo, value uint32) { info.Model = int(value) }},
{tpm2.TPMPTFirmwareVersion1, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) << 32 }}, {tpm2.TPMPTFirmwareVersion1, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) << 32 }},
{tpm2.TPMPTFirmwareVersion2, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) }}, {tpm2.TPMPTFirmwareVersion2, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) }},
{tpm2.TPMPTFamilyIndicator, toStr(&info.FamilyIndicator)},
} { } {
resp, err := tpm2.GetCapability{ resp, err := tpm2.GetCapability{
Capability: tpm2.TPMCapTPMProperties, Capability: tpm2.TPMCapTPMProperties,

@ -133,6 +133,31 @@ func TestStore(t *testing.T) {
}) })
} }
func BenchmarkInfo(b *testing.B) {
b.StopTimer()
skipWithoutTPM(b)
b.StartTimer()
for i := 0; i < b.N; i++ {
hi := info()
if hi == nil {
b.Fatalf("tpm info error")
}
}
b.StopTimer()
}
func BenchmarkTPMSupported(b *testing.B) {
b.StopTimer()
skipWithoutTPM(b)
b.StartTimer()
for i := 0; i < b.N; i++ {
if !tpmSupported() {
b.Fatalf("tpmSupported returned false")
}
}
b.StopTimer()
}
func BenchmarkStore(b *testing.B) { func BenchmarkStore(b *testing.B) {
skipWithoutTPM(b) skipWithoutTPM(b)
b.StopTimer() b.StopTimer()

@ -19,6 +19,7 @@ import (
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"tailscale.com/metrics" "tailscale.com/metrics"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tsconst"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/opt" "tailscale.com/types/opt"
@ -739,21 +740,27 @@ func TestControlHealthNotifies(t *testing.T) {
ht.SetIPNState("NeedsLogin", true) ht.SetIPNState("NeedsLogin", true)
ht.GotStreamedMapResponse() ht.GotStreamedMapResponse()
// Expect events at starup, before doing anything else // Expect events at starup, before doing anything else, skip unstable
// event and no warning event as they show up at different times.
synctest.Wait() synctest.Wait()
if err := eventbustest.ExpectExactly(tw, if err := eventbustest.Expect(tw,
eventbustest.Type[Change](), // warming-up CompareWarnableCode(t, tsconst.HealthWarnableWarmingUp),
eventbustest.Type[Change](), // is-using-unstable-version CompareWarnableCode(t, tsconst.HealthWarnableNotInMapPoll),
eventbustest.Type[Change](), // not-in-map-poll CompareWarnableCode(t, tsconst.HealthWarnableWarmingUp),
); err != nil { ); err != nil {
t.Errorf("startup error: %v", err) t.Errorf("startup error: %v", err)
} }
// Only set initial state if we need to // Only set initial state if we need to
if len(test.initialState) != 0 { if len(test.initialState) != 0 {
t.Log("Setting initial state")
ht.SetControlHealth(test.initialState) ht.SetControlHealth(test.initialState)
synctest.Wait() synctest.Wait()
if err := eventbustest.ExpectExactly(tw, eventbustest.Type[Change]()); err != nil { if err := eventbustest.Expect(tw,
CompareWarnableCode(t, tsconst.HealthWarnableMagicsockReceiveFuncError),
// Skip event with no warnable
CompareWarnableCode(t, tsconst.HealthWarnableNoDERPHome),
); err != nil {
t.Errorf("initial state error: %v", err) t.Errorf("initial state error: %v", err)
} }
} }
@ -771,6 +778,22 @@ func TestControlHealthNotifies(t *testing.T) {
} }
} }
func CompareWarnableCode(t *testing.T, code string) func(Change) bool {
t.Helper()
return func(c Change) bool {
t.Helper()
if c.Warnable != nil {
t.Logf("Warnable code: %s", c.Warnable.Code)
if string(c.Warnable.Code) == code {
return true
}
} else {
t.Log("No Warnable")
}
return false
}
}
func TestControlHealthIgnoredOutsideMapPoll(t *testing.T) { func TestControlHealthIgnoredOutsideMapPoll(t *testing.T) {
synctest.Test(t, func(t *testing.T) { synctest.Test(t, func(t *testing.T) {
bus := eventbustest.NewBus(t) bus := eventbustest.NewBus(t)

@ -9,6 +9,7 @@ import (
"time" "time"
"tailscale.com/feature/buildfeatures" "tailscale.com/feature/buildfeatures"
"tailscale.com/tsconst"
"tailscale.com/version" "tailscale.com/version"
) )
@ -26,7 +27,7 @@ This file contains definitions for the Warnables maintained within this `health`
// updateAvailableWarnable is a Warnable that warns the user that an update is available. // updateAvailableWarnable is a Warnable that warns the user that an update is available.
var updateAvailableWarnable = condRegister(func() *Warnable { var updateAvailableWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "update-available", Code: tsconst.HealthWarnableUpdateAvailable,
Title: "Update available", Title: "Update available",
Severity: SeverityLow, Severity: SeverityLow,
Text: func(args Args) string { Text: func(args Args) string {
@ -42,7 +43,7 @@ var updateAvailableWarnable = condRegister(func() *Warnable {
// securityUpdateAvailableWarnable is a Warnable that warns the user that an important security update is available. // securityUpdateAvailableWarnable is a Warnable that warns the user that an important security update is available.
var securityUpdateAvailableWarnable = condRegister(func() *Warnable { var securityUpdateAvailableWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "security-update-available", Code: tsconst.HealthWarnableSecurityUpdateAvailable,
Title: "Security update available", Title: "Security update available",
Severity: SeverityMedium, Severity: SeverityMedium,
Text: func(args Args) string { Text: func(args Args) string {
@ -59,7 +60,7 @@ var securityUpdateAvailableWarnable = condRegister(func() *Warnable {
// so they won't be surprised by all the issues that may arise. // so they won't be surprised by all the issues that may arise.
var unstableWarnable = condRegister(func() *Warnable { var unstableWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "is-using-unstable-version", Code: tsconst.HealthWarnableIsUsingUnstableVersion,
Title: "Using an unstable version", Title: "Using an unstable version",
Severity: SeverityLow, Severity: SeverityLow,
Text: StaticMessage("This is an unstable version of Tailscale meant for testing and development purposes. Please report any issues to Tailscale."), Text: StaticMessage("This is an unstable version of Tailscale meant for testing and development purposes. Please report any issues to Tailscale."),
@ -69,7 +70,7 @@ var unstableWarnable = condRegister(func() *Warnable {
// NetworkStatusWarnable is a Warnable that warns the user that the network is down. // NetworkStatusWarnable is a Warnable that warns the user that the network is down.
var NetworkStatusWarnable = condRegister(func() *Warnable { var NetworkStatusWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "network-status", Code: tsconst.HealthWarnableNetworkStatus,
Title: "Network down", Title: "Network down",
Severity: SeverityMedium, Severity: SeverityMedium,
Text: StaticMessage("Tailscale cannot connect because the network is down. Check your Internet connection."), Text: StaticMessage("Tailscale cannot connect because the network is down. Check your Internet connection."),
@ -81,7 +82,7 @@ var NetworkStatusWarnable = condRegister(func() *Warnable {
// IPNStateWarnable is a Warnable that warns the user that Tailscale is stopped. // IPNStateWarnable is a Warnable that warns the user that Tailscale is stopped.
var IPNStateWarnable = condRegister(func() *Warnable { var IPNStateWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "wantrunning-false", Code: tsconst.HealthWarnableWantRunningFalse,
Title: "Tailscale off", Title: "Tailscale off",
Severity: SeverityLow, Severity: SeverityLow,
Text: StaticMessage("Tailscale is stopped."), Text: StaticMessage("Tailscale is stopped."),
@ -91,7 +92,7 @@ var IPNStateWarnable = condRegister(func() *Warnable {
// localLogWarnable is a Warnable that warns the user that the local log is misconfigured. // localLogWarnable is a Warnable that warns the user that the local log is misconfigured.
var localLogWarnable = condRegister(func() *Warnable { var localLogWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "local-log-config-error", Code: tsconst.HealthWarnableLocalLogConfigError,
Title: "Local log misconfiguration", Title: "Local log misconfiguration",
Severity: SeverityLow, Severity: SeverityLow,
Text: func(args Args) string { Text: func(args Args) string {
@ -104,7 +105,7 @@ var localLogWarnable = condRegister(func() *Warnable {
// and provides the last login error if available. // and provides the last login error if available.
var LoginStateWarnable = condRegister(func() *Warnable { var LoginStateWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "login-state", Code: tsconst.HealthWarnableLoginState,
Title: "Logged out", Title: "Logged out",
Severity: SeverityMedium, Severity: SeverityMedium,
Text: func(args Args) string { Text: func(args Args) string {
@ -121,7 +122,7 @@ var LoginStateWarnable = condRegister(func() *Warnable {
// notInMapPollWarnable is a Warnable that warns the user that we are using a stale network map. // notInMapPollWarnable is a Warnable that warns the user that we are using a stale network map.
var notInMapPollWarnable = condRegister(func() *Warnable { var notInMapPollWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "not-in-map-poll", Code: tsconst.HealthWarnableNotInMapPoll,
Title: "Out of sync", Title: "Out of sync",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@ -134,7 +135,7 @@ var notInMapPollWarnable = condRegister(func() *Warnable {
// noDERPHomeWarnable is a Warnable that warns the user that Tailscale doesn't have a home DERP. // noDERPHomeWarnable is a Warnable that warns the user that Tailscale doesn't have a home DERP.
var noDERPHomeWarnable = condRegister(func() *Warnable { var noDERPHomeWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "no-derp-home", Code: tsconst.HealthWarnableNoDERPHome,
Title: "No home relay server", Title: "No home relay server",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{NetworkStatusWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable},
@ -147,7 +148,7 @@ var noDERPHomeWarnable = condRegister(func() *Warnable {
// noDERPConnectionWarnable is a Warnable that warns the user that Tailscale couldn't connect to a specific DERP server. // noDERPConnectionWarnable is a Warnable that warns the user that Tailscale couldn't connect to a specific DERP server.
var noDERPConnectionWarnable = condRegister(func() *Warnable { var noDERPConnectionWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "no-derp-connection", Code: tsconst.HealthWarnableNoDERPConnection,
Title: "Relay server unavailable", Title: "Relay server unavailable",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{ DependsOn: []*Warnable{
@ -177,7 +178,7 @@ var noDERPConnectionWarnable = condRegister(func() *Warnable {
// heard from the home DERP region for a while. // heard from the home DERP region for a while.
var derpTimeoutWarnable = condRegister(func() *Warnable { var derpTimeoutWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "derp-timed-out", Code: tsconst.HealthWarnableDERPTimedOut,
Title: "Relay server timed out", Title: "Relay server timed out",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{ DependsOn: []*Warnable{
@ -198,7 +199,7 @@ var derpTimeoutWarnable = condRegister(func() *Warnable {
// derpRegionErrorWarnable is a Warnable that warns the user that a DERP region is reporting an issue. // derpRegionErrorWarnable is a Warnable that warns the user that a DERP region is reporting an issue.
var derpRegionErrorWarnable = condRegister(func() *Warnable { var derpRegionErrorWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "derp-region-error", Code: tsconst.HealthWarnableDERPRegionError,
Title: "Relay server error", Title: "Relay server error",
Severity: SeverityLow, Severity: SeverityLow,
DependsOn: []*Warnable{NetworkStatusWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable},
@ -211,7 +212,7 @@ var derpRegionErrorWarnable = condRegister(func() *Warnable {
// noUDP4BindWarnable is a Warnable that warns the user that Tailscale couldn't listen for incoming UDP connections. // noUDP4BindWarnable is a Warnable that warns the user that Tailscale couldn't listen for incoming UDP connections.
var noUDP4BindWarnable = condRegister(func() *Warnable { var noUDP4BindWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "no-udp4-bind", Code: tsconst.HealthWarnableNoUDP4Bind,
Title: "NAT traversal setup failure", Title: "NAT traversal setup failure",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@ -223,7 +224,7 @@ var noUDP4BindWarnable = condRegister(func() *Warnable {
// mapResponseTimeoutWarnable is a Warnable that warns the user that Tailscale hasn't received a network map from the coordination server in a while. // mapResponseTimeoutWarnable is a Warnable that warns the user that Tailscale hasn't received a network map from the coordination server in a while.
var mapResponseTimeoutWarnable = condRegister(func() *Warnable { var mapResponseTimeoutWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "mapresponse-timeout", Code: tsconst.HealthWarnableMapResponseTimeout,
Title: "Network map response timeout", Title: "Network map response timeout",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@ -236,7 +237,7 @@ var mapResponseTimeoutWarnable = condRegister(func() *Warnable {
// tlsConnectionFailedWarnable is a Warnable that warns the user that Tailscale could not establish an encrypted connection with a server. // tlsConnectionFailedWarnable is a Warnable that warns the user that Tailscale could not establish an encrypted connection with a server.
var tlsConnectionFailedWarnable = condRegister(func() *Warnable { var tlsConnectionFailedWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "tls-connection-failed", Code: tsconst.HealthWarnableTLSConnectionFailed,
Title: "Encrypted connection failed", Title: "Encrypted connection failed",
Severity: SeverityMedium, Severity: SeverityMedium,
DependsOn: []*Warnable{NetworkStatusWarnable}, DependsOn: []*Warnable{NetworkStatusWarnable},
@ -249,7 +250,7 @@ var tlsConnectionFailedWarnable = condRegister(func() *Warnable {
// magicsockReceiveFuncWarnable is a Warnable that warns the user that one of the Magicsock functions is not running. // magicsockReceiveFuncWarnable is a Warnable that warns the user that one of the Magicsock functions is not running.
var magicsockReceiveFuncWarnable = condRegister(func() *Warnable { var magicsockReceiveFuncWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "magicsock-receive-func-error", Code: tsconst.HealthWarnableMagicsockReceiveFuncError,
Title: "MagicSock function not running", Title: "MagicSock function not running",
Severity: SeverityMedium, Severity: SeverityMedium,
Text: func(args Args) string { Text: func(args Args) string {
@ -261,7 +262,7 @@ var magicsockReceiveFuncWarnable = condRegister(func() *Warnable {
// testWarnable is a Warnable that is used within this package for testing purposes only. // testWarnable is a Warnable that is used within this package for testing purposes only.
var testWarnable = condRegister(func() *Warnable { var testWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "test-warnable", Code: tsconst.HealthWarnableTestWarnable,
Title: "Test warnable", Title: "Test warnable",
Severity: SeverityLow, Severity: SeverityLow,
Text: func(args Args) string { Text: func(args Args) string {
@ -273,7 +274,7 @@ var testWarnable = condRegister(func() *Warnable {
// applyDiskConfigWarnable is a Warnable that warns the user that there was an error applying the envknob config stored on disk. // applyDiskConfigWarnable is a Warnable that warns the user that there was an error applying the envknob config stored on disk.
var applyDiskConfigWarnable = condRegister(func() *Warnable { var applyDiskConfigWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "apply-disk-config", Code: tsconst.HealthWarnableApplyDiskConfig,
Title: "Could not apply configuration", Title: "Could not apply configuration",
Severity: SeverityMedium, Severity: SeverityMedium,
Text: func(args Args) string { Text: func(args Args) string {
@ -291,7 +292,7 @@ const warmingUpWarnableDuration = 5 * time.Second
// the backend is fully started. // the backend is fully started.
var warmingUpWarnable = condRegister(func() *Warnable { var warmingUpWarnable = condRegister(func() *Warnable {
return &Warnable{ return &Warnable{
Code: "warming-up", Code: tsconst.HealthWarnableWarmingUp,
Title: "Tailscale is starting", Title: "Tailscale is starting",
Severity: SeverityLow, Severity: SeverityLow,
Text: StaticMessage("Tailscale is starting. Please wait."), Text: StaticMessage("Tailscale is starting. Please wait."),

@ -384,6 +384,7 @@ func TestRedactNetmapPrivateKeys(t *testing.T) {
f(tailcfg.Service{}, "Port"): false, f(tailcfg.Service{}, "Port"): false,
f(tailcfg.Service{}, "Proto"): false, f(tailcfg.Service{}, "Proto"): false,
f(tailcfg.Service{}, "_"): false, f(tailcfg.Service{}, "_"): false,
f(tailcfg.TPMInfo{}, "FamilyIndicator"): false,
f(tailcfg.TPMInfo{}, "FirmwareVersion"): false, f(tailcfg.TPMInfo{}, "FirmwareVersion"): false,
f(tailcfg.TPMInfo{}, "Manufacturer"): false, f(tailcfg.TPMInfo{}, "Manufacturer"): false,
f(tailcfg.TPMInfo{}, "Model"): false, f(tailcfg.TPMInfo{}, "Model"): false,

@ -124,6 +124,7 @@ func NewLogger(cfg Config, logf tslogger.Logf) *Logger {
if cfg.Bus != nil { if cfg.Bus != nil {
l.eventClient = cfg.Bus.Client("logtail.Logger") l.eventClient = cfg.Bus.Client("logtail.Logger")
l.changeDeltaSub = eventbus.Subscribe[netmon.ChangeDelta](l.eventClient)
} }
l.SetSockstatsLabel(sockstats.LabelLogtailLogger) l.SetSockstatsLabel(sockstats.LabelLogtailLogger)
l.compressLogs = cfg.CompressLogs l.compressLogs = cfg.CompressLogs
@ -162,6 +163,7 @@ type Logger struct {
httpDoCalls atomic.Int32 httpDoCalls atomic.Int32
sockstatsLabel atomicSocktatsLabel sockstatsLabel atomicSocktatsLabel
eventClient *eventbus.Client eventClient *eventbus.Client
changeDeltaSub *eventbus.Subscriber[netmon.ChangeDelta]
procID uint32 procID uint32
includeProcSequence bool includeProcSequence bool
@ -427,9 +429,24 @@ func (l *Logger) internetUp() bool {
func (l *Logger) awaitInternetUp(ctx context.Context) { func (l *Logger) awaitInternetUp(ctx context.Context) {
if l.eventClient != nil { if l.eventClient != nil {
l.awaitInternetUpBus(ctx) for {
if l.internetUp() {
return
}
select {
case <-ctx.Done():
return // give up
case <-l.changeDeltaSub.Done():
return // give up (closing down)
case delta := <-l.changeDeltaSub.Events():
if delta.New.AnyInterfaceUp() || l.internetUp() {
fmt.Fprintf(l.stderr, "logtail: internet back up\n")
return return
} }
fmt.Fprintf(l.stderr, "logtail: network changed, but is not up")
}
}
}
upc := make(chan bool, 1) upc := make(chan bool, 1)
defer l.netMonitor.RegisterChangeCallback(func(delta *netmon.ChangeDelta) { defer l.netMonitor.RegisterChangeCallback(func(delta *netmon.ChangeDelta) {
if delta.New.AnyInterfaceUp() { if delta.New.AnyInterfaceUp() {
@ -449,24 +466,6 @@ func (l *Logger) awaitInternetUp(ctx context.Context) {
} }
} }
func (l *Logger) awaitInternetUpBus(ctx context.Context) {
if l.internetUp() {
return
}
sub := eventbus.Subscribe[netmon.ChangeDelta](l.eventClient)
defer sub.Close()
select {
case delta := <-sub.Events():
if delta.New.AnyInterfaceUp() {
fmt.Fprintf(l.stderr, "logtail: internet back up\n")
return
}
fmt.Fprintf(l.stderr, "logtail: network changed, but is not up")
case <-ctx.Done():
return
}
}
// upload uploads body to the log server. // upload uploads body to the log server.
// origlen indicates the pre-compression body length. // origlen indicates the pre-compression body length.
// origlen of -1 indicates that the body is not compressed. // origlen of -1 indicates that the body is not compressed.

@ -96,6 +96,7 @@ type Dialer struct {
dnsCache *dnscache.MessageCache // nil until first non-empty SetExitDNSDoH dnsCache *dnscache.MessageCache // nil until first non-empty SetExitDNSDoH
nextSysConnID int nextSysConnID int
activeSysConns map[int]net.Conn // active connections not yet closed activeSysConns map[int]net.Conn // active connections not yet closed
bus *eventbus.Bus // only used for comparison with already set bus.
eventClient *eventbus.Client eventClient *eventbus.Client
eventBusSubs eventbus.Monitor eventBusSubs eventbus.Monitor
} }
@ -226,14 +227,17 @@ func (d *Dialer) NetMon() *netmon.Monitor {
func (d *Dialer) SetBus(bus *eventbus.Bus) { func (d *Dialer) SetBus(bus *eventbus.Bus) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
if d.eventClient != nil { if d.bus == bus {
panic("eventbus has already been set") return
} else if d.bus != nil {
panic("different eventbus has already been set")
} }
// Having multiple watchers could lead to problems, // Having multiple watchers could lead to problems,
// so unregister the callback if it exists. // so unregister the callback if it exists.
if d.netMonUnregister != nil { if d.netMonUnregister != nil {
d.netMonUnregister() d.netMonUnregister()
} }
d.bus = bus
d.eventClient = bus.Client("tsdial.Dialer") d.eventClient = bus.Client("tsdial.Dialer")
d.eventBusSubs = d.eventClient.Monitor(d.linkChangeWatcher(d.eventClient)) d.eventBusSubs = d.eventClient.Monitor(d.linkChangeWatcher(d.eventClient))
} }

@ -928,6 +928,10 @@ type TPMInfo struct {
// https://trustedcomputinggroup.org/resource/tpm-library-specification/. // https://trustedcomputinggroup.org/resource/tpm-library-specification/.
// Before revision 184, TCG used the "01.83" format for revision 183. // Before revision 184, TCG used the "01.83" format for revision 183.
SpecRevision int `json:",omitempty"` SpecRevision int `json:",omitempty"`
// FamilyIndicator is the TPM spec family, like "2.0".
// Read from TPM_PT_FAMILY_INDICATOR.
FamilyIndicator string `json:",omitempty"`
} }
// Present reports whether a TPM device is present on this machine. // Present reports whether a TPM device is present on this machine.

@ -0,0 +1,26 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package tsconst
const (
HealthWarnableUpdateAvailable = "update-available"
HealthWarnableSecurityUpdateAvailable = "security-update-available"
HealthWarnableIsUsingUnstableVersion = "is-using-unstable-version"
HealthWarnableNetworkStatus = "network-status"
HealthWarnableWantRunningFalse = "wantrunning-false"
HealthWarnableLocalLogConfigError = "local-log-config-error"
HealthWarnableLoginState = "login-state"
HealthWarnableNotInMapPoll = "not-in-map-poll"
HealthWarnableNoDERPHome = "no-derp-home"
HealthWarnableNoDERPConnection = "no-derp-connection"
HealthWarnableDERPTimedOut = "derp-timed-out"
HealthWarnableDERPRegionError = "derp-region-error"
HealthWarnableNoUDP4Bind = "no-udp4-bind"
HealthWarnableMapResponseTimeout = "mapresponse-timeout"
HealthWarnableTLSConnectionFailed = "tls-connection-failed"
HealthWarnableMagicsockReceiveFuncError = "magicsock-receive-func-error"
HealthWarnableTestWarnable = "test-warnable"
HealthWarnableApplyDiskConfig = "apply-disk-config"
HealthWarnableWarmingUp = "warming-up"
)

@ -1,9 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build linux && (arm64 || amd64) && !ts_omit_iptables //go:build linux && !ts_omit_iptables
// TODO(#8502): add support for more architectures
package linuxfw package linuxfw

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build (linux && !(arm64 || amd64)) || ts_omit_iptables //go:build linux && ts_omit_iptables
package linuxfw package linuxfw

Loading…
Cancel
Save