tailcfg

package
v1.78.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 5, 2024 License: BSD-3-Clause Imports: 24 Imported by: 241

Documentation

Overview

Package tailcfg contains types used by the Tailscale protocol with between the node and the coordination server.

Index

Constants

View Source
const (
	MachineUnknown      = MachineStatus(iota)
	MachineUnauthorized // server has yet to approve
	MachineAuthorized   // server has approved
	MachineInvalid      // server has explicitly rejected this machine key
)
View Source
const (
	TCP        = ServiceProto("tcp")
	UDP        = ServiceProto("udp")
	PeerAPI4   = ServiceProto("peerapi4")
	PeerAPI6   = ServiceProto("peerapi6")
	PeerAPIDNS = ServiceProto("peerapi-dns-proxy")
)
View Source
const (
	// SignatureNone indicates that there is no signature, no Timestamp is
	// required (but may be specified if desired), and both DeviceCert and
	// Signature should be empty.
	SignatureNone = SignatureType(iota)
	// SignatureUnknown represents an unknown signature scheme, which should
	// be considered an error if seen.
	SignatureUnknown
	// SignatureV1 is computed as RSA-PSS-Sign(privateKeyForDeviceCert,
	// SHA256(Timestamp || ServerIdentity || DeviceCert || ServerShortPubKey ||
	// MachineShortPubKey)). The PSS salt length is equal to hash length
	// (rsa.PSSSaltLengthEqualsHash). Device cert is required.
	// Deprecated: uses old key serialization format.
	SignatureV1
	// SignatureV2 is computed as RSA-PSS-Sign(privateKeyForDeviceCert,
	// SHA256(Timestamp || ServerIdentity || DeviceCert || ServerPubKey ||
	// MachinePubKey)). The PSS salt length is equal to hash length
	// (rsa.PSSSaltLengthEqualsHash). Device cert is required.
	SignatureV2
)
View Source
const (
	EndpointUnknownType    = EndpointType(0)
	EndpointLocal          = EndpointType(1)
	EndpointSTUN           = EndpointType(2)
	EndpointPortmapped     = EndpointType(3)
	EndpointSTUN4LocalPort = EndpointType(4) // hard NAT: STUN'ed IPv4 address + local fixed port
	EndpointExplicitConf   = EndpointType(5) // explicitly configured (routing to be done by client)
)
View Source
const DerpMagicIP = "127.3.3.40"

DerpMagicIP is a fake WireGuard endpoint IP address that means to use DERP. When used (in the Node.DERP field), the port number of the WireGuard endpoint is the DERP region ID number to use.

Mnemonic: 3.3.40 are numbers above the keys D, E, R, P.

View Source
const DotInvalid = ".invalid"

DotInvalid is a fake DNS TLD used in tests for an invalid hostname.

View Source
const LBHeader = "Ts-Lb"

LBHeader is the HTTP request header used to provide a load balancer or internal reverse proxy with information about the request body without the reverse proxy needing to read the body to parse it out. Think of it akin to an HTTP Host header or SNI. The value may be absent (notably for old clients) but if present, it should match the request. A non-empty value that doesn't match the request body's.

The possible values depend on the request path, but for /machine (Noise) requests, they'll usually be a node public key (in key.NodePublic.String format), matching the Request JSON body's NodeKey.

Note that this is not a security or authentication header; it's strictly denormalized redundant data as an optimization.

For some request types, the header may have multiple values. (e.g. OldNodeKey vs NodeKey)

Variables

View Source
var DerpMagicIPAddr = netip.MustParseAddr(DerpMagicIP)
View Source
var FilterAllowAll = []FilterRule{
	{
		SrcIPs: []string{"*"},
		DstPorts: []NetPortRange{{
			IP:    "*",
			Ports: PortRange{0, 65535},
		}},
	},
}
View Source
var PortRangeAny = PortRange{0, 65535}

Functions

func CheckServiceName added in v1.78.0

func CheckServiceName(svc string) error

CheckServiceName validates svc for use as a service name. We only allow valid DNS labels, since the expectation is that these will be used as parts of domain names.

func CheckTag added in v0.98.1

func CheckTag(tag string) error

CheckTag validates tag for use as an ACL tag. For now we allow only ascii alphanumeric tags, and they need to start with a letter. No unicode shenanigans allowed, and we reserve punctuation marks other than '-' for a possible future URI scheme.

Because we're ignoring unicode entirely, we can treat utf-8 as a series of bytes. Anything >= 128 is disqualified anyway.

We might relax these rules later.

func Clone added in v1.2.0

func Clone(dst, src any) bool

Clone duplicates src into dst and reports whether it succeeded. To succeed, <src, dst> must be of types <*T, *T> or <*T, **T>, where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile.

func IsKnownServiceProto added in v1.76.0

func IsKnownServiceProto(sp ServiceProto) bool

IsKnownServiceProto checks whether sp represents a known-valid value of ServiceProto.

func UnmarshalCapJSON added in v1.48.0

func UnmarshalCapJSON[T any](cm PeerCapMap, cap PeerCapability) ([]T, error)

UnmarshalCapJSON unmarshals each JSON value in cm[cap] as T. If cap does not exist in cm, it returns (nil, nil). It returns an error if the values cannot be unmarshaled into the provided type.

func UnmarshalNodeCapJSON added in v1.50.0

func UnmarshalNodeCapJSON[T any](cm NodeCapMap, cap NodeCapability) ([]T, error)

UnmarshalNodeCapJSON unmarshals each JSON value in cm[cap] as T. If cap does not exist in cm, it returns (nil, nil). It returns an error if the values cannot be unmarshaled into the provided type.

Types

type C2NAppConnectorDomainRoutesResponse added in v1.54.0

type C2NAppConnectorDomainRoutesResponse struct {
	// Domains is a map of lower case domain names with no trailing dot,
	// to a list of resolved IP addresses.
	Domains map[string][]netip.Addr
}

C2NAppConnectorDomainRoutesResponse contains a map of domains to slice of addresses, indicating what IP addresses have been resolved for each domain.

type C2NPostureIdentityResponse added in v1.52.0

type C2NPostureIdentityResponse struct {
	// SerialNumbers is a list of serial numbers of the client machine.
	SerialNumbers []string `json:",omitempty"`

	// IfaceHardwareAddrs is a list of hardware addresses (MAC addresses)
	// of the client machine's network interfaces.
	IfaceHardwareAddrs []string `json:",omitempty"`

	// PostureDisabled indicates if the machine has opted out of
	// device posture collection.
	PostureDisabled bool `json:",omitempty"`
}

C2NPostureIdentityResponse contains either a set of identifying serial numbers and hardware addresses from the client, or a boolean flag indicating that the machine has opted out of posture collection.

type C2NSSHUsernamesRequest added in v1.32.0

type C2NSSHUsernamesRequest struct {
	// Exclude optionally specifies usernames to exclude
	// from the response.
	Exclude map[string]bool `json:",omitempty"`

	// Max is the maximum number of usernames to return.
	// If zero, a default limit is used.
	Max int `json:",omitempty"`
}

C2NSSHUsernamesRequest is the request for the /ssh/usernames. A GET request without a request body is equivalent to the zero value of this type. Otherwise, a POST request with a JSON-encoded request body is expected.

type C2NSSHUsernamesResponse added in v1.32.0

type C2NSSHUsernamesResponse struct {
	// Usernames is the list of usernames to suggest. If the machine has many
	// users, this list may be truncated. If getting the list of usernames might
	// be too slow or unavailable, this list might be empty. This is effectively
	// just a best effort set of hints.
	Usernames []string
}

C2NSSHUsernamesResponse is the response (from node to control) from the /ssh/usernames handler.

It returns username auto-complete suggestions for a user to SSH to this node. It's only shown to people who already have SSH access to the node. If this returns multiple usernames, only the usernames that would have access per the tailnet's ACLs are shown to the user so as to not leak the existence of usernames.

type C2NTLSCertInfo added in v1.56.0

type C2NTLSCertInfo struct {
	// Valid means that the node has a cached and valid (not expired)
	// certificate.
	Valid bool `json:",omitempty"`
	// Error is the error string if the certificate is not valid. If error is
	// non-empty, the other booleans below might say why.
	Error string `json:",omitempty"`

	// Missing is whether the error string indicates a missing certificate
	// that's never been fetched or isn't on disk.
	Missing bool `json:",omitempty"`

	// Expired is whether the error string indicates an expired certificate.
	Expired bool `json:",omitempty"`

	NotBefore string `json:",omitempty"` // RFC3339, if Valid
	NotAfter  string `json:",omitempty"` // RFC3339, if Valid

}

C2NTLSCertInfo describes the state of a cached TLS certificate.

type C2NUpdateResponse added in v1.50.0

type C2NUpdateResponse struct {
	// Err is the error message, if any.
	Err string `json:",omitempty"`

	// Enabled indicates whether the user has opted in to updates triggered from
	// control.
	Enabled bool

	// Supported indicates whether remote updates are supported on this
	// OS/platform.
	Supported bool

	// Started indicates whether the update has started.
	Started bool
}

C2NUpdateResponse is the response (from node to control) from the /update handler. It tells control the status of its request for the node to update its Tailscale installation.

type CapGrant added in v1.24.0

type CapGrant struct {
	// Dsts are the destination IP ranges that this capability
	// grant matches.
	Dsts []netip.Prefix

	// Caps are the capabilities the source IP matched by
	// FilterRule.SrcIPs are granted to the destination IP,
	// matched by Dsts.
	// Deprecated: use CapMap instead.
	Caps []PeerCapability `json:",omitempty"`

	// CapMap is a map of capabilities to their values.
	// The key is the capability name, and the value is a list of
	// values for that capability.
	CapMap PeerCapMap `json:",omitempty"`
}

CapGrant grants capabilities in a FilterRule.

type CapabilityVersion added in v1.24.0

type CapabilityVersion int

CapabilityVersion represents the client's capability level. That is, it can be thought of as the client's simple version number: a single monotonically increasing integer, rather than the relatively complex x.y.z-xxxxx semver+hash(es). Whenever the client gains a capability or wants to negotiate a change in semantics with the server (control plane), peers (over PeerAPI), or frontend (over LocalAPI), bump this number and document what's new.

Previously (prior to 2022-03-06), it was known as the "MapRequest version" or "mapVer" or "map cap" and that name and usage persists in places.

const CurrentCapabilityVersion CapabilityVersion = 109

CurrentCapabilityVersion is the current capability version of the codebase.

