Documentation
¶
Overview ¶
Package disco contains the discovery message types.
A discovery message is:
Header:
magic [6]byte // “TS💬” (0x54 53 f0 9f 92 ac) senderDiscoPub [32]byte // nacl public key nonce [24]byte
The recipient then decrypts the bytes following (the nacl box) and then the inner payload structure is:
messageType byte (the MessageType constants below) messageVersion byte (0 for now; but always ignore bytes at the end) message-payload [...]byte
Index ¶
- Constants
- func LooksLikeDiscoWrapper(p []byte) bool
- func MessageSummary(m Message) string
- func Source(p []byte) (src []byte, ok bool)
- func ToPCAPFrame(src netip.AddrPort, derpNodeSrc key.NodePublic, payload []byte) []byte
- type AllocateUDPRelayEndpointRequest
- type AllocateUDPRelayEndpointResponse
- type BindUDPRelayEndpoint
- type BindUDPRelayEndpointAnswer
- type BindUDPRelayEndpointChallenge
- type BindUDPRelayEndpointCommon
- type BindUDPRelayHandshakeState
- type CallMeMaybe
- type CallMeMaybeVia
- type Message
- type MessageType
- type Ping
- type Pong
- type UDPRelayEndpoint
Constants ¶
const ( TypePing = MessageType(0x01) TypePong = MessageType(0x02) TypeCallMeMaybe = MessageType(0x03) TypeBindUDPRelayEndpoint = MessageType(0x04) TypeBindUDPRelayEndpointChallenge = MessageType(0x05) TypeBindUDPRelayEndpointAnswer = MessageType(0x06) TypeCallMeMaybeVia = MessageType(0x07) TypeAllocateUDPRelayEndpointRequest = MessageType(0x08) TypeAllocateUDPRelayEndpointResponse = MessageType(0x09) )
const BindUDPRelayChallengeLen = 32
BindUDPRelayChallengeLen is the length of the Challenge field carried in BindUDPRelayEndpointChallenge & BindUDPRelayEndpointAnswer messages.
const Magic = "TS💬" // 6 bytes: 0x54 53 f0 9f 92 ac
Magic is the 6 byte header of all discovery messages.
const MessageHeaderLen = 2
MessageHeaderLen is the length of a message header, 2 bytes for type and version.
const NonceLen = 24
NonceLen is the length of the nonces used by nacl box.
const PingLen = 12 + key.NodePublicRawLen
PingLen is the length of a marshalled ping message, without the message header or padding.
Variables ¶
This section is empty.
Functions ¶
func LooksLikeDiscoWrapper ¶ added in v1.0.0
LooksLikeDiscoWrapper reports whether p looks like it's a packet containing an encrypted disco message.
func MessageSummary ¶
MessageSummary returns a short summary of m for logging purposes.
func Source ¶ added in v1.14.6
Source returns the slice of p that represents the disco public key source, and whether p looks like a disco message.
func ToPCAPFrame ¶ added in v1.48.0
ToPCAPFrame marshals the bytes for a pcap record that describe a disco frame.
Warning: Alloc garbage. Acceptable while capturing.
Types ¶
type AllocateUDPRelayEndpointRequest ¶ added in v1.86.0
type AllocateUDPRelayEndpointRequest struct { // ClientDisco are the Disco public keys of the clients that should be // permitted to handshake with the endpoint. ClientDisco [2]key.DiscoPublic // Generation represents the allocation request generation. The server must // echo it back in the [AllocateUDPRelayEndpointResponse] to enable request // and response alignment client-side. Generation uint32 }
AllocateUDPRelayEndpointRequest is a message sent only over DERP to request allocation of a relay endpoint on a tailscale.com/net/udprelay.Server
func (*AllocateUDPRelayEndpointRequest) AppendMarshal ¶ added in v1.86.0
func (m *AllocateUDPRelayEndpointRequest) AppendMarshal(b []byte) []byte
type AllocateUDPRelayEndpointResponse ¶ added in v1.86.0
type AllocateUDPRelayEndpointResponse struct { // Generation represents the allocation request generation. The server must // echo back the [AllocateUDPRelayEndpointRequest.Generation] here to enable // request and response alignment client-side. Generation uint32 UDPRelayEndpoint }
AllocateUDPRelayEndpointResponse is a message sent only over DERP in response to a AllocateUDPRelayEndpointRequest.
func (*AllocateUDPRelayEndpointResponse) AppendMarshal ¶ added in v1.86.0
func (m *AllocateUDPRelayEndpointResponse) AppendMarshal(b []byte) []byte
type BindUDPRelayEndpoint ¶ added in v1.84.0
type BindUDPRelayEndpoint struct {
BindUDPRelayEndpointCommon
}
BindUDPRelayEndpoint is the first messaged transmitted from UDP relay client towards UDP relay server as part of the 3-way bind handshake.
func (*BindUDPRelayEndpoint) AppendMarshal ¶ added in v1.84.0
func (m *BindUDPRelayEndpoint) AppendMarshal(b []byte) []byte
type BindUDPRelayEndpointAnswer ¶ added in v1.84.0
type BindUDPRelayEndpointAnswer struct {
BindUDPRelayEndpointCommon
}
BindUDPRelayEndpointAnswer is transmitted from UDP relay client to UDP relay server in response to a BindUDPRelayEndpointChallenge message.
func (*BindUDPRelayEndpointAnswer) AppendMarshal ¶ added in v1.84.0
func (m *BindUDPRelayEndpointAnswer) AppendMarshal(b []byte) []byte
type BindUDPRelayEndpointChallenge ¶ added in v1.84.0
type BindUDPRelayEndpointChallenge struct {
BindUDPRelayEndpointCommon
}
BindUDPRelayEndpointChallenge is transmitted from UDP relay server towards UDP relay client in response to a BindUDPRelayEndpoint message as part of the 3-way bind handshake.
func (*BindUDPRelayEndpointChallenge) AppendMarshal ¶ added in v1.84.0
func (m *BindUDPRelayEndpointChallenge) AppendMarshal(b []byte) []byte
type BindUDPRelayEndpointCommon ¶ added in v1.86.0
type BindUDPRelayEndpointCommon struct { // VNI is the Geneve header Virtual Network Identifier field value, which // must match this disco-sealed value upon reception. If they are // non-matching it indicates the cleartext Geneve header was tampered with // and/or mangled. VNI uint32 // Generation represents the handshake generation. Clients must set a new, // nonzero value at the start of every handshake. Generation uint32 // RemoteKey is the disco key of the remote peer participating over this // relay endpoint. RemoteKey key.DiscoPublic // Challenge is set by the server in a [BindUDPRelayEndpointChallenge] // message, and expected to be echoed back by the client in a // [BindUDPRelayEndpointAnswer] message. Its value is irrelevant in a // [BindUDPRelayEndpoint] message, where it simply serves a padding purpose // ensuring all handshake messages are equal in size. Challenge [BindUDPRelayChallengeLen]byte }
BindUDPRelayEndpointCommon contains fields that are common across all 3 UDP relay handshake message types. All 4 field values are expected to be consistent for the lifetime of a handshake besides Challenge, which is irrelevant in a BindUDPRelayEndpoint message.
type BindUDPRelayHandshakeState ¶ added in v1.84.0
type BindUDPRelayHandshakeState int
BindUDPRelayHandshakeState represents the state of the 3-way bind handshake between UDP relay client and UDP relay server. Its potential values include those for both participants, UDP relay client and UDP relay server. A UDP relay server implementation can be found in net/udprelay. This is currently considered experimental.
const ( // BindUDPRelayHandshakeStateInit represents the initial state prior to any // message being transmitted. BindUDPRelayHandshakeStateInit BindUDPRelayHandshakeState = iota // BindUDPRelayHandshakeStateBindSent is the first client state after // transmitting a BindUDPRelayEndpoint message to a UDP relay server. BindUDPRelayHandshakeStateBindSent // BindUDPRelayHandshakeStateChallengeSent is the first server state after // receiving a BindUDPRelayEndpoint message from a UDP relay client and // replying with a BindUDPRelayEndpointChallenge. BindUDPRelayHandshakeStateChallengeSent // BindUDPRelayHandshakeStateAnswerSent is a client state that is entered // after transmitting a BindUDPRelayEndpointAnswer message towards a UDP // relay server in response to a BindUDPRelayEndpointChallenge message. BindUDPRelayHandshakeStateAnswerSent // BindUDPRelayHandshakeStateAnswerReceived is a server state that is // entered after it has received a correct BindUDPRelayEndpointAnswer // message from a UDP relay client in response to a // BindUDPRelayEndpointChallenge message. BindUDPRelayHandshakeStateAnswerReceived )
type CallMeMaybe ¶
type CallMeMaybe struct { // MyNumber is what the peer believes its endpoints are. // // Prior to Tailscale 1.4, the endpoints were exchanged purely // between nodes and the control server. // // Starting with Tailscale 1.4, clients advertise their endpoints. // Older clients won't use this, but newer clients should // use any endpoints in here that aren't included from control. // // Control might have sent stale endpoints if the client was idle // before contacting us. In that case, the client likely did a STUN // request immediately before sending the CallMeMaybe to recreate // their NAT port mapping, and that new good endpoint is included // in this field, but might not yet be in control's endpoints. // (And in the future, control will stop distributing endpoints // when clients are suitably new.) MyNumber []netip.AddrPort }
CallMeMaybe is a message sent only over DERP to request that the recipient try to open up a magicsock path back to the sender.
The sender should've already sent UDP packets to the peer to open up the stateful firewall mappings inbound.
The recipient may choose to not open a path back, if it's already happy with its path. But usually it will.
func (*CallMeMaybe) AppendMarshal ¶
func (m *CallMeMaybe) AppendMarshal(b []byte) []byte
type CallMeMaybeVia ¶ added in v1.84.0
type CallMeMaybeVia struct {
UDPRelayEndpoint
}
CallMeMaybeVia is a message sent only over DERP to request that the recipient try to open up a magicsock path back to the sender. The 'Via' in CallMeMaybeVia highlights that candidate paths are served through an intermediate relay, likely a tailscale.com/net/udprelay.Server.
Usage of the candidate paths in magicsock requires a 3-way handshake involving BindUDPRelayEndpoint, BindUDPRelayEndpointChallenge, and BindUDPRelayEndpointAnswer.
CallMeMaybeVia mirrors tailscale.com/net/udprelay/endpoint.ServerEndpoint, which contains field documentation.
The recipient may choose to not open a path back if it's already happy with its path. Direct connections, e.g. CallMeMaybe-signaled, take priority over CallMeMaybeVia paths.
func (*CallMeMaybeVia) AppendMarshal ¶ added in v1.84.0
func (m *CallMeMaybeVia) AppendMarshal(b []byte) []byte
type Message ¶
type Message interface { // AppendMarshal appends the message's marshaled representation. // TODO(jwhited): consider using a signature matching encoding.BinaryAppender AppendMarshal([]byte) []byte }
Message a discovery message.
type MessageType ¶
type MessageType byte
type Ping ¶
type Ping struct { // TxID is a random client-generated per-ping transaction ID. TxID [12]byte // NodeKey is allegedly the ping sender's wireguard public key. // Old clients (~1.16.0 and earlier) don't send this field. // It shouldn't be trusted by itself, but can be combined with // netmap data to reduce the discokey:nodekey relation from 1:N to // 1:1. NodeKey key.NodePublic // Padding is the number of 0 bytes at the end of the // message. (It's used to probe path MTU.) Padding int }
func (*Ping) AppendMarshal ¶
type Pong ¶
type Pong struct { TxID [12]byte Src netip.AddrPort // 18 bytes (16+2) on the wire; v4-mapped ipv6 for IPv4 }
Pong is a response a Ping.
It includes the sender's source IP + port, so it's effectively a STUN response.
func (*Pong) AppendMarshal ¶
type UDPRelayEndpoint ¶ added in v1.86.0
type UDPRelayEndpoint struct { // ServerDisco is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.ServerDisco] ServerDisco key.DiscoPublic // ClientDisco is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.ClientDisco] ClientDisco [2]key.DiscoPublic // LamportID is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.LamportID] LamportID uint64 // VNI is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.VNI] VNI uint32 // BindLifetime is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.BindLifetime] BindLifetime time.Duration // SteadyStateLifetime is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.SteadyStateLifetime] SteadyStateLifetime time.Duration // AddrPorts is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.AddrPorts] AddrPorts []netip.AddrPort }
UDPRelayEndpoint is a mirror of tailscale.com/net/udprelay/endpoint.ServerEndpoint, refer to it for field documentation. UDPRelayEndpoint is carried in both CallMeMaybeVia and AllocateUDPRelayEndpointResponse messages.