Skip to main content

Node

Struct Node 

Source
pub struct Node<'a> {
Show 33 fields pub id: NodeId, pub stable_id: StableNodeId<'a>, pub name: Cow<'a, str>, pub user: UserId, pub sharer: UserId, pub key: NodePublicKey, pub key_expiry: Option<DateTime<Utc>>, pub key_signature: MarshaledSignature<'a>, pub machine: Option<MachinePublicKey>, pub disco_key: Option<DiscoPublicKey>, pub addresses: Vec<IpNet>, pub allowed_ips: Option<Vec<IpNet>>, pub endpoints: Vec<SocketAddr>, pub legacy_derp_string: Option<RegionId>, pub home_derp: Option<RegionId>, pub host_info: HostInfo<'a>, pub created: DateTime<Utc>, pub cap: CapabilityVersion, pub tags: Option<Vec<&'a str>>, pub primary_routes: Vec<IpNet>, pub last_seen: Option<DateTime<Utc>>, pub online: Option<bool>, pub machine_authorized: bool, pub capabilities: Vec<NodeCap<'a>>, pub cap_map: Map<'a>, pub unsigned_peer_api_only: bool, pub data_plane_audit_log_id: &'a str, pub expired: bool, pub self_node_v4_masq_addr_for_this_peer: Option<IpAddr>, pub self_node_v6_masq_addr_for_this_peer: Option<IpAddr>, pub is_wireguard_only: bool, pub is_jailed: bool, pub exit_node_dns_resolvers: Vec<DnsResolver<'a>>,
}
Expand description

A Tailscale device in a Tailnet.

The struct-level #[serde_with::apply] block makes every Vec/map field tolerate a wire null (Go marshals empty omitempty slices/maps as null; see crate::util::null_to_default). Applying it at the struct level — rather than annotating each field — means any Vec/map field added later is covered automatically, closing the recurring “forgot a field” gap that broke decoding against IPv6-off control planes. Option<Vec<…>> fields (e.g. allowed_ips, tags) are written as Option<Vec<…>>, matched by none of the rules below (the apply macro matches the type exactly as written), so they keep their nullNone semantics untouched. The path-qualified ts_nodecapability::Map rule is required because the cap_map field is written with that full path — a bare Map token would not match it.

Fields§

§id: NodeId

A unique integer ID for the Tailscale node.

§stable_id: StableNodeId<'a>

A string representation of the Tailscale node’s Node::id field.

§name: Cow<'a, str>

The fully-qualified domain name (FQDN) of this node, as well as the MagicDNS name for the node. Ends with a trailing dot, e.g. “host.tail-scale.ts.net.”

§user: UserId

Unique ID of the User who created the node.

If ACL tags are in use for the node, this field doesn’t reflect the ACL identity that the node is running as.

§sharer: UserId

Unique ID of the user who shared this node, if non-zero and different from Node::user.

§key: NodePublicKey

If populated, the public key of the Tailscale node’s NodeKeyPair.

§key_expiry: Option<DateTime<Utc>>

The date and time that the Tailscale node’s NodeKeyPair will expire.

§key_signature: MarshaledSignature<'a>

If populated, a signature of the Tailnet Key Authority (TKA) key authorizing the Tailscale node to join the Tailnet.

§machine: Option<MachinePublicKey>

If populated, the public key of the Tailscale node’s MachineKeyPair.

§disco_key: Option<DiscoPublicKey>

If populated, the public key of the Tailscale node’s DiscoKeyPair.

§addresses: Vec<IpNet>

The IP addresses (CIDR prefixes) assigned to this node in the tailnet (Go tailcfg.Node’s Addresses []netip.Prefix).

A variable-length list, NOT a fixed (v4, v6) pair: a node on an IPv4-only tailnet (e.g. an IPv6-off control plane / Headscale) is assigned only an IPv4 prefix, so this has length 1. Modeling it as a 2-tuple broke deserialization against such control planes (“invalid length 1, expected a tuple of size 2”). The domain Node picks the first IPv4 and (optionally) the first IPv6 prefix out of this list.

null tolerance is supplied by the struct-level #[serde_with::apply] block.

§allowed_ips: Option<Vec<IpNet>>

IP ranges to route to this node.

As of CapabilityVersion::V112, this may be null/undefined on the wire to indicate the value is the same as Node::addresses. Once deserialized, it must always be populated, even if those values are identical to Node::addresses.

§endpoints: Vec<SocketAddr>

IP addresses/ports that this node can be reached directly on.

Examples include public IP addresses/ports discovered via disco/STUN, or LAN-local IP addresses/ports.

§legacy_derp_string: Option<RegionId>
👎Deprecated:

use Node::home_derp field instead