History of versions:

  • 3: implicit compression, keep-alives
  • 4: opt-in keep-alives via KeepAlive field, opt-in compression via Compress
  • 5: 2020-10-19, implies IncludeIPv6, delta Peers/UserProfiles, supports MagicDNS
  • 6: 2020-12-07: means MapResponse.PacketFilter nil means unchanged
  • 7: 2020-12-15: FilterRule.SrcIPs accepts CIDRs+ranges, doesn't warn about 0.0.0.0/::
  • 8: 2020-12-19: client can buggily receive IPv6 addresses and routes if beta enabled server-side
  • 9: 2020-12-30: client doesn't auto-add implicit search domains from peers; only DNSConfig.Domains
  • 10: 2021-01-17: client understands MapResponse.PeerSeenChange
  • 11: 2021-03-03: client understands IPv6, multiple default routes, and goroutine dumping
  • 12: 2021-03-04: client understands PingRequest
  • 13: 2021-03-19: client understands FilterRule.IPProto
  • 14: 2021-04-07: client understands DNSConfig.Routes and DNSConfig.Resolvers
  • 15: 2021-04-12: client treats nil MapResponse.DNSConfig as meaning unchanged
  • 16: 2021-04-15: client understands Node.Online, MapResponse.OnlineChange
  • 17: 2021-04-18: MapResponse.Domain empty means unchanged
  • 18: 2021-04-19: MapResponse.Node nil means unchanged (all fields now omitempty)
  • 19: 2021-04-21: MapResponse.Debug.SleepSeconds
  • 20: 2021-06-11: MapResponse.LastSeen used even less (https://github.com/tailscale/tailscale/issues/2107)
  • 21: 2021-06-15: added MapResponse.DNSConfig.CertDomains
  • 22: 2021-06-16: added MapResponse.DNSConfig.ExtraRecords
  • 23: 2021-08-25: DNSConfig.Routes values may be empty (for ExtraRecords support in 1.14.1+)
  • 24: 2021-09-18: MapResponse.Health from control to node; node shows in "tailscale status"
  • 25: 2021-11-01: MapResponse.Debug.Exit
  • 26: 2022-01-12: (nothing, just bumping for 1.20.0)
  • 27: 2022-02-18: start of SSHPolicy being respected
  • 28: 2022-03-09: client can communicate over Noise.
  • 29: 2022-03-21: MapResponse.PopBrowserURL
  • 30: 2022-03-22: client can request id tokens.
  • 31: 2022-04-15: PingRequest & PingResponse TSMP & disco support
  • 32: 2022-04-17: client knows FilterRule.CapMatch
  • 33: 2022-07-20: added MapResponse.PeersChangedPatch (DERPRegion + Endpoints)
  • 34: 2022-08-02: client understands CapabilityFileSharingTarget
  • 36: 2022-08-02: added PeersChangedPatch.{Key,DiscoKey,Online,LastSeen,KeyExpiry,Capabilities}
  • 37: 2022-08-09: added Debug.{SetForceBackgroundSTUN,SetRandomizeClientPort}; Debug are sticky
  • 38: 2022-08-11: added PingRequest.URLIsNoise
  • 39: 2022-08-15: clients can talk Noise over arbitrary HTTPS port
  • 40: 2022-08-22: added Node.KeySignature, PeersChangedPatch.KeySignature
  • 41: 2022-08-30: uses 100.100.100.100 for route-less ExtraRecords if global nameservers is set
  • 42: 2022-09-06: NextDNS DoH support; see https://github.com/tailscale/tailscale/pull/5556
  • 43: 2022-09-21: clients can return usernames for SSH
  • 44: 2022-09-22: MapResponse.ControlDialPlan
  • 45: 2022-09-26: c2n /debug/{goroutines,prefs,metrics}
  • 46: 2022-10-04: c2n /debug/component-logging
  • 47: 2022-10-11: Register{Request,Response}.NodeKeySignature
  • 48: 2022-11-02: Node.UnsignedPeerAPIOnly
  • 49: 2022-11-03: Client understands EarlyNoise
  • 50: 2022-11-14: Client understands CapabilityIngress
  • 51: 2022-11-30: Client understands CapabilityTailnetLockAlpha
  • 52: 2023-01-05: client can handle c2n POST /logtail/flush
  • 53: 2023-01-18: client respects explicit Node.Expired + auto-sets based on Node.KeyExpiry
  • 54: 2023-01-19: Node.Cap added, PeersChangedPatch.Cap, uses Node.Cap for ExitDNS before Hostinfo.Services fallback
  • 55: 2023-01-23: start of c2n GET+POST /update handler
  • 56: 2023-01-24: Client understands CapabilityDebugTSDNSResolution
  • 57: 2023-01-25: Client understands CapabilityBindToInterfaceByRoute
  • 58: 2023-03-10: Client retries lite map updates before restarting map poll.
  • 59: 2023-03-16: Client understands Peers[].SelfNodeV4MasqAddrForThisPeer
  • 60: 2023-04-06: Client understands IsWireGuardOnly
  • 61: 2023-04-18: Client understand SSHAction.SSHRecorderFailureAction
  • 62: 2023-05-05: Client can notify control over noise for SSHEventNotificationRequest recording failure events
  • 63: 2023-06-08: Client understands SSHAction.AllowRemotePortForwarding.
  • 64: 2023-07-11: Client understands s/CapabilityTailnetLockAlpha/CapabilityTailnetLock
  • 65: 2023-07-12: Client understands DERPMap.HomeParams + incremental DERPMap updates with params
  • 66: 2023-07-23: UserProfile.Groups added (available via WhoIs) (removed in 87)
  • 67: 2023-07-25: Client understands PeerCapMap
  • 68: 2023-08-09: Client has dedicated updateRoutine; MapRequest.Stream true means ignore Hostinfo+Endpoints
  • 69: 2023-08-16: removed Debug.LogHeap* + GoroutineDumpURL; added c2n /debug/logheap
  • 70: 2023-08-16: removed most Debug fields; added NodeAttrDisable*, NodeAttrDebug* instead
  • 71: 2023-08-17: added NodeAttrOneCGNATEnable, NodeAttrOneCGNATDisable
  • 72: 2023-08-23: TS-2023-006 UPnP issue fixed; UPnP can now be used again
  • 73: 2023-09-01: Non-Windows clients expect to receive ClientVersion
  • 74: 2023-09-18: Client understands NodeCapMap
  • 75: 2023-09-12: Client understands NodeAttrDNSForwarderDisableTCPRetries
  • 76: 2023-09-20: Client understands ExitNodeDNSResolvers for IsWireGuardOnly nodes
  • 77: 2023-10-03: Client understands Peers[].SelfNodeV6MasqAddrForThisPeer
  • 78: 2023-10-05: can handle c2n Wake-on-LAN sending
  • 79: 2023-10-05: Client understands UrgentSecurityUpdate in ClientVersion
  • 80: 2023-11-16: can handle c2n GET /tls-cert-status
  • 81: 2023-11-17: MapResponse.PacketFilters (incremental packet filter updates)
  • 82: 2023-12-01: Client understands NodeAttrLinuxMustUseIPTables, NodeAttrLinuxMustUseNfTables, c2n /netfilter-kind
  • 83: 2023-12-18: Client understands DefaultAutoUpdate
  • 84: 2024-01-04: Client understands SeamlessKeyRenewal
  • 85: 2024-01-05: Client understands MaxKeyDuration
  • 86: 2024-01-23: Client understands NodeAttrProbeUDPLifetime
  • 87: 2024-02-11: UserProfile.Groups removed (added in 66)
  • 88: 2024-03-05: Client understands NodeAttrSuggestExitNode
  • 89: 2024-03-23: Client no longer respects deleted PeerChange.Capabilities (use CapMap)
  • 90: 2024-04-03: Client understands PeerCapabilityTaildrive.
  • 91: 2024-04-24: Client understands PeerCapabilityTaildriveSharer.
  • 92: 2024-05-06: Client understands NodeAttrUserDialUseRoutes.
  • 93: 2024-05-06: added support for stateful firewalling.
  • 94: 2024-05-06: Client understands Node.IsJailed.
  • 95: 2024-05-06: Client uses NodeAttrUserDialUseRoutes to change DNS dialing behavior.
  • 96: 2024-05-29: Client understands NodeAttrSSHBehaviorV1
  • 97: 2024-06-06: Client understands NodeAttrDisableSplitDNSWhenNoCustomResolvers
  • 98: 2024-06-13: iOS/tvOS clients may provide serial number as part of posture information
  • 99: 2024-06-14: Client understands NodeAttrDisableLocalDNSOverrideViaNRPT
  • 100: 2024-06-18: Initial support for filtertype.Match.SrcCaps - actually usable in capver 109 (issue #12542)
  • 101: 2024-07-01: Client supports SSH agent forwarding when handling connections with /bin/su
  • 102: 2024-07-12: NodeAttrDisableMagicSockCryptoRouting support
  • 103: 2024-07-24: Client supports NodeAttrDisableCaptivePortalDetection
  • 104: 2024-08-03: SelfNodeV6MasqAddrForThisPeer now works
  • 105: 2024-08-05: Fixed SSH behavior on systems that use busybox (issue #12849)
  • 106: 2024-09-03: fix panic regression from cryptokey routing change (65fe0ba7b5)
  • 107: 2024-10-30: add App Connector to conffile (PR #13942)
  • 108: 2024-11-08: Client sends ServicesHash in Hostinfo, understands c2n GET /vip-services.
  • 109: 2024-11-18: Client supports filtertype.Match.SrcCaps (issue #12542)

type ClientVersion added in v1.34.0

type ClientVersion struct {
	// RunningLatest is true if the client is running the latest build.
	RunningLatest bool `json:",omitempty"`

	// LatestVersion is the latest version.Short ("1.34.2") version available
	// for download for the client's platform and packaging type.
	// It won't be populated if RunningLatest is true.
	LatestVersion string `json:",omitempty"`

	// UrgentSecurityUpdate is set when the client is missing an important
	// security update. That update may be in LatestVersion or earlier.
	// UrgentSecurityUpdate should not be set if RunningLatest is false.
	UrgentSecurityUpdate bool `json:",omitempty"`

	// Notify is whether the client should do an OS-specific notification about
	// a new version being available. This should not be populated if
	// RunningLatest is true. The client should not notify multiple times for
	// the same LatestVersion value.
	Notify bool `json:",omitempty"`

	// NotifyURL is a URL to open in the browser when the user clicks on the
	// notification, when Notify is true.
	NotifyURL string `json:",omitempty"`

	// NotifyText is the text to show in the notification, when Notify is true.
	NotifyText string `json:",omitempty"`
}

ClientVersion is information about the latest client version that's available for the client (and whether they're already running it).

It does not include a URL to download the client, as that varies by platform.

type ControlDialPlan added in v1.32.0

type ControlDialPlan struct {
	// An empty list means the default: use DNS (unspecified which DNS).
	Candidates []ControlIPCandidate
}

ControlDialPlan is instructions from the control server to the client on how to connect to the control server; this is useful for maintaining connection if the client's network state changes after the initial connection, or due to the configuration that the control server pushes.

func (*ControlDialPlan) Clone added in v1.32.0

func (src *ControlDialPlan) Clone() *ControlDialPlan

Clone makes a deep copy of ControlDialPlan. The result aliases no memory with the original.

func (*ControlDialPlan) View added in v1.32.0

View returns a readonly view of ControlDialPlan.

type ControlDialPlanView added in v1.32.0

type ControlDialPlanView struct {
	// contains filtered or unexported fields
}

ControlDialPlanView provides a read-only view over ControlDialPlan.

Its methods should only be called if `Valid()` returns true.

func (ControlDialPlanView) AsStruct added in v1.32.0

func (v ControlDialPlanView) AsStruct() *ControlDialPlan

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (ControlDialPlanView) Candidates added in v1.32.0

func (ControlDialPlanView) MarshalJSON added in v1.32.0

func (v ControlDialPlanView) MarshalJSON() ([]byte, error)

func (*ControlDialPlanView) UnmarshalJSON added in v1.32.0

func (v *ControlDialPlanView) UnmarshalJSON(b []byte) error

func (ControlDialPlanView) Valid added in v1.32.0

func (v ControlDialPlanView) Valid() bool

Valid reports whether underlying value is non-nil.

type ControlIPCandidate added in v1.32.0

type ControlIPCandidate struct {
	// IP is the address to attempt connecting to.
	IP netip.Addr

	// DialStartSec is the number of seconds after the beginning of the
	// connection process to wait before trying this candidate.
	DialStartDelaySec float64 `json:",omitempty"`

	// DialTimeoutSec is the timeout for a connection to this candidate,
	// starting after DialStartDelaySec.
	DialTimeoutSec float64 `json:",omitempty"`

	// Priority is the relative priority of this candidate; candidates with
	// a higher priority are preferred over candidates with a lower
	// priority.
	Priority int `json:",omitempty"`
}

ControlIPCandidate represents a single candidate address to use when connecting to the control server.

type DERPAdmitClientRequest added in v1.62.0

type DERPAdmitClientRequest struct {
	NodePublic key.NodePublic // key to query for admission
	Source     netip.Addr     // derp client's IP address
}

DERPAdmitClientRequest is the JSON request body of a POST to derper's --verify-client-url admission controller URL.

type DERPAdmitClientResponse added in v1.62.0

type DERPAdmitClientResponse struct {
	Allow bool // whether to permit client

}

DERPAdmitClientResponse is the response to a DERPAdmitClientRequest.

type DERPHomeParams added in v1.46.0

type DERPHomeParams struct {
	// RegionScore scales latencies of DERP regions by a given scaling
	// factor when determining which region to use as the home
	// ("preferred") DERP. Scores in the range (0, 1) will cause this
	// region to be proportionally more preferred, and scores in the range
	// (1, ∞) will penalize a region.
	//
	// If a region is not present in this map, it is treated as having a
	// score of 1.0.
	//
	// Scores should not be 0 or negative; such scores will be ignored.
	//
	// A nil map means no change from the previous value (if any); an empty
	// non-nil map can be sent to reset all scores back to 1.0.
	RegionScore map[int]float64 `json:",omitempty"`
}

DERPHomeParams contains parameters from the server related to selecting a DERP home region (sometimes referred to as the "preferred DERP").

func (*DERPHomeParams) Clone added in v1.46.0

func (src *DERPHomeParams) Clone() *DERPHomeParams

Clone makes a deep copy of DERPHomeParams. The result aliases no memory with the original.

func (*DERPHomeParams) View added in v1.46.0

View returns a readonly view of DERPHomeParams.

type DERPHomeParamsView added in v1.46.0

type DERPHomeParamsView struct {
	// contains filtered or unexported fields
}

DERPHomeParamsView provides a read-only view over DERPHomeParams.

Its methods should only be called if `Valid()` returns true.

func (DERPHomeParamsView) AsStruct added in v1.46.0

func (v DERPHomeParamsView) AsStruct() *DERPHomeParams

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (DERPHomeParamsView) MarshalJSON added in v1.46.0

func (v DERPHomeParamsView) MarshalJSON() ([]byte, error)

func (DERPHomeParamsView) RegionScore added in v1.46.0

func (v DERPHomeParamsView) RegionScore() views.Map[int, float64]

func (*DERPHomeParamsView) UnmarshalJSON added in v1.46.0

func (v *DERPHomeParamsView) UnmarshalJSON(b []byte) error

func (DERPHomeParamsView) Valid added in v1.46.0

func (v DERPHomeParamsView) Valid() bool

Valid reports whether underlying value is non-nil.

type DERPMap added in v0.98.1

type DERPMap struct {
	// HomeParams, if non-nil, is a change in home parameters.
	//
	// The rest of the DEPRMap fields, if zero, means unchanged.
	HomeParams *DERPHomeParams `json:",omitempty"`

	// Regions is the set of geographic regions running DERP node(s).
	//
	// It's keyed by the DERPRegion.RegionID.
	//
	// The numbers are not necessarily contiguous.
	Regions map[int]*DERPRegion

	// OmitDefaultRegions specifies to not use Tailscale's DERP servers, and only use those
	// specified in this DERPMap. If there are none set outside of the defaults, this is a noop.
	//
	// This field is only meaningful if the Regions map is non-nil (indicating a change).
	OmitDefaultRegions bool `json:"omitDefaultRegions,omitempty"`
}

DERPMap describes the set of DERP packet relay servers that are available.

func (*DERPMap) Clone added in v1.10.0

func (src *DERPMap) Clone() *DERPMap

Clone makes a deep copy of DERPMap. The result aliases no memory with the original.

func (*DERPMap) RegionIDs added in v0.98.1

func (m *DERPMap) RegionIDs() []int

/ RegionIDs returns the sorted region IDs.

func (*DERPMap) View added in v1.26.0

func (p *DERPMap) View() DERPMapView

View returns a readonly view of DERPMap.

type DERPMapView added in v1.26.0

type DERPMapView struct {
	// contains filtered or unexported fields
}

DERPMapView provides a read-only view over DERPMap.

Its methods should only be called if `Valid()` returns true.

func (DERPMapView) AsStruct added in v1.26.0

func (v DERPMapView) AsStruct() *DERPMap

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (DERPMapView) HomeParams added in v1.46.0

func (v DERPMapView) HomeParams() DERPHomeParamsView

func (DERPMapView) MarshalJSON added in v1.26.0

func (v DERPMapView) MarshalJSON() ([]byte, error)

func (DERPMapView) OmitDefaultRegions added in v1.26.0

func (v DERPMapView) OmitDefaultRegions() bool

func (DERPMapView) Regions added in v1.26.0

func (*DERPMapView) UnmarshalJSON added in v1.26.0

func (v *DERPMapView) UnmarshalJSON(b []byte) error

func (DERPMapView) Valid added in v1.26.0

func (v DERPMapView) Valid() bool

Valid reports whether underlying value is non-nil.

type DERPNode added in v0.98.1

type DERPNode struct {
	// Name is a unique node name (across all regions).
	// It is not a host name.
	// It's typically of the form "1b", "2a", "3b", etc. (region
	// ID + suffix within that region)
	Name string

	// RegionID is the RegionID of the DERPRegion that this node
	// is running in.
	RegionID int

	// HostName is the DERP node's hostname.
	//
	// It is required but need not be unique; multiple nodes may
	// have the same HostName but vary in configuration otherwise.
	HostName string

	// CertName optionally specifies the expected TLS cert common
	// name. If empty, HostName is used. If CertName is non-empty,
	// HostName is only used for the TCP dial (if IPv4/IPv6 are
	// not present) + TLS ClientHello.
	CertName string `json:",omitempty"`

	// IPv4 optionally forces an IPv4 address to use, instead of using DNS.
	// If empty, A record(s) from DNS lookups of HostName are used.
	// If the string is not an IPv4 address, IPv4 is not used; the
	// conventional string to disable IPv4 (and not use DNS) is
	// "none".
	IPv4 string `json:",omitempty"`

	// IPv6 optionally forces an IPv6 address to use, instead of using DNS.
	// If empty, AAAA record(s) from DNS lookups of HostName are used.
	// If the string is not an IPv6 address, IPv6 is not used; the
	// conventional string to disable IPv6 (and not use DNS) is
	// "none".
	IPv6 string `json:",omitempty"`

	// Port optionally specifies a STUN port to use.
	// Zero means 3478.
	// To disable STUN on this node, use -1.
	STUNPort int `json:",omitempty"`

	// STUNOnly marks a node as only a STUN server and not a DERP
	// server.
	STUNOnly bool `json:",omitempty"`

	// DERPPort optionally provides an alternate TLS port number
	// for the DERP HTTPS server.
	//
	// If zero, 443 is used.
	DERPPort int `json:",omitempty"`

	// InsecureForTests is used by unit tests to disable TLS verification.
	// It should not be set by users.
	InsecureForTests bool `json:",omitempty"`

	// STUNTestIP is used in tests to override the STUN server's IP.
	// If empty, it's assumed to be the same as the DERP server.
	STUNTestIP string `json:",omitempty"`

	// CanPort80 specifies whether this DERP node is accessible over HTTP
	// on port 80 specifically. This is used for captive portal checks.
	CanPort80 bool `json:",omitempty"`
}

DERPNode describes a DERP packet relay node running within a DERPRegion.

func (*DERPNode) Clone added in v1.10.0

func (src *DERPNode) Clone() *DERPNode

Clone makes a deep copy of DERPNode. The result aliases no memory with the original.

func (*DERPNode) IsTestNode added in v1.66.0

func (n *DERPNode) IsTestNode() bool

func (*DERPNode) View added in v1.26.0

func (p *DERPNode) View() DERPNodeView

View returns a readonly view of DERPNode.

type DERPNodeView added in v1.26.0

type DERPNodeView struct {
	// contains filtered or unexported fields
}

DERPNodeView provides a read-only view over DERPNode.

Its methods should only be called if `Valid()` returns true.

func (DERPNodeView) AsStruct added in v1.26.0

func (v DERPNodeView) AsStruct() *DERPNode

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (DERPNodeView) CanPort80 added in v1.40.0

func (v DERPNodeView) CanPort80() bool

func (DERPNodeView) CertName added in v1.26.0

func (v DERPNodeView) CertName() string

func (DERPNodeView) DERPPort added in v1.26.0

func (v DERPNodeView) DERPPort() int

func (DERPNodeView) HostName added in v1.26.0

func (v DERPNodeView) HostName() string

func (DERPNodeView) IPv4 added in v1.26.0

func (v DERPNodeView) IPv4() string

func (DERPNodeView) IPv6 added in v1.26.0

func (v DERPNodeView) IPv6() string

func (DERPNodeView) InsecureForTests added in v1.26.0

func (v DERPNodeView) InsecureForTests() bool

func (DERPNodeView) MarshalJSON added in v1.26.0

func (v DERPNodeView) MarshalJSON() ([]byte, error)

func (DERPNodeView) Name added in v1.26.0

func (v DERPNodeView) Name() string

func (DERPNodeView) RegionID added in v1.26.0

func (v DERPNodeView) RegionID() int

func (DERPNodeView) STUNOnly added in v1.26.0

func (v DERPNodeView) STUNOnly() bool

func (DERPNodeView) STUNPort added in v1.26.0

func (v DERPNodeView) STUNPort() int

func (DERPNodeView) STUNTestIP added in v1.26.0

func (v DERPNodeView) STUNTestIP() string

func (*DERPNodeView) UnmarshalJSON added in v1.26.0

func (v *DERPNodeView) UnmarshalJSON(b []byte) error

func (DERPNodeView) Valid added in v1.26.0

func (v DERPNodeView) Valid() bool

Valid reports whether underlying value is non-nil.

type DERPRegion added in v0.98.1

type DERPRegion struct {
	// RegionID is a unique integer for a geographic region.
	//
	// It corresponds to the legacy derpN.tailscale.com hostnames
	// used by older clients. (Older clients will continue to resolve
	// derpN.tailscale.com when contacting peers, rather than use
	// the server-provided DERPMap)
	//
	// RegionIDs must be non-zero, positive, and guaranteed to fit
	// in a JavaScript number.
	//
	// RegionIDs in range 900-999 are reserved for end users to run their
	// own DERP nodes.
	RegionID int

	// RegionCode is a short name for the region. It's usually a popular
	// city or airport code in the region: "nyc", "sf", "sin",
	// "fra", etc.
	RegionCode string

	// RegionName is a long English name for the region: "New York City",
	// "San Francisco", "Singapore", "Frankfurt", etc.
	RegionName string

	// Latitude, Longitude are optional geographical coordinates of the DERP region's city, in degrees.
	Latitude  float64 `json:",omitempty"`
	Longitude float64 `json:",omitempty"`

	// Avoid is whether the client should avoid picking this as its home
	// region. The region should only be used if a peer is there.
	// Clients already using this region as their home should migrate
	// away to a new region without Avoid set.
	Avoid bool `json:",omitempty"`

	// Nodes are the DERP nodes running in this region, in
	// priority order for the current client. Client TLS
	// connections should ideally only go to the first entry
	// (falling back to the second if necessary). STUN packets
	// should go to the first 1 or 2.
	//
	// If nodes within a region route packets amongst themselves,
	// but not to other regions. That said, each user/domain
	// should get a the same preferred node order, so if all nodes
	// for a user/network pick the first one (as they should, when
	// things are healthy), the inter-cluster routing is minimal
	// to zero.
	Nodes []*DERPNode
}

DERPRegion is a geographic region running DERP relay node(s).

Client nodes discover which region they're closest to, advertise that "home" DERP region (previously called "home node", when there was only 1 node per region) and maintain a persistent connection that region as long as it's the closest. Client nodes will further connect to other regions as necessary to communicate with peers advertising other regions as their homes.

func (*DERPRegion) Clone added in v1.10.0

func (src *DERPRegion) Clone() *DERPRegion

Clone makes a deep copy of DERPRegion. The result aliases no memory with the original.

func (*DERPRegion) View added in v1.26.0

func (p *DERPRegion) View() DERPRegionView

View returns a readonly view of DERPRegion.

type DERPRegionView added in v1.26.0

type DERPRegionView struct {
	// contains filtered or unexported fields
}

DERPRegionView provides a read-only view over DERPRegion.

Its methods should only be called if `Valid()` returns true.

func (DERPRegionView) AsStruct added in v1.26.0

func (v DERPRegionView) AsStruct() *DERPRegion

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (DERPRegionView) Avoid added in v1.26.0

func (v DERPRegionView) Avoid() bool

func (DERPRegionView) Latitude added in v1.62.0

func (v DERPRegionView) Latitude() float64

func (DERPRegionView) Longitude added in v1.62.0

func (v DERPRegionView) Longitude() float64

func (DERPRegionView) MarshalJSON added in v1.26.0

func (v DERPRegionView) MarshalJSON() ([]byte, error)

func (DERPRegionView) Nodes added in v1.26.0

func (DERPRegionView) RegionCode added in v1.26.0

func (v DERPRegionView) RegionCode() string

func (DERPRegionView) RegionID added in v1.26.0

func (v DERPRegionView) RegionID() int

func (DERPRegionView) RegionName added in v1.26.0

func (v DERPRegionView) RegionName() string

func (*DERPRegionView) UnmarshalJSON added in v1.26.0

func (v *DERPRegionView) UnmarshalJSON(b []byte) error

func (DERPRegionView) Valid added in v1.26.0

func (v DERPRegionView) Valid() bool

Valid reports whether underlying value is non-nil.

type DNSConfig added in v1.0.1

type DNSConfig struct {
	// Resolvers are the DNS resolvers to use, in order of preference.
	Resolvers []*dnstype.Resolver `json:",omitempty"`

	// Routes maps DNS name suffixes to a set of DNS resolvers to
	// use. It is used to implement "split DNS" and other advanced DNS
	// routing overlays.
	//
	// Map keys are fully-qualified DNS name suffixes; they may
	// optionally contain a trailing dot but no leading dot.
	//
	// If the value is an empty slice, that means the suffix should still
	// be handled by Tailscale's built-in resolver (100.100.100.100), such
	// as for the purpose of handling ExtraRecords.
	Routes map[string][]*dnstype.Resolver `json:",omitempty"`

	// FallbackResolvers is like Resolvers, but is only used if a
	// split DNS configuration is requested in a configuration that
	// doesn't work yet without explicit default resolvers.
	// https://github.com/tailscale/tailscale/issues/1743
	FallbackResolvers []*dnstype.Resolver `json:",omitempty"`
	// Domains are the search domains to use.
	// Search domains must be FQDNs, but *without* the trailing dot.
	Domains []string `json:",omitempty"`
	// Proxied turns on automatic resolution of hostnames for devices
	// in the network map, aka MagicDNS.
	// Despite the (legacy) name, does not necessarily cause request
	// proxying to be enabled.
	Proxied bool `json:",omitempty"`

	// Nameservers are the IP addresses of the nameservers to use.
	Nameservers []netip.Addr `json:",omitempty"`

	// CertDomains are the set of DNS names for which the control
	// plane server will assist with provisioning TLS
	// certificates. See SetDNSRequest, which can be used to
	// answer dns-01 ACME challenges for e.g. LetsEncrypt.
	// These names are FQDNs without trailing periods, and without
	// any "_acme-challenge." prefix.
	CertDomains []string `json:",omitempty"`

	// ExtraRecords contains extra DNS records to add to the
	// MagicDNS config.
	ExtraRecords []DNSRecord `json:",omitempty"`

	// ExitNodeFilteredSuffixes are the DNS suffixes that the
	// node, when being an exit node DNS proxy, should not answer.
	//
	// The entries do not contain trailing periods and are always
	// all lowercase.
	//
	// If an entry starts with a period, it's a suffix match (but
	// suffix ".a.b" doesn't match "a.b"; a prefix is required).
	//
	// If an entry does not start with a period, it's an exact
	// match.
	//
	// Matches are case insensitive.
	ExitNodeFilteredSet []string `json:",omitempty"`

	// TempCorpIssue13969 is a temporary (2023-08-16) field for an internal hack day prototype.
	// It contains a user inputed URL that should have a list of domains to be blocked.
	// See https://github.com/tailscale/corp/issues/13969.
	TempCorpIssue13969 string `json:",omitempty"`
}

DNSConfig is the DNS configuration.

func (*DNSConfig) Clone added in v1.2.0

func (src *DNSConfig) Clone() *DNSConfig

Clone makes a deep copy of DNSConfig. The result aliases no memory with the original.

func (*DNSConfig) View added in v1.26.0

func (p *DNSConfig) View() DNSConfigView

View returns a readonly view of DNSConfig.

type DNSConfigView added in v1.26.0

type DNSConfigView struct {
	// contains filtered or unexported fields
}

DNSConfigView provides a read-only view over DNSConfig.

Its methods should only be called if `Valid()` returns true.

func (DNSConfigView) AsStruct added in v1.26.0

func (v DNSConfigView) AsStruct() *DNSConfig

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (DNSConfigView) CertDomains added in v1.26.0

func (v DNSConfigView) CertDomains() views.Slice[string]

func (DNSConfigView) Domains added in v1.26.0

func (v DNSConfigView) Domains() views.Slice[string]

func (DNSConfigView) ExitNodeFilteredSet added in v1.26.0

func (v DNSConfigView) ExitNodeFilteredSet() views.Slice[string]

func (DNSConfigView) ExtraRecords added in v1.26.0

func (v DNSConfigView) ExtraRecords() views.Slice[DNSRecord]

func (DNSConfigView) FallbackResolvers added in v1.26.0

func (DNSConfigView) MarshalJSON added in v1.26.0

func (v DNSConfigView) MarshalJSON() ([]byte, error)

func (DNSConfigView) Nameservers added in v1.26.0

func (v DNSConfigView) Nameservers() views.Slice[netip.Addr]

func (DNSConfigView) Proxied added in v1.26.0

func (v DNSConfigView) Proxied() bool

func (DNSConfigView) Resolvers added in v1.26.0

func (DNSConfigView) Routes added in v1.26.0

func (DNSConfigView) TempCorpIssue13969 added in v1.50.0

func (v DNSConfigView) TempCorpIssue13969() string

func (*DNSConfigView) UnmarshalJSON added in v1.26.0

func (v *DNSConfigView) UnmarshalJSON(b []byte) error

func (DNSConfigView) Valid added in v1.26.0

func (v DNSConfigView) Valid() bool

Valid reports whether underlying value is non-nil.

type DNSRecord added in v1.10.0

type DNSRecord struct {
	// Name is the fully qualified domain name of
	// the record to add. The trailing dot is optional.
	Name string

	// Type is the DNS record type.
	// Empty means A or AAAA, depending on value.
	// Other values are currently ignored.
	Type string `json:",omitempty"`

	// Value is the IP address in string form.
	// TODO(bradfitz): if we ever add support for record types
	// with non-UTF8 binary data, add ValueBytes []byte that
	// would take precedence.
	Value string
}

DNSRecord is an extra DNS record to add to MagicDNS.

type Debug added in v0.98.1

type Debug struct {
	// SleepSeconds requests that the client sleep for the
	// provided number of seconds.
	// The client can (and should) limit the value (such as 5
	// minutes). This exists as a safety measure to slow down
	// spinning clients, in case we introduce a bug in the
	// state machine.
	SleepSeconds float64 `json:",omitempty"`

	// DisableLogTail disables the logtail package. Once disabled it can't be
	// re-enabled for the lifetime of the process.
	//
	// This is primarily used by Headscale.
	DisableLogTail bool `json:",omitempty"`

	// Exit optionally specifies that the client should os.Exit
	// with this code. This is a safety measure in case a client is crash
	// looping or in an unsafe state and we need to remotely shut it down.
	Exit *int `json:",omitempty"`
}

Debug used to be a miscellaneous set of declarative debug config changes and imperative debug commands. They've since been mostly migrated to node attributes (MapResponse.Node.Capabilities) for the declarative things and c2n requests for the imperative things. Not much remains here. Don't add more.

type EarlyNoise added in v1.34.0

type EarlyNoise struct {
	// NodeKeyChallenge is a random per-connection public key to be used by
	// the client to prove possession of a wireguard private key.
	NodeKeyChallenge key.ChallengePublic `json:"nodeKeyChallenge"`
}

EarlyNoise is the early payload that's sent over Noise but before the HTTP/2 handshake when connecting to the coordination server.

This exists to let the server push some early info to client for that stateful HTTP/2+Noise connection without incurring an extra round trip. (This would've used HTTP/2 server push, had Go's client-side APIs been available)

type Endpoint added in v1.8.0

type Endpoint struct {
	Addr netip.AddrPort
	Type EndpointType
}

Endpoint is an endpoint IPPort and an associated type. It doesn't currently go over the wire as is but is instead broken up into two parallel slices in MapRequest, for compatibility reasons. But this type is used in the codebase.

type EndpointType added in v1.8.0

type EndpointType int

EndpointType distinguishes different sources of MapRequest.Endpoint values.

func (EndpointType) String added in v1.8.0

func (et EndpointType) String() string

type FilterRule added in v0.98.1

type FilterRule struct {
	// SrcIPs are the source IPs/networks to match.
	//
	// It may take the following forms:
	//     * an IP address (IPv4 or IPv6)
	//     * the string "*" to match everything (both IPv4 & IPv6)
	//     * a CIDR (e.g. "192.168.0.0/16")
	//     * a range of two IPs, inclusive, separated by hyphen ("2eff::1-2eff::0800")
	//     * a string "cap:<capability>" with NodeCapMap cap name
	SrcIPs []string

	// SrcBits is deprecated; it was the old way to specify a CIDR
	// prior to CapabilityVersion 7. Its values correspond to the
	// SrcIPs above.
	//
	// If an entry of SrcBits is present for the same index as a
	// SrcIPs entry, it changes the SrcIP above to be a network
	// with /n CIDR bits. If the slice is nil or insufficiently
	// long, the default value (for an IPv4 address) for a
	// position is 32, as if the SrcIPs above were a /32 mask. For
	// a "*" SrcIPs value, the corresponding SrcBits value is
	// ignored.
	//
	// This is still present in this file because the Tailscale control plane
	// code still uses this type, for 118 clients that are still connected as of
	// 2024-06-18, 3.5 years after the last release that used this type.
	SrcBits []int `json:",omitempty"`

	// DstPorts are the port ranges to allow once a source IP
	// matches (is in the CIDR described by SrcIPs).
	//
	// CapGrant and DstPorts are mutually exclusive: at most one can be non-nil.
	DstPorts []NetPortRange `json:",omitempty"`

	// IPProto are the IP protocol numbers to match.
	//
	// As a special case, nil or empty means TCP, UDP, and ICMP.
	//
	// Numbers outside the uint8 range (below 0 or above 255) are
	// reserved for Tailscale's use. Unknown ones are ignored.
	//
	// Depending on the IPProto values, DstPorts may or may not be
	// used.
	IPProto []int `json:",omitempty"`

	// CapGrant, if non-empty, are the capabilities to
	// conditionally grant to the source IP in SrcIPs.
	//
	// Think of DstPorts as "capabilities for networking" and
	// CapGrant as arbitrary application-defined capabilities
	// defined between the admin's ACLs and the application
	// doing WhoIs lookups, looking up the remote IP address's
	// application-level capabilities.
	//
	// CapGrant and DstPorts are mutually exclusive: at most one can be non-nil.
	CapGrant []CapGrant `json:",omitempty"`
}

FilterRule represents one rule in a packet filter.

A rule is logically a set of source CIDRs to match (described by SrcIPs), and a set of destination targets that are then allowed if a source IP is matches of those CIDRs.

type HealthChangeRequest added in v1.32.0

type HealthChangeRequest struct {
	Subsys string // a health.Subsystem value in string form
	Error  string // or empty if cleared

	// NodeKey is the client's current node key.
	// In clients <= 1.62.0 it was always the zero value.
	NodeKey key.NodePublic
}

HealthChangeRequest is the JSON request body type used to report node health changes to https://<control>/machine/<mkey hex>/update-health.

type Hostinfo

type Hostinfo struct {
	IPNVersion    string `json:",omitempty"` // version of this code (in version.Long format)
	FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance
	BackendLogID  string `json:",omitempty"` // logtail ID of backend instance
	OS            string `json:",omitempty"` // operating system the client runs on (a version.OS value)

	// OSVersion is the version of the OS, if available.
	//
	// For Android, it's like "10", "11", "12", etc. For iOS and macOS it's like
	// "15.6.1" or "12.4.0". For Windows it's like "10.0.19044.1889". For
	// FreeBSD it's like "12.3-STABLE".
	//
	// For Linux, prior to Tailscale 1.32, we jammed a bunch of fields into this
	// string on Linux, like "Debian 10.4; kernel=xxx; container; env=kn" and so
	// on. As of Tailscale 1.32, this is simply the kernel version on Linux, like
	// "5.10.0-17-amd64".
	OSVersion string `json:",omitempty"`

	Container      opt.Bool `json:",omitempty"` // best-effort whether the client is running in a container
	Env            string   `json:",omitempty"` // a hostinfo.EnvType in string form
	Distro         string   `json:",omitempty"` // "debian", "ubuntu", "nixos", ...
	DistroVersion  string   `json:",omitempty"` // "20.04", ...
	DistroCodeName string   `json:",omitempty"` // "jammy", "bullseye", ...

	// App is used to disambiguate Tailscale clients that run using tsnet.
	App string `json:",omitempty"` // "k8s-operator", "golinks", ...

	Desktop         opt.Bool       `json:",omitempty"` // if a desktop was detected on Linux
	Package         string         `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown)
	DeviceModel     string         `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3")
	PushDeviceToken string         `json:",omitempty"` // macOS/iOS APNs device token for notifications (and Android in the future)
	Hostname        string         `json:",omitempty"` // name of the host the client runs on
	ShieldsUp       bool           `json:",omitempty"` // indicates whether the host is blocking incoming connections
	ShareeNode      bool           `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user
	NoLogsNoSupport bool           `json:",omitempty"` // indicates that the user has opted out of sending logs and support
	WireIngress     bool           `json:",omitempty"` // indicates that the node wants the option to receive ingress connections
	AllowsUpdate    bool           `json:",omitempty"` // indicates that the node has opted-in to admin-console-drive remote updates
	Machine         string         `json:",omitempty"` // the current host's machine type (uname -m)
	GoArch          string         `json:",omitempty"` // GOARCH value (of the built binary)
	GoArchVar       string         `json:",omitempty"` // GOARM, GOAMD64, etc (of the built binary)
	GoVersion       string         `json:",omitempty"` // Go version binary was built with
	RoutableIPs     []netip.Prefix `json:",omitempty"` // set of IP ranges this client can route
	RequestTags     []string       `json:",omitempty"` // set of ACL tags this node wants to claim
	WoLMACs         []string       `json:",omitempty"` // MAC address(es) to send Wake-on-LAN packets to wake this node (lowercase hex w/ colons)
	Services        []Service      `json:",omitempty"` // services advertised by this machine
	NetInfo         *NetInfo       `json:",omitempty"`
	SSH_HostKeys    []string       `json:"sshHostKeys,omitempty"` // if advertised
	Cloud           string         `json:",omitempty"`
	Userspace       opt.Bool       `json:",omitempty"` // if the client is running in userspace (netstack) mode
	UserspaceRouter opt.Bool       `json:",omitempty"` // if the client's subnet router is running in userspace (netstack) mode
	AppConnector    opt.Bool       `json:",omitempty"` // if the client is running the app-connector service
	ServicesHash    string         `json:",omitempty"` // opaque hash of the most recent list of tailnet services, change in hash indicates config should be fetched via c2n

	// Location represents geographical location data about a
	// Tailscale host. Location is optional and only set if
	// explicitly declared by a node.
	Location *Location `json:",omitempty"`
}

Hostinfo contains a summary of a Tailscale host.

Because it contains pointers (slices), this type should not be used as a value type.

func (*Hostinfo) CheckRequestTags added in v1.4.0

func (h *Hostinfo) CheckRequestTags() error

CheckRequestTags checks that all of h.RequestTags are valid.

func (*Hostinfo) Clone

func (src *Hostinfo) Clone() *Hostinfo

Clone makes a deep copy of Hostinfo. The result aliases no memory with the original.

func (*Hostinfo) Equal

func (h *Hostinfo) Equal(h2 *Hostinfo) bool

Equal reports whether h and h2 are equal.

func (*Hostinfo) HowUnequal added in v1.20.0

func (h *Hostinfo) HowUnequal(h2 *Hostinfo) (path []string)

HowUnequal returns a list of paths through Hostinfo where h and h2 differ. If they differ in nil-ness, the path is "nil", otherwise the path is like "ShieldsUp" or "NetInfo.nil" or "NetInfo.PCP".

func (*Hostinfo) TailscaleFunnelEnabled added in v1.34.0

func (hi *Hostinfo) TailscaleFunnelEnabled() bool

TailscaleFunnelEnabled reports whether or not this node has explicitly enabled Funnel.

func (*Hostinfo) TailscaleSSHEnabled added in v1.28.0

func (hi *Hostinfo) TailscaleSSHEnabled() bool

TailscaleSSHEnabled reports whether or not this node is acting as a Tailscale SSH server.

func (*Hostinfo) View added in v1.22.0

func (p *Hostinfo) View() HostinfoView

View returns a readonly view of Hostinfo.

type HostinfoView added in v1.22.0

type HostinfoView struct {
	// contains filtered or unexported fields
}

HostinfoView provides a read-only view over Hostinfo.

Its methods should only be called if `Valid()` returns true.

func (HostinfoView) AllowsUpdate added in v1.36.0

func (v HostinfoView) AllowsUpdate() bool

func (HostinfoView) App added in v1.38.0

func (v HostinfoView) App() string

func (HostinfoView) AppConnector added in v1.54.0

func (v HostinfoView) AppConnector() opt.Bool

func (HostinfoView) AsStruct added in v1.22.0

func (v HostinfoView) AsStruct() *Hostinfo

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (HostinfoView) BackendLogID added in v1.22.0

func (v HostinfoView) BackendLogID() string

func (HostinfoView) Cloud added in v1.28.0

func (v HostinfoView) Cloud() string

func (HostinfoView) Container added in v1.32.0

func (v HostinfoView) Container() opt.Bool

func (HostinfoView) Desktop added in v1.26.0

func (v HostinfoView) Desktop() opt.Bool

func (HostinfoView) DeviceModel added in v1.22.0

func (v HostinfoView) DeviceModel() string

func (HostinfoView) Distro added in v1.32.0

func (v HostinfoView) Distro() string

func (HostinfoView) DistroCodeName added in v1.32.0

func (v HostinfoView) DistroCodeName() string

func (HostinfoView) DistroVersion added in v1.32.0

func (v HostinfoView) DistroVersion() string

func (HostinfoView) Env added in v1.32.0

func (v HostinfoView) Env() string

func (HostinfoView) Equal added in v1.22.0

func (v HostinfoView) Equal(v2 HostinfoView) bool

func (HostinfoView) FrontendLogID added in v1.22.0

func (v HostinfoView) FrontendLogID() string

func (HostinfoView) GoArch added in v1.22.0

func (v HostinfoView) GoArch() string

func (HostinfoView) GoArchVar added in v1.36.0

func (v HostinfoView) GoArchVar() string

func (HostinfoView) GoVersion added in v1.30.0

func (v HostinfoView) GoVersion() string

func (HostinfoView) Hostname added in v1.22.0

func (v HostinfoView) Hostname() string

func (HostinfoView) IPNVersion added in v1.22.0

func (v HostinfoView) IPNVersion() string

func (HostinfoView) Location added in v1.46.0

func (v HostinfoView) Location() *Location

func (HostinfoView) Machine added in v1.36.0

func (v HostinfoView) Machine() string

func (HostinfoView) MarshalJSON added in v1.22.0

func (v HostinfoView) MarshalJSON() ([]byte, error)

func (HostinfoView) NetInfo added in v1.22.0

func (v HostinfoView) NetInfo() NetInfoView

func (HostinfoView) NoLogsNoSupport added in v1.32.0

func (v HostinfoView) NoLogsNoSupport() bool

func (HostinfoView) OS added in v1.22.0

func (v HostinfoView) OS() string

func (HostinfoView) OSVersion added in v1.22.0

func (v HostinfoView) OSVersion() string

func (HostinfoView) Package added in v1.22.0

func (v HostinfoView) Package() string

func (HostinfoView) PushDeviceToken added in v1.38.0

func (v HostinfoView) PushDeviceToken() string

func (HostinfoView) RequestTags added in v1.22.0

func (v HostinfoView) RequestTags() views.Slice[string]

func (HostinfoView) RoutableIPs added in v1.22.0

func (v HostinfoView) RoutableIPs() views.Slice[netip.Prefix]

func (HostinfoView) SSH_HostKeys added in v1.22.0

func (v HostinfoView) SSH_HostKeys() views.Slice[string]

func (HostinfoView) Services added in v1.22.0

func (v HostinfoView) Services() views.Slice[Service]

func (HostinfoView) ServicesHash added in v1.78.0

func (v HostinfoView) ServicesHash() string

func (HostinfoView) ShareeNode added in v1.22.0

func (v HostinfoView) ShareeNode() bool

func (HostinfoView) ShieldsUp added in v1.22.0

func (v HostinfoView) ShieldsUp() bool

func (HostinfoView) TailscaleFunnelEnabled added in v1.34.0

func (v HostinfoView) TailscaleFunnelEnabled() bool

func (HostinfoView) TailscaleSSHEnabled added in v1.28.0

func (v HostinfoView) TailscaleSSHEnabled() bool

func (*HostinfoView) UnmarshalJSON added in v1.22.0

func (v *HostinfoView) UnmarshalJSON(b []byte) error

func (HostinfoView) Userspace added in v1.30.0

func (v HostinfoView) Userspace() opt.Bool

func (HostinfoView) UserspaceRouter added in v1.30.0

func (v HostinfoView) UserspaceRouter() opt.Bool

func (HostinfoView) Valid added in v1.22.0

func (v HostinfoView) Valid() bool

Valid reports whether underlying value is non-nil.

func (HostinfoView) WireIngress added in v1.34.0

func (v HostinfoView) WireIngress() bool

func (HostinfoView) WoLMACs added in v1.52.0

func (v HostinfoView) WoLMACs() views.Slice[string]

type ID

type ID int64

func (ID) String

func (id ID) String() string

type Location added in v1.46.0

type Location struct {
	Country     string `json:",omitempty"` // User friendly country name, with proper capitalization ("Canada")
	CountryCode string `json:",omitempty"` // ISO 3166-1 alpha-2 in upper case ("CA")
	City        string `json:",omitempty"` // User friendly city name, with proper capitalization ("Squamish")

	// CityCode is a short code representing the city in upper case.
	// CityCode is used to disambiguate a city from another location
	// with the same city name. It uniquely identifies a particular
	// geographical location, within the tailnet.
	// IATA, ICAO or ISO 3166-2 codes are recommended ("YSE")
	CityCode string `json:",omitempty"`

	// Latitude, Longitude are optional geographical coordinates of the node, in degrees.
	// No particular accuracy level is promised; the coordinates may simply be the center of the city or country.
	Latitude  float64 `json:",omitempty"`
	Longitude float64 `json:",omitempty"`

	// Priority determines the order of use of an exit node when a
	// location based preference matches more than one exit node,
	// the node with the highest priority wins. Nodes of equal
	// probability may be selected arbitrarily.
	//
	// A value of 0 means the exit node does not have a priority
	// preference. A negative int is not allowed.
	Priority int `json:",omitempty"`
}

Location represents geographical location data about a Tailscale host. Location is optional and only set if explicitly declared by a node.

func (*Location) Clone added in v1.46.0

func (src *Location) Clone() *Location

Clone makes a deep copy of Location. The result aliases no memory with the original.

func (*Location) View added in v1.46.0

func (p *Location) View() LocationView

View returns a readonly view of Location.

type LocationView added in v1.46.0

type LocationView struct {
	// contains filtered or unexported fields
}

LocationView provides a read-only view over Location.

Its methods should only be called if `Valid()` returns true.

func (LocationView) AsStruct added in v1.46.0

func (v LocationView) AsStruct() *Location

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (LocationView) City added in v1.46.0

func (v LocationView) City() string

func (LocationView) CityCode added in v1.46.0

func (v LocationView) CityCode() string

func (LocationView) Country added in v1.46.0

func (v LocationView) Country() string

func (LocationView) CountryCode added in v1.46.0

func (v LocationView) CountryCode() string

func (LocationView) Latitude added in v1.62.0

func (v LocationView) Latitude() float64

func (LocationView) Longitude added in v1.62.0

func (v LocationView) Longitude() float64

func (LocationView) MarshalJSON added in v1.46.0

func (v LocationView) MarshalJSON() ([]byte, error)

func (LocationView) Priority added in v1.46.0

func (v LocationView) Priority() int

func (*LocationView) UnmarshalJSON added in v1.46.0

func (v *LocationView) UnmarshalJSON(b []byte) error

func (LocationView) Valid added in v1.46.0

func (v LocationView) Valid() bool

Valid reports whether underlying value is non-nil.

type Login

type Login struct {
	ID            LoginID
	Provider      string
	LoginName     string
	DisplayName   string
	ProfilePicURL string
	// contains filtered or unexported fields
}

func (*Login) Clone added in v1.2.0

func (src *Login) Clone() *Login

Clone makes a deep copy of Login. The result aliases no memory with the original.

func (*Login) View added in v1.26.0

func (p *Login) View() LoginView

View returns a readonly view of Login.

type LoginID

type LoginID ID

func (LoginID) IsZero added in v1.2.0

func (u LoginID) IsZero() bool

func (LoginID) String

func (id LoginID) String() string

type LoginView added in v1.26.0

type LoginView struct {
	// contains filtered or unexported fields
}

LoginView provides a read-only view over Login.

Its methods should only be called if `Valid()` returns true.

func (LoginView) AsStruct added in v1.26.0

func (v LoginView) AsStruct() *Login

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (LoginView) DisplayName added in v1.26.0

func (v LoginView) DisplayName() string

func (LoginView) ID added in v1.26.0

func (v LoginView) ID() LoginID

func (LoginView) LoginName added in v1.26.0

func (v LoginView) LoginName() string

func (LoginView) MarshalJSON added in v1.26.0

func (v LoginView) MarshalJSON() ([]byte, error)

func (LoginView) ProfilePicURL added in v1.26.0

func (v LoginView) ProfilePicURL() string

func (LoginView) Provider added in v1.26.0

func (v LoginView) Provider() string

func (*LoginView) UnmarshalJSON added in v1.26.0

func (v *LoginView) UnmarshalJSON(b []byte) error

func (LoginView) Valid added in v1.26.0

func (v LoginView) Valid() bool

Valid reports whether underlying value is non-nil.

type MachineStatus

type MachineStatus int

func (MachineStatus) AppendText added in v1.50.0

func (m MachineStatus) AppendText(b []byte) ([]byte, error)

func (MachineStatus) MarshalText

func (m MachineStatus) MarshalText() ([]byte, error)

func (MachineStatus) String

func (m MachineStatus) String() string

func (*MachineStatus) UnmarshalText

func (m *MachineStatus) UnmarshalText(b []byte) error

type MapRequest

type MapRequest struct {
	// Version is incremented whenever the client code changes enough that
	// we want to signal to the control server that we're capable of something
	// different.
	//
	// For current values and history, see the CapabilityVersion type's docs.
	Version CapabilityVersion

	Compress  string // "zstd" or "" (no compression)
	KeepAlive bool   // whether server should send keep-alives back to us
	NodeKey   key.NodePublic
	DiscoKey  key.DiscoPublic

	// Stream is whether the client wants to receive multiple MapResponses over
	// the same HTTP connection.
	//
	// If false, the server will send a single MapResponse and then close the
	// connection.
	//
	// If true and Version >= 68, the server should treat this as a read-only
	// request and ignore any Hostinfo or other fields that might be set.
	Stream bool

	// Hostinfo is the client's current Hostinfo. Although it is always included
	// in the request, the server may choose to ignore it when Stream is true
	// and Version >= 68.
	Hostinfo *Hostinfo

	// MapSessionHandle, if non-empty, is a request to reattach to a previous
	// map session after a previous map session was interrupted for whatever
	// reason. Its value is an opaque string as returned by
	// MapResponse.MapSessionHandle.
	//
	// When set, the client must also send MapSessionSeq to specify the last
	// processed message in that prior session.
	//
	// The server may choose to ignore the request for any reason and start a
	// new map session. This is only applicable when Stream is true.
	MapSessionHandle string `json:",omitempty"`

	// MapSessionSeq is the sequence number in the map session identified by
	// MapSesssionHandle that was most recently processed by the client.
	// It is only applicable when MapSessionHandle is specified.
	// If the server chooses to honor the MapSessionHandle request, only sequence
	// numbers greater than this value will be returned.
	MapSessionSeq int64 `json:",omitempty"`

	// Endpoints are the client's magicsock UDP ip:port endpoints (IPv4 or IPv6).
	// These can be ignored if Stream is true and Version >= 68.
	Endpoints []netip.AddrPort `json:",omitempty"`
	// EndpointTypes are the types of the corresponding endpoints in Endpoints.
	EndpointTypes []EndpointType `json:",omitempty"`

	// TKAHead describes the hash of the latest AUM applied to the local
	// tailnet key authority, if one is operating.
	// It is encoded as tka.AUMHash.MarshalText.
	TKAHead string `json:",omitempty"`

	// ReadOnly was set when client just wanted to fetch the MapResponse,
	// without updating their Endpoints. The intended use was for clients to
	// discover the DERP map at start-up before their first real endpoint
	// update.
	//
	// Deprecated: always false as of Version 68.
	ReadOnly bool `json:",omitempty"`

	// OmitPeers is whether the client is okay with the Peers list being omitted
	// in the response.
	//
	// The behavior of OmitPeers being true varies based on Stream and ReadOnly:
	//
	// If OmitPeers is true, Stream is false, and ReadOnly is false,
	// then the server will let clients update their endpoints without
	// breaking existing long-polling (Stream == true) connections.
	// In this case, the server can omit the entire response; the client
	// only checks the HTTP response status code.
	//
	// If OmitPeers is true, Stream is false, but ReadOnly is true,
	// then all the response fields are included. (This is what the client does
	// when initially fetching the DERP map.)
	OmitPeers bool `json:",omitempty"`

	// DebugFlags is a list of strings specifying debugging and
	// development features to enable in handling this map
	// request. The values are deliberately unspecified, as they get
	// added and removed all the time during development, and offer no
	// compatibility promise. To roll out semantic changes, bump
	// Version instead.
	//
	// Current DebugFlags values are:
	//     * "warn-ip-forwarding-off": client is trying to be a subnet
	//       router but their IP forwarding is broken.
	//     * "warn-router-unhealthy": client's Router implementation is
	//       having problems.
	DebugFlags []string `json:",omitempty"`
}

MapRequest is sent by a client to either update the control plane about its current state, or to start a long-poll of network map updates.

The request includes a copy of the client's current set of WireGuard endpoints and general host information.

The request is encoded to JSON, encrypted with golang.org/x/crypto/nacl/box, using the local machine key, and sent to:

https://login.tailscale.com/machine/<mkey hex>/map

type MapResponse

type MapResponse struct {
	// MapSessionHandle optionally specifies a unique opaque handle for this
	// stateful MapResponse session. Servers may choose not to send it, and it's
	// only sent on the first MapResponse in a stream. The client can determine
	// whether it's reattaching to a prior stream by seeing whether this value
	// matches the requested MapRequest.MapSessionHandle.
	MapSessionHandle string `json:",omitempty"`

	// Seq is a sequence number within a named map session (a response where the
	// first message contains a MapSessionHandle). The Seq number may be omitted
	// on responses that don't change the state of the stream, such as KeepAlive
	// or certain types of PingRequests. This is the value to be sent in
	// MapRequest.MapSessionSeq to resume after this message.
	Seq int64 `json:",omitempty"`

	// KeepAlive, if set, represents an empty message just to keep
	// the connection alive. When true, all other fields except
	// PingRequest, ControlTime, and PopBrowserURL are ignored.
	KeepAlive bool `json:",omitempty"`

	// PingRequest, if non-empty, is a request to the client to
	// prove it's still there by sending an HTTP request to the
	// provided URL. No auth headers are necessary.
	// PingRequest may be sent on any MapResponse (ones with
	// KeepAlive true or false).
	PingRequest *PingRequest `json:",omitempty"`

	// PopBrowserURL, if non-empty, is a URL for the client to
	// open to complete an action. The client should dup suppress
	// identical URLs and only open it once for the same URL.
	PopBrowserURL string `json:",omitempty"`

	// Node describes the node making the map request.
	// Starting with MapRequest.Version 18, nil means unchanged.
	Node *Node `json:",omitempty"`

	// DERPMap describe the set of DERP servers available.
	// A nil value means unchanged.
	DERPMap *DERPMap `json:",omitempty"`

	// Peers, if non-empty, is the complete list of peers.
	// It will be set in the first MapResponse for a long-polled request/response.
	// Subsequent responses will be delta-encoded if MapRequest.Version >= 5 and server
	// chooses, in which case Peers will be nil or zero length.
	// If Peers is non-empty, PeersChanged and PeersRemoved should
	// be ignored (and should be empty).
	// Peers is always returned sorted by Node.ID.
	Peers []*Node `json:",omitempty"`
	// PeersChanged are the Nodes (identified by their ID) that
	// have changed or been added since the past update on the
	// HTTP response. It's not used by the server if MapRequest.Version < 5.
	// PeersChanged is always returned sorted by Node.ID.
	PeersChanged []*Node `json:",omitempty"`
	// PeersRemoved are the NodeIDs that are no longer in the peer list.
	PeersRemoved []NodeID `json:",omitempty"`

	// PeersChangedPatch, if non-nil, means that node(s) have changed.
	// This is a lighter version of the older PeersChanged support that
	// only supports certain types of updates
	//
	// These are applied after Peers* above, but in practice the
	// control server should only send these on their own, without
	// the Peers* fields also set.
	PeersChangedPatch []*PeerChange `json:",omitempty"`

	// PeerSeenChange contains information on how to update peers' LastSeen
	// times. If the value is false, the peer is gone. If the value is true,
	// the LastSeen time is now. Absent means unchanged.
	PeerSeenChange map[NodeID]bool `json:",omitempty"`

	// OnlineChange changes the value of a Peer Node.Online value.
	OnlineChange map[NodeID]bool `json:",omitempty"`

	// DNSConfig contains the DNS settings for the client to use.
	// A nil value means no change from an earlier non-nil value.
	DNSConfig *DNSConfig `json:",omitempty"`

	// Domain is the name of the network that this node is
	// in. It's either of the form "example.com" (for user
	// foo@example.com, for multi-user networks) or
	// "foo@gmail.com" (for siloed users on shared email
	// providers). Its exact form should not be depended on; new
	// forms are coming later.
	// If empty, the value is unchanged.
	Domain string `json:",omitempty"`

	// CollectServices reports whether this node's Tailnet has
	// requested that info about services be included in HostInfo.
	// If unset, the most recent non-empty MapResponse value in
	// the HTTP response stream is used.
	CollectServices opt.Bool `json:",omitempty"`

	// PacketFilter are the firewall rules.
	//
	// For MapRequest.Version >= 6, a nil value means the most
	// previously streamed non-nil MapResponse.PacketFilter within
	// the same HTTP response. A non-nil but empty list always means
	// no PacketFilter (that is, to block everything).
	//
	// Note that this package's type, due its use of a slice and omitempty, is
	// unable to marshal a zero-length non-nil slice. The control server needs
	// to marshal this type using a separate type. See MapResponse docs.
	//
	// See PacketFilters for the newer way to send PacketFilter updates.
	PacketFilter []FilterRule `json:",omitempty"`

	// PacketFilters encodes incremental packet filter updates to the client
	// without having to send the entire packet filter on any changes as
	// required by the older PacketFilter (singular) field above. The map keys
	// are server-assigned arbitrary strings. The map values are the new rules
	// for that key, or nil to delete it. The client then concatenates all the
	// rules together to generate the final packet filter. Because the
	// FilterRules can only match or not match, the ordering of filter rules
	// doesn't matter. (That said, the client generates the file merged packet
	// filter rules by concananting all the packet filter rules sorted by the
	// map key name. But it does so for stability and testability, not
	// correctness. If something needs to rely on that property, something has
	// gone wrong.)
	//
	// If the server sends a non-nil PacketFilter (above), that is equivalent to
	// a named packet filter with the key "base". It is valid for the server to
	// send both PacketFilter and PacketFilters in the same MapResponse or
	// alternate between them within a session. The PacketFilter is applied
	// first (if set) and then the PacketFilters.
	//
	// As a special case, the map key "*" with a value of nil means to clear all
	// prior named packet filters (including any implicit "base") before
	// processing the other map entries.
	PacketFilters map[string][]FilterRule `json:",omitempty"`

	// UserProfiles are the user profiles of nodes in the network.
	// As as of 1.1.541 (mapver 5), this contains new or updated
	// user profiles only.
	UserProfiles []UserProfile `json:",omitempty"`

	// Health, if non-nil, sets the health state of the node from the control
	// plane's perspective. A nil value means no change from the previous
	// MapResponse. A non-nil 0-length slice restores the health to good (no
	// known problems). A non-zero length slice are the list of problems that
	// the control place sees.
	//
	// Note that this package's type, due its use of a slice and omitempty, is
	// unable to marshal a zero-length non-nil slice. The control server needs
	// to marshal this type using a separate type. See MapResponse docs.
	Health []string `json:",omitempty"`

	// SSHPolicy, if non-nil, updates the SSH policy for how incoming
	// SSH connections should be handled.
	SSHPolicy *SSHPolicy `json:",omitempty"`

	// ControlTime, if non-zero, is the current timestamp according to the control server.
	ControlTime *time.Time `json:",omitempty"`

	// TKAInfo describes the control plane's view of tailnet
	// key authority (TKA) state.
	//
	// An initial nil TKAInfo indicates that the control plane
	// believes TKA should not be enabled. An initial non-nil TKAInfo
	// indicates the control plane believes TKA should be enabled.
	// A nil TKAInfo in a mapresponse stream (i.e. a 'delta' mapresponse)
	// indicates no change from the value sent earlier.
	TKAInfo *TKAInfo `json:",omitempty"`

	// DomainDataPlaneAuditLogID, if non-empty, is the per-tailnet log ID to be
	// used when writing data plane audit logs.
	DomainDataPlaneAuditLogID string `json:",omitempty"`

	// Debug is normally nil, except for when the control server
	// is setting debug settings on a node.
	Debug *Debug `json:",omitempty"`

	// ControlDialPlan tells the client how to connect to the control
	// server. An initial nil is equivalent to new(ControlDialPlan).
	// A subsequent streamed nil means no change.
	ControlDialPlan *ControlDialPlan `json:",omitempty"`

	// ClientVersion describes the latest client version that's available for
	// download and whether the client is using it. A nil value means no change
	// or nothing to report.
	ClientVersion *ClientVersion `json:",omitempty"`

	// DefaultAutoUpdate is the default node auto-update setting for this
	// tailnet. The node is free to opt-in or out locally regardless of this
	// value. This value is only used on first MapResponse from control, the
	// auto-update setting doesn't change if the tailnet admin flips the
	// default after the node registered.
	DefaultAutoUpdate opt.Bool `json:",omitempty"`

	// MaxKeyDuration describes the MaxKeyDuration setting for the tailnet.
	// If zero, the value is unchanged.
	MaxKeyDuration time.Duration `json:",omitempty"`
}

MapResponse is the response to a MapRequest. It describes the state of the local node, the peer nodes, the DNS configuration, the packet filter, and more. A MapRequest, depending on its parameters, may result in the control plane coordination server sending 0, 1 or a stream of multiple MapResponse values.

When the client sets MapRequest.Stream, the server sends a stream of MapResponses. That long-lived HTTP transaction is called a "map poll". In a map poll, the first MapResponse will be complete and subsequent MapResponses will be incremental updates with only changed information.

The zero value for all fields means "unchanged". Unfortunately, several fields were defined before that convention was established, so they use a slice with omitempty, meaning this type can't be used to marshal JSON containing non-nil zero-length slices (meaning explicitly now empty). The control plane uses a separate type to marshal these fields. This type is primarily used for unmarshaling responses so the omitempty annotations are mostly useless, except that this type is also used for the integration test's fake control server. (It's not necessary to marshal a non-nil zero-length slice for the things we've needed to test in the integration tests as of 2023-09-09).

type NetInfo

type NetInfo struct {
	// MappingVariesByDestIP says whether the host's NAT mappings
	// vary based on the destination IP.
	MappingVariesByDestIP opt.Bool

	// HairPinning is their router does hairpinning.
	// It reports true even if there's no NAT involved.
	HairPinning opt.Bool

	// WorkingIPv6 is whether the host has IPv6 internet connectivity.
	WorkingIPv6 opt.Bool

	// OSHasIPv6 is whether the OS supports IPv6 at all, regardless of
	// whether IPv6 internet connectivity is available.
	OSHasIPv6 opt.Bool

	// WorkingUDP is whether the host has UDP internet connectivity.
	WorkingUDP opt.Bool

	// WorkingICMPv4 is whether ICMPv4 works.
	// Empty means not checked.
	WorkingICMPv4 opt.Bool

	// HavePortMap is whether we have an existing portmap open
	// (UPnP, PMP, or PCP).
	HavePortMap bool `json:",omitempty"`

	// UPnP is whether UPnP appears present on the LAN.
	// Empty means not checked.
	UPnP opt.Bool

	// PMP is whether NAT-PMP appears present on the LAN.
	// Empty means not checked.
	PMP opt.Bool

	// PCP is whether PCP appears present on the LAN.
	// Empty means not checked.
	PCP opt.Bool

	// PreferredDERP is this node's preferred (home) DERP region ID.
	// This is where the node expects to be contacted to begin a
	// peer-to-peer connection. The node might be be temporarily
	// connected to multiple DERP servers (to speak to other nodes
	// that are located elsewhere) but PreferredDERP is the region ID
	// that the node subscribes to traffic at.
	// Zero means disconnected or unknown.
	PreferredDERP int

	// LinkType is the current link type, if known.
	LinkType string `json:",omitempty"` // "wired", "wifi", "mobile" (LTE, 4G, 3G, etc)

	// DERPLatency is the fastest recent time to reach various
	// DERP STUN servers, in seconds. The map key is the
	// "regionID-v4" or "-v6"; it was previously the DERP server's
	// STUN host:port.
	//
	// This should only be updated rarely, or when there's a
	// material change, as any change here also gets uploaded to
	// the control plane.
	DERPLatency map[string]float64 `json:",omitempty"`

	// FirewallMode encodes both which firewall mode was selected and why.
	// It is Linux-specific (at least as of 2023-08-19) and is meant to help
	// debug iptables-vs-nftables issues. The string is of the form
	// "{nft,ift}-REASON", like "nft-forced" or "ipt-default". Empty means
	// either not Linux or a configuration in which the host firewall rules
	// are not managed by tailscaled.
	FirewallMode string `json:",omitempty"`
}

NetInfo contains information about the host's network state.

func (*NetInfo) BasicallyEqual

func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool

BasicallyEqual reports whether ni and ni2 are basically equal, ignoring changes in DERP ServerLatency & RegionLatency.

func (*NetInfo) Clone

func (src *NetInfo) Clone() *NetInfo

Clone makes a deep copy of NetInfo. The result aliases no memory with the original.

func (*NetInfo) String

func (ni *NetInfo) String() string

func (*NetInfo) View added in v1.22.0

func (p *NetInfo) View() NetInfoView

View returns a readonly view of NetInfo.

type NetInfoView added in v1.22.0

type NetInfoView struct {
	// contains filtered or unexported fields
}

NetInfoView provides a read-only view over NetInfo.

Its methods should only be called if `Valid()` returns true.

func (NetInfoView) AsStruct added in v1.22.0

func (v NetInfoView) AsStruct() *NetInfo

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (NetInfoView) DERPLatency added in v1.26.0

func (v NetInfoView) DERPLatency() views.Map[string, float64]

func (NetInfoView) FirewallMode added in v1.48.0

func (v NetInfoView) FirewallMode() string

func (NetInfoView) HairPinning added in v1.22.0

func (v NetInfoView) HairPinning() opt.Bool

func (NetInfoView) HavePortMap added in v1.22.0

func (v NetInfoView) HavePortMap() bool

func (NetInfoView) LinkType added in v1.22.0

func (v NetInfoView) LinkType() string

func (NetInfoView) MappingVariesByDestIP added in v1.22.0

func (v NetInfoView) MappingVariesByDestIP() opt.Bool

func (NetInfoView) MarshalJSON added in v1.26.0

func (v NetInfoView) MarshalJSON() ([]byte, error)

func (NetInfoView) OSHasIPv6 added in v1.30.0

func (v NetInfoView) OSHasIPv6() opt.Bool

func (NetInfoView) PCP added in v1.22.0

func (v NetInfoView) PCP() opt.Bool

func (NetInfoView) PMP added in v1.22.0

func (v NetInfoView) PMP() opt.Bool

func (NetInfoView) PreferredDERP added in v1.22.0

func (v NetInfoView) PreferredDERP() int

func (NetInfoView) String added in v1.22.0

func (v NetInfoView) String() string

func (NetInfoView) UPnP added in v1.22.0

func (v NetInfoView) UPnP() opt.Bool

func (*NetInfoView) UnmarshalJSON added in v1.26.0

func (v *NetInfoView) UnmarshalJSON(b []byte) error

func (NetInfoView) Valid added in v1.22.0

func (v NetInfoView) Valid() bool

Valid reports whether underlying value is non-nil.

func (NetInfoView) WorkingICMPv4 added in v1.30.0

func (v NetInfoView) WorkingICMPv4() opt.Bool

func (NetInfoView) WorkingIPv6 added in v1.22.0

func (v NetInfoView) WorkingIPv6() opt.Bool

func (NetInfoView) WorkingUDP added in v1.22.0

func (v NetInfoView) WorkingUDP() opt.Bool

type NetPortRange added in v0.98.1

type NetPortRange struct {
	IP    string // IP, CIDR, Range, or "*" (same formats as FilterRule.SrcIPs)
	Bits  *int   // deprecated; the 2020 way to turn IP into a CIDR. See FilterRule.SrcBits.
	Ports PortRange
	// contains filtered or unexported fields
}

NetPortRange represents a range of ports that's allowed for one or more IPs.

type Node

type Node struct {
	ID       NodeID
	StableID StableNodeID

	// Name is the FQDN of the node.
	// It is also the MagicDNS name for the node.
	// It has a trailing dot.
	// e.g. "host.tail-scale.ts.net."
	Name string

	// User is the user who created the node. If ACL tags are in use for the
	// node then it doesn't reflect the ACL identity that the node is running
	// as.
	User UserID

	// Sharer, if non-zero, is the user who shared this node, if different than User.
	Sharer UserID `json:",omitempty"`

	Key          key.NodePublic
	KeyExpiry    time.Time                  // the zero value if this node does not expire
	KeySignature tkatype.MarshaledSignature `json:",omitempty"`
	Machine      key.MachinePublic
	DiscoKey     key.DiscoPublic
	Addresses    []netip.Prefix   // IP addresses of this Node directly
	AllowedIPs   []netip.Prefix   // range of IP addresses to route to this node
	Endpoints    []netip.AddrPort `json:",omitempty"` // IP+port (public via STUN, and local LANs)

	// DERP is this node's home DERP region ID integer, but shoved into an
	// IP:port string for legacy reasons. The IP address is always "127.3.3.40"
	// (a loopback address (127) followed by the digits over the letters DERP on
	// a QWERTY keyboard (3.3.40)). The "port number" is the home DERP region ID
	// integer.
	//
	// TODO(bradfitz): simplify this legacy mess; add a new HomeDERPRegionID int
	// field behind a new capver bump.
	DERP string `json:",omitempty"` // DERP-in-IP:port ("127.3.3.40:N") endpoint

	Hostinfo HostinfoView
	Created  time.Time
	Cap      CapabilityVersion `json:",omitempty"` // if non-zero, the node's capability version; old servers might not send

	// Tags are the list of ACL tags applied to this node.
	// Tags take the form of `tag:<value>` where value starts
	// with a letter and only contains alphanumerics and dashes `-`.
	// Some valid tag examples:
	//   `tag:prod`
	//   `tag:database`
	//   `tag:lab-1`
	Tags []string `json:",omitempty"`

	// PrimaryRoutes are the routes from AllowedIPs that this node
	// is currently the primary subnet router for, as determined
	// by the control plane. It does not include the self address
	// values from Addresses that are in AllowedIPs.
	PrimaryRoutes []netip.Prefix `json:",omitempty"`

	// LastSeen is when the node was last online. It is not
	// updated when Online is true. It is nil if the current
	// node doesn't have permission to know, or the node
	// has never been online.
	LastSeen *time.Time `json:",omitempty"`

	// Online is whether the node is currently connected to the
	// coordination server.  A value of nil means unknown, or the
	// current node doesn't have permission to know.
	Online *bool `json:",omitempty"`

	MachineAuthorized bool `json:",omitempty"` // TODO(crawshaw): replace with MachineStatus

	// Capabilities are capabilities that the node has.
	// They're free-form strings, but should be in the form of URLs/URIs
	// such as:
	//    "https://tailscale.com/cap/is-admin"
	//    "https://tailscale.com/cap/file-sharing"
	//
	// Deprecated: use CapMap instead. See https://github.com/tailscale/tailscale/issues/11508
	Capabilities []NodeCapability `json:",omitempty"`

	// CapMap is a map of capabilities to their optional argument/data values.
	//
	// It is valid for a capability to not have any argument/data values; such
	// capabilities can be tested for using the HasCap method. These type of
	// capabilities are used to indicate that a node has a capability, but there
	// is no additional data associated with it. These were previously
	// represented by the Capabilities field, but can now be represented by
	// CapMap with an empty value.
	//
	// See NodeCapability for more information on keys.
	//
	// Metadata about nodes can be transmitted in 3 ways:
	// 1. MapResponse.Node.CapMap describes attributes that affect behavior for
	//    this node, such as which features have been enabled through the admin
	//    panel and any associated configuration details.
	// 2. MapResponse.PacketFilter(s) describes access (both IP and application
	//    based) that should be granted to peers.
	// 3. MapResponse.Peers[].CapMap describes attributes regarding a peer node,
	//    such as which features the peer supports or if that peer is preferred
	//    for a particular task vs other peers that could also be chosen.
	CapMap NodeCapMap `json:",omitempty"`

	// UnsignedPeerAPIOnly means that this node is not signed nor subject to TKA
	// restrictions. However, in exchange for that privilege, it does not get
	// network access. It can only access this node's peerapi, which may not let
	// it do anything. It is the tailscaled client's job to double-check the
	// MapResponse's PacketFilter to verify that its AllowedIPs will not be
	// accepted by the packet filter.
	UnsignedPeerAPIOnly bool `json:",omitempty"`

	ComputedName string `json:",omitempty"` // MagicDNS base name (for normal non-shared-in nodes), FQDN (without trailing dot, for shared-in nodes), or Hostname (if no MagicDNS)

	ComputedNameWithHost string `json:",omitempty"` // either "ComputedName" or "ComputedName (computedHostIfDifferent)", if computedHostIfDifferent is set

	// DataPlaneAuditLogID is the per-node logtail ID used for data plane audit logging.
	DataPlaneAuditLogID string `json:",omitempty"`

	// Expired is whether this node's key has expired. Control may send
	// this; clients are only allowed to set this from false to true. On
	// the client, this is calculated client-side based on a timestamp sent
	// from control, to avoid clock skew issues.
	Expired bool `json:",omitempty"`

	// SelfNodeV4MasqAddrForThisPeer is the IPv4 that this peer knows the current node as.
	// It may be empty if the peer knows the current node by its native
	// IPv4 address.
	// This field is only populated in a MapResponse for peers and not
	// for the current node.
	//
	// If set, it should be used to masquerade traffic originating from the
	// current node to this peer. The masquerade address is only relevant
	// for this peer and not for other peers.
	//
	// This only applies to traffic originating from the current node to the
	// peer or any of its subnets. Traffic originating from subnet routes will
	// not be masqueraded (e.g. in case of --snat-subnet-routes).
	SelfNodeV4MasqAddrForThisPeer *netip.Addr `json:",omitempty"`

	// SelfNodeV6MasqAddrForThisPeer is the IPv6 that this peer knows the current node as.
	// It may be empty if the peer knows the current node by its native
	// IPv6 address.
	// This field is only populated in a MapResponse for peers and not
	// for the current node.
	//
	// If set, it should be used to masquerade traffic originating from the
	// current node to this peer. The masquerade address is only relevant
	// for this peer and not for other peers.
	//
	// This only applies to traffic originating from the current node to the
	// peer or any of its subnets. Traffic originating from subnet routes will
	// not be masqueraded (e.g. in case of --snat-subnet-routes).
	SelfNodeV6MasqAddrForThisPeer *netip.Addr `json:",omitempty"`

	// IsWireGuardOnly indicates that this is a non-Tailscale WireGuard peer, it
	// is not expected to speak Disco or DERP, and it must have Endpoints in
	// order to be reachable.
	IsWireGuardOnly bool `json:",omitempty"`

	// IsJailed indicates that this node is jailed and should not be allowed
	// initiate connections, however outbound connections to it should still be
	// allowed.
	IsJailed bool `json:",omitempty"`

	// ExitNodeDNSResolvers is the list of DNS servers that should be used when this
	// node is marked IsWireGuardOnly and being used as an exit node.
	ExitNodeDNSResolvers []*dnstype.Resolver `json:",omitempty"`
	// contains filtered or unexported fields
}

func (*Node) Clone

func (src *Node) Clone() *Node

Clone makes a deep copy of Node. The result aliases no memory with the original.

func (*Node) DisplayName added in v1.4.0

func (n *Node) DisplayName(forOwner bool) string

DisplayName returns the user-facing name for a node which should be shown in client UIs.

Parameter forOwner specifies whether the name is requested by the owner of the node. When forOwner is false, the hostname is never included in the return value.

Return value is either "Name" or "Name (Hostname)", where Name is the node's MagicDNS base name (for normal non-shared-in nodes), FQDN (without trailing dot, for shared-in nodes), or Hostname (if no MagicDNS). Hostname is only included in the return value if it varies from Name and forOwner is provided true.

DisplayName is only valid if InitDisplayNames has been called.

func (*Node) DisplayNames added in v1.4.0

func (n *Node) DisplayNames(forOwner bool) (name, hostIfDifferent string)

DisplayName returns the decomposed user-facing name for a node.

Parameter forOwner specifies whether the name is requested by the owner of the node. When forOwner is false, hostIfDifferent is always returned empty.

Return value name is the node's primary name, populated with the node's MagicDNS base name (for normal non-shared-in nodes), FQDN (without trailing dot, for shared-in nodes), or Hostname (if no MagicDNS).

Return value hostIfDifferent, when non-empty, is the node's hostname. hostIfDifferent is only populated when the hostname varies from name and forOwner is provided as true.

DisplayNames is only valid if InitDisplayNames has been called.

func (*Node) Equal

func (n *Node) Equal(n2 *Node) bool

Equal reports whether n and n2 are equal.

func (*Node) HasCap added in v1.50.0

func (v *Node) HasCap(cap NodeCapability) bool

HasCap reports whether the node has the given capability. It is safe to call on a nil Node.

func (*Node) InitDisplayNames added in v1.4.0

func (n *Node) InitDisplayNames(networkMagicDNSSuffix string)

InitDisplayNames computes and populates n's display name fields: n.ComputedName, n.computedHostIfDifferent, and n.ComputedNameWithHost.

func (*Node) IsTagged added in v1.38.0

func (n *Node) IsTagged() bool

IsTagged reports whether the node has any tags.

func (*Node) SharerOrUser added in v1.50.0

func (n *Node) SharerOrUser() UserID

SharerOrUser Sharer if set, else User.

func (*Node) View added in v1.26.0

func (p *Node) View() NodeView

View returns a readonly view of Node.

type NodeCapMap added in v1.50.0

type NodeCapMap map[NodeCapability][]RawMessage

NodeCapMap is a map of capabilities to their optional values. It is valid for a capability to have no values (nil slice); such capabilities can be tested for by using the Contains method.

See NodeCapability for more information on keys.

func (NodeCapMap) Contains added in v1.50.0

func (c NodeCapMap) Contains(cap NodeCapability) bool

Contains reports whether c has the capability cap. This is used to test for the existence of a capability, especially when the capability has no associated argument/data values.

func (NodeCapMap) Equal added in v1.50.0

func (c NodeCapMap) Equal(c2 NodeCapMap) bool

Equal reports whether c and c2 are equal.

type NodeCapability added in v1.50.0

type NodeCapability string

NodeCapability represents a capability granted to the self node as listed in MapResponse.Node.Capabilities.

It must be a URL like "https://tailscale.com/cap/file-sharing", or a well-known capability name like "funnel". The latter is only allowed for Tailscale-defined capabilities.

Unlike PeerCapability, NodeCapability is not in context of a peer and is granted to the node itself.

These are also referred to as "Node Attributes" in the ACL policy file.

const (
	CapabilityFileSharing        NodeCapability = "https://tailscale.com/cap/file-sharing"
	CapabilityAdmin              NodeCapability = "https://tailscale.com/cap/is-admin"
	CapabilitySSH                NodeCapability = "https://tailscale.com/cap/ssh"                   // feature enabled/available
	CapabilitySSHRuleIn          NodeCapability = "https://tailscale.com/cap/ssh-rule-in"           // some SSH rule reach this node
	CapabilityDataPlaneAuditLogs NodeCapability = "https://tailscale.com/cap/data-plane-audit-logs" // feature enabled
	CapabilityDebug              NodeCapability = "https://tailscale.com/cap/debug"                 // exposes debug endpoints over the PeerAPI
	CapabilityHTTPS              NodeCapability = "https"

	// CapabilityBindToInterfaceByRoute changes how Darwin nodes create
	// sockets (in the net/netns package). See that package for more
	// details on the behaviour of this capability.
	CapabilityBindToInterfaceByRoute NodeCapability = "https://tailscale.com/cap/bind-to-interface-by-route"

	// CapabilityDebugDisableAlternateDefaultRouteInterface changes how Darwin
	// nodes get the default interface. There is an optional hook (used by the
	// macOS and iOS clients) to override the default interface, this capability
	// disables that and uses the default behavior (of parsing the routing
	// table).
	CapabilityDebugDisableAlternateDefaultRouteInterface NodeCapability = "https://tailscale.com/cap/debug-disable-alternate-default-route-interface"

	// CapabilityDebugDisableBindConnToInterface disables the automatic binding
	// of connections to the default network interface on Darwin nodes.
	CapabilityDebugDisableBindConnToInterface NodeCapability = "https://tailscale.com/cap/debug-disable-bind-conn-to-interface"

	// CapabilityTailnetLock indicates the node may initialize tailnet lock.
	CapabilityTailnetLock NodeCapability = "https://tailscale.com/cap/tailnet-lock"

	// CapabilityWarnFunnelNoInvite indicates whether Funnel is enabled for the tailnet.
	// This cap is no longer used 2023-08-09 onwards.
	CapabilityWarnFunnelNoInvite NodeCapability = "https://tailscale.com/cap/warn-funnel-no-invite"

	// CapabilityWarnFunnelNoHTTPS indicates HTTPS has not been enabled for the tailnet.
	// This cap is no longer used 2023-08-09 onwards.
	CapabilityWarnFunnelNoHTTPS NodeCapability = "https://tailscale.com/cap/warn-funnel-no-https"

	// CapabilityDebugTSDNSResolution enables verbose debug logging for DNS
	// resolution for Tailscale-controlled domains (the control server, log
	// server, DERP servers, etc.)
	CapabilityDebugTSDNSResolution NodeCapability = "https://tailscale.com/cap/debug-ts-dns-resolution"

	// CapabilityFunnelPorts specifies the ports that the Funnel is available on.
	// The ports are specified as a comma-separated list of port numbers or port
	// ranges (e.g. "80,443,8080-8090") in the ports query parameter.
	// e.g. https://tailscale.com/cap/funnel-ports?ports=80,443,8080-8090
	CapabilityFunnelPorts NodeCapability = "https://tailscale.com/cap/funnel-ports"

	// NodeAttrOnlyTCP443 specifies that the client should not attempt to generate
	// any outbound traffic that isn't TCP on port 443 (HTTPS). This is used for
	// clients in restricted environments where only HTTPS traffic is allowed
	// other types of traffic trips outbound firewall alarms. This thus implies
	// all traffic is over DERP.
	NodeAttrOnlyTCP443 NodeCapability = "only-tcp-443"

	// NodeAttrFunnel grants the ability for a node to host ingress traffic.
	NodeAttrFunnel NodeCapability = "funnel"
	// NodeAttrSSHAggregator grants the ability for a node to collect SSH sessions.
	NodeAttrSSHAggregator NodeCapability = "ssh-aggregator"

	// NodeAttrDebugForceBackgroundSTUN forces a node to always do background
	// STUN queries regardless of inactivity.
	NodeAttrDebugForceBackgroundSTUN NodeCapability = "debug-always-stun"

	// NodeAttrDebugDisableWGTrim disables the lazy WireGuard configuration,
	// always giving WireGuard the full netmap, even for idle peers.
	NodeAttrDebugDisableWGTrim NodeCapability = "debug-no-wg-trim"

	// NodeAttrDisableSubnetsIfPAC controls whether subnet routers should be
	// disabled if WPAD is present on the network.
	NodeAttrDisableSubnetsIfPAC NodeCapability = "debug-disable-subnets-if-pac"

	// NodeAttrDisableUPnP makes the client not perform a UPnP portmapping.
	// By default, we want to enable it to see if it works on more clients.
	//
	// If UPnP catastrophically fails for people, this should be set kill
	// new attempts at UPnP connections.
	NodeAttrDisableUPnP NodeCapability = "debug-disable-upnp"

	// NodeAttrDisableDeltaUpdates makes the client not process updates via the
	// delta update mechanism and should instead treat all netmap changes as
	// "full" ones as tailscaled did in 1.48.x and earlier.
	NodeAttrDisableDeltaUpdates NodeCapability = "disable-delta-updates"

	// NodeAttrRandomizeClientPort makes magicsock UDP bind to
	// :0 to get a random local port, ignoring any configured
	// fixed port.
	NodeAttrRandomizeClientPort NodeCapability = "randomize-client-port"

	// NodeAttrSilentDisco makes the client suppress disco heartbeats to its
	// peers.
	NodeAttrSilentDisco NodeCapability = "silent-disco"

	// NodeAttrOneCGNATEnable makes the client prefer one big CGNAT /10 route
	// rather than a /32 per peer. At most one of this or
	// NodeAttrOneCGNATDisable may be set; if neither are, it's automatic.
	NodeAttrOneCGNATEnable NodeCapability = "one-cgnat?v=true"

	// NodeAttrOneCGNATDisable makes the client prefer a /32 route per peer
	// rather than one big /10 CGNAT route. At most one of this or
	// NodeAttrOneCGNATEnable may be set; if neither are, it's automatic.
	NodeAttrOneCGNATDisable NodeCapability = "one-cgnat?v=false"

	// NodeAttrPeerMTUEnable makes the client do path MTU discovery to its
	// peers. If it isn't set, it defaults to the client default.
	NodeAttrPeerMTUEnable NodeCapability = "peer-mtu-enable"

	// NodeAttrDNSForwarderDisableTCPRetries disables retrying truncated
	// DNS queries over TCP if the response is truncated.
	NodeAttrDNSForwarderDisableTCPRetries NodeCapability = "dns-forwarder-disable-tcp-retries"

	// NodeAttrLinuxMustUseIPTables forces Linux clients to use iptables for
	// netfilter management.
	// This cannot be set simultaneously with NodeAttrLinuxMustUseNfTables.
	NodeAttrLinuxMustUseIPTables NodeCapability = "linux-netfilter?v=iptables"

	// NodeAttrLinuxMustUseNfTables forces Linux clients to use nftables for
	// netfilter management.
	// This cannot be set simultaneously with NodeAttrLinuxMustUseIPTables.
	NodeAttrLinuxMustUseNfTables NodeCapability = "linux-netfilter?v=nftables"

	// NodeAttrSeamlessKeyRenewal makes clients enable beta functionality
	// of renewing node keys without breaking connections.
	NodeAttrSeamlessKeyRenewal NodeCapability = "seamless-key-renewal"

	// NodeAttrProbeUDPLifetime makes the client probe UDP path lifetime at the
	// tail end of an active direct connection in magicsock.
	NodeAttrProbeUDPLifetime NodeCapability = "probe-udp-lifetime"

	// NodeAttrsTaildriveShare enables sharing via Taildrive.
	NodeAttrsTaildriveShare NodeCapability = "drive:share"

	// NodeAttrsTaildriveAccess enables accessing shares via Taildrive.
	NodeAttrsTaildriveAccess NodeCapability = "drive:access"

	// NodeAttrSuggestExitNode is applied to each exit node which the control plane has determined
	// is a recommended exit node.
	NodeAttrSuggestExitNode NodeCapability = "suggest-exit-node"

	// NodeAttrDisableWebClient disables using the web client.
	NodeAttrDisableWebClient NodeCapability = "disable-web-client"

	// NodeAttrLogExitFlows enables exit node destinations in network flow logs.
	NodeAttrLogExitFlows NodeCapability = "log-exit-flows"

	// NodeAttrAutoExitNode permits the automatic exit nodes feature.
	NodeAttrAutoExitNode NodeCapability = "auto-exit-node"

	// NodeAttrStoreAppCRoutes configures the node to store app connector routes persistently.
	NodeAttrStoreAppCRoutes NodeCapability = "store-appc-routes"

	// NodeAttrSuggestExitNodeUI allows the currently suggested exit node to appear in the client GUI.
	NodeAttrSuggestExitNodeUI NodeCapability = "suggest-exit-node-ui"

	// NodeAttrUserDialUseRoutes makes UserDial use either the peer dialer or the system dialer,
	// depending on the destination address and the configured routes. When present, it also makes
	// the DNS forwarder use UserDial instead of SystemDial when dialing resolvers.
	NodeAttrUserDialUseRoutes NodeCapability = "user-dial-routes"

	// NodeAttrSSHBehaviorV1 forces SSH to use the V1 behavior (no su, run SFTP in-process)
	// Added 2024-05-29 in Tailscale version 1.68.
	NodeAttrSSHBehaviorV1 NodeCapability = "ssh-behavior-v1"

	// NodeAttrSSHBehaviorV2 forces SSH to use the V2 behavior (use su, run SFTP in child process).
	// This overrides NodeAttrSSHBehaviorV1 if set.
	// See forceV1Behavior in ssh/tailssh/incubator.go for distinction between
	// V1 and V2 behavior.
	// Added 2024-08-06 in Tailscale version 1.72.
	NodeAttrSSHBehaviorV2 NodeCapability = "ssh-behavior-v2"

	// NodeAttrDisableSplitDNSWhenNoCustomResolvers indicates that the node's
	// DNS manager should not adopt a split DNS configuration even though the
	// Config of the resolver only contains routes that do not specify custom
	// resolver(s), hence all DNS queries can be safely sent to the upstream
	// DNS resolver and the node's DNS forwarder doesn't need to handle all
	// DNS traffic.
	// This is for now (2024-06-06) an iOS-specific battery life optimization,
	// and this node attribute allows us to disable the optimization remotely
	// if needed.
	NodeAttrDisableSplitDNSWhenNoCustomResolvers NodeCapability = "disable-split-dns-when-no-custom-resolvers"

	// NodeAttrDisableLocalDNSOverrideViaNRPT indicates that the node's DNS manager should not
	// create a default (catch-all) Windows NRPT rule when "Override local DNS" is enabled.
	// Without this rule, Windows 8.1 and newer devices issue parallel DNS requests to DNS servers
	// associated with all network adapters, even when "Override local DNS" is enabled and/or
	// a Mullvad exit node is being used, resulting in DNS leaks.
	// We began creating this rule on 2024-06-14, and this node attribute
	// allows us to disable the new behavior remotely if needed.
	NodeAttrDisableLocalDNSOverrideViaNRPT NodeCapability = "disable-local-dns-override-via-nrpt"

	// NodeAttrDisableMagicSockCryptoRouting disables the use of the
	// magicsock cryptorouting hook. See tailscale/corp#20732.
	NodeAttrDisableMagicSockCryptoRouting NodeCapability = "disable-magicsock-crypto-routing"

	// NodeAttrDisableCaptivePortalDetection instructs the client to not perform captive portal detection
	// automatically when the network state changes.
	NodeAttrDisableCaptivePortalDetection NodeCapability = "disable-captive-portal-detection"

	// NodeAttrSSHEnvironmentVariables enables logic for handling environment variables sent
	// via SendEnv in the SSH server and applying them to the SSH session.
	NodeAttrSSHEnvironmentVariables NodeCapability = "ssh-env-vars"
)

type NodeID

type NodeID ID

func (NodeID) IsZero added in v1.2.0

func (u NodeID) IsZero() bool

func (NodeID) String

func (id NodeID) String() string

type NodeView added in v1.26.0

type NodeView struct {
	// contains filtered or unexported fields
}

NodeView provides a read-only view over Node.

Its methods should only be called if `Valid()` returns true.

func (NodeView) Addresses added in v1.26.0

func (v NodeView) Addresses() views.Slice[netip.Prefix]

func (NodeView) AllowedIPs added in v1.26.0

func (v NodeView) AllowedIPs() views.Slice[netip.Prefix]

func (NodeView) AsStruct added in v1.26.0

func (v NodeView) AsStruct() *Node

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (NodeView) Cap added in v1.36.0

func (v NodeView) Cap() CapabilityVersion

func (NodeView) CapMap added in v1.50.0

func (NodeView) Capabilities added in v1.26.0

func (v NodeView) Capabilities() views.Slice[NodeCapability]

func (NodeView) ComputedName added in v1.26.0

func (v NodeView) ComputedName() string

func (NodeView) ComputedNameWithHost added in v1.26.0

func (v NodeView) ComputedNameWithHost() string

func (NodeView) Created added in v1.26.0

func (v NodeView) Created() time.Time

func (NodeView) DERP added in v1.26.0

func (v NodeView) DERP() string

func (NodeView) DataPlaneAuditLogID added in v1.32.0

func (v NodeView) DataPlaneAuditLogID() string

func (NodeView) DiscoKey added in v1.26.0

func (v NodeView) DiscoKey() key.DiscoPublic

func (NodeView) DisplayName added in v1.50.0

func (n NodeView) DisplayName(forOwner bool) string

DisplayName wraps Node.DisplayName.

func (NodeView) Endpoints added in v1.26.0

func (v NodeView) Endpoints() views.Slice[netip.AddrPort]

func (NodeView) Equal added in v1.26.0

func (v NodeView) Equal(v2 NodeView) bool

func (NodeView) ExitNodeDNSResolvers added in v1.50.0

func (v NodeView) ExitNodeDNSResolvers() views.SliceView[*dnstype.Resolver, dnstype.ResolverView]

func (NodeView) Expired added in v1.36.0

func (v NodeView) Expired() bool

func (NodeView) HasCap added in v1.50.0

func (v NodeView) HasCap(cap NodeCapability) bool

HasCap reports whether the node has the given capability. It is safe to call on an invalid NodeView.

func (NodeView) Hostinfo added in v1.26.0

func (v NodeView) Hostinfo() HostinfoView

func (NodeView) ID added in v1.26.0

func (v NodeView) ID() NodeID

func (NodeView) IsJailed added in v1.66.0

func (v NodeView) IsJailed() bool

func (NodeView) IsTagged added in v1.50.0

func (n NodeView) IsTagged() bool

IsTagged reports whether the node has any tags.

func (NodeView) IsWireGuardOnly added in v1.40.0

func (v NodeView) IsWireGuardOnly() bool

func (NodeView) Key added in v1.26.0

func (v NodeView) Key() key.NodePublic

func (NodeView) KeyExpiry added in v1.26.0

func (v NodeView) KeyExpiry() time.Time

func (NodeView) KeySignature added in v1.30.0

func (NodeView) LastSeen added in v1.26.0

func (v NodeView) LastSeen() *time.Time

func (NodeView) Machine added in v1.26.0

func (v NodeView) Machine() key.MachinePublic

func (NodeView) MachineAuthorized added in v1.26.0

func (v NodeView) MachineAuthorized() bool

func (NodeView) MarshalJSON added in v1.26.0

func (v NodeView) MarshalJSON() ([]byte, error)

func (NodeView) Name added in v1.26.0

func (v NodeView) Name() string

func (NodeView) Online added in v1.26.0

func (v NodeView) Online() *bool

func (NodeView) PrimaryRoutes added in v1.26.0

func (v NodeView) PrimaryRoutes() views.Slice[netip.Prefix]

func (NodeView) SelfNodeV4MasqAddrForThisPeer added in v1.40.0

func (v NodeView) SelfNodeV4MasqAddrForThisPeer() *netip.Addr

func (NodeView) SelfNodeV6MasqAddrForThisPeer added in v1.50.0

func (v NodeView) SelfNodeV6MasqAddrForThisPeer() *netip.Addr

func (NodeView) Sharer added in v1.26.0

func (v NodeView) Sharer() UserID

func (NodeView) SharerOrUser added in v1.50.0

func (n NodeView) SharerOrUser() UserID

SharerOrUser wraps Node.SharerOrUser.

func (NodeView) StableID added in v1.26.0

func (v NodeView) StableID() StableNodeID

func (NodeView) Tags added in v1.26.0

func (v NodeView) Tags() views.Slice[string]

func (*NodeView) UnmarshalJSON added in v1.26.0

func (v *NodeView) UnmarshalJSON(b []byte) error

func (NodeView) UnsignedPeerAPIOnly added in v1.34.0

func (v NodeView) UnsignedPeerAPIOnly() bool

func (NodeView) User added in v1.26.0

func (v NodeView) User() UserID

func (NodeView) Valid added in v1.26.0

func (v NodeView) Valid() bool

Valid reports whether underlying value is non-nil.

type Oauth2Token added in v1.8.0

type Oauth2Token struct {
	// AccessToken is the token that authorizes and authenticates
	// the requests.
	AccessToken string `json:"access_token"`

	// TokenType is the type of token.
	// The Type method returns either this or "Bearer", the default.
	TokenType string `json:"token_type,omitempty"`

	// RefreshToken is a token that's used by the application
	// (as opposed to the user) to refresh the access token
	// if it expires.
	RefreshToken string `json:"refresh_token,omitempty"`

	// Expiry is the optional expiration time of the access token.
	//
	// If zero, TokenSource implementations will reuse the same
	// token forever and RefreshToken or equivalent
	// mechanisms for that TokenSource will not be used.
	Expiry time.Time `json:"expiry,omitempty"`
}

Oauth2Token is a copy of golang.org/x/oauth2.Token, to avoid the go.mod dependency on App Engine and grpc, which was causing problems. All we actually needed was this struct on the client side.

type OverTLSPublicKeyResponse added in v1.24.0

type OverTLSPublicKeyResponse struct {
	// LegacyPublic specifies the control plane server's original
	// NaCl crypto_box machine key.
	// It will be zero for sufficiently new clients, based on their
	// advertised "v" parameter (the CurrentMapRequestVersion).
	// In that case, only the newer Noise-based transport may be used
	// using the PublicKey field.
	LegacyPublicKey key.MachinePublic `json:"legacyPublicKey"`

	// PublicKey specifies the server's public key for the
	// Noise-based control plane protocol. (see packages
	// control/controlbase and control/controlhttp)
	PublicKey key.MachinePublic `json:"publicKey"`
}

OverTLSPublicKeyResponse is the JSON response to /key?v=<n> over HTTPS (regular TLS) to the Tailscale control plane server, where the 'v' argument is the client's current capability version (previously known as the "MapRequest version").

The "OverTLS" prefix is to loudly declare that this exchange doesn't happen over Noise and can be intercepted/MITM'ed by enterprise/corp proxies where the organization can put TLS roots on devices.

type PeerCapMap added in v1.48.0

type PeerCapMap map[PeerCapability][]RawMessage

PeerCapMap is a map of capabilities to their optional values. It is valid for a capability to have no values (nil slice); such capabilities can be tested for by using the HasCapability method.

The values are opaque to Tailscale, but are passed through from the ACLs to the application via the WhoIs API.

func (PeerCapMap) HasCapability added in v1.48.0

func (c PeerCapMap) HasCapability(cap PeerCapability) bool

HasCapability reports whether c has the capability cap. This is used to test for the existence of a capability, especially when the capability has no associated argument/data values.

type PeerCapability added in v1.48.0

type PeerCapability string

PeerCapability represents a capability granted to a peer by a FilterRule when the peer communicates with the node that has this rule. Its meaning is application-defined.

It must be a URL like "https://tailscale.com/cap/file-send".

const (
	// PeerCapabilityFileSharingTarget grants the current node the ability to send
	// files to the peer which has this capability.
	PeerCapabilityFileSharingTarget PeerCapability = "https://tailscale.com/cap/file-sharing-target"
	// PeerCapabilityFileSharingSend grants the ability to receive files from a
	// node that's owned by a different user.
	PeerCapabilityFileSharingSend PeerCapability = "https://tailscale.com/cap/file-send"
	// PeerCapabilityDebugPeer grants the ability for a peer to read this node's
	// goroutines, metrics, magicsock internal state, etc.
	PeerCapabilityDebugPeer PeerCapability = "https://tailscale.com/cap/debug-peer"
	// PeerCapabilityWakeOnLAN grants the ability to send a Wake-On-LAN packet.
	PeerCapabilityWakeOnLAN PeerCapability = "https://tailscale.com/cap/wake-on-lan"
	// PeerCapabilityIngress grants the ability for a peer to send ingress traffic.
	PeerCapabilityIngress PeerCapability = "https://tailscale.com/cap/ingress"
	// PeerCapabilityWebUI grants the ability for a peer to edit features from the
	// device Web UI.
	PeerCapabilityWebUI PeerCapability = "tailscale.com/cap/webui"
	// PeerCapabilityTaildrive grants the ability for a peer to access Taildrive
	// shares.
	PeerCapabilityTaildrive PeerCapability = "tailscale.com/cap/drive"
	// PeerCapabilityTaildriveSharer indicates that a peer has the ability to
	// share folders with us.
	PeerCapabilityTaildriveSharer PeerCapability = "tailscale.com/cap/drive-sharer"

	// PeerCapabilityKubernetes grants a peer Kubernetes-specific
	// capabilities, such as the ability to impersonate specific Tailscale
	// user groups as Kubernetes user groups. This capability is read by
	// peers that are Tailscale Kubernetes operator instances.
	PeerCapabilityKubernetes PeerCapability = "tailscale.com/cap/kubernetes"

	// PeerCapabilityServicesDestination grants a peer the ability to serve as
	// a destination for a set of given VIP services, which is provided as the
	// value of this key in NodeCapMap.
	PeerCapabilityServicesDestination PeerCapability = "tailscale.com/cap/services-destination"
)

type PeerChange added in v1.30.0

type PeerChange struct {
	// NodeID is the node ID being mutated. If the NodeID is not
	// known in the current netmap, this update should be
	// ignored. (But the server will try not to send such useless
	// updates.)
	NodeID NodeID

	// DERPRegion, if non-zero, means that NodeID's home DERP
	// region ID is now this number.
	DERPRegion int `json:",omitempty"`

	// Cap, if non-zero, means that NodeID's capability version has changed.
	Cap CapabilityVersion `json:",omitempty"`

	// CapMap, if non-nil, means that NodeID's capability map has changed.
	CapMap NodeCapMap `json:",omitempty"`

	// Endpoints, if non-empty, means that NodeID's UDP Endpoints
	// have changed to these.
	Endpoints []netip.AddrPort `json:",omitempty"`

	// Key, if non-nil, means that the NodeID's wireguard public key changed.
	Key *key.NodePublic `json:",omitempty"`

	// KeySignature, if non-nil, means that the signature of the wireguard
	// public key has changed.
	KeySignature tkatype.MarshaledSignature `json:",omitempty"`

	// DiscoKey, if non-nil, means that the NodeID's discokey changed.
	DiscoKey *key.DiscoPublic `json:",omitempty"`

	// Online, if non-nil, means that the NodeID's online status changed.
	Online *bool `json:",omitempty"`

	// LastSeen, if non-nil, means that the NodeID's online status changed.
	LastSeen *time.Time `json:",omitempty"`

	// KeyExpiry, if non-nil, changes the NodeID's key expiry.
	KeyExpiry *time.Time `json:",omitempty"`
}

PeerChange is an update to a node.

type PingRequest added in v1.6.0

type PingRequest struct {
	// URL is the URL to reply to the PingRequest to.
	// It will be a unique URL each time. No auth headers are necessary.
	// If the client sees multiple PingRequests with the same URL,
	// subsequent ones should be ignored.
	//
	// The HTTP method that the node should make back to URL depends on the other
	// fields of the PingRequest. If Types is defined, then URL is the URL to
	// send a POST request to. Otherwise, the node should just make a HEAD
	// request to URL.
	URL string

	// URLIsNoise, if true, means that the client should hit URL over the Noise
	// transport instead of TLS.
	URLIsNoise bool `json:",omitempty"`

	// Log is whether to log about this ping in the success case.
	// For failure cases, the client will log regardless.
	Log bool `json:",omitempty"`

	// Types is the types of ping that are initiated. Can be any PingType, comma
	// separated, e.g. "disco,TSMP"
	//
	// As a special case, if Types is "c2n", then this PingRequest is a
	// client-to-node HTTP request. The HTTP request should be handled by this
	// node's c2n handler and the HTTP response sent in a POST to URL. For c2n,
	// the value of URLIsNoise is ignored and only the Noise transport (back to
	// the control plane) will be used, as if URLIsNoise were true.
	Types string `json:",omitempty"`

	// IP is the ping target, when needed by the PingType(s) given in Types.
	IP netip.Addr

	// Payload is the ping payload.
	//
	// It is only used for c2n requests, in which case it's an HTTP/1.0 or
	// HTTP/1.1-formatted HTTP request as parsable with http.ReadRequest.
	Payload []byte `json:",omitempty"`
}

PingRequest with no IP and Types is a request to send an HTTP request to prove the long-polling client is still connected. PingRequest with Types and IP, will send a ping to the IP and send a POST request containing a PingResponse to the URL containing results.

type PingResponse added in v1.24.0

type PingResponse struct {
	Type PingType // ping type, such as TSMP or disco.

	IP       string `json:",omitempty"` // ping destination
	NodeIP   string `json:",omitempty"` // Tailscale IP of node handling IP (different for subnet routers)
	NodeName string `json:",omitempty"` // DNS name base or (possibly not unique) hostname

	// Err contains a short description of error conditions if the PingRequest
	// could not be fulfilled for some reason.
	// e.g. "100.1.2.3 is local Tailscale IP"
	Err string `json:",omitempty"`

	// LatencySeconds reports measurement of the round-trip time of a message to
	// the requested target, if it could be determined. If LatencySeconds is
	// omitted, Err should contain information as to the cause.
	LatencySeconds float64 `json:",omitempty"`

	// Endpoint is the ip:port if direct UDP was used.
	// It is not currently set for TSMP pings.
	Endpoint string `json:",omitempty"`

	// DERPRegionID is non-zero DERP region ID if DERP was used.
	// It is not currently set for TSMP pings.
	DERPRegionID int `json:",omitempty"`

	// DERPRegionCode is the three-letter region code
	// corresponding to DERPRegionID.
	// It is not currently set for TSMP pings.
	DERPRegionCode string `json:",omitempty"`

	// PeerAPIPort is set by TSMP ping responses for peers that
	// are running a peerapi server. This is the port they're
	// running the server on.
	PeerAPIPort uint16 `json:",omitempty"`

	// IsLocalIP is whether the ping request error is due to it being
	// a ping to the local node.
	IsLocalIP bool `json:",omitempty"`
}

PingResponse provides result information for a TSMP or Disco PingRequest. Typically populated from an ipnstate.PingResult used in `tailscale ping`.

type PingType added in v1.26.0

type PingType string

PingType is a string representing the kind of ping to perform.

const (
	// PingDisco performs a ping, without involving IP at either end.
	PingDisco PingType = "disco"
	// PingTSMP performs a ping, using the IP layer, but avoiding the OS IP stack.
	PingTSMP PingType = "TSMP"
	// PingICMP performs a ping between two tailscale nodes using ICMP that is
	// received by the target systems IP stack.
	PingICMP PingType = "ICMP"
	// PingPeerAPI performs a ping between two tailscale nodes using ICMP that is
	// received by the target systems IP stack.
	PingPeerAPI PingType = "peerapi"
)

type PortRange added in v0.98.1

type PortRange struct {
	First uint16
	Last  uint16
}

PortRange represents a range of UDP or TCP port numbers.

func (PortRange) Contains added in v1.38.0

func (pr PortRange) Contains(port uint16) bool

Contains reports whether port is in pr.

type ProtoPortRange added in v1.52.0

type ProtoPortRange struct {
	// Proto is the IP protocol number.
	// If Proto is 0, it means TCP+UDP+ICMP(4+6).
	Proto int
	Ports PortRange
}

ProtoPortRange is used to encode "proto:port" format. The following formats are supported:

"*" allows all TCP, UDP and ICMP traffic on all ports.
"<ports>" allows all TCP, UDP and ICMP traffic on the specified ports.
"proto:*" allows traffic of the specified proto on all ports.
"proto:<port>" allows traffic of the specified proto on the specified port.

Ports are either a single port number or a range of ports (e.g. "80-90"). String named protocols support names that ipproto.Proto accepts.

func ParseProtoPortRanges added in v1.52.0

func ParseProtoPortRanges(ips []string) ([]ProtoPortRange, error)

ParseProtoPortRanges parses a slice of IP port range fields.

func (*ProtoPortRange) MarshalText added in v1.52.0

func (ppr *ProtoPortRange) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface. See ProtoPortRange for the format.

func (ProtoPortRange) String added in v1.52.0

func (ppr ProtoPortRange) String() string

String implements the stringer interface. See ProtoPortRange for the format.

func (*ProtoPortRange) UnmarshalText added in v1.52.0

func (ppr *ProtoPortRange) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface. See ProtoPortRange for the format.

type QueryFeatureRequest added in v1.48.0

type QueryFeatureRequest struct {
	// Feature is the string identifier for a feature.
	Feature string `json:",omitempty"`
	// NodeKey is the client's current node key.
	NodeKey key.NodePublic `json:",omitempty"`
}

QueryFeatureRequest is a request sent to "/machine/feature/query" to get instructions on how to enable a feature, such as Funnel, for the node's tailnet.

See QueryFeatureResponse for response structure.

type QueryFeatureResponse added in v1.48.0

type QueryFeatureResponse struct {
	// Complete is true when the feature is already enabled.
	Complete bool `json:",omitempty"`

	// Text holds lines to display in the CLI with information
	// about the feature and how to enable it.
	//
	// Lines are separated by newline characters. The final
	// newline may be omitted.
	Text string `json:",omitempty"`

	// URL is the link for the user to visit to take action on
	// enabling the feature.
	//
	// When empty, there is no action for this user to take.
	URL string `json:",omitempty"`

	// ShouldWait specifies whether the CLI should block and
	// wait for the user to enable the feature.
	//
	// If this is true, the enablement from the control server
	// is expected to be a quick and uninterrupted process for
	// the user, and blocking allows them to immediately start
	// using the feature once enabled without rerunning the
	// command (e.g. no need to re-run "funnel on").
	//
	// The CLI can watch the IPN notification bus for changes in
	// required node capabilities to know when to continue.
	ShouldWait bool `json:",omitempty"`
}

QueryFeatureResponse is the response to an QueryFeatureRequest. See cli.enableFeatureInteractive for usage.

type RawMessage added in v1.50.0

type RawMessage string

RawMessage is a raw encoded JSON value. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.

It is like json.RawMessage but is a string instead of a []byte to better portray immutable data.

func MarshalCapJSON added in v1.68.0

func MarshalCapJSON[T any](capRule T) (RawMessage, error)

MarshalCapJSON returns a capability rule in RawMessage string format.

func (RawMessage) MarshalJSON added in v1.50.0

func (m RawMessage) MarshalJSON() ([]byte, error)

MarshalJSON returns m as the JSON encoding of m.

func (*RawMessage) UnmarshalJSON added in v1.50.0

func (m *RawMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON sets *m to a copy of data.

type RegisterRequest

type RegisterRequest struct {

	// Version is the client's capabilities when using the Noise
	// transport.
	//
	// When using the original nacl crypto_box transport, the
	// value must be 1.
	Version CapabilityVersion

	NodeKey    key.NodePublic
	OldNodeKey key.NodePublic
	NLKey      key.NLPublic
	Auth       *RegisterResponseAuth `json:",omitempty"`
	// Expiry optionally specifies the requested key expiry.
	// The server policy may override.
	// As a special case, if Expiry is in the past and NodeKey is
	// the node's current key, the key is expired.
	Expiry   time.Time
	Followup string // response waits until AuthURL is visited
	Hostinfo *Hostinfo

	// Ephemeral is whether the client is requesting that this
	// node be considered ephemeral and be automatically deleted
	// when it stops being active.
	Ephemeral bool `json:",omitempty"`

	// NodeKeySignature is the node's own node-key signature, re-signed
	// for its new node key using its network-lock key.
	//
	// This field is set when the client retries registration after learning
	// its NodeKeySignature (which is in need of rotation).
	NodeKeySignature tkatype.MarshaledSignature

	// The following fields are not used for SignatureNone and are required for
	// SignatureV1:
	SignatureType SignatureType `json:",omitempty"`
	Timestamp     *time.Time    `json:",omitempty"` // creation time of request to prevent replay
	DeviceCert    []byte        `json:",omitempty"` // X.509 certificate for client device
	Signature     []byte        `json:",omitempty"` // as described by SignatureType

	// Tailnet is an optional identifier specifying the name of the recommended or required
	// network that the node should join. Its exact form should not be depended on; new
	// forms are coming later. The identifier is generally a domain name (for an organization)
	// or e-mail address (for a personal account on a shared e-mail provider). It is the same name
	// used by the API, as described in /api.md#tailnet.
	// If Tailnet begins with the prefix "required:" then the server should prevent logging in to a different
	// network than the one specified. Otherwise, the server should recommend the specified network
	// but still permit logging in to other networks.
	// If empty, no recommendation is offered to the server and the login page should show all options.
	Tailnet string `json:",omitempty"`
	// contains filtered or unexported fields
}

RegisterRequest is sent by a client to register the key for a node. It is encoded to JSON, encrypted with golang.org/x/crypto/nacl/box, using the local machine key, and sent to:

https://login.tailscale.com/machine/<mkey hex>

func (*RegisterRequest) Clone

func (src *RegisterRequest) Clone() *RegisterRequest

Clone makes a deep copy of RegisterRequest. The result aliases no memory with the original.

func (*RegisterRequest) View added in v1.50.0

View returns a readonly view of RegisterRequest.

type RegisterRequestView added in v1.50.0

type RegisterRequestView struct {
	// contains filtered or unexported fields
}

RegisterRequestView provides a read-only view over RegisterRequest.

Its methods should only be called if `Valid()` returns true.

func (RegisterRequestView) AsStruct added in v1.50.0

func (v RegisterRequestView) AsStruct() *RegisterRequest

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (RegisterRequestView) Auth added in v1.50.0

func (RegisterRequestView) DeviceCert added in v1.50.0

func (v RegisterRequestView) DeviceCert() views.ByteSlice[[]byte]

func (RegisterRequestView) Ephemeral added in v1.50.0

func (v RegisterRequestView) Ephemeral() bool

func (RegisterRequestView) Expiry added in v1.50.0

func (v RegisterRequestView) Expiry() time.Time

func (RegisterRequestView) Followup added in v1.50.0

func (v RegisterRequestView) Followup() string

func (RegisterRequestView) Hostinfo added in v1.50.0

func (v RegisterRequestView) Hostinfo() HostinfoView

func (RegisterRequestView) MarshalJSON added in v1.50.0

func (v RegisterRequestView) MarshalJSON() ([]byte, error)

func (RegisterRequestView) NLKey added in v1.50.0

func (v RegisterRequestView) NLKey() key.NLPublic

func (RegisterRequestView) NodeKey added in v1.50.0

func (v RegisterRequestView) NodeKey() key.NodePublic

func (RegisterRequestView) NodeKeySignature added in v1.50.0

func (RegisterRequestView) OldNodeKey added in v1.50.0

func (v RegisterRequestView) OldNodeKey() key.NodePublic

func (RegisterRequestView) Signature added in v1.50.0

func (v RegisterRequestView) Signature() views.ByteSlice[[]byte]

func (RegisterRequestView) SignatureType added in v1.50.0

func (v RegisterRequestView) SignatureType() SignatureType

func (RegisterRequestView) Tailnet added in v1.52.0

func (v RegisterRequestView) Tailnet() string

func (RegisterRequestView) Timestamp added in v1.50.0

func (v RegisterRequestView) Timestamp() *time.Time

func (*RegisterRequestView) UnmarshalJSON added in v1.50.0

func (v *RegisterRequestView) UnmarshalJSON(b []byte) error

func (RegisterRequestView) Valid added in v1.50.0

func (v RegisterRequestView) Valid() bool

Valid reports whether underlying value is non-nil.

func (RegisterRequestView) Version added in v1.50.0

type RegisterResponse

type RegisterResponse struct {
	User              User
	Login             Login
	NodeKeyExpired    bool   // if true, the NodeKey needs to be replaced
	MachineAuthorized bool   // TODO(crawshaw): move to using MachineStatus
	AuthURL           string // if set, authorization pending

	// If set, this is the current node-key signature that needs to be
	// re-signed for the node's new node-key.
	NodeKeySignature tkatype.MarshaledSignature

	// Error indicates that authorization failed. If this is non-empty,
	// other status fields should be ignored.
	Error string
}

RegisterResponse is returned by the server in response to a RegisterRequest.

func (*RegisterResponse) Clone added in v1.2.0

func (src *RegisterResponse) Clone() *RegisterResponse

Clone makes a deep copy of RegisterResponse. The result aliases no memory with the original.

func (*RegisterResponse) View added in v1.26.0

View returns a readonly view of RegisterResponse.

type RegisterResponseAuth added in v1.50.0

type RegisterResponseAuth struct {
	Oauth2Token *Oauth2Token `json:",omitempty"` // used by pre-1.66 Android only
	AuthKey     string       `json:",omitempty"`
	// contains filtered or unexported fields
}

RegisterResponseAuth is the authentication information returned by the server in response to a RegisterRequest.

func (*RegisterResponseAuth) Clone added in v1.50.0

Clone makes a deep copy of RegisterResponseAuth. The result aliases no memory with the original.

func (*RegisterResponseAuth) View added in v1.50.0

View returns a readonly view of RegisterResponseAuth.

type RegisterResponseAuthView added in v1.50.0

type RegisterResponseAuthView struct {
	// contains filtered or unexported fields
}

RegisterResponseAuthView provides a read-only view over RegisterResponseAuth.

Its methods should only be called if `Valid()` returns true.

func (RegisterResponseAuthView) AsStruct added in v1.50.0

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (RegisterResponseAuthView) AuthKey added in v1.50.0

func (v RegisterResponseAuthView) AuthKey() string

func (RegisterResponseAuthView) MarshalJSON added in v1.50.0

func (v RegisterResponseAuthView) MarshalJSON() ([]byte, error)

func (RegisterResponseAuthView) Oauth2Token added in v1.50.0

func (v RegisterResponseAuthView) Oauth2Token() *Oauth2Token

func (*RegisterResponseAuthView) UnmarshalJSON added in v1.50.0

func (v *RegisterResponseAuthView) UnmarshalJSON(b []byte) error

func (RegisterResponseAuthView) Valid added in v1.50.0

func (v RegisterResponseAuthView) Valid() bool

Valid reports whether underlying value is non-nil.

type RegisterResponseView added in v1.26.0

type RegisterResponseView struct {
	// contains filtered or unexported fields
}

RegisterResponseView provides a read-only view over RegisterResponse.

Its methods should only be called if `Valid()` returns true.

func (RegisterResponseView) AsStruct added in v1.26.0

func (v RegisterResponseView) AsStruct() *RegisterResponse

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (RegisterResponseView) AuthURL added in v1.26.0

func (v RegisterResponseView) AuthURL() string

func (RegisterResponseView) Error added in v1.26.0

func (v RegisterResponseView) Error() string

func (RegisterResponseView) Login added in v1.26.0

func (v RegisterResponseView) Login() Login

func (RegisterResponseView) MachineAuthorized added in v1.26.0

func (v RegisterResponseView) MachineAuthorized() bool

func (RegisterResponseView) MarshalJSON added in v1.26.0

func (v RegisterResponseView) MarshalJSON() ([]byte, error)

func (RegisterResponseView) NodeKeyExpired added in v1.26.0

func (v RegisterResponseView) NodeKeyExpired() bool

func (RegisterResponseView) NodeKeySignature added in v1.34.0

func (*RegisterResponseView) UnmarshalJSON added in v1.26.0

func (v *RegisterResponseView) UnmarshalJSON(b []byte) error

func (RegisterResponseView) User added in v1.26.0

func (v RegisterResponseView) User() UserView

func (RegisterResponseView) Valid added in v1.26.0

func (v RegisterResponseView) Valid() bool

Valid reports whether underlying value is non-nil.

type SSHAction added in v1.22.0

type SSHAction struct {
	// Message, if non-empty, is shown to the user before the
	// action occurs.
	Message string `json:"message,omitempty"`

	// Reject, if true, terminates the connection. This action
	// has higher priority that Accept, if given.
	// The reason this is exists is primarily so a response
	// from HoldAndDelegate has a way to stop the poll.
	Reject bool `json:"reject,omitempty"`

	// Accept, if true, accepts the connection immediately
	// without further prompts.
	Accept bool `json:"accept,omitempty"`

	// SessionDuration, if non-zero, is how long the session can stay open
	// before being forcefully terminated.
	SessionDuration time.Duration `json:"sessionDuration,omitempty"`

	// AllowAgentForwarding, if true, allows accepted connections to forward
	// the ssh agent if requested.
	AllowAgentForwarding bool `json:"allowAgentForwarding,omitempty"`

	// HoldAndDelegate, if non-empty, is a URL that serves an
	// outcome verdict.  The connection will be accepted and will
	// block until the provided long-polling URL serves a new
	// SSHAction JSON value. The URL must be fetched using the
	// Noise transport (in package control/control{base,http}).
	// If the long poll breaks before returning a complete HTTP
	// response, it should be re-fetched as long as the SSH
	// session is open.
	//
	// The following variables in the URL are expanded by tailscaled:
	//
	//   * $SRC_NODE_IP (URL escaped)
	//   * $SRC_NODE_ID (Node.ID as int64 string)
	//   * $DST_NODE_IP (URL escaped)
	//   * $DST_NODE_ID (Node.ID as int64 string)
	//   * $SSH_USER (URL escaped, ssh user requested)
	//   * $LOCAL_USER (URL escaped, local user mapped)
	HoldAndDelegate string `json:"holdAndDelegate,omitempty"`

	// AllowLocalPortForwarding, if true, allows accepted connections
	// to use local port forwarding if requested.
	AllowLocalPortForwarding bool `json:"allowLocalPortForwarding,omitempty"`

	// AllowRemotePortForwarding, if true, allows accepted connections
	// to use remote port forwarding if requested.
	AllowRemotePortForwarding bool `json:"allowRemotePortForwarding,omitempty"`

	// Recorders defines the destinations of the SSH session recorders.
	// The recording will be uploaded to http://addr:port/record.
	Recorders []netip.AddrPort `json:"recorders,omitempty"`

	// OnRecorderFailure is the action to take if recording fails.
	// If nil, the default action is to fail open.
	OnRecordingFailure *SSHRecorderFailureAction `json:"onRecordingFailure,omitempty"`
}

SSHAction is how to handle an incoming connection. At most one field should be non-zero.

func (*SSHAction) Clone added in v1.38.4

func (src *SSHAction) Clone() *SSHAction

Clone makes a deep copy of SSHAction. The result aliases no memory with the original.

func (*SSHAction) View added in v1.38.4

func (p *SSHAction) View() SSHActionView

View returns a readonly view of SSHAction.

type SSHActionView added in v1.38.4

type SSHActionView struct {
	// contains filtered or unexported fields
}

SSHActionView provides a read-only view over SSHAction.

Its methods should only be called if `Valid()` returns true.

func (SSHActionView) Accept added in v1.38.4

func (v SSHActionView) Accept() bool

func (SSHActionView) AllowAgentForwarding added in v1.38.4

func (v SSHActionView) AllowAgentForwarding() bool

func (SSHActionView) AllowLocalPortForwarding added in v1.38.4

func (v SSHActionView) AllowLocalPortForwarding() bool

func (SSHActionView) AllowRemotePortForwarding added in v1.44.0

func (v SSHActionView) AllowRemotePortForwarding() bool

func (SSHActionView) AsStruct added in v1.38.4

func (v SSHActionView) AsStruct() *SSHAction

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (SSHActionView) HoldAndDelegate added in v1.38.4

func (v SSHActionView) HoldAndDelegate() string

func (SSHActionView) MarshalJSON added in v1.38.4

func (v SSHActionView) MarshalJSON() ([]byte, error)

func (SSHActionView) Message added in v1.38.4

func (v SSHActionView) Message() string

func (SSHActionView) OnRecordingFailure added in v1.40.0

func (v SSHActionView) OnRecordingFailure() *SSHRecorderFailureAction

func (SSHActionView) Recorders added in v1.38.4

func (v SSHActionView) Recorders() views.Slice[netip.AddrPort]

func (SSHActionView) Reject added in v1.38.4

func (v SSHActionView) Reject() bool

func (SSHActionView) SessionDuration added in v1.38.4

func (v SSHActionView) SessionDuration() time.Duration

func (*SSHActionView) UnmarshalJSON added in v1.38.4

func (v *SSHActionView) UnmarshalJSON(b []byte) error

func (SSHActionView) Valid added in v1.38.4

func (v SSHActionView) Valid() bool

Valid reports whether underlying value is non-nil.

type SSHEventNotifyRequest added in v1.42.0

type SSHEventNotifyRequest struct {
	// EventType is the type of notify request being sent.
	EventType SSHEventType

	// ConnectionID uniquely identifies a connection made to the SSH server.
	// It may be shared across multiple sessions over the same connection in
	// case a single connection creates multiple sessions.
	ConnectionID string

	// CapVersion is the client's current CapabilityVersion.
	CapVersion CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// SrcNode is the ID of the node that initiated the SSH session.
	SrcNode NodeID

	// SSHUser is the user that was presented to the SSH server.
	SSHUser string

	// LocalUser is the user that was resolved from the SSHUser for the local machine.
	LocalUser string

	// RecordingAttempts is the list of recorders that were attempted, in order.
	RecordingAttempts []*SSHRecordingAttempt
}

SSHEventNotifyRequest is the JSON payload sent to the NotifyURL for an SSH event.

type SSHEventType added in v1.42.0

type SSHEventType int

SSHEventType defines the event type linked to a SSH action or state.

const (
	UnspecifiedSSHEventType SSHEventType = 0
	// SSHSessionRecordingRejected is the event that
	// defines when a SSH session cannot be started
	// because no recorder is available for session
	// recording, and the SSHRecorderFailureAction
	// RejectSessionWithMessage is not empty.
	SSHSessionRecordingRejected SSHEventType = 1
	// SSHSessionRecordingTerminated is the event that
	// defines when session recording has failed
	// during the session and the SSHRecorderFailureAction
	// TerminateSessionWithMessage is not empty.
	SSHSessionRecordingTerminated SSHEventType = 2
	// SSHSessionRecordingFailed is the event that
	// defines when session recording is unavailable and
	// the SSHRecorderFailureAction RejectSessionWithMessage
	// or TerminateSessionWithMessage is empty.
	SSHSessionRecordingFailed SSHEventType = 3
)

type SSHPolicy added in v1.22.0

type SSHPolicy struct {
	// Rules are the rules to process for an incoming SSH connection. The first
	// matching rule takes its action and stops processing further rules.
	//
	// When an incoming connection first starts, all rules are evaluated in
	// "none" auth mode, where the client hasn't even been asked to send a
	// public key. All SSHRule.Principals requiring a public key won't match. If
	// a rule matches on the first pass and its Action is reject, the
	// authentication fails with that action's rejection message, if any.
	//
	// If the first pass rule evaluation matches nothing without matching an
	// Action with Reject set, the rules are considered to see whether public
	// keys might still result in a match. If not, "none" auth is terminated
	// before proceeding to public key mode. If so, the client is asked to try
	// public key authentication and the rules are evaluated again for each of
	// the client's present keys.
	Rules []*SSHRule `json:"rules"`
}

SSHPolicy is the policy for how to handle incoming SSH connections over Tailscale.

type SSHPrincipal added in v1.22.0

type SSHPrincipal struct {
	Node      StableNodeID `json:"node,omitempty"`
	NodeIP    string       `json:"nodeIP,omitempty"`
	UserLogin string       `json:"userLogin,omitempty"` // email-ish: foo@example.com, bar@github
	Any       bool         `json:"any,omitempty"`       // if true, match any connection

	// PubKeys, if non-empty, means that this SSHPrincipal only
	// matches if one of these public keys is presented by the user.
	//
	// As a special case, if len(PubKeys) == 1 and PubKeys[0] starts
	// with "https://", then it's fetched (like https://github.com/username.keys).
	// In that case, the following variable expansions are also supported
	// in the URL:
	//   * $LOGINNAME_EMAIL ("foo@bar.com" or "foo@github")
	//   * $LOGINNAME_LOCALPART (the "foo" from either of the above)
	PubKeys []string `json:"pubKeys,omitempty"`
}

SSHPrincipal is either a particular node or a user on any node.

func (*SSHPrincipal) Clone added in v1.30.0

func (src *SSHPrincipal) Clone() *SSHPrincipal

Clone makes a deep copy of SSHPrincipal. The result aliases no memory with the original.

func (*SSHPrincipal) View added in v1.30.0

func (p *SSHPrincipal) View() SSHPrincipalView

View returns a readonly view of SSHPrincipal.

type SSHPrincipalView added in v1.30.0

type SSHPrincipalView struct {
	// contains filtered or unexported fields
}

SSHPrincipalView provides a read-only view over SSHPrincipal.

Its methods should only be called if `Valid()` returns true.

func (SSHPrincipalView) Any added in v1.30.0

func (v SSHPrincipalView) Any() bool

func (SSHPrincipalView) AsStruct added in v1.30.0

func (v SSHPrincipalView) AsStruct() *SSHPrincipal

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (SSHPrincipalView) MarshalJSON added in v1.30.0

func (v SSHPrincipalView) MarshalJSON() ([]byte, error)

func (SSHPrincipalView) Node added in v1.30.0

func (v SSHPrincipalView) Node() StableNodeID

func (SSHPrincipalView) NodeIP added in v1.30.0

func (v SSHPrincipalView) NodeIP() string

func (SSHPrincipalView) PubKeys added in v1.30.0

func (v SSHPrincipalView) PubKeys() views.Slice[string]

func (*SSHPrincipalView) UnmarshalJSON added in v1.30.0

func (v *SSHPrincipalView) UnmarshalJSON(b []byte) error

func (SSHPrincipalView) UserLogin added in v1.30.0

func (v SSHPrincipalView) UserLogin() string

func (SSHPrincipalView) Valid added in v1.30.0

func (v SSHPrincipalView) Valid() bool

Valid reports whether underlying value is non-nil.

type SSHRecorderFailureAction added in v1.40.0

type SSHRecorderFailureAction struct {
	// RejectSessionWithMessage, if not empty, specifies that the session should
	// be rejected if the recording fails to start.
	// The message will be shown to the user before the session is rejected.
	RejectSessionWithMessage string `json:",omitempty"`

	// TerminateSessionWithMessage, if not empty, specifies that the session
	// should be terminated if the recording fails after it has started. The
	// message will be shown to the user before the session is terminated.
	TerminateSessionWithMessage string `json:",omitempty"`

	// NotifyURL, if non-empty, specifies a HTTP POST URL to notify when the
	// recording fails. The payload is the JSON encoded
	// SSHRecordingFailureNotifyRequest struct. The host field in the URL is
	// ignored, and it will be sent to control over the Noise transport.
	NotifyURL string `json:",omitempty"`
}

SSHRecorderFailureAction is the action to take if recording fails.

type SSHRecordingAttempt added in v1.40.0

type SSHRecordingAttempt struct {
	// Recorder is the address of the recorder that was attempted.
	Recorder netip.AddrPort

	// FailureMessage is the error message of the failed attempt.
	FailureMessage string
}

SSHRecordingAttempt is a single attempt to start a recording.

type SSHRule added in v1.22.0

type SSHRule struct {
	// RuleExpires, if non-nil, is when this rule expires.
	//
	// For example, a (principal,sshuser) tuple might be granted
	// prompt-free SSH access for N minutes, so this rule would be
	// before a expiration-free rule for the same principal that
	// required an auth prompt.  This permits the control plane to
	// be out of the path for already-authorized SSH pairs.
	//
	// Once a rule matches, the lifetime of any accepting connection
	// is subject to the SSHAction.SessionExpires time, if any.
	RuleExpires *time.Time `json:"ruleExpires,omitempty"`

	// Principals matches an incoming connection. If the connection
	// matches anything in this list and also matches SSHUsers,
	// then Action is applied.
	Principals []*SSHPrincipal `json:"principals"`

	// SSHUsers are the SSH users that this rule matches. It is a
	// map from either ssh-user|"*" => local-user.  The map must
	// contain a key for either ssh-user or, as a fallback, "*" to
	// match anything. If it does, the map entry's value is the
	// actual user that's logged in.
	// If the map value is the empty string (for either the
	// requested SSH user or "*"), the rule doesn't match.
	// If the map value is "=", it means the ssh-user should map
	// directly to the local-user.
	// It may be nil if the Action is reject.
	SSHUsers map[string]string `json:"sshUsers"`

	// Action is the outcome to task.
	// A nil or invalid action means to deny.
	Action *SSHAction `json:"action"`

	// AcceptEnv is a slice of environment variable names that are allowlisted
	// for the SSH rule in the policy file.
	//
	// AcceptEnv values may contain * and ? wildcard characters which match against
	// an arbitrary number of characters or a single character respectively.
	AcceptEnv []string `json:"acceptEnv,omitempty"`
}

An SSH rule is a match predicate and associated action for an incoming SSH connection.

func (*SSHRule) Clone added in v1.30.0

func (src *SSHRule) Clone() *SSHRule

Clone makes a deep copy of SSHRule. The result aliases no memory with the original.

func (*SSHRule) View added in v1.30.0

func (p *SSHRule) View() SSHRuleView

View returns a readonly view of SSHRule.

type SSHRuleView added in v1.30.0

type SSHRuleView struct {
	// contains filtered or unexported fields
}

SSHRuleView provides a read-only view over SSHRule.

Its methods should only be called if `Valid()` returns true.

func (SSHRuleView) AcceptEnv added in v1.76.0

func (v SSHRuleView) AcceptEnv() views.Slice[string]

func (SSHRuleView) Action added in v1.30.0

func (v SSHRuleView) Action() SSHActionView

func (SSHRuleView) AsStruct added in v1.30.0

func (v SSHRuleView) AsStruct() *SSHRule

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (SSHRuleView) MarshalJSON added in v1.30.0

func (v SSHRuleView) MarshalJSON() ([]byte, error)

func (SSHRuleView) Principals added in v1.30.0

func (SSHRuleView) RuleExpires added in v1.30.0

func (v SSHRuleView) RuleExpires() *time.Time

func (SSHRuleView) SSHUsers added in v1.30.0

func (v SSHRuleView) SSHUsers() views.Map[string, string]

func (*SSHRuleView) UnmarshalJSON added in v1.30.0

func (v *SSHRuleView) UnmarshalJSON(b []byte) error

func (SSHRuleView) Valid added in v1.30.0

func (v SSHRuleView) Valid() bool

Valid reports whether underlying value is non-nil.

type Service

type Service struct {

	// Proto is the type of service. It's usually the constant TCP
	// or UDP ("tcp" or "udp"), but it can also be one of the
	// following meta service values:
	//
	//     * "peerapi4": peerapi is available on IPv4; Port is the
	//        port number that the peerapi is running on the
	//        node's Tailscale IPv4 address.
	//     * "peerapi6": peerapi is available on IPv6; Port is the
	//        port number that the peerapi is running on the
	//        node's Tailscale IPv6 address.
	//     * "peerapi-dns-proxy": the local peerapi service supports
	//        being a DNS proxy (when the node is an exit
	//        node). For this service, the Port number must only be 1.
	Proto ServiceProto

	// Port is the port number.
	//
	// For Proto "peerapi-dns", it must be 1.
	Port uint16

	// Description is the textual description of the service,
	// usually the process name that's running.
	Description string `json:",omitempty"`
	// contains filtered or unexported fields
}

Service represents a service running on a node.

type ServiceProto

type ServiceProto string

ServiceProto is a service type. It's usually TCP ("tcp") or UDP ("udp"), but it can also have meta service values as defined in Service.Proto.

type SetDNSRequest added in v1.10.0

type SetDNSRequest struct {
	// Version is the client's capabilities
	// (CurrentCapabilityVersion) when using the Noise transport.
	//
	// When using the original nacl crypto_box transport, the
	// value must be 1.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Name is the domain name for which to create a record.
	// For ACME DNS-01 challenges, it should be one of the domains
	// in MapResponse.DNSConfig.CertDomains with the prefix
	// "_acme-challenge.".
	Name string

	// Type is the DNS record type. For ACME DNS-01 challenges, it
	// should be "TXT".
	Type string

	// Value is the value to add.
	Value string
}

SetDNSRequest is a request to add a DNS record.

This is used for ACME DNS-01 challenges (so people can use LetsEncrypt, etc).

The request is encoded to JSON, encrypted with golang.org/x/crypto/nacl/box, using the local machine key, and sent to:

https://login.tailscale.com/machine/<mkey hex>/set-dns

type SetDNSResponse added in v1.24.0

type SetDNSResponse struct{}

SetDNSResponse is the response to a SetDNSRequest.

type SignatureType added in v1.8.0

type SignatureType int

SignatureType specifies a scheme for signing RegisterRequest messages. It specifies the crypto algorithms to use, the contents of what is signed, and any other relevant details. Historically, requests were unsigned so the zero value is SignatureNone.

func (SignatureType) AppendText added in v1.50.0

func (st SignatureType) AppendText(b []byte) ([]byte, error)

func (SignatureType) MarshalText added in v1.8.0

func (st SignatureType) MarshalText() ([]byte, error)

func (SignatureType) String added in v1.8.0

func (st SignatureType) String() string

func (*SignatureType) UnmarshalText added in v1.8.0

func (st *SignatureType) UnmarshalText(b []byte) error

type StableID added in v1.4.0

type StableID string

type StableNodeID added in v1.4.0

type StableNodeID StableID

func (StableNodeID) IsZero added in v1.4.0

func (u StableNodeID) IsZero() bool

type TKABootstrapRequest added in v1.32.0

type TKABootstrapRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Head represents the node's head AUMHash (tka.Authority.Head), if
	// network lock is enabled.
	Head string
}

TKABootstrapRequest is sent by a node to get information necessary for enabling or disabling the tailnet key authority.

type TKABootstrapResponse added in v1.32.0

type TKABootstrapResponse struct {
	// GenesisAUM returns the initial AUM necessary to initialize TKA.
	GenesisAUM tkatype.MarshaledAUM `json:",omitempty"`

	// DisablementSecret encodes a secret necessary to disable TKA.
	DisablementSecret []byte `json:",omitempty"`
}

TKABootstrapResponse encodes values necessary to enable or disable the tailnet key authority (TKA).

type TKADisableRequest added in v1.34.0

type TKADisableRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Head represents the node's head AUMHash (tka.Authority.Head).
	// It is encoded as tka.AUMHash.MarshalText.
	Head string

	// DisablementSecret encodes the secret necessary to disable TKA.
	DisablementSecret []byte
}

TKADisableRequest disables network-lock across the tailnet using the provided disablement secret.

This is the request schema for a /tka/disable noise RPC.

type TKADisableResponse added in v1.34.0

type TKADisableResponse struct {
}

TKADisableResponse is the JSON response from a /tka/disable RPC. This schema describes the successful disablement of the tailnet's key authority.

type TKAInfo added in v1.32.0

type TKAInfo struct {
	// Head describes the hash of the latest AUM applied to the authority.
	// Head is encoded as tka.AUMHash.MarshalText.
	//
	// If the Head state differs to that known locally, the node should perform
	// synchronization via a separate RPC.
	Head string `json:",omitempty"`

	// Disabled indicates the control plane believes TKA should be disabled,
	// and the node should reach out to fetch a disablement
	// secret. If the disablement secret verifies, then the node should then
	// disable TKA locally.
	// This field exists to disambiguate a nil TKAInfo in a delta mapresponse
	// from a nil TKAInfo indicating TKA should be disabled.
	Disabled bool `json:",omitempty"`
}

TKAInfo encodes the control plane's view of tailnet key authority (TKA) state. This information is transmitted as part of the MapResponse.

type TKAInitBeginRequest added in v1.30.0

type TKAInitBeginRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// GenesisAUM is the initial (genesis) AUM that the node generated
	// to bootstrap tailnet key authority state.
	GenesisAUM tkatype.MarshaledAUM
}

TKAInitBeginRequest submits a genesis AUM to seed the creation of the tailnet's key authority.

type TKAInitBeginResponse added in v1.30.0

type TKAInitBeginResponse struct {
	// NeedSignatures specify information about the nodes in your tailnet
	// which need initial signatures to function once the tailnet key
	// authority is in use. The generated signatures should then be
	// submitted in a /tka/init/finish RPC.
	NeedSignatures []TKASignInfo
}

TKAInitBeginResponse is the JSON response from a /tka/init/begin RPC. This structure describes node information which must be signed to complete initialization of the tailnets' key authority.

type TKAInitFinishRequest added in v1.30.0

type TKAInitFinishRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Signatures are serialized tka.NodeKeySignatures for all nodes
	// in the tailnet.
	Signatures map[NodeID]tkatype.MarshaledSignature

	// SupportDisablement is a disablement secret for Tailscale support.
	// This is only generated if --gen-disablement-for-support is specified
	// in an invocation to 'tailscale lock init'.
	SupportDisablement []byte `json:",omitempty"`
}

TKAInitFinishRequest is the JSON request of a /tka/init/finish RPC. This RPC finalizes initialization of the tailnet key authority by submitting node-key signatures for all existing nodes.

type TKAInitFinishResponse added in v1.30.0

type TKAInitFinishResponse struct {
}

TKAInitFinishResponse is the JSON response from a /tka/init/finish RPC. This schema describes the successful enablement of the tailnet's key authority.

type TKASignInfo added in v1.30.0

type TKASignInfo struct {
	// NodeID is the ID of the node which needs a signature. It must
	// correspond to NodePublic.
	NodeID NodeID
	// NodePublic is the node (Wireguard) public key which is being
	// signed.
	NodePublic key.NodePublic

	// RotationPubkey specifies the public key which may sign
	// a NodeKeySignature (NKS), which rotates the node key.
	//
	// This is necessary so the node can rotate its node-key without
	// talking to a node which holds a trusted network-lock key.
	// It does this by nesting the original NKS in a 'rotation' NKS,
	// which it then signs with the key corresponding to RotationPubkey.
	//
	// This field expects a raw ed25519 public key.
	RotationPubkey []byte
}

TKASignInfo describes information about an existing node that needs to be signed into a node-key signature.

type TKASignaturesUsingKeyRequest added in v1.38.0

type TKASignaturesUsingKeyRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// KeyID is the key we are querying using.
	KeyID tkatype.KeyID
}

TKASignaturesUsingKeyRequest asks the control plane for all signatures which are signed by the provided keyID.

This is the request schema for a /tka/affected-sigs RPC.

type TKASignaturesUsingKeyResponse added in v1.38.0

type TKASignaturesUsingKeyResponse struct {
	Signatures []tkatype.MarshaledSignature
}

TKASignaturesUsingKeyResponse is the JSON response to a /tka/affected-sigs RPC.

It enumerates all signatures which are signed by the queried keyID.

type TKASubmitSignatureRequest added in v1.34.0

type TKASubmitSignatureRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key. The node-key which
	// is being signed is embedded in Signature.
	NodeKey key.NodePublic

	// Signature encodes the node-key signature being submitted.
	Signature tkatype.MarshaledSignature
}

TKASubmitSignatureRequest transmits a node-key signature to the control plane.

This is the request schema for a /tka/sign noise RPC.

type TKASubmitSignatureResponse added in v1.34.0

type TKASubmitSignatureResponse struct {
}

TKASubmitSignatureResponse is the JSON response from a /tka/sign RPC.

type TKASyncOfferRequest added in v1.32.0

type TKASyncOfferRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Head represents the node's head AUMHash (tka.Authority.Head). This
	// corresponds to tka.SyncOffer.Head.
	Head string
	// Ancestors represents a selection of ancestor AUMHash values ascending
	// from the current head. This corresponds to tka.SyncOffer.Ancestors.
	Ancestors []string
}

TKASyncOfferRequest encodes a request to synchronize tailnet key authority state (TKA). Values of type tka.AUMHash are encoded as strings in their MarshalText form.

type TKASyncOfferResponse added in v1.32.0

type TKASyncOfferResponse struct {
	// Head represents the control plane's head AUMHash (tka.Authority.Head).
	// This corresponds to tka.SyncOffer.Head.
	Head string
	// Ancestors represents a selection of ancestor AUMHash values ascending
	// from the control plane's head. This corresponds to
	// tka.SyncOffer.Ancestors.
	Ancestors []string
	// MissingAUMs encodes AUMs that the control plane believes the node
	// is missing.
	MissingAUMs []tkatype.MarshaledAUM
}

TKASyncOfferResponse encodes a response in synchronizing a node's tailnet key authority state. Values of type tka.AUMHash are encoded as strings in their MarshalText form.

type TKASyncSendRequest added in v1.32.0

type TKASyncSendRequest struct {
	// Version is the client's capabilities.
	Version CapabilityVersion

	// NodeKey is the client's current node key.
	NodeKey key.NodePublic

	// Head represents the node's head AUMHash (tka.Authority.Head) after
	// applying any AUMs from the sync-offer response.
	// It is encoded as tka.AUMHash.MarshalText.
	Head string

	// MissingAUMs encodes AUMs that the node believes the control plane
	// is missing.
	MissingAUMs []tkatype.MarshaledAUM

	// Interactive is true if additional error checking should be performed as
	// the request is on behalf of an interactive operation (e.g., an
	// administrator publishing new changes) as opposed to an automatic
	// synchronization that may be reporting lost data.
	Interactive bool
}

TKASyncSendRequest encodes AUMs that a node believes the control plane is missing, and notifies control of its local TKA state (specifically the head hash).

type TKASyncSendResponse added in v1.32.0

type TKASyncSendResponse struct {
	// Head represents the control plane's head AUMHash (tka.Authority.Head),
	// after applying the missing AUMs.
	Head string
}

TKASyncSendResponse encodes the control plane's response to a node submitting AUMs during AUM synchronization.

type TokenRequest added in v1.24.0

type TokenRequest struct {
	// CapVersion is the client's current CapabilityVersion.
	CapVersion CapabilityVersion
	// NodeKey is the client's current node key.
	NodeKey key.NodePublic
	// Audience the token is being requested for.
	Audience string
}

TokenRequest is a request to get an OIDC ID token for an audience. The token can be presented to any resource provider which offers OIDC Federation.

It is JSON-encoded and sent over Noise to "/machine/id-token".

type TokenResponse added in v1.24.0

type TokenResponse struct {
	// IDToken is a JWT encoding the following standard claims:
	//
	//   `sub` | the MagicDNS name of the node
	//   `aud` | Audience from the request
	//   `exp` | Token expiry
	//   `iat` | Token issuance time
	//   `iss` | Issuer
	//   `jti` | Random token identifier
	//   `nbf` | Not before time
	//
	// It also encodes the following Tailscale specific claims:
	//
	//   `key`       | the node public key
	//   `addresses` | the Tailscale IPs of the node
	//   `nid`       | the node ID
	//   `node`      | the name of the node
	//   `domain`    | the domain of the node, it has the same format as MapResponse.Domain.
	//   `tags`      | an array of <domain:tag> on the node (like alice.github:tag:foo or example.com:tag:foo)
	//   `user`      | user emailish (like alice.github:alice@github or example.com:bob@example.com), if not tagged
	//   `uid`       | user ID, if not tagged
	IDToken string `json:"id_token"`
}

TokenResponse is the response to a TokenRequest.

type User

type User struct {
	ID            UserID
	LoginName     string `json:"-"` // not stored, filled from Login // TODO REMOVE
	DisplayName   string // if non-empty overrides Login field
	ProfilePicURL string // if non-empty overrides Login field
	Logins        []LoginID
	Created       time.Time
}

User is an IPN user.

A user can have multiple logins associated with it (e.g. gmail and github oauth). (Note: none of our UIs support this yet.)

Some properties are inherited from the logins and can be overridden, such as display name and profile picture.

Other properties must be the same for all logins associated with a user. In particular: domain. If a user has a "tailscale.io" domain login, they cannot have a general gmail address login associated with the user.

func (*User) Clone

func (src *User) Clone() *User

Clone makes a deep copy of User. The result aliases no memory with the original.

func (*User) View added in v1.26.0

func (p *User) View() UserView

View returns a readonly view of User.

type UserID

type UserID ID

func (UserID) IsZero added in v1.2.0

func (u UserID) IsZero() bool

func (UserID) String

func (id UserID) String() string

type UserProfile

type UserProfile struct {
	ID            UserID
	LoginName     string // "alice@smith.com"; for display purposes only (provider is not listed)
	DisplayName   string // "Alice Smith"
	ProfilePicURL string

	// Roles exists for legacy reasons, to keep old macOS clients
	// happy. It JSON marshals as [].
	Roles emptyStructJSONSlice
}

A UserProfile is display-friendly data for a user. It includes the LoginName for display purposes but *not* the Provider. It also includes derived data from one of the user's logins.

func (*UserProfile) Clone added in v1.48.0

func (src *UserProfile) Clone() *UserProfile

Clone makes a deep copy of UserProfile. The result aliases no memory with the original.

func (*UserProfile) Equal added in v1.48.0

func (p *UserProfile) Equal(p2 *UserProfile) bool

func (*UserProfile) View added in v1.48.0

func (p *UserProfile) View() UserProfileView

View returns a readonly view of UserProfile.

type UserProfileView added in v1.48.0

type UserProfileView struct {
	// contains filtered or unexported fields
}

UserProfileView provides a read-only view over UserProfile.

Its methods should only be called if `Valid()` returns true.

func (UserProfileView) AsStruct added in v1.48.0

func (v UserProfileView) AsStruct() *UserProfile

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (UserProfileView) DisplayName added in v1.48.0

func (v UserProfileView) DisplayName() string

func (UserProfileView) Equal added in v1.48.0

func (v UserProfileView) Equal(v2 UserProfileView) bool

func (UserProfileView) ID added in v1.48.0

func (v UserProfileView) ID() UserID

func (UserProfileView) LoginName added in v1.48.0

func (v UserProfileView) LoginName() string

func (UserProfileView) MarshalJSON added in v1.48.0

func (v UserProfileView) MarshalJSON() ([]byte, error)

func (UserProfileView) ProfilePicURL added in v1.48.0

func (v UserProfileView) ProfilePicURL() string

func (UserProfileView) Roles added in v1.48.0

func (v UserProfileView) Roles() emptyStructJSONSlice

func (*UserProfileView) UnmarshalJSON added in v1.48.0

func (v *UserProfileView) UnmarshalJSON(b []byte) error

func (UserProfileView) Valid added in v1.48.0

func (v UserProfileView) Valid() bool

Valid reports whether underlying value is non-nil.

type UserView added in v1.26.0

type UserView struct {
	// contains filtered or unexported fields
}

UserView provides a read-only view over User.

Its methods should only be called if `Valid()` returns true.

func (UserView) AsStruct added in v1.26.0

func (v UserView) AsStruct() *User

AsStruct returns a clone of the underlying value which aliases no memory with the original.

func (UserView) Created added in v1.26.0

func (v UserView) Created() time.Time

func (UserView) DisplayName added in v1.26.0

func (v UserView) DisplayName() string

func (UserView) ID added in v1.26.0

func (v UserView) ID() UserID

func (UserView) LoginName added in v1.26.0

func (v UserView) LoginName() string

func (UserView) Logins added in v1.26.0

func (v UserView) Logins() views.Slice[LoginID]

func (UserView) MarshalJSON added in v1.26.0

func (v UserView) MarshalJSON() ([]byte, error)

func (UserView) ProfilePicURL added in v1.26.0

func (v UserView) ProfilePicURL() string

func (*UserView) UnmarshalJSON added in v1.26.0

func (v *UserView) UnmarshalJSON(b []byte) error

func (UserView) Valid added in v1.26.0

func (v UserView) Valid() bool

Valid reports whether underlying value is non-nil.

type VIPService added in v1.78.0

type VIPService struct {
	// Name is the name of the service, of the form `svc:dns-label`.
	// See CheckServiceName for a validation func.
	// Name uniquely identifies a service on a particular tailnet,
	// and so also corresponds uniquely to the pair of IP addresses
	// belonging to the VIP service.
	Name string

	// Ports specify which ProtoPorts are made available by this node
	// on the service's IPs.
	Ports []ProtoPortRange

	// Active specifies whether new requests for the service should be
	// sent to this node by control.
	Active bool
}

VIPService represents a service created on a tailnet from the perspective of a node providing that service. These services have an virtual IP (VIP) address pair distinct from the node's IPs.

type WebClientAuthResponse added in v1.52.0

type WebClientAuthResponse struct {
	// ID is a unique identifier for the session auth request.
	// It can be supplied to "/machine/webclient/wait" to pause until
	// the session authentication has been completed.
	ID string `json:",omitempty"`

	// URL is the link for the user to visit to authenticate the session.
	//
	// When empty, there is no action for the user to take.
	URL string `json:",omitempty"`

	// Complete is true when the session authentication has been completed.
	Complete bool `json:",omitempty"`
}

WebClientAuthResponse is the response to a web client authentication request sent to "/machine/webclient/action" or "/machine/webclient/wait". See client/web for usage.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL