handshake_manager.go 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. package nebula
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/rand"
  6. "encoding/binary"
  7. "errors"
  8. "log/slog"
  9. "net/netip"
  10. "slices"
  11. "sync"
  12. "sync/atomic"
  13. "time"
  14. "github.com/rcrowley/go-metrics"
  15. "github.com/slackhq/nebula/cert"
  16. "github.com/slackhq/nebula/handshake"
  17. "github.com/slackhq/nebula/handshake/fragment"
  18. "github.com/slackhq/nebula/header"
  19. "github.com/slackhq/nebula/ratelimit"
  20. "github.com/slackhq/nebula/udp"
  21. )
  22. const (
  23. DefaultHandshakeTryInterval = time.Millisecond * 100
  24. DefaultHandshakeRetries = 10
  25. DefaultHandshakeTriggerBuffer = 64
  26. // maxCachedPackets is how many unsent packets we'll buffer per pending
  27. // handshake before dropping further ones.
  28. maxCachedPackets = 100
  29. // HandshakePacket map keys mirror the IX protocol stage convention:
  30. // stage 0 = the initiator's first message (and what the responder
  31. // receives, stripped of header)
  32. // stage 2 = the responder's reply
  33. // Other handshake patterns will need new keys when added.
  34. handshakePacketStage0 uint8 = 0
  35. handshakePacketStage2 uint8 = 2
  36. )
  37. var (
  38. defaultHandshakeConfig = HandshakeConfig{
  39. tryInterval: DefaultHandshakeTryInterval,
  40. retries: DefaultHandshakeRetries,
  41. triggerBuffer: DefaultHandshakeTriggerBuffer,
  42. }
  43. )
  44. type HandshakeConfig struct {
  45. tryInterval time.Duration
  46. retries int64
  47. triggerBuffer int
  48. pq pqHandshakeConfig
  49. messageMetrics *MessageMetrics
  50. }
  51. type HandshakeManager struct {
  52. // Mutex for interacting with the vpnIps and indexes maps.
  53. // Lock order is hostmap, then this lock, then the lighthouse, then a RemoteList.
  54. sync.RWMutex
  55. vpnIps map[netip.Addr]*HandshakeHostInfo
  56. indexes map[uint32]*HandshakeHostInfo
  57. mainHostMap *HostMap
  58. lightHouse *LightHouse
  59. outside udp.Conn
  60. config HandshakeConfig
  61. OutboundHandshakeTimer *LockingTimerWheel[netip.Addr]
  62. messageMetrics *MessageMetrics
  63. metricInitiated metrics.Counter
  64. metricTimedOut metrics.Counter
  65. f *Interface
  66. l *slog.Logger
  67. // can be used to trigger outbound handshake for the given vpnIp
  68. trigger chan netip.Addr
  69. // pq holds the post-quantum settings, which change on reload.
  70. pq atomic.Pointer[pqHandshakeConfig]
  71. // pqTable reassembles post-quantum msg1s from senders that have not authenticated yet.
  72. pqTable *fragment.Table[pqFragKey, pqFragSource]
  73. // pqPeers holds vpn addresses that completed a post-quantum handshake, for sticky mode.
  74. pqPeers sync.Map
  75. // pqAnswered recognises repeats of post-quantum msg1s already answered.
  76. pqAnswered *pqAnswered
  77. // pqCookies and pqCookieLimiter serve cookies while pqTable is under load.
  78. pqCookies *pqCookies
  79. pqCookieLimiter *ratelimit.Limiter
  80. // hybrid holds hybrid handshakes waiting on their third message.
  81. hybrid hybridState
  82. }
  83. type HandshakeHostInfo struct {
  84. sync.Mutex
  85. startTime time.Time // Time that we first started trying with this handshake
  86. ready bool // Is the handshake ready
  87. initiatingVersionOverride cert.Version // Should we use a non-default cert version for this handshake?
  88. counter int64 // How many attempts have we made so far
  89. lastRemotes []netip.AddrPort // Remotes that we sent to during the previous attempt
  90. lastRelays []netip.Addr // Relays we attempted to use during the previous attempt
  91. packetStore []*cachedPacket // A set of packets to be transmitted once the handshake completes
  92. hostinfo *HostInfo
  93. machine *handshake.Machine // The handshake state machine, set during stage 0 (initiator) or beginHandshake (responder multi-message)
  94. pq *pqAttempt // The initiator's post-quantum attempt, pending alongside the classical one
  95. lastPQ bool // Whether the latest attempt was post-quantum
  96. noPQ bool // The post-quantum attempt failed for good, only classical is left
  97. responder *hybridResponder // Set for a responder's hybrid handshake waiting for msg3
  98. }
  99. func (hh *HandshakeHostInfo) cachePacket(l *slog.Logger, t header.MessageType, st header.MessageSubType, packet []byte, f packetCallback, m *cachedPacketMetrics) {
  100. if len(hh.packetStore) < maxCachedPackets {
  101. tempPacket := make([]byte, len(packet))
  102. copy(tempPacket, packet)
  103. hh.packetStore = append(hh.packetStore, &cachedPacket{t, st, f, tempPacket})
  104. if l.Enabled(context.Background(), slog.LevelDebug) {
  105. hh.hostinfo.logger(l).Debug("Packet store",
  106. "length", len(hh.packetStore),
  107. "stored", true,
  108. )
  109. }
  110. } else {
  111. m.dropped.Inc(1)
  112. if l.Enabled(context.Background(), slog.LevelDebug) {
  113. hh.hostinfo.logger(l).Debug("Packet store",
  114. "length", len(hh.packetStore),
  115. "stored", false,
  116. )
  117. }
  118. }
  119. }
  120. func NewHandshakeManager(l *slog.Logger, mainHostMap *HostMap, lightHouse *LightHouse, outside udp.Conn, config HandshakeConfig) *HandshakeManager {
  121. // A retrying initiator is answered again at most once per retry interval on
  122. // each path its msg1 arrives by.
  123. tableCfg := pqTableConfig
  124. tableCfg.RepeatInterval = config.tryInterval
  125. hm := &HandshakeManager{
  126. vpnIps: map[netip.Addr]*HandshakeHostInfo{},
  127. indexes: map[uint32]*HandshakeHostInfo{},
  128. mainHostMap: mainHostMap,
  129. lightHouse: lightHouse,
  130. outside: outside,
  131. config: config,
  132. trigger: make(chan netip.Addr, config.triggerBuffer),
  133. OutboundHandshakeTimer: NewLockingTimerWheel[netip.Addr](config.tryInterval, hsTimeout(config.retries, config.tryInterval)),
  134. messageMetrics: config.messageMetrics,
  135. metricInitiated: metrics.GetOrRegisterCounter("handshake_manager.initiated", nil),
  136. metricTimedOut: metrics.GetOrRegisterCounter("handshake_manager.timed_out", nil),
  137. l: l,
  138. pqTable: fragment.NewTable[pqFragKey, pqFragSource](tableCfg),
  139. pqAnswered: newPQAnswered(hsTimeout(config.retries, config.tryInterval)),
  140. hybrid: newHybridState(),
  141. }
  142. pq := config.pq
  143. hm.pq.Store(&pq)
  144. hm.pqCookies = newPQCookies(time.Now())
  145. // Cookie replies are tiny, but a flood of spoofed fragments must not turn
  146. // into a flood of replies.
  147. hm.pqCookieLimiter, _ = ratelimit.New(256, time.Millisecond)
  148. return hm
  149. }
  150. func (hm *HandshakeManager) Run(ctx context.Context) {
  151. clockSource := time.NewTicker(hm.config.tryInterval)
  152. defer clockSource.Stop()
  153. for {
  154. select {
  155. case <-ctx.Done():
  156. return
  157. case vpnIP := <-hm.trigger:
  158. hm.handleOutbound(vpnIP, true)
  159. case now := <-clockSource.C:
  160. hm.NextOutboundHandshakeTimerTick(now)
  161. hm.pqTable.Expire(now)
  162. hm.pqAnswered.expire(now)
  163. hm.expireHybridResponders(now)
  164. hm.tickHybridConfirms(now)
  165. }
  166. }
  167. }
  168. func (hm *HandshakeManager) HandleIncoming(via ViaSender, packet []byte, h *header.H) {
  169. // Gate on known handshake subtypes. Unknown subtypes (or future ones we
  170. // don't yet support) are dropped here rather than silently routed through
  171. // the IX path. Add a case when introducing a new pattern.
  172. switch {
  173. case h.Subtype == header.HandshakeIXPSK0, handshake.IsHybrid(h.Subtype):
  174. // supported
  175. default:
  176. hm.l.Debug("dropping handshake with unsupported subtype",
  177. "from", via, "subtype", h.Subtype)
  178. return
  179. }
  180. // First remote allow list check before we know the vpnIp
  181. if !via.IsRelayed {
  182. if !hm.lightHouse.GetRemoteAllowList().AllowUnknownVpnAddr(via.UdpAddr.Addr()) {
  183. hm.l.Debug("lighthouse.remote_allow_list denied incoming handshake", "from", via)
  184. return
  185. }
  186. }
  187. if header.IsFragmented(h.Subtype) {
  188. hm.handleFragment(via, packet, h)
  189. return
  190. }
  191. // First message of a new handshake. The wire format requires RemoteIndex
  192. // to be zero here (the initiator has no responder index to fill in yet),
  193. // and generateIndex never allocates 0, so any non-zero RemoteIndex on a
  194. // stage-1 packet is malformed or someone probing for an index collision.
  195. // Drop without paying the cost of running noise on a pending Machine.
  196. if h.MessageCounter == 1 {
  197. if h.RemoteIndex != 0 {
  198. hm.l.Debug("dropping stage-1 handshake with non-zero RemoteIndex",
  199. "from", via, "remoteIndex", h.RemoteIndex)
  200. return
  201. }
  202. if hm.pqConfig().require {
  203. hm.l.Debug("dropping classical handshake, post-quantum handshakes are required", "from", via)
  204. return
  205. }
  206. hm.beginHandshake(via, packet, h, 0)
  207. return
  208. }
  209. // Continuation message must match a pending handshake by index.
  210. // Anything else is an orphaned packet (e.g., late retransmit after
  211. // timeout) and is dropped.
  212. if hh := hm.queryIndex(h.RemoteIndex); hh != nil {
  213. hm.continueHandshake(via, hh, packet)
  214. return
  215. }
  216. }
  217. func (hm *HandshakeManager) NextOutboundHandshakeTimerTick(now time.Time) {
  218. hm.OutboundHandshakeTimer.Advance(now)
  219. for {
  220. vpnIp, has := hm.OutboundHandshakeTimer.Purge()
  221. if !has {
  222. break
  223. }
  224. hm.handleOutbound(vpnIp, false)
  225. }
  226. }
  227. func (hm *HandshakeManager) handleOutbound(vpnIp netip.Addr, lighthouseTriggered bool) {
  228. hh := hm.queryVpnIp(vpnIp)
  229. if hh == nil {
  230. return
  231. }
  232. hh.Lock()
  233. defer hh.Unlock()
  234. hostinfo := hh.hostinfo
  235. // If we are out of time, clean up
  236. if hh.counter >= hm.config.retries {
  237. fields := []any{
  238. "udpAddrs", hh.hostinfo.remotes.CopyAddrs(hm.mainHostMap.GetPreferredRanges()),
  239. "initiatorIndex", hh.hostinfo.localIndexId,
  240. "durationNs", time.Since(hh.startTime).Nanoseconds(),
  241. }
  242. // hh.machine can be nil here if buildStage0Packet never succeeded
  243. // (e.g., no certificate available). In that case there's no useful
  244. // handshake metadata to log.
  245. if hh.machine != nil {
  246. fields = append(fields, "handshake", m{
  247. "stage": uint64(hh.machine.MessageIndex()),
  248. "style": header.SubTypeName(header.Handshake, hh.machine.Subtype()),
  249. })
  250. }
  251. if hh.pq != nil {
  252. fields = append(fields, "pqInitiatorIndex", hh.pq.index)
  253. }
  254. hh.hostinfo.logger(hm.l).Info("Handshake timed out", fields...)
  255. hm.metricTimedOut.Inc(1)
  256. hm.DeleteHostInfo(hostinfo)
  257. return
  258. }
  259. // Increment the counter to increase our delay, linear backoff
  260. hh.counter++
  261. // Pick this attempt's style and make sure its first message exists. A PQ
  262. // attempt sends msg1 as fragments: now goes out immediately, later after the
  263. // repair delay, and every attempt offers fresh repair symbols.
  264. var now, later [][]byte
  265. var machine *handshake.Machine
  266. hh.lastPQ = hm.usePQ(hh, vpnIp, lighthouseTriggered)
  267. if hh.lastPQ {
  268. if hh.pq == nil && !hm.buildPQAttempt(hh) {
  269. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  270. return
  271. }
  272. var err error
  273. now, later, err = hh.pq.sender.Attempt(fragment.DefaultRepair(hh.pq.sender.Layout().K))
  274. if err != nil {
  275. hostinfo.logger(hm.l).Error("Failed to fragment handshake", "error", err)
  276. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  277. return
  278. }
  279. machine = hh.pq.machine
  280. } else {
  281. if !hh.ready {
  282. if !hm.buildStage0Packet(hh) {
  283. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  284. return
  285. }
  286. }
  287. // TODO: this hardcodes "always retransmit stage 0", which is correct for
  288. // IX (the initiator only ever sends one packet, msg1) but wrong the
  289. // moment a 3+ message pattern lands. The retry loop should resend the
  290. // most recent outgoing message, not always stage 0. That implies
  291. // HandshakeHostInfo tracking a single "currentOutbound" packet (bytes +
  292. // header metadata) that gets replaced as the handshake progresses,
  293. // instead of indexing into HandshakePacket.
  294. now = [][]byte{hostinfo.HandshakePacket[handshakePacketStage0]}
  295. machine = hh.machine
  296. }
  297. hsFields := m{
  298. "stage": uint64(machine.MessageIndex()),
  299. "style": header.SubTypeName(header.Handshake, machine.Subtype()),
  300. }
  301. remotes := hostinfo.remotes.CopyAddrs(hm.mainHostMap.GetPreferredRanges())
  302. remotesHaveChanged := !slices.Equal(remotes, hh.lastRemotes)
  303. // We only care about a lighthouse trigger if we have new remotes to send to.
  304. // This is a very specific optimization for a fast lighthouse reply.
  305. if lighthouseTriggered && !remotesHaveChanged {
  306. // If we didn't return here a lighthouse could cause us to aggressively send handshakes
  307. return
  308. }
  309. hh.lastRemotes = remotes
  310. // This will generate a load of queries for hosts with only 1 ip
  311. // (such as ones registered to the lighthouse with only a private IP)
  312. // So we only do it one time after attempting 5 handshakes already.
  313. if len(remotes) <= 1 && hh.counter == 5 {
  314. // If we only have 1 remote it is highly likely our query raced with the other host registered within the lighthouse
  315. // Our vpnIp here has a tunnel with a lighthouse but has yet to send a host update packet there so we only know about
  316. // the learned public ip for them. Query again to short circuit the promotion counter
  317. hm.lightHouse.QueryServer(vpnIp)
  318. }
  319. // Send the handshake to all known ips, stage 2 takes care of assigning the hostinfo.remote based on the first to reply
  320. var sentTo []netip.AddrPort
  321. hostinfo.remotes.ForEach(hm.mainHostMap.GetPreferredRanges(), func(addr netip.AddrPort, _ bool) {
  322. hm.messageMetrics.Tx(header.Handshake, machine.Subtype(), int64(len(now)+len(later)))
  323. err := hm.sendFragmented(now, later, func(p []byte) error {
  324. return hm.outside.WriteTo(p, addr)
  325. })
  326. if err != nil {
  327. // These repeat every attempt, so match the success log below and only shout when the remotes changed
  328. level := slog.LevelDebug
  329. if remotesHaveChanged {
  330. level = slog.LevelError
  331. }
  332. hostinfo.logger(hm.l).Log(context.Background(), level, "Failed to send handshake message",
  333. "udpAddr", addr,
  334. "initiatorIndex", hostinfo.localIndexId,
  335. "handshake", hsFields,
  336. "error", err,
  337. )
  338. } else {
  339. sentTo = append(sentTo, addr)
  340. }
  341. })
  342. // Don't be too noisy or confusing if we fail to send a handshake - if we don't get through we'll eventually log a timeout,
  343. // so only log when the list of remotes has changed
  344. if remotesHaveChanged {
  345. hostinfo.logger(hm.l).Info("Handshake message sent",
  346. "udpAddrs", sentTo,
  347. "initiatorIndex", hostinfo.localIndexId,
  348. "handshake", hsFields,
  349. )
  350. } else if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  351. hostinfo.logger(hm.l).Debug("Handshake message sent",
  352. "udpAddrs", sentTo,
  353. "initiatorIndex", hostinfo.localIndexId,
  354. "handshake", hsFields,
  355. )
  356. }
  357. hm.f.relayManager.StartRelays(hm.f, vpnIp, hh, now, later)
  358. // If a lighthouse triggered this attempt then we are still in the timer wheel and do not need to re-add
  359. if !lighthouseTriggered {
  360. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  361. }
  362. }
  363. // GetOrHandshake will try to find a hostinfo with a fully formed tunnel or start a new handshake if one is not present
  364. // The 2nd argument will be true if the hostinfo is ready to transmit traffic
  365. func (hm *HandshakeManager) GetOrHandshake(vpnIp netip.Addr, cacheCb func(*HandshakeHostInfo)) (*HostInfo, bool) {
  366. hm.mainHostMap.RLock()
  367. h, ok := hm.mainHostMap.Hosts[vpnIp]
  368. hm.mainHostMap.RUnlock()
  369. if ok {
  370. // Do not attempt promotion if you are a lighthouse
  371. if !hm.lightHouse.amLighthouse {
  372. h.TryPromoteBest(hm.mainHostMap.GetPreferredRanges(), hm.f)
  373. }
  374. return h, true
  375. }
  376. return hm.StartHandshake(vpnIp, cacheCb), false
  377. }
  378. // StartHandshake will ensure a handshake is currently being attempted for the provided vpn ip
  379. func (hm *HandshakeManager) StartHandshake(vpnAddr netip.Addr, cacheCb func(*HandshakeHostInfo)) *HostInfo {
  380. hm.Lock()
  381. if hh, ok := hm.vpnIps[vpnAddr]; ok {
  382. // We are already trying to handshake with this vpn ip
  383. if cacheCb != nil {
  384. cacheCb(hh)
  385. }
  386. hm.Unlock()
  387. return hh.hostinfo
  388. }
  389. hostinfo := &HostInfo{
  390. vpnAddrs: []netip.Addr{vpnAddr},
  391. HandshakePacket: make(map[uint8][]byte, 0),
  392. // Attached here so a pending hostinfo never exists without one: SetRemote dereferences
  393. // it, and create-tunnel -address can reach SetRemote before the handshake loop runs.
  394. remotes: hm.lightHouse.QueryCache([]netip.Addr{vpnAddr}),
  395. relayState: RelayState{
  396. relays: nil,
  397. relayForByAddr: map[netip.Addr]*Relay{},
  398. relayForByIdx: map[uint32]*Relay{},
  399. },
  400. }
  401. hh := &HandshakeHostInfo{
  402. hostinfo: hostinfo,
  403. startTime: time.Now(),
  404. }
  405. hm.vpnIps[vpnAddr] = hh
  406. hm.metricInitiated.Inc(1)
  407. hm.OutboundHandshakeTimer.Add(vpnAddr, hm.config.tryInterval)
  408. if cacheCb != nil {
  409. cacheCb(hh)
  410. }
  411. // If this is a static host, we don't need to wait for the HostQueryReply
  412. // We can trigger the handshake right now
  413. _, doTrigger := hm.lightHouse.GetStaticHostList()[vpnAddr]
  414. if !doTrigger {
  415. // Add any calculated remotes, and trigger early handshake if one found
  416. doTrigger = hm.lightHouse.addCalculatedRemotes(vpnAddr)
  417. }
  418. if doTrigger {
  419. select {
  420. case hm.trigger <- vpnAddr:
  421. default:
  422. }
  423. }
  424. hm.Unlock()
  425. hm.lightHouse.QueryServer(vpnAddr)
  426. return hostinfo
  427. }
  428. var (
  429. ErrExistingHostInfo = errors.New("existing hostinfo")
  430. ErrAlreadySeen = errors.New("already seen")
  431. ErrLocalIndexCollision = errors.New("local index collision")
  432. )
  433. // CheckAndComplete checks for any conflicts in the main and pending hostmap
  434. // before adding hostinfo to main. If err is nil, it was added. Otherwise err will be:
  435. //
  436. // ErrAlreadySeen if we already have an entry in the hostmap that has seen the
  437. // exact same handshake packet
  438. //
  439. // ErrExistingHostInfo if we already have an entry in the hostmap for this
  440. // VpnIp and the new handshake was older than the one we currently have
  441. //
  442. // ErrLocalIndexCollision if we already have an entry in the main or pending
  443. // hostmap for the hostinfo.localIndexId.
  444. func (hm *HandshakeManager) CheckAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface) (*HostInfo, error) {
  445. return hm.checkAndComplete(hostinfo, handshakePacket, f, false)
  446. }
  447. // checkAndComplete is CheckAndComplete. committed means the initiator has shown it
  448. // uses this tunnel, as a hybrid msg3 does, so an existing tunnel is replaced even
  449. // when its handshake is newer.
  450. func (hm *HandshakeManager) checkAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface, committed bool) (*HostInfo, error) {
  451. hm.mainHostMap.Lock()
  452. defer hm.mainHostMap.Unlock()
  453. hm.Lock()
  454. defer hm.Unlock()
  455. // Check if we already have a tunnel with this vpn ip
  456. existingHostInfo, found := hm.mainHostMap.Hosts[hostinfo.vpnAddrs[0]]
  457. if found && existingHostInfo != nil {
  458. // Is it just a delayed handshake packet? Check every hostinfo we hold for this address.
  459. for _, testHostInfo := range hm.mainHostMap.unlockedGetHostList(hostinfo.vpnAddrs[0]) {
  460. if bytes.Equal(hostinfo.HandshakePacket[handshakePacket], testHostInfo.HandshakePacket[handshakePacket]) {
  461. return testHostInfo, ErrAlreadySeen
  462. }
  463. }
  464. // Is this a newer handshake?
  465. if !committed && existingHostInfo.lastHandshakeTime >= hostinfo.lastHandshakeTime && !existingHostInfo.ConnectionState.initiator {
  466. return existingHostInfo, ErrExistingHostInfo
  467. }
  468. existingHostInfo.logger(hm.l).Info("Taking new handshake")
  469. }
  470. existingIndex, found := hm.mainHostMap.Indexes[hostinfo.localIndexId]
  471. if found {
  472. // We have a collision, but for a different hostinfo
  473. return existingIndex, ErrLocalIndexCollision
  474. }
  475. existingPendingIndex, found := hm.indexes[hostinfo.localIndexId]
  476. if found && existingPendingIndex.hostinfo != hostinfo {
  477. // We have a collision, but for a different hostinfo
  478. return existingPendingIndex.hostinfo, ErrLocalIndexCollision
  479. }
  480. existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]
  481. if found && existingRemoteIndex != nil && existingRemoteIndex.vpnAddrs[0] != hostinfo.vpnAddrs[0] {
  482. // We have a collision, but this can happen since we can't control
  483. // the remote ID. Just log about the situation as a note.
  484. hostinfo.logger(hm.l).Info("New host shadows existing host remoteIndex",
  485. "collision", existingRemoteIndex.vpnAddrs,
  486. )
  487. }
  488. hm.mainHostMap.unlockedAddHostInfo(hostinfo, f)
  489. return existingHostInfo, nil
  490. }
  491. // Complete is a simpler version of CheckAndComplete when we already know we
  492. // won't have a localIndexId collision because we already have an entry in the
  493. // pendingHostMap. An existing hostinfo is returned if there was one.
  494. func (hm *HandshakeManager) Complete(hostinfo *HostInfo, f *Interface) {
  495. hm.mainHostMap.Lock()
  496. defer hm.mainHostMap.Unlock()
  497. hm.Lock()
  498. defer hm.Unlock()
  499. existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]
  500. if found && existingRemoteIndex != nil {
  501. // We have a collision, but this can happen since we can't control
  502. // the remote ID. Just log about the situation as a note.
  503. hostinfo.logger(hm.l).Info("New host shadows existing host remoteIndex",
  504. "collision", existingRemoteIndex.vpnAddrs,
  505. )
  506. }
  507. // We need to remove from the pending hostmap first to avoid undoing work when after to the main hostmap.
  508. hm.unlockedDeleteHostInfo(hostinfo)
  509. hm.mainHostMap.unlockedAddHostInfo(hostinfo, f)
  510. }
  511. // allocateIndex generates a unique localIndexId for this HostInfo
  512. // and adds it to the pendingHostMap. Will error if we are unable to generate
  513. // a unique localIndexId
  514. func (hm *HandshakeManager) allocateIndex(hh *HandshakeHostInfo) (uint32, error) {
  515. hm.mainHostMap.RLock()
  516. defer hm.mainHostMap.RUnlock()
  517. hm.Lock()
  518. defer hm.Unlock()
  519. for range 32 {
  520. index, err := generateIndex(hm.l)
  521. if err != nil {
  522. return 0, err
  523. }
  524. _, inPending := hm.indexes[index]
  525. _, inMain := hm.mainHostMap.Indexes[index]
  526. if !inMain && !inPending {
  527. hh.hostinfo.localIndexId = index
  528. hm.indexes[index] = hh
  529. return index, nil
  530. }
  531. }
  532. return 0, errors.New("failed to generate unique localIndexId")
  533. }
  534. func (hm *HandshakeManager) DeleteHostInfo(hostinfo *HostInfo) {
  535. hm.Lock()
  536. defer hm.Unlock()
  537. hm.unlockedDeleteHostInfo(hostinfo)
  538. }
  539. func (hm *HandshakeManager) unlockedDeleteHostInfo(hostinfo *HostInfo) {
  540. for _, addr := range hostinfo.vpnAddrs {
  541. if cur, ok := hm.vpnIps[addr]; ok && cur.hostinfo == hostinfo {
  542. // A PQ attempt holds its own index alongside the hostinfo's.
  543. if idx := cur.pqIndex(); idx != 0 && hm.indexes[idx] == cur {
  544. delete(hm.indexes, idx)
  545. }
  546. delete(hm.vpnIps, addr)
  547. }
  548. }
  549. if len(hm.vpnIps) == 0 {
  550. hm.vpnIps = map[netip.Addr]*HandshakeHostInfo{}
  551. }
  552. delete(hm.indexes, hostinfo.localIndexId)
  553. if len(hm.indexes) == 0 {
  554. hm.indexes = map[uint32]*HandshakeHostInfo{}
  555. }
  556. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  557. hm.l.Debug("Pending hostmap hostInfo deleted",
  558. "hostMap", m{"mapTotalSize": len(hm.vpnIps),
  559. "vpnAddrs": hostinfo.vpnAddrs, "indexNumber": hostinfo.localIndexId, "remoteIndexNumber": hostinfo.remoteIndexId},
  560. )
  561. }
  562. }
  563. func (hm *HandshakeManager) QueryVpnAddr(vpnIp netip.Addr) *HostInfo {
  564. hh := hm.queryVpnIp(vpnIp)
  565. if hh != nil {
  566. return hh.hostinfo
  567. }
  568. return nil
  569. }
  570. func (hm *HandshakeManager) queryVpnIp(vpnIp netip.Addr) *HandshakeHostInfo {
  571. hm.RLock()
  572. defer hm.RUnlock()
  573. return hm.vpnIps[vpnIp]
  574. }
  575. func (hm *HandshakeManager) QueryIndex(index uint32) *HostInfo {
  576. hh := hm.queryIndex(index)
  577. if hh != nil {
  578. return hh.hostinfo
  579. }
  580. return nil
  581. }
  582. func (hm *HandshakeManager) queryIndex(index uint32) *HandshakeHostInfo {
  583. hm.RLock()
  584. defer hm.RUnlock()
  585. return hm.indexes[index]
  586. }
  587. func (hm *HandshakeManager) GetPreferredRanges() []netip.Prefix {
  588. return hm.mainHostMap.GetPreferredRanges()
  589. }
  590. func (hm *HandshakeManager) ForEachVpnAddr(f controlEach) {
  591. hm.RLock()
  592. defer hm.RUnlock()
  593. for _, v := range hm.vpnIps {
  594. f(v.hostinfo)
  595. }
  596. }
  597. func (hm *HandshakeManager) ForEachIndex(f controlEach) {
  598. hm.RLock()
  599. defer hm.RUnlock()
  600. for _, v := range hm.indexes {
  601. f(v.hostinfo)
  602. }
  603. }
  604. func (hm *HandshakeManager) EmitStats() {
  605. hm.RLock()
  606. hostLen := len(hm.vpnIps)
  607. indexLen := len(hm.indexes)
  608. hm.RUnlock()
  609. metrics.GetOrRegisterGauge("hostmap.pending.hosts", nil).Update(int64(hostLen))
  610. metrics.GetOrRegisterGauge("hostmap.pending.indexes", nil).Update(int64(indexLen))
  611. hm.mainHostMap.EmitStats()
  612. }
  613. // Utility functions below
  614. func generateIndex(l *slog.Logger) (uint32, error) {
  615. b := make([]byte, 4)
  616. // Let zero mean we don't know the ID, so don't generate zero
  617. var index uint32
  618. for index == 0 {
  619. _, err := rand.Read(b)
  620. if err != nil {
  621. l.Error("Failed to generate index", "error", err)
  622. return 0, err
  623. }
  624. index = binary.BigEndian.Uint32(b)
  625. }
  626. if l.Enabled(context.Background(), slog.LevelDebug) {
  627. l.Debug("Generated index", "index", index)
  628. }
  629. return index, nil
  630. }
  631. func hsTimeout(tries int64, interval time.Duration) time.Duration {
  632. return time.Duration(tries / 2 * ((2 * int64(interval)) + (tries-1)*int64(interval)))
  633. }
  634. // initiatingVersion picks the certificate version to initiate a handshake with.
  635. func (hm *HandshakeManager) initiatingVersion(hh *HandshakeHostInfo, cs *CertState) cert.Version {
  636. v := cs.DefaultVersion()
  637. if hh.initiatingVersionOverride != cert.VersionPre1 {
  638. v = hh.initiatingVersionOverride
  639. } else if v < cert.Version2 {
  640. for _, a := range hh.hostinfo.vpnAddrs {
  641. if a.Is6() {
  642. v = cert.Version2
  643. break
  644. }
  645. }
  646. }
  647. return v
  648. }
  649. // buildStage0Packet creates the initial handshake packet for the initiator.
  650. func (hm *HandshakeManager) buildStage0Packet(hh *HandshakeHostInfo) bool {
  651. cs := hm.f.pki.getCertState()
  652. v := hm.initiatingVersion(hh, cs)
  653. cred := cs.GetCredential(v)
  654. if cred == nil {
  655. hm.f.l.Error("Unable to handshake with host because no certificate is available",
  656. "vpnAddrs", hh.hostinfo.vpnAddrs, "certVersion", v)
  657. return false
  658. }
  659. machine, err := handshake.NewMachine(
  660. v, cs.GetCredential,
  661. hm.certVerifier(), func() (uint32, error) { return hm.allocateIndex(hh) },
  662. true, header.HandshakeIXPSK0,
  663. )
  664. if err != nil {
  665. hm.f.l.Error("Failed to create handshake machine",
  666. "vpnAddrs", hh.hostinfo.vpnAddrs, "error", err)
  667. return false
  668. }
  669. msg, err := machine.Initiate(nil)
  670. if err != nil {
  671. hm.f.l.Error("Failed to initiate handshake",
  672. "vpnAddrs", hh.hostinfo.vpnAddrs, "error", err)
  673. return false
  674. }
  675. // hostinfo.ConnectionState stays nil until the handshake completes in
  676. // continueHandshake. Pre-completion control surfaces guard with nil
  677. // checks; the data plane never observes a pending hostinfo.
  678. hh.hostinfo.HandshakePacket[handshakePacketStage0] = msg
  679. hh.machine = machine
  680. hh.ready = true
  681. return true
  682. }
  683. // beginHandshake handles an incoming handshake packet that doesn't match any
  684. // existing pending handshake. It creates a new responder Machine and processes
  685. // the first message.
  686. //
  687. // received is the number of bytes a fragmented msg1 arrived in, which bounds the
  688. // response sent back before the address is validated; 0 for unfragmented ones.
  689. func (hm *HandshakeManager) beginHandshake(via ViaSender, packet []byte, h *header.H, received int) {
  690. f := hm.f
  691. cs := f.pki.getCertState()
  692. v := cs.DefaultVersion()
  693. allocIndex := func() (uint32, error) { return generateIndex(f.l) }
  694. // A hybrid responder answers with its v3 certificate and has to wait for msg3,
  695. // so its index is registered right away for msg3 to find.
  696. var pending *HandshakeHostInfo
  697. if handshake.IsHybrid(h.Subtype) {
  698. v = cert.Version3
  699. pending = &HandshakeHostInfo{
  700. hostinfo: &HostInfo{
  701. HandshakePacket: make(map[uint8][]byte, 0),
  702. relayState: RelayState{
  703. relays: nil,
  704. relayForByAddr: map[netip.Addr]*Relay{},
  705. relayForByIdx: map[uint32]*Relay{},
  706. },
  707. },
  708. startTime: time.Now(),
  709. responder: &hybridResponder{},
  710. }
  711. // The index is visible to msg3 as soon as it is allocated, so hold the
  712. // entry until it is filled in.
  713. pending.Lock()
  714. defer pending.Unlock()
  715. allocIndex = func() (uint32, error) { return hm.allocateIndex(pending) }
  716. }
  717. if cs.GetCredential(v) == nil {
  718. f.l.Error("Unable to handshake with host because no certificate is available",
  719. "from", via, "certVersion", v)
  720. return
  721. }
  722. machine, err := handshake.NewMachine(
  723. v, cs.GetCredential,
  724. hm.certVerifier(), allocIndex,
  725. false, h.Subtype,
  726. )
  727. if err != nil {
  728. f.l.Error("Failed to create handshake machine", "from", via, "error", err)
  729. return
  730. }
  731. response, result, err := machine.ProcessPacket(nil, packet)
  732. if err != nil {
  733. if pending != nil {
  734. hm.DeleteHostInfo(pending.hostinfo)
  735. }
  736. f.l.Error("Failed to process handshake packet", "from", via, "error", err)
  737. return
  738. }
  739. if result == nil && pending != nil {
  740. hm.awaitMsg3(via, pending, machine, packet, response, received)
  741. return
  742. }
  743. if result == nil {
  744. // Multi-message pattern: the responder Machine would need to be
  745. // registered in hm.indexes so a future inbound packet finds it via
  746. // continueHandshake. The current manager doesn't do that yet, so
  747. // fail loudly rather than silently dropping the in-flight handshake.
  748. // TODO: support multi-message responder flows (XX, pqIX, etc.).
  749. // See also the IX-shaped cipher key assignment in handshake.Machine.
  750. f.l.Error("multi-message handshake responder is not supported",
  751. "from", via, "error", handshake.ErrMultiMessageUnsupported)
  752. return
  753. }
  754. remoteCert := result.RemoteCert
  755. if remoteCert == nil {
  756. f.l.Error("Handshake did not produce a peer certificate", "from", via)
  757. return
  758. }
  759. // Validate peer identity
  760. vpnAddrs, anyVpnAddrsInCommon, ok := hm.validatePeerCert(via, remoteCert)
  761. if !ok {
  762. return
  763. }
  764. // A classical attempt crossing the peer's hybrid one goes unanswered.
  765. if !handshake.IsHybrid(machine.Subtype()) && hm.crossesHybrid(vpnAddrs, time.Now()) {
  766. f.l.Debug("Ignoring classical handshake that crossed a hybrid one",
  767. "vpnAddrs", vpnAddrs, "from", via, "window", hm.hybridWindow())
  768. return
  769. }
  770. connState, err := newConnectionStateFromResult(result)
  771. if err != nil {
  772. f.l.Error("Discarding handshake with an invalid message index", "error", err, "vpnAddrs", vpnAddrs)
  773. return
  774. }
  775. hostinfo := &HostInfo{
  776. ConnectionState: connState,
  777. localIndexId: result.LocalIndex,
  778. remoteIndexId: result.RemoteIndex,
  779. vpnAddrs: vpnAddrs,
  780. HandshakePacket: make(map[uint8][]byte, 0),
  781. lastHandshakeTime: result.HandshakeTime,
  782. relayState: RelayState{
  783. relays: nil,
  784. relayForByAddr: map[netip.Addr]*Relay{},
  785. relayForByIdx: map[uint32]*Relay{},
  786. },
  787. }
  788. msg := "Handshake message received"
  789. if !anyVpnAddrsInCommon {
  790. msg = "Handshake message received, but no vpnNetworks in common."
  791. }
  792. f.l.Info(msg,
  793. "vpnAddrs", vpnAddrs,
  794. "from", via,
  795. "certName", remoteCert.Certificate.Name(),
  796. "certVersion", remoteCert.Certificate.Version(),
  797. "fingerprint", remoteCert.Fingerprint,
  798. "issuer", remoteCert.Certificate.Issuer(),
  799. "initiatorIndex", result.RemoteIndex,
  800. "responderIndex", result.LocalIndex,
  801. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  802. )
  803. // packet aliases the listener's incoming buffer, so this copy must stay.
  804. hostinfo.HandshakePacket[handshakePacketStage0] = make([]byte, len(packet[header.Len:]))
  805. copy(hostinfo.HandshakePacket[handshakePacketStage0], packet[header.Len:])
  806. // response was freshly allocated by ProcessPacket; safe to retain directly.
  807. if response != nil {
  808. hostinfo.HandshakePacket[handshakePacketStage2] = response
  809. }
  810. hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs)
  811. if !via.IsRelayed {
  812. hostinfo.SetRemote(via.UdpAddr)
  813. }
  814. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  815. existing, err := hm.CheckAndComplete(hostinfo, handshakePacketStage0, f)
  816. if err != nil {
  817. hm.handleCheckAndCompleteError(err, existing, hostinfo, via, machine.Subtype(), received)
  818. return
  819. }
  820. hm.sendHandshakeResponse(via, response, hostinfo, false, received)
  821. if header.IsFragmented(machine.Subtype()) {
  822. hm.pqAnswered.add(packet[header.Len:], hostinfo, time.Now())
  823. }
  824. hm.notePQPeer(machine.Subtype(), vpnAddrs)
  825. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  826. // Don't wait for UpdateWorker
  827. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  828. f.lightHouse.TriggerUpdate()
  829. }
  830. }
  831. // continueHandshake feeds an incoming packet to an existing pending handshake Machine.
  832. func (hm *HandshakeManager) continueHandshake(via ViaSender, hh *HandshakeHostInfo, packet []byte) {
  833. hh.Lock()
  834. defer hh.Unlock()
  835. if !hm.stillPending(hh, hh.hostinfo.localIndexId) {
  836. return
  837. }
  838. hm.processResponse(via, hh, hh.machine, packet)
  839. }
  840. // stillPending re-verifies hh is still tracked under index. Between queryIndex
  841. // returning and the caller taking hh.Lock, handleOutbound may have timed out and
  842. // deleted it. Once hh.Lock is held no other deleter can race the index:
  843. // handleOutbound also takes hh.Lock first, and handleRecvError targets a
  844. // main-hostmap entry with a different localIndexId. The caller must hold hh.Lock.
  845. func (hm *HandshakeManager) stillPending(hh *HandshakeHostInfo, index uint32) bool {
  846. hm.RLock()
  847. defer hm.RUnlock()
  848. cur, ok := hm.indexes[index]
  849. return ok && cur == hh
  850. }
  851. // processResponse runs a responder's message through one of the initiator's
  852. // pending attempts and completes the tunnel when the handshake finishes. The
  853. // caller must hold hh.Lock.
  854. func (hm *HandshakeManager) processResponse(via ViaSender, hh *HandshakeHostInfo, machine *handshake.Machine, packet []byte) {
  855. f := hm.f
  856. hostinfo := hh.hostinfo
  857. if !via.IsRelayed {
  858. if !f.lightHouse.GetRemoteAllowList().AllowAll(hostinfo.vpnAddrs, via.UdpAddr.Addr()) {
  859. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  860. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  861. return
  862. }
  863. }
  864. if machine == nil {
  865. f.l.Error("No handshake machine available for continuation",
  866. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  867. hm.DeleteHostInfo(hostinfo)
  868. return
  869. }
  870. response, result, err := machine.ProcessPacket(nil, packet)
  871. if err != nil {
  872. // Recoverable errors are routine noise, log at Debug. Fatal errors get a Warn.
  873. if !machine.Failed() {
  874. f.l.Debug("Failed to process handshake packet",
  875. "vpnAddrs", hostinfo.vpnAddrs, "from", via, "error", err)
  876. } else if hh.pq != nil && machine == hh.pq.machine && !hm.pqConfig().require {
  877. // A post-quantum attempt can fail where the classical one would not, a v3
  878. // certificate from a CA only trusted in its v2 form for one. Keep going
  879. // with classical alone.
  880. f.l.Warn("Failed to process post-quantum handshake packet, continuing with classical",
  881. "vpnAddrs", hostinfo.vpnAddrs, "from", via, "error", err)
  882. hm.abandonPQ(hh)
  883. } else {
  884. f.l.Warn("Failed to process handshake packet, abandoning",
  885. "vpnAddrs", hostinfo.vpnAddrs, "from", via, "error", err)
  886. hm.DeleteHostInfo(hostinfo)
  887. }
  888. return
  889. }
  890. if result == nil {
  891. if response != nil {
  892. hm.sendHandshakeResponse(via, response, hostinfo, false, 0)
  893. }
  894. return
  895. }
  896. // Handshake complete; build the ConnectionState now that we have keys and a verified peer cert.
  897. cs, err := newConnectionStateFromResult(result)
  898. if err != nil {
  899. f.l.Error("Discarding handshake with an invalid message index", "error", err, "vpnAddrs", hostinfo.vpnAddrs)
  900. hm.DeleteHostInfo(hostinfo)
  901. return
  902. }
  903. hostinfo.ConnectionState = cs
  904. remoteCert := result.RemoteCert
  905. if remoteCert == nil {
  906. f.l.Error("Handshake completed without peer certificate",
  907. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  908. hm.DeleteHostInfo(hostinfo)
  909. return
  910. }
  911. vpnNetworks := remoteCert.Certificate.Networks()
  912. hostinfo.remoteIndexId = result.RemoteIndex
  913. hostinfo.lastHandshakeTime = result.HandshakeTime
  914. if !via.IsRelayed {
  915. hostinfo.SetRemote(via.UdpAddr)
  916. } else {
  917. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  918. }
  919. // Verify correct host responded (initiator check)
  920. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  921. correctHostResponded := false
  922. anyVpnAddrsInCommon := false
  923. for i, network := range vpnNetworks {
  924. // inside.go drops self-routed packets at the firewall stage, but we'd
  925. // rather not let a self-handshake complete in the first place: it
  926. // wastes a hostmap slot, suppresses no log, and obscures routing
  927. // misconfig. Explicit refusal here mirrors the responder-side check
  928. // in validatePeerCert.
  929. if f.myVpnAddrsTable.Contains(network.Addr()) {
  930. f.l.Error("Refusing to handshake with myself",
  931. "vpnNetworks", vpnNetworks,
  932. "from", via,
  933. "certName", remoteCert.Certificate.Name(),
  934. "certVersion", remoteCert.Certificate.Version(),
  935. "fingerprint", remoteCert.Fingerprint,
  936. "issuer", remoteCert.Certificate.Issuer(),
  937. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  938. )
  939. hm.DeleteHostInfo(hostinfo)
  940. return
  941. }
  942. vpnAddrs[i] = network.Addr()
  943. if hostinfo.vpnAddrs[0] == network.Addr() {
  944. correctHostResponded = true
  945. }
  946. if f.myVpnNetworksTable.Contains(network.Addr()) {
  947. anyVpnAddrsInCommon = true
  948. }
  949. }
  950. if !correctHostResponded {
  951. f.l.Info("Incorrect host responded to handshake",
  952. "intendedVpnAddrs", hostinfo.vpnAddrs,
  953. "haveVpnNetworks", vpnNetworks,
  954. "from", via,
  955. "certName", remoteCert.Certificate.Name(),
  956. "certVersion", remoteCert.Certificate.Version(),
  957. "fingerprint", remoteCert.Fingerprint,
  958. "issuer", remoteCert.Certificate.Issuer(),
  959. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  960. )
  961. hm.DeleteHostInfo(hostinfo)
  962. hm.StartHandshake(hostinfo.vpnAddrs[0], func(newHH *HandshakeHostInfo) {
  963. newHH.hostinfo.remotes.BlockRemote(via)
  964. newHH.packetStore = hh.packetStore
  965. hh.packetStore = []*cachedPacket{}
  966. })
  967. // sendCloseTunnel may take the hostmap lock, so it must not run under the handshake
  968. // manager lock that StartHandshake holds around the callback.
  969. hostinfo.vpnAddrs = vpnAddrs
  970. f.sendCloseTunnel(hostinfo)
  971. return
  972. }
  973. duration := time.Since(hh.startTime).Nanoseconds()
  974. msg := "Handshake message received"
  975. if !anyVpnAddrsInCommon {
  976. msg = "Handshake message received, but no vpnNetworks in common."
  977. }
  978. f.l.Info(msg,
  979. "vpnAddrs", vpnAddrs,
  980. "from", via,
  981. "certName", remoteCert.Certificate.Name(),
  982. "certVersion", remoteCert.Certificate.Version(),
  983. "fingerprint", remoteCert.Fingerprint,
  984. "issuer", remoteCert.Certificate.Issuer(),
  985. "initiatorIndex", result.LocalIndex,
  986. "responderIndex", result.RemoteIndex,
  987. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  988. "durationNs", duration,
  989. "sentCachedPackets", len(hh.packetStore),
  990. )
  991. hostinfo.vpnAddrs = vpnAddrs
  992. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  993. // The classical and PQ attempts each hold an index; keep the one that won.
  994. hm.settleIndex(hh, result.LocalIndex)
  995. hm.Complete(hostinfo, f)
  996. hm.notePQPeer(machine.Subtype(), vpnAddrs)
  997. // A three message pattern finishes with our msg3, which goes out before any
  998. // cached packets do and keeps going until the responder is heard from.
  999. if response != nil {
  1000. hm.startHybridConfirm(via, hostinfo, response, result.MessageIndex)
  1001. }
  1002. if len(hh.packetStore) > 0 {
  1003. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  1004. hostinfo.logger(f.l).Debug("Sending stored packets", "count", len(hh.packetStore))
  1005. }
  1006. nb := make([]byte, 12, 12)
  1007. out := make([]byte, mtu)
  1008. for _, cp := range hh.packetStore {
  1009. // TODO: use a SendBatch here. Each callback lands in
  1010. // sendNoMetrics -> WriteTo: one syscall per cached packet,
  1011. // where one sendmmsg could flush the whole store.
  1012. cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
  1013. }
  1014. f.cachedPacketMetrics.sent.Inc(int64(len(hh.packetStore)))
  1015. }
  1016. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  1017. f.metricHandshakes.Update(duration)
  1018. // Don't wait for UpdateWorker
  1019. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  1020. f.lightHouse.TriggerUpdate()
  1021. }
  1022. }
  1023. // validatePeerCert checks the peer certificate for self-connection and remote allow list.
  1024. // Returns the VPN addrs, whether any of them fall within one of our own VPN
  1025. // networks, and true if valid; false if rejected.
  1026. func (hm *HandshakeManager) validatePeerCert(via ViaSender, remoteCert *cert.CachedCertificate) ([]netip.Addr, bool, bool) {
  1027. f := hm.f
  1028. vpnNetworks := remoteCert.Certificate.Networks()
  1029. // The cert package rejects host certs with no networks at parse time, so
  1030. // reaching this state would mean an invariant was bypassed elsewhere.
  1031. // Refuse explicitly so downstream code (which indexes vpnAddrs[0]) can't
  1032. // panic if that invariant ever changes.
  1033. if len(vpnNetworks) == 0 {
  1034. f.l.Info("No networks in certificate",
  1035. "from", via, "cert", remoteCert)
  1036. return nil, false, false
  1037. }
  1038. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  1039. anyVpnAddrsInCommon := false
  1040. for i, network := range vpnNetworks {
  1041. if f.myVpnAddrsTable.Contains(network.Addr()) {
  1042. f.l.Error("Refusing to handshake with myself",
  1043. "vpnNetworks", vpnNetworks,
  1044. "from", via,
  1045. "certName", remoteCert.Certificate.Name(),
  1046. "certVersion", remoteCert.Certificate.Version(),
  1047. "fingerprint", remoteCert.Fingerprint,
  1048. "issuer", remoteCert.Certificate.Issuer(),
  1049. )
  1050. return nil, false, false
  1051. }
  1052. vpnAddrs[i] = network.Addr()
  1053. if f.myVpnNetworksTable.Contains(network.Addr()) {
  1054. anyVpnAddrsInCommon = true
  1055. }
  1056. }
  1057. if !via.IsRelayed {
  1058. if !f.lightHouse.GetRemoteAllowList().AllowAll(vpnAddrs, via.UdpAddr.Addr()) {
  1059. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  1060. "vpnAddrs", vpnAddrs, "from", via)
  1061. return nil, false, false
  1062. }
  1063. }
  1064. return vpnAddrs, anyVpnAddrsInCommon, true
  1065. }
  1066. // sendHandshakeResponse sends a handshake response via the appropriate transport.
  1067. // cached is true when msg is a stored response being retransmitted because
  1068. // the peer's stage-1 retransmit landed (the ErrAlreadySeen path); false on a
  1069. // fresh response.
  1070. //
  1071. // received is the number of bytes a fragmented msg1 arrived in; it bounds what a
  1072. // fragmented response may send back. It is ignored for unfragmented subtypes.
  1073. func (hm *HandshakeManager) sendHandshakeResponse(via ViaSender, msg []byte, hostinfo *HostInfo, cached bool, received int) {
  1074. if msg == nil {
  1075. return
  1076. }
  1077. f := hm.f
  1078. subtype := header.MessageSubType(msg[1])
  1079. // Common log fields. peerCert may be nil during intermediate
  1080. // multi-message flows (handshake hasn't completed yet); skip the cert
  1081. // block if so.
  1082. logFields := []any{
  1083. "vpnAddrs", hostinfo.vpnAddrs,
  1084. "handshake", m{"stage": uint64(2), "style": header.SubTypeName(header.Handshake, subtype)},
  1085. "cached", cached,
  1086. "initiatorIndex", hostinfo.remoteIndexId,
  1087. "responderIndex", hostinfo.localIndexId,
  1088. }
  1089. if hostinfo.ConnectionState == nil {
  1090. // A hybrid responder answers msg1 before it has keys.
  1091. } else if peerCert := hostinfo.ConnectionState.peerCert; peerCert != nil {
  1092. logFields = append(logFields,
  1093. "certName", peerCert.Certificate.Name(),
  1094. "certVersion", peerCert.Certificate.Version(),
  1095. "fingerprint", peerCert.Fingerprint,
  1096. "issuer", peerCert.Certificate.Issuer(),
  1097. )
  1098. }
  1099. if header.IsFragmented(subtype) {
  1100. fields := append(logFields, "from", via)
  1101. if err := hm.sendFragmentedResponse(via, msg, hostinfo, received); err != nil {
  1102. f.l.Debug("Did not send handshake message", append(fields, "error", err)...)
  1103. } else {
  1104. f.l.Info("Handshake message sent", fields...)
  1105. }
  1106. return
  1107. }
  1108. f.messageMetrics.Tx(header.Handshake, subtype, 1)
  1109. if !via.IsRelayed {
  1110. fields := append(logFields, "from", via)
  1111. err := f.outside.WriteTo(msg, via.UdpAddr)
  1112. if err != nil {
  1113. f.l.Error("Failed to send handshake message", append(fields, "error", err)...)
  1114. } else {
  1115. f.l.Info("Handshake message sent", fields...)
  1116. }
  1117. } else {
  1118. if via.relay == nil {
  1119. f.l.Error("Handshake send failed: both addr and via.relay are nil.")
  1120. return
  1121. }
  1122. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  1123. // We received a valid handshake on this relay, so make sure the relay
  1124. // state reflects that, in case it had been marked Disestablished.
  1125. via.relayHI.relayState.UpdateRelayForByIdxState(via.relay.LocalIndex, Established)
  1126. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false, 0)
  1127. f.l.Info("Handshake message sent", append(logFields, "relay", via.relayHI.vpnAddrs[0])...)
  1128. }
  1129. }
  1130. // handleCheckAndCompleteError handles errors from CheckAndComplete.
  1131. // This only fires from the responder-side beginHandshake path, after the
  1132. // peer cert has been validated and ConnectionState populated, so peerCert
  1133. // is always non-nil for the cases that log it.
  1134. func (hm *HandshakeManager) handleCheckAndCompleteError(err error, existing, hostinfo *HostInfo, via ViaSender, subtype header.MessageSubType, received int) {
  1135. f := hm.f
  1136. peerCert := hostinfo.ConnectionState.peerCert
  1137. hsFields := m{"stage": uint64(1), "style": header.SubTypeName(header.Handshake, subtype)}
  1138. switch err {
  1139. case ErrAlreadySeen:
  1140. if existing.SetRemoteIfPreferred(f.hostMap, via) {
  1141. f.SendMessageToVpnAddr(header.Test, header.TestRequest, hostinfo.vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  1142. }
  1143. // Resend the original response. The peer is committed to that response's
  1144. // ephemeral keys; a freshly-built one would have different keys and break
  1145. // the tunnel even though both sides "completed" the handshake.
  1146. if msg := existing.HandshakePacket[handshakePacketStage2]; msg != nil {
  1147. hm.sendHandshakeResponse(via, msg, existing, true, received)
  1148. }
  1149. case ErrExistingHostInfo:
  1150. f.l.Info("Handshake too old",
  1151. "vpnAddrs", hostinfo.vpnAddrs,
  1152. "from", via,
  1153. "certName", peerCert.Certificate.Name(),
  1154. "certVersion", peerCert.Certificate.Version(),
  1155. "fingerprint", peerCert.Fingerprint,
  1156. "issuer", peerCert.Certificate.Issuer(),
  1157. "oldHandshakeTime", existing.lastHandshakeTime,
  1158. "newHandshakeTime", hostinfo.lastHandshakeTime,
  1159. "initiatorIndex", hostinfo.remoteIndexId,
  1160. "responderIndex", hostinfo.localIndexId,
  1161. "handshake", hsFields,
  1162. )
  1163. f.SendMessageToVpnAddr(header.Test, header.TestRequest, hostinfo.vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  1164. case ErrLocalIndexCollision:
  1165. f.l.Error("Failed to add HostInfo due to localIndex collision",
  1166. "vpnAddrs", hostinfo.vpnAddrs,
  1167. "from", via,
  1168. "certName", peerCert.Certificate.Name(),
  1169. "certVersion", peerCert.Certificate.Version(),
  1170. "fingerprint", peerCert.Fingerprint,
  1171. "issuer", peerCert.Certificate.Issuer(),
  1172. "localIndex", hostinfo.localIndexId,
  1173. "initiatorIndex", hostinfo.remoteIndexId,
  1174. "responderIndex", hostinfo.localIndexId,
  1175. "handshake", hsFields,
  1176. )
  1177. default:
  1178. f.l.Error("Failed to add HostInfo to HostMap",
  1179. "vpnAddrs", hostinfo.vpnAddrs,
  1180. "from", via,
  1181. "error", err,
  1182. "certName", peerCert.Certificate.Name(),
  1183. "certVersion", peerCert.Certificate.Version(),
  1184. "fingerprint", peerCert.Fingerprint,
  1185. "issuer", peerCert.Certificate.Issuer(),
  1186. "initiatorIndex", hostinfo.remoteIndexId,
  1187. "responderIndex", hostinfo.localIndexId,
  1188. "handshake", hsFields,
  1189. )
  1190. }
  1191. }
  1192. // certVerifier returns a CertVerifier that validates certs against the current CA pool.
  1193. func (hm *HandshakeManager) certVerifier() handshake.CertVerifier {
  1194. return func(c cert.Certificate) (*cert.CachedCertificate, error) {
  1195. return hm.f.pki.GetCAPool().VerifyCertificate(time.Now(), c)
  1196. }
  1197. }