Deprecated. This node’s home DERP region ID, 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 number keys over the letters DERP on a QWERTY keyboard (3.3.40)). The “port number” is the home DERP region ID.

The Node::home_derp field has replaced this since capability version 111, but old servers might still send this field (see tailscale/tailscale#14636). Do not use this field in code other than to upgrade/canonicalize the value to use Node::home_derp if a "LegacyDERPString" field arrives on the wire.

§home_derp: Option<RegionId>

Unique ID of this node’s home DERP region.

May be zero if not yet known, but will ideally always be non-zero for normal connectivity; as DERP is used to discover direct connections, a home DERP region ID of zero prevents direct connection types from being discovered until its home DERP region ID is populated.

Preferred over the Node::legacy_derp_string field and supported by clients as of CapabilityVersion 111.

§host_info: HostInfo<'a>

A summary of the host that a Tailscale node is running on. Includes information about the version of Tailscale running on the host, the operating system, running services, and various diagnostic/logging and configuration values.

Wire key Hostinfo — Go names the field Hostinfo (lowercase i, tailcfg.go:406), so serde PascalCase (HostInfo) is wrong and a strict Go decoder drops it.

§created: DateTime<Utc>

The date/time this Tailscale node was created (added to the Tailnet for the first time).

§cap: CapabilityVersion

The node’s CapabilityVersion; old servers may not send this value across the wire.

§tags: Option<Vec<&'a str>>

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
§primary_routes: Vec<IpNet>

The routes from Node::allowed_ips 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 Node::addresses that are in Node::allowed_ips.

§last_seen: Option<DateTime<Utc>>

When the node was last online. Only updated when Node::online is false. It is None if the current node doesn’t have permission to know, or the node has never been online.

§online: Option<bool>

Whether the node is currently connected to the control plane. A value of None means:

  1. The online status of the node is unknown
  2. The current node doesn’t have permission to know whether this node is online
  3. The node has never been online
§machine_authorized: bool

Whether or not the Tailscale node is authorized to be part of the Tailnet.

§capabilities: Vec<NodeCap<'a>>
👎Deprecated:

use Node::cap_map instead

Deprecated. Capabilities of this node.

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

Replaced by the Node::cap_map field since capability version 89; use that field instead (see tailscale/tailscale#11508).

§cap_map: Map<'a>

Map of capabilities to their optional argument/data values.

It is valid for a capability to not have any argument/data values. These type of capabilities 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 an entry in Node::cap_map with an empty value.

See NodeCap for more information on keys.

Metadata about nodes can be transmitted in 3 ways:

  1. MapResponse::node::cap_map 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::packet_filters describes access (both IP- and application-based) that should be granted to peers.
  3. MapResponse::peers::cap_map 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.
§unsigned_peer_api_only: bool

Indicates this node is not signed nor subject to Tailnet Key Authority (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 Tailscale client’s job to double-check the MapResponse::packet_filter field to verify that its Node::allowed_ips will not be accepted by the packet filter.

§data_plane_audit_log_id: &'a str

The per-node logtail ID used for data plane audit logging.

§expired: bool

Whether or not 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.

§self_node_v4_masq_addr_for_this_peer: Option<IpAddr>

The IPv4 address that this peer knows the current node as. It may be None if the peer knows the current node by its native IPv4 address.

This field is only populated in MapResponse::peers, and will not be populated 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).

§self_node_v6_masq_addr_for_this_peer: Option<IpAddr>

The IPv6 address that this peer knows the current node as. It may be None if the peer knows the current node by its native IPv6 address.

This field is only populated in MapResponse::peers, and will not be populated 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).

§is_wireguard_only: bool

Indicates that this is a non-Tailscale WireGuard peer.

WireGuard-only peers are not expected to speak Disco or DERP, and must have valid values in Node::endpoints to be reachable.

§is_jailed: bool

Indicates that this node is jailed and should not be allowed initiate connections, but should be allowed to accept inbound connections.

§exit_node_dns_resolvers: Vec<DnsResolver<'a>>

The list of DNS servers that should be used when this node is WireGuard-only and being used as an exit node.

Trait Implementations§

Source§

impl<'a> Clone for Node<'a>

Source§

fn clone(&self) -> Node<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for Node<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Default for Node<'a>

Source§

fn default() -> Node<'a>

Returns the “default value” for a type. Read more
Source§

impl<'de: 'a, 'a> Deserialize<'de> for Node<'a>
where Node<'a>: Default,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<'a> Serialize for Node<'a>

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Node<'a>

§

impl<'a> RefUnwindSafe for Node<'a>

§

impl<'a> Send for Node<'a>

§

impl<'a> Sync for Node<'a>

§

impl<'a> Unpin for Node<'a>

§

impl<'a> UnsafeUnpin for Node<'a>

§

impl<'a> UnwindSafe for Node<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.