Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+5
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package health
|
||||
@@ -36,4 +36,8 @@ const (
|
||||
// ArgServerName provides a Warnable with comma delimited list of the hostname of the servers involved in the unhealthy state.
|
||||
// If no nameservers were available to query, this will be an empty string.
|
||||
ArgDNSServers Arg = "dns-servers"
|
||||
|
||||
// ArgDomains provides a Warnable with a comma-delimited list of domain
|
||||
// names involved in the unhealthy state.
|
||||
ArgDomains Arg = "domains"
|
||||
)
|
||||
+76
-16
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Package health is a registry for other packages to report & check
|
||||
@@ -115,11 +115,11 @@ type Tracker struct {
|
||||
lastMapPollEndedAt time.Time
|
||||
lastStreamedMapResponse time.Time
|
||||
lastNoiseDial time.Time
|
||||
derpHomeRegion int
|
||||
derpHomeRegion tailcfg.DERPRegionID
|
||||
derpHomeless bool
|
||||
derpRegionConnected map[int]bool
|
||||
derpRegionHealthProblem map[int]string
|
||||
derpRegionLastFrame map[int]time.Time
|
||||
derpRegionConnected map[tailcfg.DERPRegionID]bool
|
||||
derpRegionHealthProblem map[tailcfg.DERPRegionID]string
|
||||
derpRegionLastFrame map[tailcfg.DERPRegionID]time.Time
|
||||
derpMap *tailcfg.DERPMap // last DERP map from control, could be nil if never received one
|
||||
lastMapRequestHeard time.Time // time we got a 200 from control for a MapRequest
|
||||
ipnState string
|
||||
@@ -132,6 +132,11 @@ type Tracker struct {
|
||||
localLogConfigErr error
|
||||
tlsConnectionErrors map[string]error // map[ServerName]error
|
||||
metricHealthMessage any // nil or *metrics.MultiLabelMap[metricHealthMessageLabel]
|
||||
|
||||
// IP forwarding check
|
||||
// If non-nil, called periodically to check if IP forwarding is broken.
|
||||
// Should return true if broken, false if healthy.
|
||||
isIPForwardingBroken func() bool
|
||||
}
|
||||
|
||||
// NewTracker contructs a new [Tracker] and attaches the given eventbus.
|
||||
@@ -348,6 +353,15 @@ func (t *Tracker) nil() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ProbeLocks acquires and releases the tracker's internal mutex.
|
||||
func (t *Tracker) ProbeLocks() {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
t.mu.Lock()
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
// Severity represents how serious an error is. Each GUI interprets this severity value in different ways,
|
||||
// to surface the error in a more or less visible way. For instance, the macOS GUI could change its menubar
|
||||
// icon to display an exclamation mark and present a modal notification for SeverityHigh warnings, but not
|
||||
@@ -487,7 +501,12 @@ func (t *Tracker) SetHealthy(w *Warnable) {
|
||||
}
|
||||
|
||||
func (t *Tracker) setHealthyLocked(w *Warnable) {
|
||||
if !buildfeatures.HasHealth || t.warnableVal[w] == nil {
|
||||
if !buildfeatures.HasHealth {
|
||||
return
|
||||
}
|
||||
|
||||
ws := t.warnableVal[w]
|
||||
if ws == nil {
|
||||
// Nothing to remove
|
||||
return
|
||||
}
|
||||
@@ -496,15 +515,28 @@ func (t *Tracker) setHealthyLocked(w *Warnable) {
|
||||
|
||||
// Stop any pending visiblity timers for this Warnable
|
||||
if canc, ok := t.pendingVisibleTimers[w]; ok {
|
||||
// We removed the warningState for this Warnable,
|
||||
// and we hold the lock, so even if the timer callback
|
||||
// has already started, it won't find a warningState
|
||||
// for this Warnable and won't publish any changes.
|
||||
canc.Stop()
|
||||
delete(t.pendingVisibleTimers, w)
|
||||
}
|
||||
|
||||
change := Change{
|
||||
WarnableChanged: true,
|
||||
Warnable: w,
|
||||
// Only publish a change if the Warnable was unhealthy long
|
||||
// enough to become visible to the user. Otherwise, it would
|
||||
// not have been published as unhealthy, so there is no need
|
||||
// to publish it as healthy. This prevents eventbus (and by
|
||||
// extension the IPN bus) churn for Warnables that are marked
|
||||
// unhealthy and then healthy again. Notably, this includes
|
||||
// warnables touched by [Tracker.updateBuiltinWarnablesLocked].
|
||||
if w.IsVisible(ws, t.now) {
|
||||
change := Change{
|
||||
WarnableChanged: true,
|
||||
Warnable: w,
|
||||
}
|
||||
t.changePub.Publish(change)
|
||||
}
|
||||
t.changePub.Publish(change)
|
||||
}
|
||||
|
||||
// notifyWatchersControlChangedLocked calls each watcher to signal that control
|
||||
@@ -750,7 +782,7 @@ func (t *Tracker) GetInPollNetMap() bool {
|
||||
//
|
||||
// The homeless parameter is whether magicsock is running in DERP-disconnected
|
||||
// mode, without discovering and maintaining a connection to its home DERP.
|
||||
func (t *Tracker) SetMagicSockDERPHome(region int, homeless bool) {
|
||||
func (t *Tracker) SetMagicSockDERPHome(region tailcfg.DERPRegionID, homeless bool) {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
@@ -777,7 +809,7 @@ func (t *Tracker) NoteMapRequestHeard(mr *tailcfg.MapRequest) {
|
||||
t.selfCheckLocked()
|
||||
}
|
||||
|
||||
func (t *Tracker) SetDERPRegionConnectedState(region int, connected bool) {
|
||||
func (t *Tracker) SetDERPRegionConnectedState(region tailcfg.DERPRegionID, connected bool) {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
@@ -789,7 +821,7 @@ func (t *Tracker) SetDERPRegionConnectedState(region int, connected bool) {
|
||||
|
||||
// SetDERPRegionHealth sets or clears any problem associated with the
|
||||
// provided DERP region.
|
||||
func (t *Tracker) SetDERPRegionHealth(region int, problem string) {
|
||||
func (t *Tracker) SetDERPRegionHealth(region tailcfg.DERPRegionID, problem string) {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
@@ -805,7 +837,7 @@ func (t *Tracker) SetDERPRegionHealth(region int, problem string) {
|
||||
|
||||
// NoteDERPRegionReceivedFrame is called to note that a frame was received from
|
||||
// the given DERP region at the current time.
|
||||
func (t *Tracker) NoteDERPRegionReceivedFrame(region int) {
|
||||
func (t *Tracker) NoteDERPRegionReceivedFrame(region tailcfg.DERPRegionID) {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
@@ -818,7 +850,7 @@ func (t *Tracker) NoteDERPRegionReceivedFrame(region int) {
|
||||
// GetDERPRegionReceivedTime returns the last time that a frame was received
|
||||
// from the given DERP region, or the zero time if no communication with that
|
||||
// region has occurred.
|
||||
func (t *Tracker) GetDERPRegionReceivedTime(region int) time.Time {
|
||||
func (t *Tracker) GetDERPRegionReceivedTime(region tailcfg.DERPRegionID) time.Time {
|
||||
if t.nil() {
|
||||
return time.Time{}
|
||||
}
|
||||
@@ -841,7 +873,7 @@ func (t *Tracker) SetDERPMap(dm *tailcfg.DERPMap) {
|
||||
|
||||
// derpRegionNameLocked returns the name of the DERP region with the given ID
|
||||
// or the empty string if unknown.
|
||||
func (t *Tracker) derpRegionNameLocked(regID int) string {
|
||||
func (t *Tracker) derpRegionNameLocked(regID tailcfg.DERPRegionID) string {
|
||||
if t.derpMap == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -1097,6 +1129,8 @@ func (t *Tracker) updateBuiltinWarnablesLocked() {
|
||||
t.setHealthyLocked(NetworkStatusWarnable)
|
||||
}
|
||||
|
||||
t.updateIPForwardingWarnableLocked()
|
||||
|
||||
if t.localLogConfigErr != nil {
|
||||
t.setUnhealthyLocked(localLogWarnable, Args{
|
||||
ArgError: t.localLogConfigErr.Error(),
|
||||
@@ -1389,3 +1423,29 @@ func (t *Tracker) LastNoiseDialWasRecent() bool {
|
||||
t.lastNoiseDial = now
|
||||
return dur < 2*time.Minute
|
||||
}
|
||||
|
||||
// SetIPForwardingCheck sets the function to check if IP forwarding is broken.
|
||||
// The function should return true if IP forwarding is broken, false if healthy.
|
||||
// Pass nil to disable IP forwarding checks.
|
||||
func (t *Tracker) SetIPForwardingCheck(checkFunc func() bool) {
|
||||
if t.nil() {
|
||||
return
|
||||
}
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
t.isIPForwardingBroken = checkFunc
|
||||
|
||||
// Run an immediate check to set initial state
|
||||
t.updateIPForwardingWarnableLocked()
|
||||
}
|
||||
|
||||
// updateIPForwardingWarnableLocked checks the IP forwarding state and
|
||||
// sets or clears the ipForwardingWarnable accordingly.
|
||||
func (t *Tracker) updateIPForwardingWarnableLocked() {
|
||||
if t.isIPForwardingBroken != nil && t.isIPForwardingBroken() {
|
||||
t.setUnhealthyLocked(ipForwardingWarnable, Args{})
|
||||
} else {
|
||||
t.setHealthyLocked(ipForwardingWarnable)
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Package healthmsg contains some constants for health messages.
|
||||
@@ -11,7 +11,5 @@ const (
|
||||
WarnAcceptRoutesOff = "Some peers are advertising routes but --accept-routes is false"
|
||||
TailscaleSSHOnBut = "Tailscale SSH enabled, but " // + ... something from caller
|
||||
LockedOut = "this node is locked out; it will not have connectivity until it is signed. For more info, see https://tailscale.com/s/locked-out"
|
||||
WarnExitNodeUsage = "The following issues on your machine will likely make usage of exit nodes impossible"
|
||||
DisableRPFilter = "Please set rp_filter=2 instead of rp_filter=1; see https://github.com/tailscale/tailscale/issues/3310"
|
||||
InMemoryTailnetLockState = "Tailnet Lock state is only being stored in-memory. Set --statedir to store state on disk, which is more secure. See https://tailscale.com/kb/1226/tailnet-lock#tailnet-lock-state"
|
||||
)
|
||||
+5
-8
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package health
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/util/mak"
|
||||
)
|
||||
|
||||
// State contains the health status of the backend, and is
|
||||
@@ -128,11 +129,7 @@ func (t *Tracker) CurrentState() *State {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.warnableVal == nil || len(t.warnableVal) == 0 {
|
||||
return &State{}
|
||||
}
|
||||
|
||||
wm := map[WarnableCode]UnhealthyState{}
|
||||
var wm map[WarnableCode]UnhealthyState
|
||||
|
||||
for w, ws := range t.warnableVal {
|
||||
if !w.IsVisible(ws, t.now) {
|
||||
@@ -145,7 +142,7 @@ func (t *Tracker) CurrentState() *State {
|
||||
continue
|
||||
}
|
||||
state := w.unhealthyState(ws)
|
||||
wm[w.Code] = state.withETag()
|
||||
mak.Set(&wm, w.Code, state.withETag())
|
||||
}
|
||||
|
||||
for id, msg := range t.lastNotifiedControlMessages {
|
||||
@@ -165,7 +162,7 @@ func (t *Tracker) CurrentState() *State {
|
||||
}
|
||||
}
|
||||
|
||||
wm[state.WarnableCode] = state.withETag()
|
||||
mak.Set(&wm, state.WarnableCode, state.withETag())
|
||||
}
|
||||
|
||||
return &State{
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !ts_omit_health && !ts_omit_usermetrics
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build ts_omit_health || ts_omit_usermetrics
|
||||
|
||||
+14
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package health
|
||||
@@ -298,3 +298,16 @@ var warmingUpWarnable = condRegister(func() *Warnable {
|
||||
Text: StaticMessage("Tailscale is starting. Please wait."),
|
||||
}
|
||||
})
|
||||
|
||||
// ipForwardingWarnable is a Warnable that warns the user that IP forwarding is disabled
|
||||
// but subnet routing or exit node functionality is being used.
|
||||
var ipForwardingWarnable = condRegister(func() *Warnable {
|
||||
return &Warnable{
|
||||
Code: "ip-forwarding-off",
|
||||
Title: "IP forwarding is off",
|
||||
Severity: SeverityMedium,
|
||||
MapDebugFlag: "warn-ip-forwarding-off",
|
||||
Text: StaticMessage("Subnet routing is enabled, but IP forwarding is disabled. Check that IP forwarding is enabled on your machine."),
|
||||
ImpactsConnectivity: true,
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user