disco.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package disco contains the discovery message types.
  4. //
  5. // A discovery message is:
  6. //
  7. // Header:
  8. //
  9. // magic [6]byte // “TS💬” (0x54 53 f0 9f 92 ac)
  10. // senderDiscoPub [32]byte // nacl public key
  11. // nonce [24]byte
  12. //
  13. // The recipient then decrypts the bytes following (the nacl box)
  14. // and then the inner payload structure is:
  15. //
  16. // messageType byte (the MessageType constants below)
  17. // messageVersion byte (0 for now; but always ignore bytes at the end)
  18. // message-payload [...]byte
  19. package disco
  20. import (
  21. "encoding/binary"
  22. "errors"
  23. "fmt"
  24. "net"
  25. "net/netip"
  26. "time"
  27. "go4.org/mem"
  28. "tailscale.com/types/key"
  29. )
  30. // Magic is the 6 byte header of all discovery messages.
  31. const Magic = "TS💬" // 6 bytes: 0x54 53 f0 9f 92 ac
  32. const keyLen = 32
  33. // NonceLen is the length of the nonces used by nacl box.
  34. const NonceLen = 24
  35. type MessageType byte
  36. const (
  37. TypePing = MessageType(0x01)
  38. TypePong = MessageType(0x02)
  39. TypeCallMeMaybe = MessageType(0x03)
  40. TypeBindUDPRelayEndpoint = MessageType(0x04)
  41. TypeBindUDPRelayEndpointChallenge = MessageType(0x05)
  42. TypeBindUDPRelayEndpointAnswer = MessageType(0x06)
  43. TypeCallMeMaybeVia = MessageType(0x07)
  44. TypeAllocateUDPRelayEndpointRequest = MessageType(0x08)
  45. TypeAllocateUDPRelayEndpointResponse = MessageType(0x09)
  46. )
  47. const v0 = byte(0)
  48. var errShort = errors.New("short message")
  49. // LooksLikeDiscoWrapper reports whether p looks like it's a packet
  50. // containing an encrypted disco message.
  51. func LooksLikeDiscoWrapper(p []byte) bool {
  52. if len(p) < len(Magic)+keyLen+NonceLen {
  53. return false
  54. }
  55. return string(p[:len(Magic)]) == Magic
  56. }
  57. // Source returns the slice of p that represents the
  58. // disco public key source, and whether p looks like
  59. // a disco message.
  60. func Source(p []byte) (src []byte, ok bool) {
  61. if !LooksLikeDiscoWrapper(p) {
  62. return nil, false
  63. }
  64. return p[len(Magic):][:keyLen], true
  65. }
  66. // Parse parses the encrypted part of the message from inside the
  67. // nacl box.
  68. func Parse(p []byte) (Message, error) {
  69. if len(p) < 2 {
  70. return nil, errShort
  71. }
  72. t, ver, p := MessageType(p[0]), p[1], p[2:]
  73. switch t {
  74. // TODO(jwhited): consider using a signature matching encoding.BinaryUnmarshaler
  75. case TypePing:
  76. return parsePing(ver, p)
  77. case TypePong:
  78. return parsePong(ver, p)
  79. case TypeCallMeMaybe:
  80. return parseCallMeMaybe(ver, p)
  81. case TypeBindUDPRelayEndpoint:
  82. return parseBindUDPRelayEndpoint(ver, p)
  83. case TypeBindUDPRelayEndpointChallenge:
  84. return parseBindUDPRelayEndpointChallenge(ver, p)
  85. case TypeBindUDPRelayEndpointAnswer:
  86. return parseBindUDPRelayEndpointAnswer(ver, p)
  87. case TypeCallMeMaybeVia:
  88. return parseCallMeMaybeVia(ver, p)
  89. case TypeAllocateUDPRelayEndpointRequest:
  90. return parseAllocateUDPRelayEndpointRequest(ver, p)
  91. case TypeAllocateUDPRelayEndpointResponse:
  92. return parseAllocateUDPRelayEndpointResponse(ver, p)
  93. default:
  94. return nil, fmt.Errorf("unknown message type 0x%02x", byte(t))
  95. }
  96. }
  97. // Message a discovery message.
  98. type Message interface {
  99. // AppendMarshal appends the message's marshaled representation.
  100. // TODO(jwhited): consider using a signature matching encoding.BinaryAppender
  101. AppendMarshal([]byte) []byte
  102. }
  103. // MessageHeaderLen is the length of a message header, 2 bytes for type and version.
  104. const MessageHeaderLen = 2
  105. // appendMsgHeader appends two bytes (for t and ver) and then also
  106. // dataLen bytes to b, returning the appended slice in all. The
  107. // returned data slice is a subslice of all with just dataLen bytes of
  108. // where the caller will fill in the data.
  109. func appendMsgHeader(b []byte, t MessageType, ver uint8, dataLen int) (all, data []byte) {
  110. // TODO: optimize this?
  111. all = append(b, make([]byte, dataLen+2)...)
  112. all[len(b)] = byte(t)
  113. all[len(b)+1] = ver
  114. data = all[len(b)+2:]
  115. return
  116. }
  117. type Ping struct {
  118. // TxID is a random client-generated per-ping transaction ID.
  119. TxID [12]byte
  120. // NodeKey is allegedly the ping sender's wireguard public key.
  121. // Old clients (~1.16.0 and earlier) don't send this field.
  122. // It shouldn't be trusted by itself, but can be combined with
  123. // netmap data to reduce the discokey:nodekey relation from 1:N to
  124. // 1:1.
  125. NodeKey key.NodePublic
  126. // Padding is the number of 0 bytes at the end of the
  127. // message. (It's used to probe path MTU.)
  128. Padding int
  129. }
  130. // PingLen is the length of a marshalled ping message, without the message
  131. // header or padding.
  132. const PingLen = 12 + key.NodePublicRawLen
  133. func (m *Ping) AppendMarshal(b []byte) []byte {
  134. dataLen := 12
  135. hasKey := !m.NodeKey.IsZero()
  136. if hasKey {
  137. dataLen += key.NodePublicRawLen
  138. }
  139. ret, d := appendMsgHeader(b, TypePing, v0, dataLen+m.Padding)
  140. n := copy(d, m.TxID[:])
  141. if hasKey {
  142. m.NodeKey.AppendTo(d[:n])
  143. }
  144. return ret
  145. }
  146. func parsePing(ver uint8, p []byte) (m *Ping, err error) {
  147. if len(p) < 12 {
  148. return nil, errShort
  149. }
  150. m = new(Ping)
  151. m.Padding = len(p)
  152. p = p[copy(m.TxID[:], p):]
  153. m.Padding -= 12
  154. // Deliberately lax on longer-than-expected messages, for future
  155. // compatibility.
  156. if len(p) >= key.NodePublicRawLen {
  157. m.NodeKey = key.NodePublicFromRaw32(mem.B(p[:key.NodePublicRawLen]))
  158. m.Padding -= key.NodePublicRawLen
  159. }
  160. return m, nil
  161. }
  162. // CallMeMaybe is a message sent only over DERP to request that the recipient try
  163. // to open up a magicsock path back to the sender.
  164. //
  165. // The sender should've already sent UDP packets to the peer to open
  166. // up the stateful firewall mappings inbound.
  167. //
  168. // The recipient may choose to not open a path back, if it's already
  169. // happy with its path. But usually it will.
  170. type CallMeMaybe struct {
  171. // MyNumber is what the peer believes its endpoints are.
  172. //
  173. // Prior to Tailscale 1.4, the endpoints were exchanged purely
  174. // between nodes and the control server.
  175. //
  176. // Starting with Tailscale 1.4, clients advertise their endpoints.
  177. // Older clients won't use this, but newer clients should
  178. // use any endpoints in here that aren't included from control.
  179. //
  180. // Control might have sent stale endpoints if the client was idle
  181. // before contacting us. In that case, the client likely did a STUN
  182. // request immediately before sending the CallMeMaybe to recreate
  183. // their NAT port mapping, and that new good endpoint is included
  184. // in this field, but might not yet be in control's endpoints.
  185. // (And in the future, control will stop distributing endpoints
  186. // when clients are suitably new.)
  187. MyNumber []netip.AddrPort
  188. }
  189. const epLength = 16 + 2 // 16 byte IP address + 2 byte port
  190. func (m *CallMeMaybe) AppendMarshal(b []byte) []byte {
  191. ret, p := appendMsgHeader(b, TypeCallMeMaybe, v0, epLength*len(m.MyNumber))
  192. for _, ipp := range m.MyNumber {
  193. a := ipp.Addr().As16()
  194. copy(p[:], a[:])
  195. binary.BigEndian.PutUint16(p[16:], ipp.Port())
  196. p = p[epLength:]
  197. }
  198. return ret
  199. }
  200. func parseCallMeMaybe(ver uint8, p []byte) (m *CallMeMaybe, err error) {
  201. m = new(CallMeMaybe)
  202. if len(p)%epLength != 0 || ver != 0 || len(p) == 0 {
  203. return m, nil
  204. }
  205. m.MyNumber = make([]netip.AddrPort, 0, len(p)/epLength)
  206. for len(p) > 0 {
  207. var a [16]byte
  208. copy(a[:], p)
  209. m.MyNumber = append(m.MyNumber, netip.AddrPortFrom(
  210. netip.AddrFrom16(a).Unmap(),
  211. binary.BigEndian.Uint16(p[16:18])))
  212. p = p[epLength:]
  213. }
  214. return m, nil
  215. }
  216. // Pong is a response a Ping.
  217. //
  218. // It includes the sender's source IP + port, so it's effectively a
  219. // STUN response.
  220. type Pong struct {
  221. TxID [12]byte
  222. Src netip.AddrPort // 18 bytes (16+2) on the wire; v4-mapped ipv6 for IPv4
  223. }
  224. // pongLen is the length of a marshalled pong message, without the message
  225. // header or padding.
  226. const pongLen = 12 + 16 + 2
  227. func (m *Pong) AppendMarshal(b []byte) []byte {
  228. ret, d := appendMsgHeader(b, TypePong, v0, pongLen)
  229. d = d[copy(d, m.TxID[:]):]
  230. ip16 := m.Src.Addr().As16()
  231. d = d[copy(d, ip16[:]):]
  232. binary.BigEndian.PutUint16(d, m.Src.Port())
  233. return ret
  234. }
  235. func parsePong(ver uint8, p []byte) (m *Pong, err error) {
  236. if len(p) < pongLen {
  237. return nil, errShort
  238. }
  239. m = new(Pong)
  240. copy(m.TxID[:], p)
  241. p = p[12:]
  242. srcIP, _ := netip.AddrFromSlice(net.IP(p[:16]))
  243. p = p[16:]
  244. port := binary.BigEndian.Uint16(p)
  245. m.Src = netip.AddrPortFrom(srcIP.Unmap(), port)
  246. return m, nil
  247. }
  248. // MessageSummary returns a short summary of m for logging purposes.
  249. func MessageSummary(m Message) string {
  250. switch m := m.(type) {
  251. case *Ping:
  252. return fmt.Sprintf("ping tx=%x padding=%v", m.TxID[:6], m.Padding)
  253. case *Pong:
  254. return fmt.Sprintf("pong tx=%x", m.TxID[:6])
  255. case *CallMeMaybe:
  256. return "call-me-maybe"
  257. case *CallMeMaybeVia:
  258. return "call-me-maybe-via"
  259. case *BindUDPRelayEndpoint:
  260. return "bind-udp-relay-endpoint"
  261. case *BindUDPRelayEndpointChallenge:
  262. return "bind-udp-relay-endpoint-challenge"
  263. case *BindUDPRelayEndpointAnswer:
  264. return "bind-udp-relay-endpoint-answer"
  265. case *AllocateUDPRelayEndpointRequest:
  266. return "allocate-udp-relay-endpoint-request"
  267. case *AllocateUDPRelayEndpointResponse:
  268. return "allocate-udp-relay-endpoint-response"
  269. default:
  270. return fmt.Sprintf("%#v", m)
  271. }
  272. }
  273. // BindUDPRelayHandshakeState represents the state of the 3-way bind handshake
  274. // between UDP relay client and UDP relay server. Its potential values include
  275. // those for both participants, UDP relay client and UDP relay server. A UDP
  276. // relay server implementation can be found in net/udprelay. This is currently
  277. // considered experimental.
  278. type BindUDPRelayHandshakeState int
  279. const (
  280. // BindUDPRelayHandshakeStateInit represents the initial state prior to any
  281. // message being transmitted.
  282. BindUDPRelayHandshakeStateInit BindUDPRelayHandshakeState = iota
  283. // BindUDPRelayHandshakeStateBindSent is the first client state after
  284. // transmitting a BindUDPRelayEndpoint message to a UDP relay server.
  285. BindUDPRelayHandshakeStateBindSent
  286. // BindUDPRelayHandshakeStateChallengeSent is the first server state after
  287. // receiving a BindUDPRelayEndpoint message from a UDP relay client and
  288. // replying with a BindUDPRelayEndpointChallenge.
  289. BindUDPRelayHandshakeStateChallengeSent
  290. // BindUDPRelayHandshakeStateAnswerSent is a client state that is entered
  291. // after transmitting a BindUDPRelayEndpointAnswer message towards a UDP
  292. // relay server in response to a BindUDPRelayEndpointChallenge message.
  293. BindUDPRelayHandshakeStateAnswerSent
  294. // BindUDPRelayHandshakeStateAnswerReceived is a server state that is
  295. // entered after it has received a correct BindUDPRelayEndpointAnswer
  296. // message from a UDP relay client in response to a
  297. // BindUDPRelayEndpointChallenge message.
  298. BindUDPRelayHandshakeStateAnswerReceived
  299. )
  300. // bindUDPRelayEndpointCommonLen is the length of a marshalled
  301. // [BindUDPRelayEndpointCommon], without the message header.
  302. const bindUDPRelayEndpointCommonLen = 72
  303. // BindUDPRelayChallengeLen is the length of the Challenge field carried in
  304. // [BindUDPRelayEndpointChallenge] & [BindUDPRelayEndpointAnswer] messages.
  305. const BindUDPRelayChallengeLen = 32
  306. // BindUDPRelayEndpointCommon contains fields that are common across all 3
  307. // UDP relay handshake message types. All 4 field values are expected to be
  308. // consistent for the lifetime of a handshake besides Challenge, which is
  309. // irrelevant in a [BindUDPRelayEndpoint] message.
  310. type BindUDPRelayEndpointCommon struct {
  311. // VNI is the Geneve header Virtual Network Identifier field value, which
  312. // must match this disco-sealed value upon reception. If they are
  313. // non-matching it indicates the cleartext Geneve header was tampered with
  314. // and/or mangled.
  315. VNI uint32
  316. // Generation represents the handshake generation. Clients must set a new,
  317. // nonzero value at the start of every handshake.
  318. Generation uint32
  319. // RemoteKey is the disco key of the remote peer participating over this
  320. // relay endpoint.
  321. RemoteKey key.DiscoPublic
  322. // Challenge is set by the server in a [BindUDPRelayEndpointChallenge]
  323. // message, and expected to be echoed back by the client in a
  324. // [BindUDPRelayEndpointAnswer] message. Its value is irrelevant in a
  325. // [BindUDPRelayEndpoint] message, where it simply serves a padding purpose
  326. // ensuring all handshake messages are equal in size.
  327. Challenge [BindUDPRelayChallengeLen]byte
  328. }
  329. // encode encodes m in b. b must be at least bindUDPRelayEndpointCommonLen bytes
  330. // long.
  331. func (m *BindUDPRelayEndpointCommon) encode(b []byte) {
  332. binary.BigEndian.PutUint32(b, m.VNI)
  333. b = b[4:]
  334. binary.BigEndian.PutUint32(b, m.Generation)
  335. b = b[4:]
  336. m.RemoteKey.AppendTo(b[:0])
  337. b = b[key.DiscoPublicRawLen:]
  338. copy(b, m.Challenge[:])
  339. }
  340. // decode decodes m from b.
  341. func (m *BindUDPRelayEndpointCommon) decode(b []byte) error {
  342. if len(b) < bindUDPRelayEndpointCommonLen {
  343. return errShort
  344. }
  345. m.VNI = binary.BigEndian.Uint32(b)
  346. b = b[4:]
  347. m.Generation = binary.BigEndian.Uint32(b)
  348. b = b[4:]
  349. m.RemoteKey = key.DiscoPublicFromRaw32(mem.B(b[:key.DiscoPublicRawLen]))
  350. b = b[key.DiscoPublicRawLen:]
  351. copy(m.Challenge[:], b[:BindUDPRelayChallengeLen])
  352. return nil
  353. }
  354. // BindUDPRelayEndpoint is the first messaged transmitted from UDP relay client
  355. // towards UDP relay server as part of the 3-way bind handshake.
  356. type BindUDPRelayEndpoint struct {
  357. BindUDPRelayEndpointCommon
  358. }
  359. func (m *BindUDPRelayEndpoint) AppendMarshal(b []byte) []byte {
  360. ret, d := appendMsgHeader(b, TypeBindUDPRelayEndpoint, v0, bindUDPRelayEndpointCommonLen)
  361. m.BindUDPRelayEndpointCommon.encode(d)
  362. return ret
  363. }
  364. func parseBindUDPRelayEndpoint(ver uint8, p []byte) (m *BindUDPRelayEndpoint, err error) {
  365. m = new(BindUDPRelayEndpoint)
  366. err = m.BindUDPRelayEndpointCommon.decode(p)
  367. if err != nil {
  368. return nil, err
  369. }
  370. return m, nil
  371. }
  372. // BindUDPRelayEndpointChallenge is transmitted from UDP relay server towards
  373. // UDP relay client in response to a BindUDPRelayEndpoint message as part of the
  374. // 3-way bind handshake.
  375. type BindUDPRelayEndpointChallenge struct {
  376. BindUDPRelayEndpointCommon
  377. }
  378. func (m *BindUDPRelayEndpointChallenge) AppendMarshal(b []byte) []byte {
  379. ret, d := appendMsgHeader(b, TypeBindUDPRelayEndpointChallenge, v0, bindUDPRelayEndpointCommonLen)
  380. m.BindUDPRelayEndpointCommon.encode(d)
  381. return ret
  382. }
  383. func parseBindUDPRelayEndpointChallenge(ver uint8, p []byte) (m *BindUDPRelayEndpointChallenge, err error) {
  384. m = new(BindUDPRelayEndpointChallenge)
  385. err = m.BindUDPRelayEndpointCommon.decode(p)
  386. if err != nil {
  387. return nil, err
  388. }
  389. return m, nil
  390. }
  391. // BindUDPRelayEndpointAnswer is transmitted from UDP relay client to UDP relay
  392. // server in response to a BindUDPRelayEndpointChallenge message.
  393. type BindUDPRelayEndpointAnswer struct {
  394. BindUDPRelayEndpointCommon
  395. }
  396. func (m *BindUDPRelayEndpointAnswer) AppendMarshal(b []byte) []byte {
  397. ret, d := appendMsgHeader(b, TypeBindUDPRelayEndpointAnswer, v0, bindUDPRelayEndpointCommonLen)
  398. m.BindUDPRelayEndpointCommon.encode(d)
  399. return ret
  400. }
  401. func parseBindUDPRelayEndpointAnswer(ver uint8, p []byte) (m *BindUDPRelayEndpointAnswer, err error) {
  402. m = new(BindUDPRelayEndpointAnswer)
  403. err = m.BindUDPRelayEndpointCommon.decode(p)
  404. if err != nil {
  405. return nil, err
  406. }
  407. return m, nil
  408. }
  409. // AllocateUDPRelayEndpointRequest is a message sent only over DERP to request
  410. // allocation of a relay endpoint on a [tailscale.com/net/udprelay.Server]
  411. type AllocateUDPRelayEndpointRequest struct {
  412. // ClientDisco are the Disco public keys of the clients that should be
  413. // permitted to handshake with the endpoint.
  414. ClientDisco [2]key.DiscoPublic
  415. // Generation represents the allocation request generation. The server must
  416. // echo it back in the [AllocateUDPRelayEndpointResponse] to enable request
  417. // and response alignment client-side.
  418. Generation uint32
  419. }
  420. // allocateUDPRelayEndpointRequestLen is the length of a marshaled
  421. // [AllocateUDPRelayEndpointRequest] message without the message header.
  422. const allocateUDPRelayEndpointRequestLen = key.DiscoPublicRawLen*2 + // ClientDisco
  423. 4 // Generation
  424. func (m *AllocateUDPRelayEndpointRequest) AppendMarshal(b []byte) []byte {
  425. ret, p := appendMsgHeader(b, TypeAllocateUDPRelayEndpointRequest, v0, allocateUDPRelayEndpointRequestLen)
  426. for i := 0; i < len(m.ClientDisco); i++ {
  427. disco := m.ClientDisco[i].AppendTo(nil)
  428. copy(p, disco)
  429. p = p[key.DiscoPublicRawLen:]
  430. }
  431. binary.BigEndian.PutUint32(p, m.Generation)
  432. return ret
  433. }
  434. func parseAllocateUDPRelayEndpointRequest(ver uint8, p []byte) (m *AllocateUDPRelayEndpointRequest, err error) {
  435. m = new(AllocateUDPRelayEndpointRequest)
  436. if ver != 0 {
  437. return
  438. }
  439. if len(p) < allocateUDPRelayEndpointRequestLen {
  440. return m, errShort
  441. }
  442. for i := 0; i < len(m.ClientDisco); i++ {
  443. m.ClientDisco[i] = key.DiscoPublicFromRaw32(mem.B(p[:key.DiscoPublicRawLen]))
  444. p = p[key.DiscoPublicRawLen:]
  445. }
  446. m.Generation = binary.BigEndian.Uint32(p)
  447. return m, nil
  448. }
  449. // AllocateUDPRelayEndpointResponse is a message sent only over DERP in response
  450. // to a [AllocateUDPRelayEndpointRequest].
  451. type AllocateUDPRelayEndpointResponse struct {
  452. // Generation represents the allocation request generation. The server must
  453. // echo back the [AllocateUDPRelayEndpointRequest.Generation] here to enable
  454. // request and response alignment client-side.
  455. Generation uint32
  456. UDPRelayEndpoint
  457. }
  458. func (m *AllocateUDPRelayEndpointResponse) AppendMarshal(b []byte) []byte {
  459. endpointsLen := epLength * len(m.AddrPorts)
  460. generationLen := 4
  461. ret, d := appendMsgHeader(b, TypeAllocateUDPRelayEndpointResponse, v0, generationLen+udpRelayEndpointLenMinusAddrPorts+endpointsLen)
  462. binary.BigEndian.PutUint32(d, m.Generation)
  463. m.encode(d[4:])
  464. return ret
  465. }
  466. func parseAllocateUDPRelayEndpointResponse(ver uint8, p []byte) (m *AllocateUDPRelayEndpointResponse, err error) {
  467. m = new(AllocateUDPRelayEndpointResponse)
  468. if ver != 0 {
  469. return m, nil
  470. }
  471. if len(p) < 4 {
  472. return m, errShort
  473. }
  474. m.Generation = binary.BigEndian.Uint32(p)
  475. err = m.decode(p[4:])
  476. return m, err
  477. }
  478. const udpRelayEndpointLenMinusAddrPorts = key.DiscoPublicRawLen + // ServerDisco
  479. (key.DiscoPublicRawLen * 2) + // ClientDisco
  480. 8 + // LamportID
  481. 4 + // VNI
  482. 8 + // BindLifetime
  483. 8 // SteadyStateLifetime
  484. // UDPRelayEndpoint is a mirror of [tailscale.com/net/udprelay/endpoint.ServerEndpoint],
  485. // refer to it for field documentation. [UDPRelayEndpoint] is carried in both
  486. // [CallMeMaybeVia] and [AllocateUDPRelayEndpointResponse] messages.
  487. type UDPRelayEndpoint struct {
  488. // ServerDisco is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.ServerDisco]
  489. ServerDisco key.DiscoPublic
  490. // ClientDisco is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.ClientDisco]
  491. ClientDisco [2]key.DiscoPublic
  492. // LamportID is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.LamportID]
  493. LamportID uint64
  494. // VNI is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.VNI]
  495. VNI uint32
  496. // BindLifetime is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.BindLifetime]
  497. BindLifetime time.Duration
  498. // SteadyStateLifetime is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.SteadyStateLifetime]
  499. SteadyStateLifetime time.Duration
  500. // AddrPorts is [tailscale.com/net/udprelay/endpoint.ServerEndpoint.AddrPorts]
  501. AddrPorts []netip.AddrPort
  502. }
  503. // encode encodes m in b. b must be at least [udpRelayEndpointLenMinusAddrPorts]
  504. // + [epLength] * len(m.AddrPorts) bytes long.
  505. func (m *UDPRelayEndpoint) encode(b []byte) {
  506. disco := m.ServerDisco.AppendTo(nil)
  507. copy(b, disco)
  508. b = b[key.DiscoPublicRawLen:]
  509. for i := 0; i < len(m.ClientDisco); i++ {
  510. disco = m.ClientDisco[i].AppendTo(nil)
  511. copy(b, disco)
  512. b = b[key.DiscoPublicRawLen:]
  513. }
  514. binary.BigEndian.PutUint64(b[:8], m.LamportID)
  515. b = b[8:]
  516. binary.BigEndian.PutUint32(b[:4], m.VNI)
  517. b = b[4:]
  518. binary.BigEndian.PutUint64(b[:8], uint64(m.BindLifetime))
  519. b = b[8:]
  520. binary.BigEndian.PutUint64(b[:8], uint64(m.SteadyStateLifetime))
  521. b = b[8:]
  522. for _, ipp := range m.AddrPorts {
  523. a := ipp.Addr().As16()
  524. copy(b, a[:])
  525. binary.BigEndian.PutUint16(b[16:18], ipp.Port())
  526. b = b[epLength:]
  527. }
  528. }
  529. // decode decodes m from b.
  530. func (m *UDPRelayEndpoint) decode(b []byte) error {
  531. if len(b) < udpRelayEndpointLenMinusAddrPorts+epLength ||
  532. (len(b)-udpRelayEndpointLenMinusAddrPorts)%epLength != 0 {
  533. return errShort
  534. }
  535. m.ServerDisco = key.DiscoPublicFromRaw32(mem.B(b[:key.DiscoPublicRawLen]))
  536. b = b[key.DiscoPublicRawLen:]
  537. for i := 0; i < len(m.ClientDisco); i++ {
  538. m.ClientDisco[i] = key.DiscoPublicFromRaw32(mem.B(b[:key.DiscoPublicRawLen]))
  539. b = b[key.DiscoPublicRawLen:]
  540. }
  541. m.LamportID = binary.BigEndian.Uint64(b[:8])
  542. b = b[8:]
  543. m.VNI = binary.BigEndian.Uint32(b[:4])
  544. b = b[4:]
  545. m.BindLifetime = time.Duration(binary.BigEndian.Uint64(b[:8]))
  546. b = b[8:]
  547. m.SteadyStateLifetime = time.Duration(binary.BigEndian.Uint64(b[:8]))
  548. b = b[8:]
  549. m.AddrPorts = make([]netip.AddrPort, 0, len(b)-udpRelayEndpointLenMinusAddrPorts/epLength)
  550. for len(b) > 0 {
  551. var a [16]byte
  552. copy(a[:], b)
  553. m.AddrPorts = append(m.AddrPorts, netip.AddrPortFrom(
  554. netip.AddrFrom16(a).Unmap(),
  555. binary.BigEndian.Uint16(b[16:18])))
  556. b = b[epLength:]
  557. }
  558. return nil
  559. }
  560. // CallMeMaybeVia is a message sent only over DERP to request that the recipient
  561. // try to open up a magicsock path back to the sender. The 'Via' in
  562. // CallMeMaybeVia highlights that candidate paths are served through an
  563. // intermediate relay, likely a [tailscale.com/net/udprelay.Server].
  564. //
  565. // Usage of the candidate paths in magicsock requires a 3-way handshake
  566. // involving [BindUDPRelayEndpoint], [BindUDPRelayEndpointChallenge], and
  567. // [BindUDPRelayEndpointAnswer].
  568. //
  569. // CallMeMaybeVia mirrors [tailscale.com/net/udprelay/endpoint.ServerEndpoint],
  570. // which contains field documentation.
  571. //
  572. // The recipient may choose to not open a path back if it's already happy with
  573. // its path. Direct connections, e.g. [CallMeMaybe]-signaled, take priority over
  574. // CallMeMaybeVia paths.
  575. type CallMeMaybeVia struct {
  576. UDPRelayEndpoint
  577. }
  578. func (m *CallMeMaybeVia) AppendMarshal(b []byte) []byte {
  579. endpointsLen := epLength * len(m.AddrPorts)
  580. ret, p := appendMsgHeader(b, TypeCallMeMaybeVia, v0, udpRelayEndpointLenMinusAddrPorts+endpointsLen)
  581. m.encode(p)
  582. return ret
  583. }
  584. func parseCallMeMaybeVia(ver uint8, p []byte) (m *CallMeMaybeVia, err error) {
  585. m = new(CallMeMaybeVia)
  586. if ver != 0 {
  587. return m, nil
  588. }
  589. err = m.decode(p)
  590. return m, err
  591. }