handshake_ix.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. package nebula
  2. import (
  3. "bytes"
  4. "context"
  5. "log/slog"
  6. "net/netip"
  7. "time"
  8. "github.com/flynn/noise"
  9. "github.com/slackhq/nebula/cert"
  10. "github.com/slackhq/nebula/header"
  11. )
  12. // NOISE IX Handshakes
  13. // This function constructs a handshake packet, but does not actually send it
  14. // Sending is done by the handshake manager
  15. func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
  16. err := f.handshakeManager.allocateIndex(hh)
  17. if err != nil {
  18. f.l.Error("Failed to generate index",
  19. "error", err,
  20. "vpnAddrs", hh.hostinfo.vpnAddrs,
  21. "handshake", m{"stage": 0, "style": "ix_psk0"},
  22. )
  23. return false
  24. }
  25. cs := f.pki.getCertState()
  26. v := cs.initiatingVersion
  27. if hh.initiatingVersionOverride != cert.VersionPre1 {
  28. v = hh.initiatingVersionOverride
  29. } else if v < cert.Version2 {
  30. // If we're connecting to a v6 address we should encourage use of a V2 cert
  31. for _, a := range hh.hostinfo.vpnAddrs {
  32. if a.Is6() {
  33. v = cert.Version2
  34. break
  35. }
  36. }
  37. }
  38. crt := cs.getCertificate(v)
  39. if crt == nil {
  40. f.l.Error("Unable to handshake with host because no certificate is available",
  41. "vpnAddrs", hh.hostinfo.vpnAddrs,
  42. "handshake", m{"stage": 0, "style": "ix_psk0"},
  43. "certVersion", v,
  44. )
  45. return false
  46. }
  47. crtHs := cs.getHandshakeBytes(v)
  48. if crtHs == nil {
  49. f.l.Error("Unable to handshake with host because no certificate handshake bytes is available",
  50. "vpnAddrs", hh.hostinfo.vpnAddrs,
  51. "handshake", m{"stage": 0, "style": "ix_psk0"},
  52. "certVersion", v,
  53. )
  54. return false
  55. }
  56. ci, err := NewConnectionState(cs, crt, true, noise.HandshakeIX)
  57. if err != nil {
  58. f.l.Error("Failed to create connection state",
  59. "error", err,
  60. "vpnAddrs", hh.hostinfo.vpnAddrs,
  61. "handshake", m{"stage": 0, "style": "ix_psk0"},
  62. "certVersion", v,
  63. )
  64. return false
  65. }
  66. hh.hostinfo.ConnectionState = ci
  67. hs := &NebulaHandshake{
  68. Details: &NebulaHandshakeDetails{
  69. InitiatorIndex: hh.hostinfo.localIndexId,
  70. Time: uint64(time.Now().UnixNano()),
  71. Cert: crtHs,
  72. CertVersion: uint32(v),
  73. },
  74. }
  75. hsBytes, err := hs.Marshal()
  76. if err != nil {
  77. f.l.Error("Failed to marshal handshake message",
  78. "error", err,
  79. "vpnAddrs", hh.hostinfo.vpnAddrs,
  80. "certVersion", v,
  81. "handshake", m{"stage": 0, "style": "ix_psk0"},
  82. )
  83. return false
  84. }
  85. h := header.Encode(make([]byte, header.Len), header.Version, header.Handshake, header.HandshakeIXPSK0, 0, 1)
  86. msg, _, _, err := ci.H.WriteMessage(h, hsBytes)
  87. if err != nil {
  88. f.l.Error("Failed to call noise.WriteMessage",
  89. "error", err,
  90. "vpnAddrs", hh.hostinfo.vpnAddrs,
  91. "handshake", m{"stage": 0, "style": "ix_psk0"},
  92. )
  93. return false
  94. }
  95. // We are sending handshake packet 1, so we don't expect to receive
  96. // handshake packet 1 from the responder
  97. ci.window.Update(f.l, 1)
  98. hh.hostinfo.HandshakePacket[0] = msg
  99. hh.ready = true
  100. return true
  101. }
  102. func ixHandshakeStage1(f *Interface, via ViaSender, packet []byte, h *header.H) {
  103. cs := f.pki.getCertState()
  104. crt := cs.GetDefaultCertificate()
  105. if crt == nil {
  106. f.l.Error("Unable to handshake with host because no certificate is available",
  107. "from", via,
  108. "handshake", m{"stage": 0, "style": "ix_psk0"},
  109. "certVersion", cs.initiatingVersion,
  110. )
  111. return
  112. }
  113. ci, err := NewConnectionState(cs, crt, false, noise.HandshakeIX)
  114. if err != nil {
  115. f.l.Error("Failed to create connection state",
  116. "error", err,
  117. "from", via,
  118. "handshake", m{"stage": 1, "style": "ix_psk0"},
  119. )
  120. return
  121. }
  122. // Mark packet 1 as seen so it doesn't show up as missed
  123. ci.window.Update(f.l, 1)
  124. msg, _, _, err := ci.H.ReadMessage(nil, packet[header.Len:])
  125. if err != nil {
  126. f.l.Error("Failed to call noise.ReadMessage",
  127. "error", err,
  128. "from", via,
  129. "handshake", m{"stage": 1, "style": "ix_psk0"},
  130. )
  131. return
  132. }
  133. hs := &NebulaHandshake{}
  134. err = hs.Unmarshal(msg)
  135. if err != nil || hs.Details == nil {
  136. f.l.Error("Failed unmarshal handshake message",
  137. "error", err,
  138. "from", via,
  139. "handshake", m{"stage": 1, "style": "ix_psk0"},
  140. )
  141. return
  142. }
  143. rc, err := cert.Recombine(cert.Version(hs.Details.CertVersion), hs.Details.Cert, ci.H.PeerStatic(), ci.Curve())
  144. if err != nil {
  145. f.l.Info("Handshake did not contain a certificate",
  146. "error", err,
  147. "from", via,
  148. "handshake", m{"stage": 1, "style": "ix_psk0"},
  149. )
  150. return
  151. }
  152. remoteCert, err := f.pki.GetCAPool().VerifyCertificate(time.Now(), rc)
  153. if err != nil {
  154. fp, fperr := rc.Fingerprint()
  155. if fperr != nil {
  156. fp = "<error generating certificate fingerprint>"
  157. }
  158. attrs := []slog.Attr{
  159. slog.Any("error", err),
  160. slog.Any("from", via),
  161. slog.Any("handshake", m{"stage": 1, "style": "ix_psk0"}),
  162. slog.Any("certVpnNetworks", rc.Networks()),
  163. slog.String("certFingerprint", fp),
  164. }
  165. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  166. attrs = append(attrs, slog.Any("cert", rc))
  167. }
  168. // LogAttrs is intentional: attrs is a pre-built []slog.Attr slice that
  169. // callers grow conditionally, which has no pair-form equivalent.
  170. //nolint:sloglint
  171. f.l.LogAttrs(context.Background(), slog.LevelInfo, "Invalid certificate from host", attrs...)
  172. return
  173. }
  174. if !bytes.Equal(remoteCert.Certificate.PublicKey(), ci.H.PeerStatic()) {
  175. f.l.Info("public key mismatch between certificate and handshake",
  176. "from", via,
  177. "handshake", m{"stage": 1, "style": "ix_psk0"},
  178. "cert", remoteCert,
  179. )
  180. return
  181. }
  182. if remoteCert.Certificate.Version() != ci.myCert.Version() {
  183. // We started off using the wrong certificate version, lets see if we can match the version that was sent to us
  184. myCertOtherVersion := cs.getCertificate(remoteCert.Certificate.Version())
  185. if myCertOtherVersion == nil {
  186. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  187. f.l.Debug("Might be unable to handshake with host due to missing certificate version",
  188. "error", err,
  189. "from", via,
  190. "handshake", m{"stage": 1, "style": "ix_psk0"},
  191. "cert", remoteCert,
  192. )
  193. }
  194. } else {
  195. // Record the certificate we are actually using
  196. ci.myCert = myCertOtherVersion
  197. }
  198. }
  199. if len(remoteCert.Certificate.Networks()) == 0 {
  200. f.l.Info("No networks in certificate",
  201. "error", err,
  202. "from", via,
  203. "cert", remoteCert,
  204. "handshake", m{"stage": 1, "style": "ix_psk0"},
  205. )
  206. return
  207. }
  208. certName := remoteCert.Certificate.Name()
  209. certVersion := remoteCert.Certificate.Version()
  210. fingerprint := remoteCert.Fingerprint
  211. issuer := remoteCert.Certificate.Issuer()
  212. vpnNetworks := remoteCert.Certificate.Networks()
  213. anyVpnAddrsInCommon := false
  214. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  215. for i, network := range vpnNetworks {
  216. if f.myVpnAddrsTable.Contains(network.Addr()) {
  217. f.l.Error("Refusing to handshake with myself",
  218. "vpnNetworks", vpnNetworks,
  219. "from", via,
  220. "certName", certName,
  221. "certVersion", certVersion,
  222. "fingerprint", fingerprint,
  223. "issuer", issuer,
  224. "handshake", m{"stage": 1, "style": "ix_psk0"},
  225. )
  226. return
  227. }
  228. vpnAddrs[i] = network.Addr()
  229. if f.myVpnNetworksTable.Contains(network.Addr()) {
  230. anyVpnAddrsInCommon = true
  231. }
  232. }
  233. if !via.IsRelayed {
  234. // We only want to apply the remote allow list for direct tunnels here
  235. if !f.lightHouse.GetRemoteAllowList().AllowAll(vpnAddrs, via.UdpAddr.Addr()) {
  236. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  237. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  238. "vpnAddrs", vpnAddrs,
  239. "from", via,
  240. )
  241. }
  242. return
  243. }
  244. }
  245. myIndex, err := generateIndex(f.l)
  246. if err != nil {
  247. f.l.Error("Failed to generate index",
  248. "error", err,
  249. "vpnAddrs", vpnAddrs,
  250. "from", via,
  251. "certName", certName,
  252. "certVersion", certVersion,
  253. "fingerprint", fingerprint,
  254. "issuer", issuer,
  255. "handshake", m{"stage": 1, "style": "ix_psk0"},
  256. )
  257. return
  258. }
  259. hostinfo := &HostInfo{
  260. ConnectionState: ci,
  261. localIndexId: myIndex,
  262. remoteIndexId: hs.Details.InitiatorIndex,
  263. vpnAddrs: vpnAddrs,
  264. HandshakePacket: make(map[uint8][]byte, 0),
  265. lastHandshakeTime: hs.Details.Time,
  266. relayState: RelayState{
  267. relays: nil,
  268. relayForByAddr: map[netip.Addr]*Relay{},
  269. relayForByIdx: map[uint32]*Relay{},
  270. },
  271. }
  272. msgRxL := f.l.With(
  273. "vpnAddrs", vpnAddrs,
  274. "from", via,
  275. "certName", certName,
  276. "certVersion", certVersion,
  277. "fingerprint", fingerprint,
  278. "issuer", issuer,
  279. "initiatorIndex", hs.Details.InitiatorIndex,
  280. "responderIndex", hs.Details.ResponderIndex,
  281. "remoteIndex", h.RemoteIndex,
  282. "handshake", m{"stage": 1, "style": "ix_psk0"},
  283. )
  284. if anyVpnAddrsInCommon {
  285. msgRxL.Info("Handshake message received")
  286. } else {
  287. //todo warn if not lighthouse or relay?
  288. msgRxL.Info("Handshake message received, but no vpnNetworks in common.")
  289. }
  290. hs.Details.ResponderIndex = myIndex
  291. hs.Details.Cert = cs.getHandshakeBytes(ci.myCert.Version())
  292. if hs.Details.Cert == nil {
  293. msgRxL.Error("Unable to handshake with host because no certificate handshake bytes is available",
  294. "myCertVersion", ci.myCert.Version(),
  295. )
  296. return
  297. }
  298. hs.Details.CertVersion = uint32(ci.myCert.Version())
  299. // Update the time in case their clock is way off from ours
  300. hs.Details.Time = uint64(time.Now().UnixNano())
  301. hsBytes, err := hs.Marshal()
  302. if err != nil {
  303. f.l.Error("Failed to marshal handshake message",
  304. "error", err,
  305. "vpnAddrs", hostinfo.vpnAddrs,
  306. "from", via,
  307. "certName", certName,
  308. "certVersion", certVersion,
  309. "fingerprint", fingerprint,
  310. "issuer", issuer,
  311. "handshake", m{"stage": 1, "style": "ix_psk0"},
  312. )
  313. return
  314. }
  315. nh := header.Encode(make([]byte, header.Len), header.Version, header.Handshake, header.HandshakeIXPSK0, hs.Details.InitiatorIndex, 2)
  316. msg, dKey, eKey, err := ci.H.WriteMessage(nh, hsBytes)
  317. if err != nil {
  318. f.l.Error("Failed to call noise.WriteMessage",
  319. "error", err,
  320. "vpnAddrs", hostinfo.vpnAddrs,
  321. "from", via,
  322. "certName", certName,
  323. "certVersion", certVersion,
  324. "fingerprint", fingerprint,
  325. "issuer", issuer,
  326. "handshake", m{"stage": 1, "style": "ix_psk0"},
  327. )
  328. return
  329. } else if dKey == nil || eKey == nil {
  330. f.l.Error("Noise did not arrive at a key",
  331. "vpnAddrs", hostinfo.vpnAddrs,
  332. "from", via,
  333. "certName", certName,
  334. "certVersion", certVersion,
  335. "fingerprint", fingerprint,
  336. "issuer", issuer,
  337. "handshake", m{"stage": 1, "style": "ix_psk0"},
  338. )
  339. return
  340. }
  341. hostinfo.HandshakePacket[0] = make([]byte, len(packet[header.Len:]))
  342. copy(hostinfo.HandshakePacket[0], packet[header.Len:])
  343. // Regardless of whether you are the sender or receiver, you should arrive here
  344. // and complete standing up the connection.
  345. hostinfo.HandshakePacket[2] = make([]byte, len(msg))
  346. copy(hostinfo.HandshakePacket[2], msg)
  347. // We are sending handshake packet 2, so we don't expect to receive
  348. // handshake packet 2 from the initiator.
  349. ci.window.Update(f.l, 2)
  350. ci.peerCert = remoteCert
  351. ci.dKey = NewNebulaCipherState(dKey)
  352. ci.eKey = NewNebulaCipherState(eKey)
  353. hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs)
  354. if !via.IsRelayed {
  355. hostinfo.SetRemote(via.UdpAddr)
  356. }
  357. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  358. existing, err := f.handshakeManager.CheckAndComplete(hostinfo, 0, f)
  359. if err != nil {
  360. switch err {
  361. case ErrAlreadySeen:
  362. // Update remote if preferred
  363. if existing.SetRemoteIfPreferred(f.hostMap, via) {
  364. // Send a test packet to ensure the other side has also switched to
  365. // the preferred remote
  366. f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  367. }
  368. msg = existing.HandshakePacket[2]
  369. f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
  370. if !via.IsRelayed {
  371. err := f.outside.WriteTo(msg, via.UdpAddr)
  372. if err != nil {
  373. f.l.Error("Failed to send handshake message",
  374. "vpnAddrs", existing.vpnAddrs,
  375. "from", via,
  376. "handshake", m{"stage": 2, "style": "ix_psk0"},
  377. "cached", true,
  378. "error", err,
  379. )
  380. } else {
  381. f.l.Info("Handshake message sent",
  382. "vpnAddrs", existing.vpnAddrs,
  383. "from", via,
  384. "handshake", m{"stage": 2, "style": "ix_psk0"},
  385. "cached", true,
  386. )
  387. }
  388. return
  389. } else {
  390. if via.relay == nil {
  391. f.l.Error("Handshake send failed: both addr and via.relay are nil.")
  392. return
  393. }
  394. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  395. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
  396. f.l.Info("Handshake message sent",
  397. "vpnAddrs", existing.vpnAddrs,
  398. "relay", via.relayHI.vpnAddrs[0],
  399. "handshake", m{"stage": 2, "style": "ix_psk0"},
  400. "cached", true,
  401. )
  402. return
  403. }
  404. case ErrExistingHostInfo:
  405. // This means there was an existing tunnel and this handshake was older than the one we are currently based on
  406. f.l.Info("Handshake too old",
  407. "vpnAddrs", vpnAddrs,
  408. "from", via,
  409. "certName", certName,
  410. "certVersion", certVersion,
  411. "oldHandshakeTime", existing.lastHandshakeTime,
  412. "newHandshakeTime", hostinfo.lastHandshakeTime,
  413. "fingerprint", fingerprint,
  414. "issuer", issuer,
  415. "initiatorIndex", hs.Details.InitiatorIndex,
  416. "responderIndex", hs.Details.ResponderIndex,
  417. "remoteIndex", h.RemoteIndex,
  418. "handshake", m{"stage": 1, "style": "ix_psk0"},
  419. )
  420. // Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
  421. f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  422. return
  423. case ErrLocalIndexCollision:
  424. // This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
  425. f.l.Error("Failed to add HostInfo due to localIndex collision",
  426. "vpnAddrs", vpnAddrs,
  427. "from", via,
  428. "certName", certName,
  429. "certVersion", certVersion,
  430. "fingerprint", fingerprint,
  431. "issuer", issuer,
  432. "initiatorIndex", hs.Details.InitiatorIndex,
  433. "responderIndex", hs.Details.ResponderIndex,
  434. "remoteIndex", h.RemoteIndex,
  435. "handshake", m{"stage": 1, "style": "ix_psk0"},
  436. "localIndex", hostinfo.localIndexId,
  437. "collision", existing.vpnAddrs,
  438. )
  439. return
  440. default:
  441. // Shouldn't happen, but just in case someone adds a new error type to CheckAndComplete
  442. // And we forget to update it here
  443. f.l.Error("Failed to add HostInfo to HostMap",
  444. "error", err,
  445. "vpnAddrs", vpnAddrs,
  446. "from", via,
  447. "certName", certName,
  448. "certVersion", certVersion,
  449. "fingerprint", fingerprint,
  450. "issuer", issuer,
  451. "initiatorIndex", hs.Details.InitiatorIndex,
  452. "responderIndex", hs.Details.ResponderIndex,
  453. "remoteIndex", h.RemoteIndex,
  454. "handshake", m{"stage": 1, "style": "ix_psk0"},
  455. )
  456. return
  457. }
  458. }
  459. // Do the send
  460. f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
  461. if !via.IsRelayed {
  462. err = f.outside.WriteTo(msg, via.UdpAddr)
  463. log := f.l.With(
  464. "vpnAddrs", vpnAddrs,
  465. "from", via,
  466. "certName", certName,
  467. "certVersion", certVersion,
  468. "fingerprint", fingerprint,
  469. "issuer", issuer,
  470. "initiatorIndex", hs.Details.InitiatorIndex,
  471. "responderIndex", hs.Details.ResponderIndex,
  472. "remoteIndex", h.RemoteIndex,
  473. "handshake", m{"stage": 2, "style": "ix_psk0"},
  474. )
  475. if err != nil {
  476. log.Error("Failed to send handshake", "error", err)
  477. } else {
  478. log.Info("Handshake message sent")
  479. }
  480. } else {
  481. if via.relay == nil {
  482. f.l.Error("Handshake send failed: both addr and via.relay are nil.")
  483. return
  484. }
  485. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  486. // I successfully received a handshake. Just in case I marked this tunnel as 'Disestablished', ensure
  487. // it's correctly marked as working.
  488. via.relayHI.relayState.UpdateRelayForByIdxState(via.remoteIdx, Established)
  489. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
  490. f.l.Info("Handshake message sent",
  491. "vpnAddrs", vpnAddrs,
  492. "relay", via.relayHI.vpnAddrs[0],
  493. "certName", certName,
  494. "certVersion", certVersion,
  495. "fingerprint", fingerprint,
  496. "issuer", issuer,
  497. "initiatorIndex", hs.Details.InitiatorIndex,
  498. "responderIndex", hs.Details.ResponderIndex,
  499. "remoteIndex", h.RemoteIndex,
  500. "handshake", m{"stage": 2, "style": "ix_psk0"},
  501. )
  502. }
  503. f.connectionManager.AddTrafficWatch(hostinfo)
  504. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  505. // Don't wait for UpdateWorker
  506. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  507. f.lightHouse.TriggerUpdate()
  508. }
  509. return
  510. }
  511. func ixHandshakeStage2(f *Interface, via ViaSender, hh *HandshakeHostInfo, packet []byte, h *header.H) bool {
  512. if hh == nil {
  513. // Nothing here to tear down, got a bogus stage 2 packet
  514. return true
  515. }
  516. hh.Lock()
  517. defer hh.Unlock()
  518. hostinfo := hh.hostinfo
  519. if !via.IsRelayed {
  520. // The vpnAddr we know about is the one we tried to handshake with, use it to apply the remote allow list.
  521. if !f.lightHouse.GetRemoteAllowList().AllowAll(hostinfo.vpnAddrs, via.UdpAddr.Addr()) {
  522. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  523. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  524. "vpnAddrs", hostinfo.vpnAddrs,
  525. "from", via,
  526. )
  527. }
  528. return false
  529. }
  530. }
  531. ci := hostinfo.ConnectionState
  532. msg, eKey, dKey, err := ci.H.ReadMessage(nil, packet[header.Len:])
  533. if err != nil {
  534. f.l.Error("Failed to call noise.ReadMessage",
  535. "error", err,
  536. "vpnAddrs", hostinfo.vpnAddrs,
  537. "from", via,
  538. "handshake", m{"stage": 2, "style": "ix_psk0"},
  539. "header", h,
  540. )
  541. // We don't want to tear down the connection on a bad ReadMessage because it could be an attacker trying
  542. // to DOS us. Every other error condition after should to allow a possible good handshake to complete in the
  543. // near future
  544. return false
  545. } else if dKey == nil || eKey == nil {
  546. f.l.Error("Noise did not arrive at a key",
  547. "vpnAddrs", hostinfo.vpnAddrs,
  548. "from", via,
  549. "handshake", m{"stage": 2, "style": "ix_psk0"},
  550. )
  551. // This should be impossible in IX but just in case, if we get here then there is no chance to recover
  552. // the handshake state machine. Tear it down
  553. return true
  554. }
  555. hs := &NebulaHandshake{}
  556. err = hs.Unmarshal(msg)
  557. if err != nil || hs.Details == nil {
  558. f.l.Error("Failed unmarshal handshake message",
  559. "error", err,
  560. "vpnAddrs", hostinfo.vpnAddrs,
  561. "from", via,
  562. "handshake", m{"stage": 2, "style": "ix_psk0"},
  563. )
  564. // The handshake state machine is complete, if things break now there is no chance to recover. Tear down and start again
  565. return true
  566. }
  567. rc, err := cert.Recombine(cert.Version(hs.Details.CertVersion), hs.Details.Cert, ci.H.PeerStatic(), ci.Curve())
  568. if err != nil {
  569. f.l.Info("Handshake did not contain a certificate",
  570. "error", err,
  571. "from", via,
  572. "vpnAddrs", hostinfo.vpnAddrs,
  573. "handshake", m{"stage": 2, "style": "ix_psk0"},
  574. )
  575. return true
  576. }
  577. remoteCert, err := f.pki.GetCAPool().VerifyCertificate(time.Now(), rc)
  578. if err != nil {
  579. fp, err := rc.Fingerprint()
  580. if err != nil {
  581. fp = "<error generating certificate fingerprint>"
  582. }
  583. attrs := []slog.Attr{
  584. slog.Any("error", err),
  585. slog.Any("from", via),
  586. slog.Any("vpnAddrs", hostinfo.vpnAddrs),
  587. slog.Any("handshake", m{"stage": 2, "style": "ix_psk0"}),
  588. slog.String("certFingerprint", fp),
  589. slog.Any("certVpnNetworks", rc.Networks()),
  590. }
  591. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  592. attrs = append(attrs, slog.Any("cert", rc))
  593. }
  594. // LogAttrs is intentional: attrs is a pre-built []slog.Attr slice that
  595. // callers grow conditionally, which has no pair-form equivalent.
  596. //nolint:sloglint
  597. f.l.LogAttrs(context.Background(), slog.LevelInfo, "Invalid certificate from host", attrs...)
  598. return true
  599. }
  600. if !bytes.Equal(remoteCert.Certificate.PublicKey(), ci.H.PeerStatic()) {
  601. f.l.Info("public key mismatch between certificate and handshake",
  602. "from", via,
  603. "handshake", m{"stage": 2, "style": "ix_psk0"},
  604. "cert", remoteCert,
  605. )
  606. return true
  607. }
  608. if len(remoteCert.Certificate.Networks()) == 0 {
  609. f.l.Info("No networks in certificate",
  610. "error", err,
  611. "from", via,
  612. "vpnAddrs", hostinfo.vpnAddrs,
  613. "cert", remoteCert,
  614. "handshake", m{"stage": 2, "style": "ix_psk0"},
  615. )
  616. return true
  617. }
  618. vpnNetworks := remoteCert.Certificate.Networks()
  619. certName := remoteCert.Certificate.Name()
  620. certVersion := remoteCert.Certificate.Version()
  621. fingerprint := remoteCert.Fingerprint
  622. issuer := remoteCert.Certificate.Issuer()
  623. hostinfo.remoteIndexId = hs.Details.ResponderIndex
  624. hostinfo.lastHandshakeTime = hs.Details.Time
  625. // Store their cert and our symmetric keys
  626. ci.peerCert = remoteCert
  627. ci.dKey = NewNebulaCipherState(dKey)
  628. ci.eKey = NewNebulaCipherState(eKey)
  629. // Make sure the current udpAddr being used is set for responding
  630. if !via.IsRelayed {
  631. hostinfo.SetRemote(via.UdpAddr)
  632. } else {
  633. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  634. }
  635. correctHostResponded := false
  636. anyVpnAddrsInCommon := false
  637. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  638. for i, network := range vpnNetworks {
  639. vpnAddrs[i] = network.Addr()
  640. if f.myVpnNetworksTable.Contains(network.Addr()) {
  641. anyVpnAddrsInCommon = true
  642. }
  643. if hostinfo.vpnAddrs[0] == network.Addr() {
  644. // todo is it more correct to see if any of hostinfo.vpnAddrs are in the cert? it should have len==1, but one day it might not?
  645. correctHostResponded = true
  646. }
  647. }
  648. // Ensure the right host responded
  649. if !correctHostResponded {
  650. f.l.Info("Incorrect host responded to handshake",
  651. "intendedVpnAddrs", hostinfo.vpnAddrs,
  652. "haveVpnNetworks", vpnNetworks,
  653. "from", via,
  654. "certName", certName,
  655. "certVersion", certVersion,
  656. "handshake", m{"stage": 2, "style": "ix_psk0"},
  657. )
  658. // Release our old handshake from pending, it should not continue
  659. f.handshakeManager.DeleteHostInfo(hostinfo)
  660. // Create a new hostinfo/handshake for the intended vpn ip
  661. //TODO is hostinfo.vpnAddrs[0] always the address to use?
  662. f.handshakeManager.StartHandshake(hostinfo.vpnAddrs[0], func(newHH *HandshakeHostInfo) {
  663. // Block the current used address
  664. newHH.hostinfo.remotes = hostinfo.remotes
  665. newHH.hostinfo.remotes.BlockRemote(via)
  666. f.l.Info("Blocked addresses for handshakes",
  667. "blockedUdpAddrs", newHH.hostinfo.remotes.CopyBlockedRemotes(),
  668. "vpnNetworks", vpnNetworks,
  669. "remotes", newHH.hostinfo.remotes.CopyAddrs(f.hostMap.GetPreferredRanges()),
  670. )
  671. // Swap the packet store to benefit the original intended recipient
  672. newHH.packetStore = hh.packetStore
  673. hh.packetStore = []*cachedPacket{}
  674. // Finally, put the correct vpn addrs in the host info, tell them to close the tunnel, and return true to tear down
  675. hostinfo.vpnAddrs = vpnAddrs
  676. f.sendCloseTunnel(hostinfo)
  677. })
  678. return true
  679. }
  680. // Mark packet 2 as seen so it doesn't show up as missed
  681. ci.window.Update(f.l, 2)
  682. duration := time.Since(hh.startTime).Nanoseconds()
  683. msgRxL := f.l.With(
  684. "vpnAddrs", vpnAddrs,
  685. "from", via,
  686. "certName", certName,
  687. "certVersion", certVersion,
  688. "fingerprint", fingerprint,
  689. "issuer", issuer,
  690. "initiatorIndex", hs.Details.InitiatorIndex,
  691. "responderIndex", hs.Details.ResponderIndex,
  692. "remoteIndex", h.RemoteIndex,
  693. "handshake", m{"stage": 2, "style": "ix_psk0"},
  694. "durationNs", duration,
  695. "sentCachedPackets", len(hh.packetStore),
  696. )
  697. if anyVpnAddrsInCommon {
  698. msgRxL.Info("Handshake message received")
  699. } else {
  700. //todo warn if not lighthouse or relay?
  701. msgRxL.Info("Handshake message received, but no vpnNetworks in common.")
  702. }
  703. // Build up the radix for the firewall if we have subnets in the cert
  704. hostinfo.vpnAddrs = vpnAddrs
  705. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  706. // Complete our handshake and update metrics, this will replace any existing tunnels for the vpnAddrs here
  707. f.handshakeManager.Complete(hostinfo, f)
  708. f.connectionManager.AddTrafficWatch(hostinfo)
  709. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  710. hostinfo.logger(f.l).Debug("Sending stored packets",
  711. "count", len(hh.packetStore),
  712. )
  713. }
  714. if len(hh.packetStore) > 0 {
  715. nb := make([]byte, 12, 12)
  716. out := make([]byte, mtu)
  717. for _, cp := range hh.packetStore {
  718. cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
  719. }
  720. f.cachedPacketMetrics.sent.Inc(int64(len(hh.packetStore)))
  721. }
  722. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  723. f.metricHandshakes.Update(duration)
  724. // Don't wait for UpdateWorker
  725. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  726. f.lightHouse.TriggerUpdate()
  727. }
  728. return false
  729. }