relay_manager.go 19 KB

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