handshake_ix.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. package nebula
  2. import (
  3. "sync/atomic"
  4. "time"
  5. "github.com/flynn/noise"
  6. "github.com/golang/protobuf/proto"
  7. )
  8. // NOISE IX Handshakes
  9. // This function constructs a handshake packet, but does not actually send it
  10. // Sending is done by the handshake manager
  11. func ixHandshakeStage0(f *Interface, vpnIp uint32, hostinfo *HostInfo) {
  12. // This queries the lighthouse if we don't know a remote for the host
  13. if hostinfo.remote == nil {
  14. ips, err := f.lightHouse.Query(vpnIp, f)
  15. if err != nil {
  16. //l.Debugln(err)
  17. }
  18. for _, ip := range ips {
  19. hostinfo.AddRemote(ip)
  20. }
  21. }
  22. err := f.handshakeManager.AddIndexHostInfo(hostinfo)
  23. if err != nil {
  24. f.l.WithError(err).WithField("vpnIp", IntIp(vpnIp)).
  25. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to generate index")
  26. return
  27. }
  28. ci := hostinfo.ConnectionState
  29. hsProto := &NebulaHandshakeDetails{
  30. InitiatorIndex: hostinfo.localIndexId,
  31. Time: uint64(time.Now().Unix()),
  32. Cert: ci.certState.rawCertificateNoKey,
  33. }
  34. hsBytes := []byte{}
  35. hs := &NebulaHandshake{
  36. Details: hsProto,
  37. }
  38. hsBytes, err = proto.Marshal(hs)
  39. if err != nil {
  40. f.l.WithError(err).WithField("vpnIp", IntIp(vpnIp)).
  41. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
  42. return
  43. }
  44. header := HeaderEncode(make([]byte, HeaderLen), Version, uint8(handshake), handshakeIXPSK0, 0, 1)
  45. atomic.AddUint64(&ci.atomicMessageCounter, 1)
  46. msg, _, _, err := ci.H.WriteMessage(header, hsBytes)
  47. if err != nil {
  48. f.l.WithError(err).WithField("vpnIp", IntIp(vpnIp)).
  49. WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
  50. return
  51. }
  52. // We are sending handshake packet 1, so we don't expect to receive
  53. // handshake packet 1 from the responder
  54. ci.window.Update(f.l, 1)
  55. hostinfo.HandshakePacket[0] = msg
  56. hostinfo.HandshakeReady = true
  57. hostinfo.handshakeStart = time.Now()
  58. }
  59. func ixHandshakeStage1(f *Interface, addr *udpAddr, packet []byte, h *Header) {
  60. ci := f.newConnectionState(f.l, false, noise.HandshakeIX, []byte{}, 0)
  61. // Mark packet 1 as seen so it doesn't show up as missed
  62. ci.window.Update(f.l, 1)
  63. msg, _, _, err := ci.H.ReadMessage(nil, packet[HeaderLen:])
  64. if err != nil {
  65. f.l.WithError(err).WithField("udpAddr", addr).
  66. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to call noise.ReadMessage")
  67. return
  68. }
  69. hs := &NebulaHandshake{}
  70. err = proto.Unmarshal(msg, hs)
  71. /*
  72. l.Debugln("GOT INDEX: ", hs.Details.InitiatorIndex)
  73. */
  74. if err != nil || hs.Details == nil {
  75. f.l.WithError(err).WithField("udpAddr", addr).
  76. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed unmarshal handshake message")
  77. return
  78. }
  79. remoteCert, err := RecombineCertAndValidate(ci.H, hs.Details.Cert, f.caPool)
  80. if err != nil {
  81. f.l.WithError(err).WithField("udpAddr", addr).
  82. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).WithField("cert", remoteCert).
  83. Info("Invalid certificate from host")
  84. return
  85. }
  86. vpnIP := ip2int(remoteCert.Details.Ips[0].IP)
  87. certName := remoteCert.Details.Name
  88. fingerprint, _ := remoteCert.Sha256Sum()
  89. if vpnIP == ip2int(f.certState.certificate.Details.Ips[0].IP) {
  90. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  91. WithField("certName", certName).
  92. WithField("fingerprint", fingerprint).
  93. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Refusing to handshake with myself")
  94. return
  95. }
  96. myIndex, err := generateIndex(f.l)
  97. if err != nil {
  98. f.l.WithError(err).WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  99. WithField("certName", certName).
  100. WithField("fingerprint", fingerprint).
  101. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to generate index")
  102. return
  103. }
  104. hostinfo := &HostInfo{
  105. ConnectionState: ci,
  106. Remotes: []*udpAddr{},
  107. localIndexId: myIndex,
  108. remoteIndexId: hs.Details.InitiatorIndex,
  109. hostId: vpnIP,
  110. HandshakePacket: make(map[uint8][]byte, 0),
  111. }
  112. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  113. WithField("certName", certName).
  114. WithField("fingerprint", fingerprint).
  115. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  116. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  117. Info("Handshake message received")
  118. hs.Details.ResponderIndex = myIndex
  119. hs.Details.Cert = ci.certState.rawCertificateNoKey
  120. hsBytes, err := proto.Marshal(hs)
  121. if err != nil {
  122. f.l.WithError(err).WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  123. WithField("certName", certName).
  124. WithField("fingerprint", fingerprint).
  125. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to marshal handshake message")
  126. return
  127. }
  128. header := HeaderEncode(make([]byte, HeaderLen), Version, uint8(handshake), handshakeIXPSK0, hs.Details.InitiatorIndex, 2)
  129. msg, dKey, eKey, err := ci.H.WriteMessage(header, hsBytes)
  130. if err != nil {
  131. f.l.WithError(err).WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  132. WithField("certName", certName).
  133. WithField("fingerprint", fingerprint).
  134. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Failed to call noise.WriteMessage")
  135. return
  136. } else if dKey == nil || eKey == nil {
  137. f.l.WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  138. WithField("certName", certName).
  139. WithField("fingerprint", fingerprint).
  140. WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).Error("Noise did not arrive at a key")
  141. return
  142. }
  143. hostinfo.HandshakePacket[0] = make([]byte, len(packet[HeaderLen:]))
  144. copy(hostinfo.HandshakePacket[0], packet[HeaderLen:])
  145. // Regardless of whether you are the sender or receiver, you should arrive here
  146. // and complete standing up the connection.
  147. hostinfo.HandshakePacket[2] = make([]byte, len(msg))
  148. copy(hostinfo.HandshakePacket[2], msg)
  149. // We are sending handshake packet 2, so we don't expect to receive
  150. // handshake packet 2 from the initiator.
  151. ci.window.Update(f.l, 2)
  152. ci.peerCert = remoteCert
  153. ci.dKey = NewNebulaCipherState(dKey)
  154. ci.eKey = NewNebulaCipherState(eKey)
  155. //l.Debugln("got symmetric pairs")
  156. //hostinfo.ClearRemotes()
  157. hostinfo.AddRemote(addr)
  158. hostinfo.ForcePromoteBest(f.hostMap.preferredRanges)
  159. hostinfo.CreateRemoteCIDR(remoteCert)
  160. hostinfo.Lock()
  161. defer hostinfo.Unlock()
  162. // Only overwrite existing record if we should win the handshake race
  163. overwrite := vpnIP > ip2int(f.certState.certificate.Details.Ips[0].IP)
  164. existing, err := f.handshakeManager.CheckAndComplete(hostinfo, 0, overwrite, f)
  165. if err != nil {
  166. switch err {
  167. case ErrAlreadySeen:
  168. msg = existing.HandshakePacket[2]
  169. f.messageMetrics.Tx(handshake, NebulaMessageSubType(msg[1]), 1)
  170. err := f.outside.WriteTo(msg, addr)
  171. if err != nil {
  172. f.l.WithField("vpnIp", IntIp(existing.hostId)).WithField("udpAddr", addr).
  173. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
  174. WithError(err).Error("Failed to send handshake message")
  175. } else {
  176. f.l.WithField("vpnIp", IntIp(existing.hostId)).WithField("udpAddr", addr).
  177. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("cached", true).
  178. Info("Handshake message sent")
  179. }
  180. return
  181. case ErrExistingHostInfo:
  182. // This means there was an existing tunnel and we didn't win
  183. // handshake avoidance
  184. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  185. WithField("certName", certName).
  186. WithField("fingerprint", fingerprint).
  187. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  188. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  189. Info("Prevented a handshake race")
  190. // Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
  191. f.SendMessageToVpnIp(test, testRequest, vpnIP, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  192. return
  193. case ErrLocalIndexCollision:
  194. // This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
  195. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  196. WithField("certName", certName).
  197. WithField("fingerprint", fingerprint).
  198. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  199. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  200. WithField("localIndex", hostinfo.localIndexId).WithField("collision", IntIp(existing.hostId)).
  201. Error("Failed to add HostInfo due to localIndex collision")
  202. return
  203. default:
  204. // Shouldn't happen, but just in case someone adds a new error type to CheckAndComplete
  205. // And we forget to update it here
  206. f.l.WithError(err).WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  207. WithField("certName", certName).
  208. WithField("fingerprint", fingerprint).
  209. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  210. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 1, "style": "ix_psk0"}).
  211. Error("Failed to add HostInfo to HostMap")
  212. return
  213. }
  214. }
  215. // Do the send
  216. f.messageMetrics.Tx(handshake, NebulaMessageSubType(msg[1]), 1)
  217. err = f.outside.WriteTo(msg, addr)
  218. if err != nil {
  219. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  220. WithField("certName", certName).
  221. WithField("fingerprint", fingerprint).
  222. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  223. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  224. WithError(err).Error("Failed to send handshake")
  225. } else {
  226. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  227. WithField("certName", certName).
  228. WithField("fingerprint", fingerprint).
  229. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  230. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  231. Info("Handshake message sent")
  232. }
  233. hostinfo.handshakeComplete(f.l)
  234. return
  235. }
  236. func ixHandshakeStage2(f *Interface, addr *udpAddr, hostinfo *HostInfo, packet []byte, h *Header) bool {
  237. if hostinfo == nil {
  238. // Nothing here to tear down, got a bogus stage 2 packet
  239. return true
  240. }
  241. hostinfo.Lock()
  242. defer hostinfo.Unlock()
  243. ci := hostinfo.ConnectionState
  244. if ci.ready {
  245. f.l.WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  246. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("header", h).
  247. Info("Handshake is already complete")
  248. // We already have a complete tunnel, there is nothing that can be done by processing further stage 1 packets
  249. return false
  250. }
  251. //TODO: we need this to merge in https://github.com/flynn/noise/pull/39
  252. msg, eKey, dKey, err := ci.H.ReadMessage(nil, packet[HeaderLen:])
  253. if err != nil {
  254. f.l.WithError(err).WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  255. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).WithField("header", h).
  256. Error("Failed to call noise.ReadMessage")
  257. // We don't want to tear down the connection on a bad ReadMessage because it could be an attacker trying
  258. // to DOS us. Every other error condition after should to allow a possible good handshake to complete in the
  259. // near future
  260. return false
  261. } else if dKey == nil || eKey == nil {
  262. f.l.WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  263. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  264. Error("Noise did not arrive at a key")
  265. // This should be impossible in IX but just in case, if we get here then there is no chance to recover
  266. // the handshake state machine. Tear it down
  267. return true
  268. }
  269. hs := &NebulaHandshake{}
  270. err = proto.Unmarshal(msg, hs)
  271. if err != nil || hs.Details == nil {
  272. f.l.WithError(err).WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  273. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).Error("Failed unmarshal handshake message")
  274. // The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
  275. return true
  276. }
  277. remoteCert, err := RecombineCertAndValidate(ci.H, hs.Details.Cert, f.caPool)
  278. if err != nil {
  279. f.l.WithError(err).WithField("vpnIp", IntIp(hostinfo.hostId)).WithField("udpAddr", addr).
  280. WithField("cert", remoteCert).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  281. Error("Invalid certificate from host")
  282. // The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
  283. return true
  284. }
  285. vpnIP := ip2int(remoteCert.Details.Ips[0].IP)
  286. certName := remoteCert.Details.Name
  287. fingerprint, _ := remoteCert.Sha256Sum()
  288. if vpnIP != hostinfo.hostId {
  289. f.l.WithField("intendedVpnIp", IntIp(hostinfo.hostId)).WithField("haveVpnIp", IntIp(vpnIP)).
  290. WithField("udpAddr", addr).WithField("certName", certName).
  291. WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  292. Info("Incorrect host responded to handshake")
  293. if ho, _ := f.handshakeManager.pendingHostMap.QueryVpnIP(vpnIP); ho != nil {
  294. // We might have a pending tunnel to this host already, clear out that attempt since we have a tunnel now
  295. f.handshakeManager.pendingHostMap.DeleteHostInfo(ho)
  296. }
  297. // Create a new hostinfo/handshake for the intended vpn ip, but first release the lock
  298. f.handshakeManager.pendingHostMap.DeleteHostInfo(hostinfo)
  299. //TODO: this adds it to the timer wheel in a way that aggressively retries
  300. newHostInfo := f.getOrHandshake(hostinfo.hostId)
  301. newHostInfo.Lock()
  302. // Block the current used address
  303. newHostInfo.unlockedBlockRemote(addr)
  304. // If this is an ongoing issue our previous hostmap will have some bad ips too
  305. for _, v := range hostinfo.badRemotes {
  306. newHostInfo.unlockedBlockRemote(v)
  307. }
  308. //TODO: this is me enabling tests
  309. newHostInfo.ForcePromoteBest(f.hostMap.preferredRanges)
  310. f.l.WithField("blockedUdpAddrs", newHostInfo.badRemotes).WithField("vpnIp", IntIp(vpnIP)).
  311. WithField("remotes", newHostInfo.Remotes).
  312. Info("Blocked addresses for handshakes")
  313. // Swap the packet store to benefit the original intended recipient
  314. newHostInfo.packetStore = hostinfo.packetStore
  315. hostinfo.packetStore = []*cachedPacket{}
  316. // Set the current hostId to the new vpnIp
  317. hostinfo.hostId = vpnIP
  318. newHostInfo.Unlock()
  319. }
  320. // Mark packet 2 as seen so it doesn't show up as missed
  321. ci.window.Update(f.l, 2)
  322. duration := time.Since(hostinfo.handshakeStart).Nanoseconds()
  323. f.l.WithField("vpnIp", IntIp(vpnIP)).WithField("udpAddr", addr).
  324. WithField("certName", certName).
  325. WithField("fingerprint", fingerprint).
  326. WithField("initiatorIndex", hs.Details.InitiatorIndex).WithField("responderIndex", hs.Details.ResponderIndex).
  327. WithField("remoteIndex", h.RemoteIndex).WithField("handshake", m{"stage": 2, "style": "ix_psk0"}).
  328. WithField("durationNs", duration).
  329. Info("Handshake message received")
  330. hostinfo.remoteIndexId = hs.Details.ResponderIndex
  331. hs.Details.Cert = ci.certState.rawCertificateNoKey
  332. // Store their cert and our symmetric keys
  333. ci.peerCert = remoteCert
  334. ci.dKey = NewNebulaCipherState(dKey)
  335. ci.eKey = NewNebulaCipherState(eKey)
  336. // Make sure the current udpAddr being used is set for responding
  337. hostinfo.SetRemote(addr)
  338. // Build up the radix for the firewall if we have subnets in the cert
  339. hostinfo.CreateRemoteCIDR(remoteCert)
  340. // Complete our handshake and update metrics, this will replace any existing tunnels for this vpnIp
  341. //TODO: Complete here does not do a race avoidance, it will just take the new tunnel. Is this ok?
  342. f.handshakeManager.Complete(hostinfo, f)
  343. hostinfo.handshakeComplete(f.l)
  344. f.metricHandshakes.Update(duration)
  345. return false
  346. }