1
0

relay_manager.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. package nebula
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "log/slog"
  8. "net/netip"
  9. "slices"
  10. "sync/atomic"
  11. "github.com/slackhq/nebula/cert"
  12. "github.com/slackhq/nebula/config"
  13. "github.com/slackhq/nebula/header"
  14. )
  15. type relayManager struct {
  16. l *slog.Logger
  17. hostmap *HostMap
  18. amRelay atomic.Bool
  19. useRelays atomic.Bool
  20. }
  21. func NewRelayManager(ctx context.Context, l *slog.Logger, hostmap *HostMap, c *config.C) *relayManager {
  22. rm := &relayManager{
  23. l: l,
  24. hostmap: hostmap,
  25. }
  26. rm.reload(c, true)
  27. c.RegisterReloadCallback(func(c *config.C) {
  28. err := rm.reload(c, false)
  29. if err != nil {
  30. rm.l.Error("Failed to reload relay_manager", "error", err)
  31. }
  32. })
  33. return rm
  34. }
  35. func (rm *relayManager) reload(c *config.C, initial bool) error {
  36. if initial || c.HasChanged("relay.am_relay") || c.HasChanged("relay.use_relays") {
  37. amRelay := c.GetBool("relay.am_relay", false)
  38. rm.amRelay.Store(amRelay)
  39. rm.useRelays.Store(c.GetBool("relay.use_relays", true) && !amRelay)
  40. }
  41. return nil
  42. }
  43. func (rm *relayManager) GetAmRelay() bool {
  44. return rm.amRelay.Load()
  45. }
  46. func (rm *relayManager) GetUseRelays() bool {
  47. return rm.useRelays.Load()
  48. }
  49. // StartRelays drives the relay-establishment side of an outbound handshake attempt.
  50. // For each candidate relay it either kicks off a handshake to the relay, sends a CreateRelayRequest, retransmits
  51. // one that may have been lost, or, once the relay is Established, forwards the in-progress
  52. // stage 0 handshake packet for vpnIp through it.
  53. func (rm *relayManager) StartRelays(f *Interface, vpnIp netip.Addr, hh *HandshakeHostInfo, stage0 []byte) {
  54. hostinfo := hh.hostinfo
  55. if !rm.GetUseRelays() || len(hostinfo.remotes.relays) == 0 {
  56. hh.lastRelays = nil
  57. return
  58. }
  59. relays := hostinfo.remotes.relays
  60. listLevel := slog.LevelDebug
  61. prior := hh.lastRelays
  62. if !slices.Equal(relays, prior) {
  63. listLevel = slog.LevelInfo
  64. hh.lastRelays = slices.Clone(relays)
  65. }
  66. hl := hostinfo.logger(rm.l)
  67. hl.Log(context.Background(), listLevel, "Attempt to relay through hosts", "relays", relays)
  68. // Send a RelayRequest to all known Relay IP's
  69. for _, relay := range relays {
  70. // Don't relay through the host I'm trying to connect to
  71. if relay == vpnIp {
  72. continue
  73. }
  74. // Don't relay to myself
  75. if f.myVpnAddrsTable.Contains(relay) {
  76. continue
  77. }
  78. // Each relay's per-attempt log fires at Info on the first time we hit it and Debug after that.
  79. level := slog.LevelInfo
  80. if slices.Contains(prior, relay) {
  81. level = slog.LevelDebug
  82. }
  83. relayHostInfo := rm.hostmap.QueryVpnAddr(relay)
  84. if relayHostInfo == nil || !relayHostInfo.GetRemote().IsValid() {
  85. hl.Log(context.Background(), level, "Establish tunnel to relay target", "relay", relay.String())
  86. f.Handshake(relay)
  87. continue
  88. }
  89. // Check the relay HostInfo to see if we already established a relay through
  90. existingRelay, ok := relayHostInfo.relayState.QueryRelayForByIp(vpnIp)
  91. if !ok {
  92. // No relays exist or requested yet.
  93. if relayHostInfo.GetRemote().IsValid() {
  94. idx, err := AddRelay(rm.l, relayHostInfo, rm.hostmap, vpnIp, nil, TerminalType, Requested)
  95. if err != nil {
  96. hl.Info("Failed to add relay to hostmap", "relay", relay.String(), "error", err)
  97. }
  98. m := NebulaControl{
  99. Type: NebulaControl_CreateRelayRequest,
  100. InitiatorRelayIndex: idx,
  101. }
  102. switch relayHostInfo.GetCert().Certificate.Version() {
  103. case cert.Version1:
  104. if !f.myVpnAddrs[0].Is4() {
  105. hl.Error("can not establish v1 relay with a v6 network because the relay is not running a current nebula version")
  106. continue
  107. }
  108. if !vpnIp.Is4() {
  109. hl.Error("can not establish v1 relay with a v6 remote network because the relay is not running a current nebula version")
  110. continue
  111. }
  112. b := f.myVpnAddrs[0].As4()
  113. m.OldRelayFromAddr = binary.BigEndian.Uint32(b[:])
  114. b = vpnIp.As4()
  115. m.OldRelayToAddr = binary.BigEndian.Uint32(b[:])
  116. case cert.Version2:
  117. m.RelayFromAddr = netAddrToProtoAddr(f.myVpnAddrs[0])
  118. m.RelayToAddr = netAddrToProtoAddr(vpnIp)
  119. default:
  120. hl.Error("Unknown certificate version found while creating relay")
  121. continue
  122. }
  123. msg, err := m.Marshal()
  124. if err != nil {
  125. hl.Error("Failed to marshal Control message to create relay", "error", err)
  126. } else {
  127. f.SendMessageToHostInfo(header.Control, 0, relayHostInfo, msg, make([]byte, 12), make([]byte, mtu))
  128. rm.l.Log(context.Background(), level, "send CreateRelayRequest",
  129. "relayFrom", f.myVpnAddrs[0],
  130. "relayTo", vpnIp,
  131. "initiatorRelayIndex", idx,
  132. "relay", relay,
  133. )
  134. }
  135. }
  136. continue
  137. }
  138. switch existingRelay.State {
  139. case Established:
  140. hl.Log(context.Background(), level, "Send handshake via relay", "relay", relay.String())
  141. f.SendVia(relayHostInfo, existingRelay, stage0, make([]byte, 12), make([]byte, mtu), false)
  142. case Disestablished:
  143. // Mark this relay as 'requested'
  144. relayHostInfo.relayState.UpdateRelayForByIpState(vpnIp, Requested)
  145. fallthrough
  146. case Requested:
  147. hl.Log(context.Background(), level, "Re-send CreateRelay request", "relay", relay.String())
  148. // Re-send the CreateRelay request, in case the previous one was lost.
  149. m := NebulaControl{
  150. Type: NebulaControl_CreateRelayRequest,
  151. InitiatorRelayIndex: existingRelay.LocalIndex,
  152. }
  153. switch relayHostInfo.GetCert().Certificate.Version() {
  154. case cert.Version1:
  155. if !f.myVpnAddrs[0].Is4() {
  156. hl.Error("can not establish v1 relay with a v6 network because the relay is not running a current nebula version")
  157. continue
  158. }
  159. if !vpnIp.Is4() {
  160. hl.Error("can not establish v1 relay with a v6 remote network because the relay is not running a current nebula version")
  161. continue
  162. }
  163. b := f.myVpnAddrs[0].As4()
  164. m.OldRelayFromAddr = binary.BigEndian.Uint32(b[:])
  165. b = vpnIp.As4()
  166. m.OldRelayToAddr = binary.BigEndian.Uint32(b[:])
  167. case cert.Version2:
  168. m.RelayFromAddr = netAddrToProtoAddr(f.myVpnAddrs[0])
  169. m.RelayToAddr = netAddrToProtoAddr(vpnIp)
  170. default:
  171. hl.Error("Unknown certificate version found while creating relay")
  172. continue
  173. }
  174. msg, err := m.Marshal()
  175. if err != nil {
  176. hl.Error("Failed to marshal Control message to create relay", "error", err)
  177. } else {
  178. // This must send over the hostinfo, not over hm.Hosts[ip]
  179. f.SendMessageToHostInfo(header.Control, 0, relayHostInfo, msg, make([]byte, 12), make([]byte, mtu))
  180. rm.l.Log(context.Background(), level, "send CreateRelayRequest",
  181. "relayFrom", f.myVpnAddrs[0],
  182. "relayTo", vpnIp,
  183. "initiatorRelayIndex", existingRelay.LocalIndex,
  184. "relay", relay,
  185. )
  186. }
  187. case PeerRequested:
  188. // PeerRequested only occurs in Forwarding relays, not Terminal relays, and this is a Terminal relay case.
  189. fallthrough
  190. default:
  191. hl.Error("Relay unexpected state",
  192. "vpnIp", vpnIp,
  193. "state", existingRelay.State,
  194. "relay", relay,
  195. )
  196. }
  197. }
  198. }
  199. // AddRelay finds an available relay index on the hostmap, and associates the relay info with it.
  200. // relayHostInfo is the Nebula peer which can be used as a relay to access the target vpnIp.
  201. func AddRelay(l *slog.Logger, relayHostInfo *HostInfo, hm *HostMap, vpnIp netip.Addr, remoteIdx *uint32, relayType int, state int) (uint32, error) {
  202. hm.Lock()
  203. defer hm.Unlock()
  204. for range 32 {
  205. index, err := generateIndex(l)
  206. if err != nil {
  207. return 0, err
  208. }
  209. _, inRelays := hm.Relays[index]
  210. if !inRelays {
  211. // Avoid standing up a relay that can't be used since only the primary hostinfo
  212. // will be pointed to by the relay logic
  213. //TODO: if there was an existing primary and it had relay state, should we merge?
  214. hm.unlockedMakePrimary(relayHostInfo)
  215. hm.Relays[index] = relayHostInfo
  216. newRelay := Relay{
  217. Type: relayType,
  218. State: state,
  219. LocalIndex: index,
  220. PeerAddr: vpnIp,
  221. }
  222. if remoteIdx != nil {
  223. newRelay.RemoteIndex = *remoteIdx
  224. }
  225. relayHostInfo.relayState.InsertRelay(vpnIp, index, &newRelay)
  226. return index, nil
  227. }
  228. }
  229. return 0, errors.New("failed to generate unique localIndexId")
  230. }
  231. // EstablishRelay updates a Requested Relay to become an Established Relay, which can pass traffic.
  232. func (rm *relayManager) EstablishRelay(relayHostInfo *HostInfo, m *NebulaControl) (*Relay, error) {
  233. relay, ok := relayHostInfo.relayState.CompleteRelayByIdx(m.InitiatorRelayIndex, m.ResponderRelayIndex)
  234. if !ok {
  235. var relayFrom, relayTo any
  236. if m.RelayFromAddr == nil {
  237. relayFrom = m.OldRelayFromAddr
  238. } else {
  239. relayFrom = m.RelayFromAddr
  240. }
  241. if m.RelayToAddr == nil {
  242. relayTo = m.OldRelayToAddr
  243. } else {
  244. relayTo = m.RelayToAddr
  245. }
  246. rm.l.Info("relayManager failed to update relay",
  247. "relay", relayHostInfo.vpnAddrs[0],
  248. "initiatorRelayIndex", m.InitiatorRelayIndex,
  249. "relayFrom", relayFrom,
  250. "relayTo", relayTo,
  251. )
  252. return nil, fmt.Errorf("unknown relay")
  253. }
  254. return relay, nil
  255. }
  256. func (rm *relayManager) HandleControlMsg(h *HostInfo, d []byte, f *Interface) {
  257. msg := &NebulaControl{}
  258. err := msg.Unmarshal(d)
  259. if err != nil {
  260. h.logger(f.l).Error("Failed to unmarshal control message", "error", err)
  261. return
  262. }
  263. var v cert.Version
  264. if msg.OldRelayFromAddr > 0 || msg.OldRelayToAddr > 0 {
  265. v = cert.Version1
  266. b := [4]byte{}
  267. binary.BigEndian.PutUint32(b[:], msg.OldRelayFromAddr)
  268. msg.RelayFromAddr = netAddrToProtoAddr(netip.AddrFrom4(b))
  269. binary.BigEndian.PutUint32(b[:], msg.OldRelayToAddr)
  270. msg.RelayToAddr = netAddrToProtoAddr(netip.AddrFrom4(b))
  271. } else {
  272. v = cert.Version2
  273. }
  274. // validate:
  275. switch msg.Type {
  276. case NebulaControl_CreateRelayRequest, NebulaControl_CreateRelayResponse:
  277. if msg.RelayFromAddr == nil {
  278. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  279. h.logger(f.l).Debug("Control message received with nil RelayFromAddr", "type", msg.Type)
  280. }
  281. return
  282. } else if msg.RelayToAddr == nil {
  283. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  284. h.logger(f.l).Debug("Control message received with nil RelayToAddr", "type", msg.Type)
  285. }
  286. return
  287. }
  288. }
  289. switch msg.Type {
  290. case NebulaControl_CreateRelayRequest:
  291. rm.handleCreateRelayRequest(v, h, f, msg)
  292. case NebulaControl_CreateRelayResponse:
  293. rm.handleCreateRelayResponse(v, h, f, msg)
  294. }
  295. }
  296. func (rm *relayManager) handleCreateRelayResponse(v cert.Version, h *HostInfo, f *Interface, m *NebulaControl) {
  297. //nil-checks for protoAddrToNetAddr handled by caller
  298. relayFrom := protoAddrToNetAddr(m.RelayFromAddr)
  299. relayTo := protoAddrToNetAddr(m.RelayToAddr)
  300. rm.l.Info("handleCreateRelayResponse",
  301. "relayFrom", relayFrom,
  302. "relayTo", relayTo,
  303. "initiatorRelayIndex", m.InitiatorRelayIndex,
  304. "responderRelayIndex", m.ResponderRelayIndex,
  305. "vpnAddrs", h.vpnAddrs,
  306. )
  307. relay, err := rm.EstablishRelay(h, m)
  308. if err != nil {
  309. rm.l.Error("Failed to update relay for relayTo", "error", err)
  310. return
  311. }
  312. // Do I need to complete the relays now?
  313. if relay.Type == TerminalType {
  314. return
  315. }
  316. // I'm the middle man. Let the initiator know that the I've established the relay they requested.
  317. peerHostInfo := rm.hostmap.QueryVpnAddr(relay.PeerAddr)
  318. if peerHostInfo == nil {
  319. rm.l.Error("Can't find a HostInfo for peer", "relayTo", relay.PeerAddr)
  320. return
  321. }
  322. peerRelay, ok := peerHostInfo.relayState.QueryRelayForByIp(relayTo)
  323. if !ok {
  324. rm.l.Error("peerRelay does not have Relay state for relayTo", "relayTo", peerHostInfo.vpnAddrs[0])
  325. return
  326. }
  327. switch peerRelay.State {
  328. case Requested:
  329. // I initiated the request to this peer, but haven't heard back from the peer yet. I must wait for this peer
  330. // to respond to complete the connection.
  331. case PeerRequested, Disestablished, Established:
  332. peerHostInfo.relayState.UpdateRelayForByIpState(relayTo, Established)
  333. resp := NebulaControl{
  334. Type: NebulaControl_CreateRelayResponse,
  335. ResponderRelayIndex: peerRelay.LocalIndex,
  336. InitiatorRelayIndex: peerRelay.RemoteIndex,
  337. }
  338. peer := peerHostInfo.vpnAddrs[0]
  339. if v == cert.Version1 {
  340. if !peer.Is4() {
  341. rm.l.Error("Refusing to CreateRelayResponse for a v1 relay with an ipv6 address",
  342. "relayFrom", peer,
  343. "relayTo", relayTo,
  344. "initiatorRelayIndex", resp.InitiatorRelayIndex,
  345. "responderRelayIndex", resp.ResponderRelayIndex,
  346. "vpnAddrs", peerHostInfo.vpnAddrs,
  347. )
  348. return
  349. }
  350. b := peer.As4()
  351. resp.OldRelayFromAddr = binary.BigEndian.Uint32(b[:])
  352. b = relayTo.As4()
  353. resp.OldRelayToAddr = binary.BigEndian.Uint32(b[:])
  354. } else {
  355. resp.RelayFromAddr = netAddrToProtoAddr(peer)
  356. resp.RelayToAddr = m.RelayToAddr
  357. }
  358. msg, err := resp.Marshal()
  359. if err != nil {
  360. rm.l.Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay", "error", err)
  361. return
  362. }
  363. f.SendMessageToHostInfo(header.Control, 0, peerHostInfo, msg, make([]byte, 12), make([]byte, mtu))
  364. rm.l.Info("send CreateRelayResponse",
  365. "relayFrom", peer,
  366. "relayTo", relayTo,
  367. "initiatorRelayIndex", resp.InitiatorRelayIndex,
  368. "responderRelayIndex", resp.ResponderRelayIndex,
  369. "vpnAddrs", peerHostInfo.vpnAddrs,
  370. )
  371. }
  372. }
  373. func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f *Interface, m *NebulaControl) {
  374. //nil-checks for protoAddrToNetAddr handled by caller
  375. from := protoAddrToNetAddr(m.RelayFromAddr)
  376. target := protoAddrToNetAddr(m.RelayToAddr)
  377. logMsg := rm.l.With(
  378. "relayFrom", from,
  379. "relayTo", target,
  380. "initiatorRelayIndex", m.InitiatorRelayIndex,
  381. "vpnAddrs", h.vpnAddrs,
  382. )
  383. logMsg.Info("handleCreateRelayRequest")
  384. // Is the source of the relay me? This should never happen, but did happen due to
  385. // an issue migrating relays over to newly re-handshaked host info objects.
  386. if f.myVpnAddrsTable.Contains(from) {
  387. logMsg.Error("Discarding relay request from myself", "myIP", from)
  388. return
  389. }
  390. // Is the target of the relay me?
  391. if f.myVpnAddrsTable.Contains(target) {
  392. existingRelay, ok := h.relayState.QueryRelayForByIp(from)
  393. if ok {
  394. switch existingRelay.State {
  395. case Requested:
  396. ok = h.relayState.CompleteRelayByIP(from, m.InitiatorRelayIndex)
  397. if !ok {
  398. logMsg.Error("Relay State not found")
  399. return
  400. }
  401. case Established:
  402. if existingRelay.RemoteIndex != m.InitiatorRelayIndex {
  403. // We got a brand new Relay request, because its index is different than what we saw before.
  404. // This should never happen. The peer should never change an index, once created.
  405. logMsg.Error("Existing relay mismatch with CreateRelayRequest",
  406. "existingRemoteIndex", existingRelay.RemoteIndex)
  407. return
  408. }
  409. case Disestablished:
  410. if existingRelay.RemoteIndex != m.InitiatorRelayIndex {
  411. // We got a brand new Relay request, because its index is different than what we saw before.
  412. // This should never happen. The peer should never change an index, once created.
  413. logMsg.Error("Existing relay mismatch with CreateRelayRequest",
  414. "existingRemoteIndex", existingRelay.RemoteIndex)
  415. return
  416. }
  417. // Mark the relay as 'Established' because it's safe to use again
  418. h.relayState.UpdateRelayForByIpState(from, Established)
  419. case PeerRequested:
  420. // I should never be in this state, because I am terminal, not forwarding.
  421. logMsg.Error("Unexpected Relay State found",
  422. "existingRemoteIndex", existingRelay.RemoteIndex,
  423. "state", existingRelay.State)
  424. }
  425. } else {
  426. _, err := AddRelay(rm.l, h, f.hostMap, from, &m.InitiatorRelayIndex, TerminalType, Established)
  427. if err != nil {
  428. logMsg.Error("Failed to add relay", "error", err)
  429. return
  430. }
  431. }
  432. relay, ok := h.relayState.QueryRelayForByIp(from)
  433. if !ok {
  434. logMsg.Error("Relay State not found", "from", from)
  435. return
  436. }
  437. resp := NebulaControl{
  438. Type: NebulaControl_CreateRelayResponse,
  439. ResponderRelayIndex: relay.LocalIndex,
  440. InitiatorRelayIndex: relay.RemoteIndex,
  441. }
  442. if v == cert.Version1 {
  443. b := from.As4()
  444. resp.OldRelayFromAddr = binary.BigEndian.Uint32(b[:])
  445. b = target.As4()
  446. resp.OldRelayToAddr = binary.BigEndian.Uint32(b[:])
  447. } else {
  448. resp.RelayFromAddr = netAddrToProtoAddr(from)
  449. resp.RelayToAddr = netAddrToProtoAddr(target)
  450. }
  451. msg, err := resp.Marshal()
  452. if err != nil {
  453. logMsg.Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay", "error", err)
  454. } else {
  455. f.SendMessageToHostInfo(header.Control, 0, h, msg, make([]byte, 12), make([]byte, mtu))
  456. rm.l.Info("send CreateRelayResponse",
  457. "relayFrom", from,
  458. "relayTo", target,
  459. "initiatorRelayIndex", resp.InitiatorRelayIndex,
  460. "responderRelayIndex", resp.ResponderRelayIndex,
  461. "vpnAddrs", h.vpnAddrs,
  462. )
  463. }
  464. return
  465. } else {
  466. // the target is not me. Create a relay to the target, from me.
  467. if !rm.GetAmRelay() {
  468. return
  469. }
  470. peer := rm.hostmap.QueryVpnAddr(target)
  471. if peer == nil {
  472. // Try to establish a connection to this host. If we get a future relay request,
  473. // we'll be ready!
  474. f.Handshake(target)
  475. return
  476. }
  477. if !peer.GetRemote().IsValid() {
  478. // Only create relays to peers for whom I have a direct connection
  479. return
  480. }
  481. var index uint32
  482. var err error
  483. targetRelay, ok := peer.relayState.QueryRelayForByIp(from)
  484. if ok {
  485. index = targetRelay.LocalIndex
  486. } else {
  487. // Allocate an index in the hostMap for this relay peer
  488. index, err = AddRelay(rm.l, peer, f.hostMap, from, nil, ForwardingType, Requested)
  489. if err != nil {
  490. return
  491. }
  492. }
  493. peer.relayState.UpdateRelayForByIpState(from, Requested)
  494. // Send a CreateRelayRequest to the peer.
  495. req := NebulaControl{
  496. Type: NebulaControl_CreateRelayRequest,
  497. InitiatorRelayIndex: index,
  498. }
  499. if v == cert.Version1 {
  500. if !h.vpnAddrs[0].Is4() {
  501. rm.l.Error("Refusing to CreateRelayRequest for a v1 relay with an ipv6 address",
  502. "relayFrom", h.vpnAddrs[0],
  503. "relayTo", target,
  504. "initiatorRelayIndex", req.InitiatorRelayIndex,
  505. "responderRelayIndex", req.ResponderRelayIndex,
  506. "vpnAddr", target,
  507. )
  508. return
  509. }
  510. b := h.vpnAddrs[0].As4()
  511. req.OldRelayFromAddr = binary.BigEndian.Uint32(b[:])
  512. b = target.As4()
  513. req.OldRelayToAddr = binary.BigEndian.Uint32(b[:])
  514. } else {
  515. req.RelayFromAddr = netAddrToProtoAddr(h.vpnAddrs[0])
  516. req.RelayToAddr = netAddrToProtoAddr(target)
  517. }
  518. msg, err := req.Marshal()
  519. if err != nil {
  520. logMsg.Error("relayManager Failed to marshal Control message to create relay", "error", err)
  521. } else {
  522. f.SendMessageToHostInfo(header.Control, 0, peer, msg, make([]byte, 12), make([]byte, mtu))
  523. rm.l.Info("send CreateRelayRequest",
  524. "relayFrom", h.vpnAddrs[0],
  525. "relayTo", target,
  526. "initiatorRelayIndex", req.InitiatorRelayIndex,
  527. "responderRelayIndex", req.ResponderRelayIndex,
  528. "vpnAddr", target,
  529. )
  530. }
  531. // Also track the half-created Relay state just received
  532. _, ok = h.relayState.QueryRelayForByIp(target)
  533. if !ok {
  534. _, err := AddRelay(rm.l, h, f.hostMap, target, &m.InitiatorRelayIndex, ForwardingType, PeerRequested)
  535. if err != nil {
  536. logMsg.Error("relayManager Failed to allocate a local index for relay", "error", err)
  537. return
  538. }
  539. }
  540. }
  541. }