handshake_ix.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. package nebula
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/flynn/noise"
  6. "github.com/sirupsen/logrus"
  7. "github.com/slackhq/nebula/header"
  8. "github.com/slackhq/nebula/iputil"
  9. "github.com/slackhq/nebula/udp"
  10. )
  11. // NOISE IX Handshakes
  12. // This function constructs a handshake packet, but does not actually send it
  13. // Sending is done by the handshake manager
  14. func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
  15. err := f.handshakeManager.allocateIndex(hh)
  16. if err != nil {
  17. f.l.WithError(err).WithField("vpnIp", hh.hostinfo.vpnIp).
  18. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to generate index")
  19. return false
  20. }
  21. certState := f.pki.GetCertState()
  22. ci := NewConnectionState(f.l, f.cipher, certState, true, noise.HandshakeIX, []byte{}, 0)
  23. hh.hostinfo.ConnectionState = ci
  24. hsProto := &NebulaHandshakeDetails{
  25. InitiatorIndex: hh.hostinfo.localIndexId,
  26. Time: uint64(time.Now().UnixNano()),
  27. Cert: certState.RawCertificateNoKey,
  28. }
  29. hsBytes := []byte{}
  30. hs := &NebulaHandshake{
  31. Details: hsProto,
  32. }
  33. hsBytes, err = hs.Marshal()
  34. if err != nil {
  35. f.l.WithError(err).WithField("vpnIp", hh.hostinfo.vpnIp).
  36. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
  37. return false
  38. }
  39. h := header.Encode(make([]byte, header.Len), header.Version, header.Handshake, header.HandshakeIXPSK0, 0, 1)
  40. ci.messageCounter.Add(1)
  41. msg, _, _, err := ci.H.WriteMessage(h, hsBytes)
  42. if err != nil {
  43. f.l.WithError(err).WithField("vpnIp", hh.hostinfo.vpnIp).
  44. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
  45. return false
  46. }
  47. // We are sending handshake packet 1, so we don't expect to receive
  48. // handshake packet 1 from the responder
  49. ci.window.Update(f.l, 1)
  50. hh.hostinfo.HandshakePacket[0] = msg
  51. hh.ready = true
  52. return true
  53. }
  54. func ixHandshakeStage1(f *Interface, addr *udp.Addr, via *ViaSender, packet []byte, h *header.H) {
  55. certState := f.pki.GetCertState()
  56. ci := NewConnectionState(f.l, f.cipher, certState, false, noise.HandshakeIX, []byte{}, 0)
  57. // Mark packet 1 as seen so it doesn't show up as missed
  58. ci.window.Update(f.l, 1)
  59. msg, _, _, err := ci.H.ReadMessage(nil, packet[header.Len:])
  60. if err != nil {
  61. f.l.WithError(err).WithField("udpAddr", addr).
  62. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to call noise.ReadMessage")
  63. return
  64. }
  65. hs := &NebulaHandshake{}
  66. err = hs.Unmarshal(msg)
  67. /*
  68. l.Debugln("GOT INDEX: ", hs.Details.InitiatorIndex)
  69. */
  70. if err != nil || hs.Details == nil {
  71. f.l.WithError(err).WithField("udpAddr", addr).
  72. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed unmarshal handshake message")
  73. return
  74. }
  75. remoteCert, err := RecombineCertAndValidate(ci.H, hs.Details.Cert, f.pki.GetCAPool())
  76. if err != nil {
  77. e := f.l.WithError(err).WithField("udpAddr", addr).
  78. WithField("handshake", m{"stage": 1, "style": "ix_psk0"})
  79. if f.l.Level > logrus.DebugLevel {
  80. e = e.WithField("cert", remoteCert)
  81. }
  82. e.Info("Invalid certificate from host")
  83. return
  84. }
  85. vpnIp := iputil.Ip2VpnIp(remoteCert.Details.Ips[0].IP)
  86. certName := remoteCert.Details.Name
  87. fingerprint, _ := remoteCert.Sha256Sum()
  88. issuer := remoteCert.Details.Issuer
  89. if vpnIp == f.myVpnIp {
  90. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  91. WithField("certName", certName).
  92. WithField("fingerprint", fingerprint).
  93. WithField("issuer", issuer).
  94. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Refusing to handshake with myself")
  95. return
  96. }
  97. if addr != nil {
  98. if !f.lightHouse.GetRemoteAllowList().Allow(vpnIp, addr.IP) {
  99. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).Debug("lighthouse.remote_allow_list denied incoming handshake")
  100. return
  101. }
  102. }
  103. myIndex, err := generateIndex(f.l)
  104. if err != nil {
  105. f.l.WithError(err).WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  106. WithField("certName", certName).
  107. WithField("fingerprint", fingerprint).
  108. WithField("issuer", issuer).
  109. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to generate index")
  110. return
  111. }
  112. hostinfo := &HostInfo{
  113. ConnectionState: ci,
  114. localIndexId: myIndex,
  115. remoteIndexId: hs.Details.InitiatorIndex,
  116. vpnIp: vpnIp,
  117. HandshakePacket: make(map[uint8][]byte, 0),
  118. lastHandshakeTime: hs.Details.Time,
  119. relayState: RelayState{
  120. relays: map[iputil.VpnIp]struct{}{},
  121. relayForByIp: map[iputil.VpnIp]*Relay{},
  122. relayForByIdx: map[uint32]*Relay{},
  123. },
  124. }
  125. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  126. WithField("certName", certName).
  127. WithField("fingerprint", fingerprint).
  128. WithField("issuer", issuer).
  129. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  130. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  131. Info("Handshake message received")
  132. hs.Details.ResponderIndex = myIndex
  133. hs.Details.Cert = certState.RawCertificateNoKey
  134. // Update the time in case their clock is way off from ours
  135. hs.Details.Time = uint64(time.Now().UnixNano())
  136. hsBytes, err := hs.Marshal()
  137. if err != nil {
  138. f.l.WithError(err).WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  139. WithField("certName", certName).
  140. WithField("fingerprint", fingerprint).
  141. WithField("issuer", issuer).
  142. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
  143. return
  144. }
  145. nh := header.Encode(make([]byte, header.Len), header.Version, header.Handshake, header.HandshakeIXPSK0, hs.Details.InitiatorIndex, 2)
  146. msg, dKey, eKey, err := ci.H.WriteMessage(nh, hsBytes)
  147. if err != nil {
  148. f.l.WithError(err).WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  149. WithField("certName", certName).
  150. WithField("fingerprint", fingerprint).
  151. WithField("issuer", issuer).
  152. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
  153. return
  154. } else if dKey == nil || eKey == nil {
  155. f.l.WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  156. WithField("certName", certName).
  157. WithField("fingerprint", fingerprint).
  158. WithField("issuer", issuer).
  159. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Noise did not arrive at a key")
  160. return
  161. }
  162. hostinfo.HandshakePacket[0] = make([]byte, len(packet[header.Len:]))
  163. copy(hostinfo.HandshakePacket[0], packet[header.Len:])
  164. // Regardless of whether you are the sender or receiver, you should arrive here
  165. // and complete standing up the connection.
  166. hostinfo.HandshakePacket[2] = make([]byte, len(msg))
  167. copy(hostinfo.HandshakePacket[2], msg)
  168. // We are sending handshake packet 2, so we don't expect to receive
  169. // handshake packet 2 from the initiator.
  170. ci.window.Update(f.l, 2)
  171. ci.peerCert = remoteCert
  172. ci.dKey = NewNebulaCipherState(dKey)
  173. ci.eKey = NewNebulaCipherState(eKey)
  174. hostinfo.remotes = f.lightHouse.QueryCache(vpnIp)
  175. hostinfo.SetRemote(addr)
  176. hostinfo.CreateRemoteCIDR(remoteCert)
  177. existing, err := f.handshakeManager.CheckAndComplete(hostinfo, 0, f)
  178. if err != nil {
  179. switch err {
  180. case ErrAlreadySeen:
  181. // Update remote if preferred
  182. if existing.SetRemoteIfPreferred(f.hostMap, addr) {
  183. // Send a test packet to ensure the other side has also switched to
  184. // the preferred remote
  185. f.SendMessageToVpnIp(header.Test, header.TestRequest, vpnIp, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  186. }
  187. msg = existing.HandshakePacket[2]
  188. f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
  189. if addr != nil {
  190. err := f.outside.WriteTo(msg, addr)
  191. if err != nil {
  192. f.l.WithField("vpnIp", existing.vpnIp).WithField("udpAddr", addr).
  193. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
  194. WithError(err).Error("Failed to send handshake message")
  195. } else {
  196. f.l.WithField("vpnIp", existing.vpnIp).WithField("udpAddr", addr).
  197. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
  198. Info("Handshake message sent")
  199. }
  200. return
  201. } else {
  202. if via == nil {
  203. f.l.Error("Handshake send failed: both addr and via are nil.")
  204. return
  205. }
  206. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnIp)
  207. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
  208. f.l.WithField("vpnIp", existing.vpnIp).WithField("relay", via.relayHI.vpnIp).
  209. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
  210. Info("Handshake message sent")
  211. return
  212. }
  213. case ErrExistingHostInfo:
  214. // This means there was an existing tunnel and this handshake was older than the one we are currently based on
  215. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  216. WithField("certName", certName).
  217. WithField("oldHandshakeTime", existing.lastHandshakeTime).
  218. WithField("newHandshakeTime", hostinfo.lastHandshakeTime).
  219. WithField("fingerprint", fingerprint).
  220. WithField("issuer", issuer).
  221. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  222. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  223. Info("Handshake too old")
  224. // Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
  225. f.SendMessageToVpnIp(header.Test, header.TestRequest, vpnIp, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  226. return
  227. case ErrLocalIndexCollision:
  228. // This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
  229. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  230. WithField("certName", certName).
  231. WithField("fingerprint", fingerprint).
  232. WithField("issuer", issuer).
  233. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  234. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  235. WithField("localIndex", hostinfo.localIndexId).WithField("collision", existing.vpnIp).
  236. Error("Failed to add HostInfo due to localIndex collision")
  237. return
  238. default:
  239. // Shouldn't happen, but just in case someone adds a new error type to CheckAndComplete
  240. // And we forget to update it here
  241. f.l.WithError(err).WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  242. WithField("certName", certName).
  243. WithField("fingerprint", fingerprint).
  244. WithField("issuer", issuer).
  245. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  246. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  247. Error("Failed to add HostInfo to HostMap")
  248. return
  249. }
  250. }
  251. // Do the send
  252. f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
  253. if addr != nil {
  254. err = f.outside.WriteTo(msg, addr)
  255. if err != nil {
  256. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  257. WithField("certName", certName).
  258. WithField("fingerprint", fingerprint).
  259. WithField("issuer", issuer).
  260. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  261. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  262. WithError(err).Error("Failed to send handshake")
  263. } else {
  264. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  265. WithField("certName", certName).
  266. WithField("fingerprint", fingerprint).
  267. WithField("issuer", issuer).
  268. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  269. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  270. Info("Handshake message sent")
  271. }
  272. } else {
  273. if via == nil {
  274. f.l.Error("Handshake send failed: both addr and via are nil.")
  275. return
  276. }
  277. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnIp)
  278. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
  279. f.l.WithField("vpnIp", vpnIp).WithField("relay", via.relayHI.vpnIp).
  280. WithField("certName", certName).
  281. WithField("fingerprint", fingerprint).
  282. WithField("issuer", issuer).
  283. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  284. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  285. Info("Handshake message sent")
  286. }
  287. f.connectionManager.AddTrafficWatch(hostinfo.localIndexId)
  288. prev := hostinfo.ConnectionState.messageCounter.Swap(2)
  289. if prev > 2 {
  290. panic(fmt.Errorf("invalid state: messageCounter > 2 before handshake complete: %v", prev))
  291. }
  292. hostinfo.remotes.ResetBlockedRemotes()
  293. return
  294. }
  295. func ixHandshakeStage2(f *Interface, addr *udp.Addr, via *ViaSender, hh *HandshakeHostInfo, packet []byte, h *header.H) bool {
  296. if hh == nil {
  297. // Nothing here to tear down, got a bogus stage 2 packet
  298. return true
  299. }
  300. hh.Lock()
  301. defer hh.Unlock()
  302. hostinfo := hh.hostinfo
  303. if addr != nil {
  304. if !f.lightHouse.GetRemoteAllowList().Allow(hostinfo.vpnIp, addr.IP) {
  305. f.l.WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).Debug("lighthouse.remote_allow_list denied incoming handshake")
  306. return false
  307. }
  308. }
  309. ci := hostinfo.ConnectionState
  310. msg, eKey, dKey, err := ci.H.ReadMessage(nil, packet[header.Len:])
  311. if err != nil {
  312. f.l.WithError(err).WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  313. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("header", h).
  314. Error("Failed to call noise.ReadMessage")
  315. // We don't want to tear down the connection on a bad ReadMessage because it could be an attacker trying
  316. // to DOS us. Every other error condition after should to allow a possible good handshake to complete in the
  317. // near future
  318. return false
  319. } else if dKey == nil || eKey == nil {
  320. f.l.WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  321. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  322. Error("Noise did not arrive at a key")
  323. // This should be impossible in IX but just in case, if we get here then there is no chance to recover
  324. // the handshake state machine. Tear it down
  325. return true
  326. }
  327. hs := &NebulaHandshake{}
  328. err = hs.Unmarshal(msg)
  329. if err != nil || hs.Details == nil {
  330. f.l.WithError(err).WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  331. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).Error("Failed unmarshal handshake message")
  332. // The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
  333. return true
  334. }
  335. remoteCert, err := RecombineCertAndValidate(ci.H, hs.Details.Cert, f.pki.GetCAPool())
  336. if err != nil {
  337. e := f.l.WithError(err).WithField("vpnIp", hostinfo.vpnIp).WithField("udpAddr", addr).
  338. WithField("handshake", m{"stage": 2, "style": "ix_psk0"})
  339. if f.l.Level > logrus.DebugLevel {
  340. e = e.WithField("cert", remoteCert)
  341. }
  342. e.Error("Invalid certificate from host")
  343. // The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
  344. return true
  345. }
  346. vpnIp := iputil.Ip2VpnIp(remoteCert.Details.Ips[0].IP)
  347. certName := remoteCert.Details.Name
  348. fingerprint, _ := remoteCert.Sha256Sum()
  349. issuer := remoteCert.Details.Issuer
  350. // Ensure the right host responded
  351. if vpnIp != hostinfo.vpnIp {
  352. f.l.WithField("intendedVpnIp", hostinfo.vpnIp).WithField("haveVpnIp", vpnIp).
  353. WithField("udpAddr", addr).WithField("certName", certName).
  354. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  355. Info("Incorrect host responded to handshake")
  356. // Release our old handshake from pending, it should not continue
  357. f.handshakeManager.DeleteHostInfo(hostinfo)
  358. // Create a new hostinfo/handshake for the intended vpn ip
  359. f.handshakeManager.StartHandshake(hostinfo.vpnIp, func(newHH *HandshakeHostInfo) {
  360. //TODO: this doesnt know if its being added or is being used for caching a packet
  361. // Block the current used address
  362. newHH.hostinfo.remotes = hostinfo.remotes
  363. newHH.hostinfo.remotes.BlockRemote(addr)
  364. // Get the correct remote list for the host we did handshake with
  365. hostinfo.remotes = f.lightHouse.QueryCache(vpnIp)
  366. f.l.WithField("blockedUdpAddrs", newHH.hostinfo.remotes.CopyBlockedRemotes()).WithField("vpnIp", vpnIp).
  367. WithField("remotes", newHH.hostinfo.remotes.CopyAddrs(f.hostMap.GetPreferredRanges())).
  368. Info("Blocked addresses for handshakes")
  369. // Swap the packet store to benefit the original intended recipient
  370. newHH.packetStore = hh.packetStore
  371. hh.packetStore = []*cachedPacket{}
  372. // Finally, put the correct vpn ip in the host info, tell them to close the tunnel, and return true to tear down
  373. hostinfo.vpnIp = vpnIp
  374. f.sendCloseTunnel(hostinfo)
  375. })
  376. return true
  377. }
  378. // Mark packet 2 as seen so it doesn't show up as missed
  379. ci.window.Update(f.l, 2)
  380. duration := time.Since(hh.startTime).Nanoseconds()
  381. f.l.WithField("vpnIp", vpnIp).WithField("udpAddr", addr).
  382. WithField("certName", certName).
  383. WithField("fingerprint", fingerprint).
  384. WithField("issuer", issuer).
  385. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  386. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  387. WithField("durationNs", duration).
  388. WithField("sentCachedPackets", len(hh.packetStore)).
  389. Info("Handshake message received")
  390. hostinfo.remoteIndexId = hs.Details.ResponderIndex
  391. hostinfo.lastHandshakeTime = hs.Details.Time
  392. // Store their cert and our symmetric keys
  393. ci.peerCert = remoteCert
  394. ci.dKey = NewNebulaCipherState(dKey)
  395. ci.eKey = NewNebulaCipherState(eKey)
  396. // Make sure the current udpAddr being used is set for responding
  397. if addr != nil {
  398. hostinfo.SetRemote(addr)
  399. } else {
  400. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnIp)
  401. }
  402. // Build up the radix for the firewall if we have subnets in the cert
  403. hostinfo.CreateRemoteCIDR(remoteCert)
  404. prev := hostinfo.ConnectionState.messageCounter.Swap(2)
  405. if prev > 2 {
  406. panic(fmt.Errorf("invalid state: messageCounter > 2 before handshake complete: %v", prev))
  407. }
  408. // Complete our handshake and update metrics, this will replace any existing tunnels for this vpnIp
  409. f.handshakeManager.Complete(hostinfo, f)
  410. f.connectionManager.AddTrafficWatch(hostinfo.localIndexId)
  411. if f.l.Level >= logrus.DebugLevel {
  412. hostinfo.logger(f.l).Debugf("Sending %d stored packets", len(hh.packetStore))
  413. }
  414. if len(hh.packetStore) > 0 {
  415. nb := make([]byte, 12, 12)
  416. out := make([]byte, mtu)
  417. for _, cp := range hh.packetStore {
  418. cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
  419. }
  420. f.cachedPacketMetrics.sent.Inc(int64(len(hh.packetStore)))
  421. }
  422. hostinfo.remotes.ResetBlockedRemotes()
  423. f.metricHandshakes.Update(duration)
  424. return false
  425. }