tailcfg

package
v1.26.1 Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2022 License: BSD-3-Clause Imports: 15 Imported by: 181

Documentation

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
)
View Source
const (
	CapabilityFileSharing = "https://tailscale.com/cap/file-sharing"
	CapabilityAdmin       = "https://tailscale.com/cap/is-admin"
	CapabilitySSH         = "https://tailscale.com/cap/ssh"         // feature enabled/available
	CapabilitySSHRuleIn   = "https://tailscale.com/cap/ssh-rule-in" // some SSH rule reach this node

	// CapabilityFileSharingSend grants the ability to receive files from a
	// node that's owned by a different user.
	CapabilityFileSharingSend = "https://tailscale.com/cap/file-send"
	// CapabilityDebugPeer grants the ability for a peer to read this node's
	// goroutines, metrics, magicsock internal state, etc.
	CapabilityDebugPeer = "https://tailscale.com/cap/debug-peer"
	// CapabilityWakeOnLAN grants the ability to send a Wake-On-LAN packet.
	CapabilityWakeOnLAN = "https://tailscale.com/cap/wake-on-lan"
)

Variables

View Source
var FilterAllowAll = []FilterRule{
	{
		SrcIPs:  []string{"*"},
		SrcBits: nil,
		DstPorts: []NetPortRange{{
			IP:    "*",
			Bits:  nil,
			Ports: PortRange{0, 65535},
		}},
	},
}
View Source
var PortRangeAny = PortRange{0, 65535}

Functions

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,DERPRegion,DERPMap,DERPNode.

Types

type CapGrant added in v1.24.0

type CapGrant struct {
	// Dsts are the destination IP ranges that this capabilty
	// grant matches.
	Dsts []netaddr.IPPrefix

	// Caps are the capabilities the source IP matched by
	// FilterRule.SrcIPs are granted to the destination IP,
	// matched by Dsts.
	Caps []string `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), 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 = 32

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

type DERPMap added in v0.98.1

type DERPMap struct {
	// 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.
	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) 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"`
}

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) 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) 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

	// 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) 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 []netaddr.IP `json:",omitempty"`

	// PerDomain is not set by the control server, and does nothing.
	PerDomain bool `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 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
}

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[netaddr.IP]

func (DNSConfigView) PerDomain added in v1.26.0

func (v DNSConfigView) PerDomain() bool

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) 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 {
	// LogHeapPprof controls whether the client should log
	// its heap pprof data. Each true value sent from the server
	// means that client should do one more log.
	LogHeapPprof bool `json:",omitempty"`

	// LogHeapURL is the URL to POST its heap pprof to.
	// Empty means to not log.
	LogHeapURL string `json:",omitempty"`

	// ForceBackgroundSTUN controls whether magicsock should
	// always do its background STUN queries (see magicsock's
	// periodicReSTUN), regardless of inactivity.
	ForceBackgroundSTUN bool `json:",omitempty"`

	// DERPRoute controls whether the DERP reverse path
	// optimization (see Issue 150) should be enabled or
	// disabled. The environment variable in magicsock is the
	// highest priority (if set), then this (if set), then the
	// binary default value.
	DERPRoute opt.Bool `json:",omitempty"`

	// TrimWGConfig controls whether Tailscale does lazy, on-demand
	// wireguard configuration of peers.
	TrimWGConfig opt.Bool `json:",omitempty"`

	// DisableSubnetsIfPAC controls whether subnet routers should be
	// disabled if WPAD is present on the network.
	DisableSubnetsIfPAC opt.Bool `json:",omitempty"`

	// GoroutineDumpURL, if non-empty, requests that the client do
	// a one-time dump of its active goroutines to the given URL.
	GoroutineDumpURL string `json:",omitempty"`

	// SleepSeconds requests that the client sleep for the
	// provided number of seconds.
	// The client can (and should) limit the value (such as 5
	// minutes).
	SleepSeconds float64 `json:",omitempty"`

	// RandomizeClientPort is whether magicsock should UDP bind to
	// :0 to get a random local port, ignoring any configured
	// fixed port.
	RandomizeClientPort bool `json:",omitempty"`

	// OneCGNATRoute controls whether the client should prefer to make one
	// big CGNAT /10 route rather than a /32 per peer.
	OneCGNATRoute opt.Bool `json:",omitempty"`

	// DisableUPnP is whether the client will attempt to 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 to True to kill
	// new attempts at UPnP connections.
	DisableUPnP opt.Bool `json:",omitempty"`

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

	// Exit optionally specifies that the client should os.Exit
	// with this code.
	Exit *int `json:",omitempty"`
}

Debug are instructions from the control server to the client to adjust debug settings.

type Endpoint added in v1.8.0

type Endpoint struct {
	Addr netaddr.IPPort
	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")
	SrcIPs []string

	// SrcBits is deprecated; it's 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.
	SrcBits []int `json:",omitempty"`

	// DstPorts are the port ranges to allow once a source IP
	// matches (is in the CIDR described by SrcIPs & SrcBits).
	//
	// 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 SrcBits), and a set of destination targets that are then allowed if a source IP is mathces of those CIDRs.

type Hostinfo

type Hostinfo struct {
	IPNVersion    string             `json:",omitempty"` // version of this code
	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     string             `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041")
	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")
	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
	GoArch        string             `json:",omitempty"` // the host's GOARCH value (of the running binary)
	RoutableIPs   []netaddr.IPPrefix `json:",omitempty"` // set of IP ranges this client can route
	RequestTags   []string           `json:",omitempty"` // set of ACL tags this node wants to claim
	Services      []Service          `json:",omitempty"` // services advertised by this machine
	NetInfo       *NetInfo           `json:",omitempty"`
	SSH_HostKeys  []string           `json:"sshHostKeys,omitempty"` // if advertised

}

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) 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) 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) 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) 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) 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) 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) 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) 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.IPPrefixSlice

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) 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) UnmarshalJSON added in v1.22.0

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

func (HostinfoView) Valid added in v1.22.0

func (v HostinfoView) Valid() bool

Valid reports whether underlying value is non-nil.

type ID

type ID int64

func (ID) String

func (id ID) String() string

type Login

type Login struct {
	ID            LoginID
	Provider      string
	LoginName     string
	DisplayName   string
	ProfilePicURL string
	Domain        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) Domain added in v1.26.0

func (v LoginView) Domain() 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) 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
	IncludeIPv6 bool `json:",omitempty"` // include IPv6 endpoints in returned Node Endpoints (for Version 4 clients)
	Stream      bool // if true, multiple MapResponse objects are returned
	Hostinfo    *Hostinfo

	// Endpoints are the client's magicsock UDP ip:port endpoints (IPv4 or IPv6).
	Endpoints []string
	// EndpointTypes are the types of the corresponding endpoints in Endpoints.
	EndpointTypes []EndpointType `json:",omitempty"`

	// ReadOnly is whether the client just wants to fetch the
	// MapResponse, without updating their Endpoints. The
	// Endpoints field will be ignored and LastSeen will not be
	// updated and peers will not be notified of changes.
	//
	// The intended use is for clients to discover the DERP map at
	// start-up before their first real endpoint update.
	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 start a long-poll 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 {
	// 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

	// 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"`

	// 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"`

	// DNS is the same as DNSConfig.Nameservers.
	// Only populated if MapRequest.Version < 9.
	DNS []netaddr.IP `json:",omitempty"`

	// SearchPaths is the old way to specify DNS search domains.
	// Only populated if MapRequest.Version < 9.
	SearchPaths []string `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).
	PacketFilter []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.
	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"`

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

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 IPv6 works.
	WorkingIPv6 opt.Bool

	// WorkingUDP is whether UDP works.
	WorkingUDP 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 DERP server
	// for incoming traffic. The node might be be temporarily
	// connected to multiple DERP servers (to send to other nodes)
	// but PreferredDERP is the instance number 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"`
}

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) 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) 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) 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 old way to turn IP into a CIDR
	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     string // DNS

	// 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
	Machine    key.MachinePublic
	DiscoKey   key.DiscoPublic
	Addresses  []netaddr.IPPrefix // IP addresses of this Node directly
	AllowedIPs []netaddr.IPPrefix // range of IP addresses to route to this node
	Endpoints  []string           `json:",omitempty"` // IP+port (public via STUN, and local LANs)
	DERP       string             `json:",omitempty"` // DERP-in-IP:port ("127.3.3.40:N") endpoint
	Hostinfo   HostinfoView
	Created    time.Time

	// 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 []netaddr.IPPrefix `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"`

	KeepAlive bool `json:",omitempty"` // open and keep open a connection to this peer

	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"
	Capabilities []string `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
	// 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 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) 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) View added in v1.26.0

func (p *Node) View() NodeView

View returns a readonly view of Node.

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.IPPrefixSlice

func (NodeView) AllowedIPs added in v1.26.0

func (v NodeView) AllowedIPs() views.IPPrefixSlice

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) Capabilities added in v1.26.0

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

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) DiscoKey added in v1.26.0

func (v NodeView) DiscoKey() key.DiscoPublic

func (NodeView) Endpoints added in v1.26.0

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

func (NodeView) Equal added in v1.26.0

func (v NodeView) Equal(v2 NodeView) bool

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) KeepAlive added in v1.26.0

func (v NodeView) KeepAlive() 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) 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.IPPrefixSlice

func (NodeView) Sharer added in v1.26.0

func (v NodeView) Sharer() UserID

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) 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 orgnanization can put TLS roots on devices.

type PingRequest added in v1.6.0

type PingRequest struct {
	// URL is the URL to send a HEAD request 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.
	// If Types and IP are defined, then URL is the URL to send a POST request to.
	URL string

	// 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"
	Types string

	// IP is the ping target.
	// It is used in TSMP pings, if IP is invalid or empty then do a HEAD request to the URL.
	IP netaddr.IP
}

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.

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
	Auth       struct {

		// One of Provider/LoginName, Oauth2Token, or AuthKey is set.
		Provider, LoginName string
		Oauth2Token         *Oauth2Token
		AuthKey             string
		// contains filtered or unexported fields
	}
	// 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"`

	// 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
	// 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 (req *RegisterRequest) Clone() *RegisterRequest

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

TODO: extend cmd/cloner to generate this method.

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

	// Error indiciates 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 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) 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"`
}

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

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.

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"`
}

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

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": the local peerapi service supports
	//        being a DNS proxy (when the node is an exit
	//        node). For this service, the Port number is really
	//        the version number of the service.
	Proto ServiceProto

	// Port is the port number.
	//
	// For Proto "peerapi-dns", it's the version number of the DNS proxy,
	// currently 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) 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 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
	Domain        string
	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 inhereted 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.

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) Domain added in v1.26.0

func (v UserView) Domain() 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.

Jump to

Keyboard shortcuts

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