handshake_manager.go 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585
  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. "time"
  13. "github.com/rcrowley/go-metrics"
  14. "github.com/slackhq/nebula/cert"
  15. "github.com/slackhq/nebula/handshake"
  16. "github.com/slackhq/nebula/header"
  17. "github.com/slackhq/nebula/udp"
  18. )
  19. const (
  20. DefaultHandshakeTryInterval = time.Millisecond * 100
  21. DefaultHandshakeRetries = 10
  22. DefaultHandshakeTriggerBuffer = 64
  23. // maxCachedPackets is how many unsent packets we'll buffer per pending
  24. // handshake before dropping further ones.
  25. maxCachedPackets = 100
  26. // HandshakePacket map keys mirror the IX protocol stage convention:
  27. // stage 0 = the initiator's first message (and what the responder
  28. // receives, stripped of header)
  29. // stage 2 = the responder's reply
  30. // Other handshake patterns will need new keys when added.
  31. handshakePacketStage0 uint8 = 0
  32. handshakePacketStage2 uint8 = 2
  33. )
  34. var (
  35. defaultHandshakeConfig = HandshakeConfig{
  36. tryInterval: DefaultHandshakeTryInterval,
  37. retries: DefaultHandshakeRetries,
  38. triggerBuffer: DefaultHandshakeTriggerBuffer,
  39. }
  40. )
  41. type HandshakeConfig struct {
  42. tryInterval time.Duration
  43. retries int64
  44. triggerBuffer int
  45. // Multiport lane parameters; laneCount == 0 means multiport is disabled.
  46. // laneCount includes implicit lane 0 (the base tunnel), so lanes
  47. // 1..laneCount-1 are initiated. lanePortCount/laneBasePort describe our
  48. // own bound port range and are advertised in every handshake payload.
  49. laneCount int
  50. lanePortCount uint16
  51. laneBasePort uint16
  52. messageMetrics *MessageMetrics
  53. }
  54. type HandshakeManager struct {
  55. // Mutex for interacting with the vpnIps and indexes maps
  56. sync.RWMutex
  57. vpnIps map[netip.Addr]*HandshakeHostInfo
  58. indexes map[uint32]*HandshakeHostInfo
  59. mainHostMap *HostMap
  60. lightHouse *LightHouse
  61. outside udp.Conn
  62. config HandshakeConfig
  63. OutboundHandshakeTimer *LockingTimerWheel[netip.Addr]
  64. // OutboundLaneTimer drives lane handshake retries. Lanes never enter
  65. // vpnIps (they would collide with base handshakes for the same address),
  66. // so their wheel is keyed by pending localIndexId instead.
  67. OutboundLaneTimer *LockingTimerWheel[uint32]
  68. messageMetrics *MessageMetrics
  69. metricInitiated metrics.Counter
  70. metricTimedOut metrics.Counter
  71. f *Interface
  72. l *slog.Logger
  73. // can be used to trigger outbound handshake for the given vpnIp
  74. trigger chan netip.Addr
  75. }
  76. type HandshakeHostInfo struct {
  77. sync.Mutex
  78. startTime time.Time // Time that we first started trying with this handshake
  79. ready bool // Is the handshake ready
  80. initiatingVersionOverride cert.Version // Should we use a non-default cert version for this handshake?
  81. counter int64 // How many attempts have we made so far
  82. lastRemotes []netip.AddrPort // Remotes that we sent to during the previous attempt
  83. lastRelays []netip.Addr // Relays we attempted to use during the previous attempt
  84. packetStore []*cachedPacket // A set of packets to be transmitted once the handshake completes
  85. hostinfo *HostInfo
  86. machine *handshake.Machine // The handshake state machine, set during stage 0 (initiator) or beginHandshake (responder multi-message)
  87. // laneTarget is the single pinned destination for a lane handshake
  88. // (base-tunnel remote IP at the peer's lane port). Lane handshakes never
  89. // broadcast to the RemoteList.
  90. laneTarget netip.AddrPort
  91. }
  92. func (hh *HandshakeHostInfo) cachePacket(l *slog.Logger, t header.MessageType, st header.MessageSubType, packet []byte, f packetCallback, m *cachedPacketMetrics) {
  93. if len(hh.packetStore) < maxCachedPackets {
  94. tempPacket := make([]byte, len(packet))
  95. copy(tempPacket, packet)
  96. hh.packetStore = append(hh.packetStore, &cachedPacket{t, st, f, tempPacket})
  97. if l.Enabled(context.Background(), slog.LevelDebug) {
  98. hh.hostinfo.logger(l).Debug("Packet store",
  99. "length", len(hh.packetStore),
  100. "stored", true,
  101. )
  102. }
  103. } else {
  104. m.dropped.Inc(1)
  105. if l.Enabled(context.Background(), slog.LevelDebug) {
  106. hh.hostinfo.logger(l).Debug("Packet store",
  107. "length", len(hh.packetStore),
  108. "stored", false,
  109. )
  110. }
  111. }
  112. }
  113. func NewHandshakeManager(l *slog.Logger, mainHostMap *HostMap, lightHouse *LightHouse, outside udp.Conn, config HandshakeConfig) *HandshakeManager {
  114. return &HandshakeManager{
  115. vpnIps: map[netip.Addr]*HandshakeHostInfo{},
  116. indexes: map[uint32]*HandshakeHostInfo{},
  117. mainHostMap: mainHostMap,
  118. lightHouse: lightHouse,
  119. outside: outside,
  120. config: config,
  121. trigger: make(chan netip.Addr, config.triggerBuffer),
  122. OutboundHandshakeTimer: NewLockingTimerWheel[netip.Addr](config.tryInterval, hsTimeout(config.retries, config.tryInterval)),
  123. OutboundLaneTimer: NewLockingTimerWheel[uint32](config.tryInterval, hsTimeout(config.retries, config.tryInterval)),
  124. messageMetrics: config.messageMetrics,
  125. metricInitiated: metrics.GetOrRegisterCounter("handshake_manager.initiated", nil),
  126. metricTimedOut: metrics.GetOrRegisterCounter("handshake_manager.timed_out", nil),
  127. l: l,
  128. }
  129. }
  130. func (hm *HandshakeManager) Run(ctx context.Context) {
  131. clockSource := time.NewTicker(hm.config.tryInterval)
  132. defer clockSource.Stop()
  133. for {
  134. select {
  135. case <-ctx.Done():
  136. return
  137. case vpnIP := <-hm.trigger:
  138. hm.handleOutbound(vpnIP, true)
  139. case now := <-clockSource.C:
  140. hm.NextOutboundHandshakeTimerTick(now)
  141. hm.NextOutboundLaneTimerTick(now)
  142. }
  143. }
  144. }
  145. func (hm *HandshakeManager) HandleIncoming(via ViaSender, packet []byte, h *header.H) {
  146. // Gate on known handshake subtypes. Unknown subtypes (or future ones we
  147. // don't yet support) are dropped here rather than silently routed through
  148. // the IX path. Add a case when introducing a new pattern.
  149. switch h.Subtype {
  150. case header.HandshakeIXPSK0:
  151. // supported
  152. default:
  153. hm.l.Debug("dropping handshake with unsupported subtype",
  154. "from", via, "subtype", h.Subtype)
  155. return
  156. }
  157. // First remote allow list check before we know the vpnIp
  158. if !via.IsRelayed {
  159. if !hm.lightHouse.GetRemoteAllowList().AllowUnknownVpnAddr(via.UdpAddr.Addr()) {
  160. hm.l.Debug("lighthouse.remote_allow_list denied incoming handshake", "from", via)
  161. return
  162. }
  163. }
  164. // First message of a new handshake. The wire format requires RemoteIndex
  165. // to be zero here (the initiator has no responder index to fill in yet),
  166. // and generateIndex never allocates 0, so any non-zero RemoteIndex on a
  167. // stage-1 packet is malformed or someone probing for an index collision.
  168. // Drop without paying the cost of running noise on a pending Machine.
  169. if h.MessageCounter == 1 {
  170. if h.RemoteIndex != 0 {
  171. hm.l.Debug("dropping stage-1 handshake with non-zero RemoteIndex",
  172. "from", via, "remoteIndex", h.RemoteIndex)
  173. return
  174. }
  175. hm.beginHandshake(via, packet, h)
  176. return
  177. }
  178. // Continuation message must match a pending handshake by index.
  179. // Anything else is an orphaned packet (e.g., late retransmit after
  180. // timeout) and is dropped.
  181. if hh := hm.queryIndex(h.RemoteIndex); hh != nil {
  182. hm.continueHandshake(via, hh, packet)
  183. return
  184. }
  185. }
  186. func (hm *HandshakeManager) NextOutboundHandshakeTimerTick(now time.Time) {
  187. hm.OutboundHandshakeTimer.Advance(now)
  188. for {
  189. vpnIp, has := hm.OutboundHandshakeTimer.Purge()
  190. if !has {
  191. break
  192. }
  193. hm.handleOutbound(vpnIp, false)
  194. }
  195. }
  196. func (hm *HandshakeManager) handleOutbound(vpnIp netip.Addr, lighthouseTriggered bool) {
  197. hh := hm.queryVpnIp(vpnIp)
  198. if hh == nil {
  199. return
  200. }
  201. hh.Lock()
  202. defer hh.Unlock()
  203. hostinfo := hh.hostinfo
  204. // If we are out of time, clean up
  205. if hh.counter >= hm.config.retries {
  206. fields := []any{
  207. "udpAddrs", hh.hostinfo.remotes.CopyAddrs(hm.mainHostMap.GetPreferredRanges()),
  208. "initiatorIndex", hh.hostinfo.localIndexId,
  209. "durationNs", time.Since(hh.startTime).Nanoseconds(),
  210. }
  211. // hh.machine can be nil here if buildStage0Packet never succeeded
  212. // (e.g., no certificate available). In that case there's no useful
  213. // handshake metadata to log.
  214. if hh.machine != nil {
  215. fields = append(fields, "handshake", m{
  216. "stage": uint64(hh.machine.MessageIndex()),
  217. "style": header.SubTypeName(header.Handshake, hh.machine.Subtype()),
  218. })
  219. }
  220. hh.hostinfo.logger(hm.l).Info("Handshake timed out", fields...)
  221. hm.metricTimedOut.Inc(1)
  222. hm.DeleteHostInfo(hostinfo)
  223. return
  224. }
  225. // Increment the counter to increase our delay, linear backoff
  226. hh.counter++
  227. // Check if we have a handshake packet to transmit yet
  228. if !hh.ready {
  229. if !hm.buildStage0Packet(hh) {
  230. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  231. return
  232. }
  233. }
  234. // TODO: this hardcodes "always retransmit stage 0", which is correct for
  235. // IX (the initiator only ever sends one packet, msg1) but wrong the
  236. // moment a 3+ message pattern lands. The retry loop should resend the
  237. // most recent outgoing message, not always stage 0. That implies
  238. // HandshakeHostInfo tracking a single "currentOutbound" packet (bytes +
  239. // header metadata) that gets replaced as the handshake progresses,
  240. // instead of indexing into HandshakePacket.
  241. stage0 := hostinfo.HandshakePacket[handshakePacketStage0]
  242. hsFields := m{
  243. "stage": uint64(hh.machine.MessageIndex()),
  244. "style": header.SubTypeName(header.Handshake, hh.machine.Subtype()),
  245. }
  246. // Get a remotes object if we don't already have one.
  247. // This is mainly to protect us as this should never be the case
  248. // NB ^ This comment doesn't jive. It's how the thing gets initialized.
  249. // It's the common path. Should it update every time, in case a future LH query/queries give us more info?
  250. if hostinfo.remotes == nil {
  251. hostinfo.remotes = hm.lightHouse.QueryCache([]netip.Addr{vpnIp})
  252. }
  253. remotes := hostinfo.remotes.CopyAddrs(hm.mainHostMap.GetPreferredRanges())
  254. remotesHaveChanged := !slices.Equal(remotes, hh.lastRemotes)
  255. // We only care about a lighthouse trigger if we have new remotes to send to.
  256. // This is a very specific optimization for a fast lighthouse reply.
  257. if lighthouseTriggered && !remotesHaveChanged {
  258. // If we didn't return here a lighthouse could cause us to aggressively send handshakes
  259. return
  260. }
  261. hh.lastRemotes = remotes
  262. // This will generate a load of queries for hosts with only 1 ip
  263. // (such as ones registered to the lighthouse with only a private IP)
  264. // So we only do it one time after attempting 5 handshakes already.
  265. if len(remotes) <= 1 && hh.counter == 5 {
  266. // If we only have 1 remote it is highly likely our query raced with the other host registered within the lighthouse
  267. // Our vpnIp here has a tunnel with a lighthouse but has yet to send a host update packet there so we only know about
  268. // the learned public ip for them. Query again to short circuit the promotion counter
  269. hm.lightHouse.QueryServer(vpnIp)
  270. }
  271. // Send the handshake to all known ips, stage 2 takes care of assigning the hostinfo.remote based on the first to reply
  272. var sentTo []netip.AddrPort
  273. hostinfo.remotes.ForEach(hm.mainHostMap.GetPreferredRanges(), func(addr netip.AddrPort, _ bool) {
  274. hm.messageMetrics.Tx(header.Handshake, hh.machine.Subtype(), 1)
  275. err := hm.outside.WriteTo(stage0, addr)
  276. if err != nil {
  277. hostinfo.logger(hm.l).Error("Failed to send handshake message",
  278. "udpAddr", addr,
  279. "initiatorIndex", hostinfo.localIndexId,
  280. "handshake", hsFields,
  281. "error", err,
  282. )
  283. } else {
  284. sentTo = append(sentTo, addr)
  285. }
  286. })
  287. // 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,
  288. // so only log when the list of remotes has changed
  289. if remotesHaveChanged {
  290. hostinfo.logger(hm.l).Info("Handshake message sent",
  291. "udpAddrs", sentTo,
  292. "initiatorIndex", hostinfo.localIndexId,
  293. "handshake", hsFields,
  294. )
  295. } else if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  296. hostinfo.logger(hm.l).Debug("Handshake message sent",
  297. "udpAddrs", sentTo,
  298. "initiatorIndex", hostinfo.localIndexId,
  299. "handshake", hsFields,
  300. )
  301. }
  302. hm.f.relayManager.StartRelays(hm.f, vpnIp, hh, stage0)
  303. // If a lighthouse triggered this attempt then we are still in the timer wheel and do not need to re-add
  304. if !lighthouseTriggered {
  305. hm.OutboundHandshakeTimer.Add(vpnIp, hm.config.tryInterval*time.Duration(hh.counter))
  306. }
  307. }
  308. // GetOrHandshake will try to find a hostinfo with a fully formed tunnel or start a new handshake if one is not present
  309. // The 2nd argument will be true if the hostinfo is ready to transmit traffic
  310. func (hm *HandshakeManager) GetOrHandshake(vpnIp netip.Addr, cacheCb func(*HandshakeHostInfo)) (*HostInfo, bool) {
  311. hm.mainHostMap.RLock()
  312. h, ok := hm.mainHostMap.Hosts[vpnIp]
  313. hm.mainHostMap.RUnlock()
  314. if ok {
  315. // Do not attempt promotion if you are a lighthouse
  316. if !hm.lightHouse.amLighthouse {
  317. h.TryPromoteBest(hm.mainHostMap.GetPreferredRanges(), hm.f)
  318. }
  319. return h, true
  320. }
  321. return hm.StartHandshake(vpnIp, cacheCb), false
  322. }
  323. // StartHandshake will ensure a handshake is currently being attempted for the provided vpn ip
  324. func (hm *HandshakeManager) StartHandshake(vpnAddr netip.Addr, cacheCb func(*HandshakeHostInfo)) *HostInfo {
  325. hm.Lock()
  326. if hh, ok := hm.vpnIps[vpnAddr]; ok {
  327. // We are already trying to handshake with this vpn ip
  328. if cacheCb != nil {
  329. cacheCb(hh)
  330. }
  331. hm.Unlock()
  332. return hh.hostinfo
  333. }
  334. hostinfo := &HostInfo{
  335. vpnAddrs: []netip.Addr{vpnAddr},
  336. HandshakePacket: make(map[uint8][]byte, 0),
  337. relayState: RelayState{
  338. relays: nil,
  339. relayForByAddr: map[netip.Addr]*Relay{},
  340. relayForByIdx: map[uint32]*Relay{},
  341. },
  342. }
  343. hh := &HandshakeHostInfo{
  344. hostinfo: hostinfo,
  345. startTime: time.Now(),
  346. }
  347. hm.vpnIps[vpnAddr] = hh
  348. hm.metricInitiated.Inc(1)
  349. hm.OutboundHandshakeTimer.Add(vpnAddr, hm.config.tryInterval)
  350. if cacheCb != nil {
  351. cacheCb(hh)
  352. }
  353. // If this is a static host, we don't need to wait for the HostQueryReply
  354. // We can trigger the handshake right now
  355. _, doTrigger := hm.lightHouse.GetStaticHostList()[vpnAddr]
  356. if !doTrigger {
  357. // Add any calculated remotes, and trigger early handshake if one found
  358. doTrigger = hm.lightHouse.addCalculatedRemotes(vpnAddr)
  359. }
  360. if doTrigger {
  361. select {
  362. case hm.trigger <- vpnAddr:
  363. default:
  364. }
  365. }
  366. hm.Unlock()
  367. hm.lightHouse.QueryServer(vpnAddr)
  368. return hostinfo
  369. }
  370. var (
  371. ErrExistingHostInfo = errors.New("existing hostinfo")
  372. ErrAlreadySeen = errors.New("already seen")
  373. ErrLocalIndexCollision = errors.New("local index collision")
  374. )
  375. // CheckAndComplete checks for any conflicts in the main and pending hostmap
  376. // before adding hostinfo to main. If err is nil, it was added. Otherwise err will be:
  377. //
  378. // ErrAlreadySeen if we already have an entry in the hostmap that has seen the
  379. // exact same handshake packet
  380. //
  381. // ErrExistingHostInfo if we already have an entry in the hostmap for this
  382. // VpnIp and the new handshake was older than the one we currently have
  383. //
  384. // ErrLocalIndexCollision if we already have an entry in the main or pending
  385. // hostmap for the hostinfo.localIndexId.
  386. func (hm *HandshakeManager) CheckAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface) (*HostInfo, error) {
  387. hm.mainHostMap.Lock()
  388. defer hm.mainHostMap.Unlock()
  389. hm.Lock()
  390. defer hm.Unlock()
  391. // Check if we already have a tunnel with this vpn ip
  392. existingHostInfo, found := hm.mainHostMap.Hosts[hostinfo.vpnAddrs[0]]
  393. if found && existingHostInfo != nil {
  394. // Is it just a delayed handshake packet? Check every hostinfo we hold for this address.
  395. for _, testHostInfo := range hm.mainHostMap.unlockedGetHostList(hostinfo.vpnAddrs[0]) {
  396. if bytes.Equal(hostinfo.HandshakePacket[handshakePacket], testHostInfo.HandshakePacket[handshakePacket]) {
  397. return testHostInfo, ErrAlreadySeen
  398. }
  399. }
  400. // Is this a newer handshake?
  401. if existingHostInfo.lastHandshakeTime >= hostinfo.lastHandshakeTime && !existingHostInfo.ConnectionState.initiator {
  402. return existingHostInfo, ErrExistingHostInfo
  403. }
  404. existingHostInfo.logger(hm.l).Info("Taking new handshake")
  405. }
  406. existingIndex, found := hm.mainHostMap.Indexes[hostinfo.localIndexId]
  407. if found {
  408. // We have a collision, but for a different hostinfo
  409. return existingIndex, ErrLocalIndexCollision
  410. }
  411. existingPendingIndex, found := hm.indexes[hostinfo.localIndexId]
  412. if found && existingPendingIndex.hostinfo != hostinfo {
  413. // We have a collision, but for a different hostinfo
  414. return existingPendingIndex.hostinfo, ErrLocalIndexCollision
  415. }
  416. existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]
  417. if found && existingRemoteIndex != nil && existingRemoteIndex.vpnAddrs[0] != hostinfo.vpnAddrs[0] {
  418. // We have a collision, but this can happen since we can't control
  419. // the remote ID. Just log about the situation as a note.
  420. hostinfo.logger(hm.l).Info("New host shadows existing host remoteIndex",
  421. "collision", existingRemoteIndex.vpnAddrs,
  422. )
  423. }
  424. hm.mainHostMap.unlockedAddHostInfo(hostinfo, f)
  425. return existingHostInfo, nil
  426. }
  427. // Complete is a simpler version of CheckAndComplete when we already know we
  428. // won't have a localIndexId collision because we already have an entry in the
  429. // pendingHostMap. An existing hostinfo is returned if there was one.
  430. func (hm *HandshakeManager) Complete(hostinfo *HostInfo, f *Interface) {
  431. hm.mainHostMap.Lock()
  432. defer hm.mainHostMap.Unlock()
  433. hm.Lock()
  434. defer hm.Unlock()
  435. existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]
  436. if found && existingRemoteIndex != nil {
  437. // We have a collision, but this can happen since we can't control
  438. // the remote ID. Just log about the situation as a note.
  439. hostinfo.logger(hm.l).Info("New host shadows existing host remoteIndex",
  440. "collision", existingRemoteIndex.vpnAddrs,
  441. )
  442. }
  443. // We need to remove from the pending hostmap first to avoid undoing work when after to the main hostmap.
  444. hm.unlockedDeleteHostInfo(hostinfo)
  445. hm.mainHostMap.unlockedAddHostInfo(hostinfo, f)
  446. }
  447. // allocateIndex generates a unique localIndexId for this HostInfo
  448. // and adds it to the pendingHostMap. Will error if we are unable to generate
  449. // a unique localIndexId
  450. func (hm *HandshakeManager) allocateIndex(hh *HandshakeHostInfo) (uint32, error) {
  451. hm.mainHostMap.RLock()
  452. defer hm.mainHostMap.RUnlock()
  453. hm.Lock()
  454. defer hm.Unlock()
  455. for range 32 {
  456. index, err := generateIndex(hm.l)
  457. if err != nil {
  458. return 0, err
  459. }
  460. _, inPending := hm.indexes[index]
  461. _, inMain := hm.mainHostMap.Indexes[index]
  462. if !inMain && !inPending {
  463. hh.hostinfo.localIndexId = index
  464. hm.indexes[index] = hh
  465. return index, nil
  466. }
  467. }
  468. return 0, errors.New("failed to generate unique localIndexId")
  469. }
  470. func (hm *HandshakeManager) DeleteHostInfo(hostinfo *HostInfo) {
  471. hm.Lock()
  472. defer hm.Unlock()
  473. hm.unlockedDeleteHostInfo(hostinfo)
  474. }
  475. func (hm *HandshakeManager) unlockedDeleteHostInfo(hostinfo *HostInfo) {
  476. for _, addr := range hostinfo.vpnAddrs {
  477. // Only delete the pending entry if it is actually ours. Lane
  478. // handshakes never live in vpnIps, and an unconditional delete here
  479. // could evict a concurrently pending base handshake for the same
  480. // address.
  481. if cur, ok := hm.vpnIps[addr]; ok && cur.hostinfo == hostinfo {
  482. delete(hm.vpnIps, addr)
  483. }
  484. }
  485. if len(hm.vpnIps) == 0 {
  486. hm.vpnIps = map[netip.Addr]*HandshakeHostInfo{}
  487. }
  488. delete(hm.indexes, hostinfo.localIndexId)
  489. if len(hm.indexes) == 0 {
  490. hm.indexes = map[uint32]*HandshakeHostInfo{}
  491. }
  492. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  493. hm.l.Debug("Pending hostmap hostInfo deleted",
  494. "hostMap", m{"mapTotalSize": len(hm.vpnIps),
  495. "vpnAddrs": hostinfo.vpnAddrs, "indexNumber": hostinfo.localIndexId, "remoteIndexNumber": hostinfo.remoteIndexId},
  496. )
  497. }
  498. }
  499. func (hm *HandshakeManager) QueryVpnAddr(vpnIp netip.Addr) *HostInfo {
  500. hh := hm.queryVpnIp(vpnIp)
  501. if hh != nil {
  502. return hh.hostinfo
  503. }
  504. return nil
  505. }
  506. func (hm *HandshakeManager) queryVpnIp(vpnIp netip.Addr) *HandshakeHostInfo {
  507. hm.RLock()
  508. defer hm.RUnlock()
  509. return hm.vpnIps[vpnIp]
  510. }
  511. func (hm *HandshakeManager) QueryIndex(index uint32) *HostInfo {
  512. hh := hm.queryIndex(index)
  513. if hh != nil {
  514. return hh.hostinfo
  515. }
  516. return nil
  517. }
  518. func (hm *HandshakeManager) queryIndex(index uint32) *HandshakeHostInfo {
  519. hm.RLock()
  520. defer hm.RUnlock()
  521. return hm.indexes[index]
  522. }
  523. func (hm *HandshakeManager) GetPreferredRanges() []netip.Prefix {
  524. return hm.mainHostMap.GetPreferredRanges()
  525. }
  526. func (hm *HandshakeManager) ForEachVpnAddr(f controlEach) {
  527. hm.RLock()
  528. defer hm.RUnlock()
  529. for _, v := range hm.vpnIps {
  530. f(v.hostinfo)
  531. }
  532. }
  533. func (hm *HandshakeManager) ForEachIndex(f controlEach) {
  534. hm.RLock()
  535. defer hm.RUnlock()
  536. for _, v := range hm.indexes {
  537. f(v.hostinfo)
  538. }
  539. }
  540. func (hm *HandshakeManager) EmitStats() {
  541. hm.RLock()
  542. hostLen := len(hm.vpnIps)
  543. indexLen := len(hm.indexes)
  544. hm.RUnlock()
  545. metrics.GetOrRegisterGauge("hostmap.pending.hosts", nil).Update(int64(hostLen))
  546. metrics.GetOrRegisterGauge("hostmap.pending.indexes", nil).Update(int64(indexLen))
  547. hm.mainHostMap.EmitStats()
  548. }
  549. // Utility functions below
  550. func generateIndex(l *slog.Logger) (uint32, error) {
  551. b := make([]byte, 4)
  552. // Let zero mean we don't know the ID, so don't generate zero
  553. var index uint32
  554. for index == 0 {
  555. _, err := rand.Read(b)
  556. if err != nil {
  557. l.Error("Failed to generate index", "error", err)
  558. return 0, err
  559. }
  560. index = binary.BigEndian.Uint32(b)
  561. }
  562. if l.Enabled(context.Background(), slog.LevelDebug) {
  563. l.Debug("Generated index", "index", index)
  564. }
  565. return index, nil
  566. }
  567. func hsTimeout(tries int64, interval time.Duration) time.Duration {
  568. return time.Duration(tries / 2 * ((2 * int64(interval)) + (tries-1)*int64(interval)))
  569. }
  570. // buildStage0Packet creates the initial handshake packet for the initiator.
  571. func (hm *HandshakeManager) buildStage0Packet(hh *HandshakeHostInfo) bool {
  572. cs := hm.f.pki.getCertState()
  573. v := cs.DefaultVersion()
  574. if hh.initiatingVersionOverride != cert.VersionPre1 {
  575. v = hh.initiatingVersionOverride
  576. } else if v < cert.Version2 {
  577. for _, a := range hh.hostinfo.vpnAddrs {
  578. if a.Is6() {
  579. v = cert.Version2
  580. break
  581. }
  582. }
  583. }
  584. cred := cs.GetCredential(v)
  585. if cred == nil {
  586. hm.f.l.Error("Unable to handshake with host because no certificate is available",
  587. "vpnAddrs", hh.hostinfo.vpnAddrs, "certVersion", v)
  588. return false
  589. }
  590. machine, err := handshake.NewMachine(
  591. v, cs.GetCredential,
  592. hm.certVerifier(), func() (uint32, error) { return hm.allocateIndex(hh) },
  593. true, header.HandshakeIXPSK0,
  594. hm.laneAdvert(uint32(hh.hostinfo.laneIndex)),
  595. )
  596. if err != nil {
  597. hm.f.l.Error("Failed to create handshake machine",
  598. "vpnAddrs", hh.hostinfo.vpnAddrs, "error", err)
  599. return false
  600. }
  601. msg, err := machine.Initiate(nil)
  602. if err != nil {
  603. hm.f.l.Error("Failed to initiate handshake",
  604. "vpnAddrs", hh.hostinfo.vpnAddrs, "error", err)
  605. return false
  606. }
  607. // hostinfo.ConnectionState stays nil until the handshake completes in
  608. // continueHandshake. Pre-completion control surfaces guard with nil
  609. // checks; the data plane never observes a pending hostinfo.
  610. hh.hostinfo.HandshakePacket[handshakePacketStage0] = msg
  611. hh.machine = machine
  612. hh.ready = true
  613. return true
  614. }
  615. // laneAdvert returns our multiport advert for a handshake payload, or nil
  616. // when multiport is disabled (which keeps the payload byte-identical to
  617. // vanilla). laneIndex is 0 for base handshakes and our lane number for lane
  618. // handshakes.
  619. func (hm *HandshakeManager) laneAdvert(laneIndex uint32) *handshake.LaneDetails {
  620. if hm.config.laneCount == 0 {
  621. return nil
  622. }
  623. return &handshake.LaneDetails{
  624. PortCount: uint32(hm.config.lanePortCount),
  625. BasePort: uint32(hm.config.laneBasePort),
  626. LaneIndex: laneIndex,
  627. }
  628. }
  629. // maybeAllocLaneState attaches a laneState to a just-completed base tunnel
  630. // when both sides advertised multiport. Must run before the hostinfo becomes
  631. // visible in the hostmap: the data plane reads base.lanes lock-free.
  632. func (hm *HandshakeManager) maybeAllocLaneState(hostinfo *HostInfo, result *handshake.Result) {
  633. if hm.config.laneCount == 0 || result.PeerPortCount == 0 || result.PeerLaneIndex != 0 {
  634. return
  635. }
  636. peerPorts := result.PeerPortCount
  637. if peerPorts > 256 {
  638. // A certified-but-hostile peer doesn't get to size our state.
  639. peerPorts = 256
  640. }
  641. var offset uint16
  642. if len(hm.f.myVpnAddrs) > 0 && len(hostinfo.vpnAddrs) > 0 {
  643. offset = lanePortOffset(hm.f.myVpnAddrs[0], hostinfo.vpnAddrs[0], uint16(peerPorts))
  644. }
  645. hostinfo.lanes = newLaneState(hm.config.laneCount, uint16(peerPorts), uint16(result.PeerBasePort), offset)
  646. }
  647. // EnsureLanes starts lane handshakes for every empty, non-pending, retry-due
  648. // slot of a base tunnel. Called on base handshake completion (both sides) and
  649. // from the connection manager's per-tunnel tick, so a dead lane re-establishes
  650. // within one check interval, subject to per-slot backoff.
  651. func (hm *HandshakeManager) EnsureLanes(base *HostInfo) {
  652. ls := base.lanes
  653. if ls == nil || hm.config.laneCount <= 1 {
  654. return
  655. }
  656. now := time.Now()
  657. var starts []int
  658. ls.Lock()
  659. n := min(len(ls.txLanes), hm.config.laneCount)
  660. for i := 1; i < n; i++ {
  661. if ls.txLanes[i].Load() != nil || ls.txPending[i] || now.Before(ls.txRetryAt[i]) {
  662. continue
  663. }
  664. ls.txPending[i] = true
  665. starts = append(starts, i)
  666. }
  667. ls.Unlock()
  668. for _, i := range starts {
  669. hm.startLaneHandshake(base, i)
  670. }
  671. }
  672. // startLaneHandshake initiates lane i of base: a full Noise handshake from
  673. // local socket i to the peer's advertised lane port. The caller has already
  674. // claimed the slot (txPending[i] = true); every failure path must release it
  675. // via noteLaneFailure.
  676. func (hm *HandshakeManager) startLaneHandshake(base *HostInfo, i int) {
  677. ls := base.lanes
  678. remote := base.GetRemote()
  679. if !remote.IsValid() || ls.peerPortCount == 0 {
  680. // Relay-only peer (or a zero advert that should not have allocated
  681. // lanes). Retried if a direct path shows up later.
  682. ls.noteLaneFailure(i)
  683. return
  684. }
  685. target := netip.AddrPortFrom(remote.Addr(), ls.laneTargetPort(i))
  686. hostinfo := &HostInfo{
  687. vpnAddrs: slices.Clone(base.vpnAddrs),
  688. HandshakePacket: make(map[uint8][]byte, 0),
  689. relayState: RelayState{
  690. relays: nil,
  691. relayForByAddr: map[netip.Addr]*Relay{},
  692. relayForByIdx: map[uint32]*Relay{},
  693. },
  694. // A private RemoteList: SetRemote must never leak lane ports into the
  695. // shared lighthouse-learned cache that base handshakes broadcast to.
  696. remotes: NewRemoteList(base.vpnAddrs, nil),
  697. sockIdx: i,
  698. laneIndex: uint16(i),
  699. laneOwned: true,
  700. parent: base,
  701. }
  702. hh := &HandshakeHostInfo{
  703. hostinfo: hostinfo,
  704. startTime: time.Now(),
  705. laneTarget: target,
  706. }
  707. if cs := base.ConnectionState; cs != nil && cs.myCert != nil {
  708. // Pin the lane to the base tunnel's negotiated cert version rather
  709. // than re-running version selection.
  710. hh.initiatingVersionOverride = cs.myCert.Version()
  711. }
  712. // Build stage 0 eagerly: allocateIndex registers hh in hm.indexes so
  713. // continueHandshake can find it, and gives us the key for the lane timer.
  714. hh.Lock()
  715. ok := hm.buildStage0Packet(hh)
  716. hh.Unlock()
  717. if !ok {
  718. ls.noteLaneFailure(i)
  719. return
  720. }
  721. hostinfo.logger(hm.l).Info("Lane handshake started",
  722. "laneIndex", i,
  723. "udpAddr", target,
  724. "initiatorIndex", hostinfo.localIndexId,
  725. )
  726. hm.metricInitiated.Inc(1)
  727. hm.OutboundLaneTimer.Add(hostinfo.localIndexId, hm.config.tryInterval)
  728. hm.handleOutboundLane(hostinfo.localIndexId)
  729. }
  730. func (hm *HandshakeManager) NextOutboundLaneTimerTick(now time.Time) {
  731. hm.OutboundLaneTimer.Advance(now)
  732. for {
  733. idx, has := hm.OutboundLaneTimer.Purge()
  734. if !has {
  735. break
  736. }
  737. hm.handleOutboundLane(idx)
  738. }
  739. }
  740. // handleOutboundLane is handleOutbound for lane handshakes: single pinned
  741. // target, egress via the lane's own socket, no lighthouse and no relays.
  742. func (hm *HandshakeManager) handleOutboundLane(localIndex uint32) {
  743. hh := hm.queryIndex(localIndex)
  744. if hh == nil || !hh.hostinfo.isLane() {
  745. return
  746. }
  747. hh.Lock()
  748. defer hh.Unlock()
  749. hostinfo := hh.hostinfo
  750. if hh.counter >= hm.config.retries {
  751. hostinfo.logger(hm.l).Info("Lane handshake timed out",
  752. "laneIndex", hostinfo.laneIndex,
  753. "udpAddr", hh.laneTarget,
  754. "initiatorIndex", hostinfo.localIndexId,
  755. "durationNs", time.Since(hh.startTime).Nanoseconds(),
  756. )
  757. hm.metricTimedOut.Inc(1)
  758. hm.DeleteHostInfo(hostinfo)
  759. hostinfo.parent.lanes.noteLaneFailure(int(hostinfo.laneIndex))
  760. return
  761. }
  762. hh.counter++
  763. stage0 := hostinfo.HandshakePacket[handshakePacketStage0]
  764. hm.messageMetrics.Tx(header.Handshake, hh.machine.Subtype(), 1)
  765. err := hm.f.writers[hostinfo.sockIdx].WriteTo(stage0, hh.laneTarget)
  766. if err != nil {
  767. hostinfo.logger(hm.l).Error("Failed to send lane handshake message",
  768. "laneIndex", hostinfo.laneIndex,
  769. "udpAddr", hh.laneTarget,
  770. "initiatorIndex", hostinfo.localIndexId,
  771. "error", err,
  772. )
  773. } else if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  774. hostinfo.logger(hm.l).Debug("Lane handshake message sent",
  775. "laneIndex", hostinfo.laneIndex,
  776. "udpAddr", hh.laneTarget,
  777. "initiatorIndex", hostinfo.localIndexId,
  778. )
  779. }
  780. hm.OutboundLaneTimer.Add(localIndex, hm.config.tryInterval*time.Duration(hh.counter))
  781. }
  782. // deletePendingHostInfo abandons a pending handshake. For lanes it also
  783. // releases the base's slot claim with failure backoff so ensureLanes can
  784. // retry later.
  785. func (hm *HandshakeManager) deletePendingHostInfo(hostinfo *HostInfo) {
  786. hm.DeleteHostInfo(hostinfo)
  787. if hostinfo.isLane() {
  788. hostinfo.parent.lanes.noteLaneFailure(int(hostinfo.laneIndex))
  789. }
  790. }
  791. // completeLane moves a finished lane out of the pending map and registers it
  792. // in the main hostmap's index maps (never Hosts). The caller publishes it to
  793. // the base's txLanes/peerLanes afterwards.
  794. func (hm *HandshakeManager) completeLane(hostinfo *HostInfo, f *Interface) {
  795. hm.mainHostMap.Lock()
  796. defer hm.mainHostMap.Unlock()
  797. hm.Lock()
  798. defer hm.Unlock()
  799. existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]
  800. if found && existingRemoteIndex != nil {
  801. hostinfo.logger(hm.l).Info("New lane shadows existing host remoteIndex",
  802. "collision", existingRemoteIndex.vpnAddrs,
  803. )
  804. }
  805. hm.unlockedDeleteHostInfo(hostinfo)
  806. hm.mainHostMap.unlockedAddLane(hostinfo, f)
  807. }
  808. // beginHandshake handles an incoming handshake packet that doesn't match any
  809. // existing pending handshake. It creates a new responder Machine and processes
  810. // the first message.
  811. func (hm *HandshakeManager) beginHandshake(via ViaSender, packet []byte, h *header.H) {
  812. f := hm.f
  813. cs := f.pki.getCertState()
  814. v := cs.DefaultVersion()
  815. if cs.GetCredential(v) == nil {
  816. f.l.Error("Unable to handshake with host because no certificate is available",
  817. "from", via, "certVersion", v)
  818. return
  819. }
  820. machine, err := handshake.NewMachine(
  821. v, cs.GetCredential,
  822. hm.certVerifier(), func() (uint32, error) { return generateIndex(f.l) },
  823. false, header.HandshakeIXPSK0,
  824. hm.laneAdvert(0),
  825. )
  826. if err != nil {
  827. f.l.Error("Failed to create handshake machine", "from", via, "error", err)
  828. return
  829. }
  830. response, result, err := machine.ProcessPacket(nil, packet)
  831. if err != nil {
  832. f.l.Error("Failed to process handshake packet", "from", via, "error", err)
  833. return
  834. }
  835. if result == nil {
  836. // Multi-message pattern: the responder Machine would need to be
  837. // registered in hm.indexes so a future inbound packet finds it via
  838. // continueHandshake. The current manager doesn't do that yet, so
  839. // fail loudly rather than silently dropping the in-flight handshake.
  840. // TODO: support multi-message responder flows (XX, pqIX, etc.).
  841. // See also the IX-shaped cipher key assignment in handshake.Machine.
  842. f.l.Error("multi-message handshake responder is not supported",
  843. "from", via, "error", handshake.ErrMultiMessageUnsupported)
  844. return
  845. }
  846. remoteCert := result.RemoteCert
  847. if remoteCert == nil {
  848. f.l.Error("Handshake did not produce a peer certificate", "from", via)
  849. return
  850. }
  851. // Validate peer identity
  852. vpnAddrs, anyVpnAddrsInCommon, ok := hm.validatePeerCert(via, remoteCert)
  853. if !ok {
  854. return
  855. }
  856. // A nonzero lane tag makes this a lane handshake for an existing base
  857. // tunnel rather than a (possibly duplicate) tunnel of its own.
  858. if result.PeerLaneIndex > 0 {
  859. hm.completeLaneResponder(via, packet, response, result, vpnAddrs)
  860. return
  861. }
  862. hostinfo := &HostInfo{
  863. ConnectionState: newConnectionStateFromResult(result),
  864. localIndexId: result.LocalIndex,
  865. remoteIndexId: result.RemoteIndex,
  866. vpnAddrs: vpnAddrs,
  867. HandshakePacket: make(map[uint8][]byte, 0),
  868. lastHandshakeTime: result.HandshakeTime,
  869. relayState: RelayState{
  870. relays: nil,
  871. relayForByAddr: map[netip.Addr]*Relay{},
  872. relayForByIdx: map[uint32]*Relay{},
  873. },
  874. }
  875. msg := "Handshake message received"
  876. if !anyVpnAddrsInCommon {
  877. msg = "Handshake message received, but no vpnNetworks in common."
  878. }
  879. f.l.Info(msg,
  880. "vpnAddrs", vpnAddrs,
  881. "from", via,
  882. "certName", remoteCert.Certificate.Name(),
  883. "certVersion", remoteCert.Certificate.Version(),
  884. "fingerprint", remoteCert.Fingerprint,
  885. "issuer", remoteCert.Certificate.Issuer(),
  886. "initiatorIndex", result.RemoteIndex,
  887. "responderIndex", result.LocalIndex,
  888. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  889. )
  890. // packet aliases the listener's incoming buffer, so this copy must stay.
  891. hostinfo.HandshakePacket[handshakePacketStage0] = make([]byte, len(packet[header.Len:]))
  892. copy(hostinfo.HandshakePacket[handshakePacketStage0], packet[header.Len:])
  893. // response was freshly allocated by ProcessPacket; safe to retain directly.
  894. if response != nil {
  895. hostinfo.HandshakePacket[handshakePacketStage2] = response
  896. }
  897. hostinfo.remotes = f.lightHouse.QueryCache(vpnAddrs)
  898. if !via.IsRelayed {
  899. hostinfo.SetRemote(via.UdpAddr)
  900. }
  901. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  902. hm.maybeAllocLaneState(hostinfo, result)
  903. existing, err := hm.CheckAndComplete(hostinfo, handshakePacketStage0, f)
  904. if err != nil {
  905. hm.handleCheckAndCompleteError(err, existing, hostinfo, via)
  906. return
  907. }
  908. hm.sendHandshakeResponse(via, response, hostinfo, false)
  909. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  910. hm.EnsureLanes(hostinfo)
  911. // Don't wait for UpdateWorker
  912. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  913. f.lightHouse.TriggerUpdate()
  914. }
  915. }
  916. // completeLaneResponder finishes the responder side of a lane handshake:
  917. // associate with the base tunnel by the peer's certified vpn address, dedup
  918. // replays per lane, register the lane in the index maps, and reply from the
  919. // arrival socket. Handshakes with no live base are dropped — the initiator's
  920. // retry loop converges once the base exists.
  921. func (hm *HandshakeManager) completeLaneResponder(via ViaSender, packet, response []byte, result *handshake.Result, vpnAddrs []netip.Addr) {
  922. f := hm.f
  923. if via.IsRelayed {
  924. hm.l.Debug("dropping relayed lane handshake", "vpnAddrs", vpnAddrs, "from", via)
  925. return
  926. }
  927. if hm.config.laneCount == 0 {
  928. hm.l.Debug("dropping lane handshake, multiport is disabled", "vpnAddrs", vpnAddrs, "from", via)
  929. return
  930. }
  931. base := hm.mainHostMap.QueryVpnAddr(vpnAddrs[0])
  932. if base == nil || base.ConnectionState == nil || base.lanes == nil {
  933. hm.l.Debug("dropping lane handshake with no base tunnel",
  934. "vpnAddrs", vpnAddrs, "from", via, "laneIndex", result.PeerLaneIndex)
  935. return
  936. }
  937. ls := base.lanes
  938. // The owner's lane index is bounded by its own advertised port count
  939. // (lanes are one-per-routine and PortCount == routines on the owner).
  940. laneIndex := result.PeerLaneIndex
  941. if laneIndex >= uint32(ls.peerPortCount) || laneIndex > 256 {
  942. hm.l.Debug("dropping lane handshake with out-of-range lane index",
  943. "vpnAddrs", vpnAddrs, "from", via, "laneIndex", laneIndex)
  944. return
  945. }
  946. // Per-lane replay dedup against the existing lane with the same index.
  947. stage0 := packet[header.Len:]
  948. var existing *HostInfo
  949. ls.Lock()
  950. for _, h := range ls.peerLanes {
  951. if h.laneIndex == uint16(laneIndex) {
  952. existing = h
  953. break
  954. }
  955. }
  956. ls.Unlock()
  957. if existing != nil {
  958. if bytes.Equal(stage0, existing.HandshakePacket[handshakePacketStage0]) {
  959. // Stage-0 retransmit: the peer is committed to the original
  960. // response's ephemeral keys, resend it from the arrival socket.
  961. if msg := existing.HandshakePacket[handshakePacketStage2]; msg != nil {
  962. hm.sendHandshakeResponse(via, msg, existing, true)
  963. }
  964. return
  965. }
  966. if existing.lastHandshakeTime >= result.HandshakeTime {
  967. existing.logger(hm.l).Debug("dropping stale lane handshake",
  968. "laneIndex", laneIndex, "from", via)
  969. return
  970. }
  971. // Newer handshake wins; the initiator only re-initiates after it
  972. // declared the old lane dead. Silent local teardown.
  973. hm.mainHostMap.DeleteHostInfo(existing)
  974. }
  975. hostinfo := &HostInfo{
  976. ConnectionState: newConnectionStateFromResult(result),
  977. localIndexId: result.LocalIndex,
  978. remoteIndexId: result.RemoteIndex,
  979. vpnAddrs: vpnAddrs,
  980. HandshakePacket: make(map[uint8][]byte, 0),
  981. lastHandshakeTime: result.HandshakeTime,
  982. relayState: RelayState{
  983. relays: nil,
  984. relayForByAddr: map[netip.Addr]*Relay{},
  985. relayForByIdx: map[uint32]*Relay{},
  986. },
  987. // Private RemoteList: lane roaming must not touch the shared
  988. // lighthouse-learned cache.
  989. remotes: NewRemoteList(vpnAddrs, nil),
  990. sockIdx: via.SockIdx,
  991. laneIndex: uint16(laneIndex),
  992. laneOwned: false,
  993. parent: base,
  994. }
  995. // packet aliases the listener's incoming buffer, so this copy must stay.
  996. hostinfo.HandshakePacket[handshakePacketStage0] = make([]byte, len(stage0))
  997. copy(hostinfo.HandshakePacket[handshakePacketStage0], stage0)
  998. if response != nil {
  999. hostinfo.HandshakePacket[handshakePacketStage2] = response
  1000. }
  1001. hostinfo.SetRemote(via.UdpAddr)
  1002. hostinfo.buildNetworks(f.myVpnNetworksTable, result.RemoteCert.Certificate)
  1003. // Index-collision checks, mirroring CheckAndComplete minus the Hosts
  1004. // dedup (lanes are keyed by (base, laneIndex), not by address).
  1005. hm.mainHostMap.Lock()
  1006. hm.Lock()
  1007. if existingIndex, found := hm.mainHostMap.Indexes[hostinfo.localIndexId]; found && existingIndex != hostinfo {
  1008. hm.Unlock()
  1009. hm.mainHostMap.Unlock()
  1010. hostinfo.logger(hm.l).Error("Failed to add lane due to localIndex collision", "laneIndex", laneIndex)
  1011. return
  1012. }
  1013. if existingPendingIndex, found := hm.indexes[hostinfo.localIndexId]; found && existingPendingIndex.hostinfo != hostinfo {
  1014. hm.Unlock()
  1015. hm.mainHostMap.Unlock()
  1016. hostinfo.logger(hm.l).Error("Failed to add lane due to pending localIndex collision", "laneIndex", laneIndex)
  1017. return
  1018. }
  1019. if existingRemoteIndex, found := hm.mainHostMap.RemoteIndexes[hostinfo.remoteIndexId]; found && existingRemoteIndex != nil {
  1020. hostinfo.logger(hm.l).Info("New lane shadows existing host remoteIndex",
  1021. "collision", existingRemoteIndex.vpnAddrs,
  1022. )
  1023. }
  1024. hm.mainHostMap.unlockedAddLane(hostinfo, f)
  1025. hm.Unlock()
  1026. hm.mainHostMap.Unlock()
  1027. ls.Lock()
  1028. ls.peerLanes = append(ls.peerLanes, hostinfo)
  1029. ls.Unlock()
  1030. hostinfo.logger(hm.l).Info("Lane handshake received",
  1031. "laneIndex", laneIndex,
  1032. "from", via,
  1033. "initiatorIndex", result.RemoteIndex,
  1034. "responderIndex", result.LocalIndex,
  1035. )
  1036. hm.sendHandshakeResponse(via, response, hostinfo, false)
  1037. }
  1038. // continueHandshake feeds an incoming packet to an existing pending handshake Machine.
  1039. func (hm *HandshakeManager) continueHandshake(via ViaSender, hh *HandshakeHostInfo, packet []byte) {
  1040. f := hm.f
  1041. hh.Lock()
  1042. defer hh.Unlock()
  1043. // Re-verify hh is still tracked. Between queryIndex returning and us taking
  1044. // hh.Lock, handleOutbound may have timed out and deleted it. Once we hold
  1045. // hh.Lock no other deleter can race our index: handleOutbound also takes
  1046. // hh.Lock first, and handleRecvError targets a main-hostmap entry with a
  1047. // different localIndexId.
  1048. hm.RLock()
  1049. cur, ok := hm.indexes[hh.hostinfo.localIndexId]
  1050. hm.RUnlock()
  1051. if !ok || cur != hh {
  1052. return
  1053. }
  1054. hostinfo := hh.hostinfo
  1055. if hostinfo.isLane() && via.IsRelayed {
  1056. // Lane handshakes are direct-only; a relayed continuation is a stray
  1057. // or a protocol violation. Drop without failing the machine so the
  1058. // direct stage-2 can still land.
  1059. f.l.Debug("dropping relayed lane handshake continuation",
  1060. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  1061. return
  1062. }
  1063. if !via.IsRelayed {
  1064. if !f.lightHouse.GetRemoteAllowList().AllowAll(hostinfo.vpnAddrs, via.UdpAddr.Addr()) {
  1065. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  1066. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  1067. return
  1068. }
  1069. }
  1070. machine := hh.machine
  1071. if machine == nil {
  1072. f.l.Error("No handshake machine available for continuation",
  1073. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  1074. hm.deletePendingHostInfo(hostinfo)
  1075. return
  1076. }
  1077. response, result, err := machine.ProcessPacket(nil, packet)
  1078. if err != nil {
  1079. // Recoverable errors are routine noise, log at Debug. Fatal errors get a Warn.
  1080. if machine.Failed() {
  1081. f.l.Warn("Failed to process handshake packet, abandoning",
  1082. "vpnAddrs", hostinfo.vpnAddrs, "from", via, "error", err)
  1083. hm.deletePendingHostInfo(hostinfo)
  1084. } else {
  1085. f.l.Debug("Failed to process handshake packet",
  1086. "vpnAddrs", hostinfo.vpnAddrs, "from", via, "error", err)
  1087. }
  1088. return
  1089. }
  1090. if response != nil {
  1091. hm.sendHandshakeResponse(via, response, hostinfo, false)
  1092. }
  1093. if result == nil {
  1094. return
  1095. }
  1096. // Handshake complete; build the ConnectionState now that we have keys and a verified peer cert.
  1097. hostinfo.ConnectionState = newConnectionStateFromResult(result)
  1098. remoteCert := result.RemoteCert
  1099. if remoteCert == nil {
  1100. f.l.Error("Handshake completed without peer certificate",
  1101. "vpnAddrs", hostinfo.vpnAddrs, "from", via)
  1102. hm.deletePendingHostInfo(hostinfo)
  1103. return
  1104. }
  1105. vpnNetworks := remoteCert.Certificate.Networks()
  1106. hostinfo.remoteIndexId = result.RemoteIndex
  1107. hostinfo.lastHandshakeTime = result.HandshakeTime
  1108. if !via.IsRelayed {
  1109. hostinfo.SetRemote(via.UdpAddr)
  1110. } else {
  1111. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  1112. }
  1113. // Verify correct host responded (initiator check)
  1114. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  1115. correctHostResponded := false
  1116. anyVpnAddrsInCommon := false
  1117. for i, network := range vpnNetworks {
  1118. // inside.go drops self-routed packets at the firewall stage, but we'd
  1119. // rather not let a self-handshake complete in the first place: it
  1120. // wastes a hostmap slot, suppresses no log, and obscures routing
  1121. // misconfig. Explicit refusal here mirrors the responder-side check
  1122. // in validatePeerCert.
  1123. if f.myVpnAddrsTable.Contains(network.Addr()) {
  1124. f.l.Error("Refusing to handshake with myself",
  1125. "vpnNetworks", vpnNetworks,
  1126. "from", via,
  1127. "certName", remoteCert.Certificate.Name(),
  1128. "certVersion", remoteCert.Certificate.Version(),
  1129. "fingerprint", remoteCert.Fingerprint,
  1130. "issuer", remoteCert.Certificate.Issuer(),
  1131. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  1132. )
  1133. hm.deletePendingHostInfo(hostinfo)
  1134. return
  1135. }
  1136. vpnAddrs[i] = network.Addr()
  1137. if hostinfo.vpnAddrs[0] == network.Addr() {
  1138. correctHostResponded = true
  1139. }
  1140. if f.myVpnNetworksTable.Contains(network.Addr()) {
  1141. anyVpnAddrsInCommon = true
  1142. }
  1143. }
  1144. if !correctHostResponded {
  1145. f.l.Info("Incorrect host responded to handshake",
  1146. "intendedVpnAddrs", hostinfo.vpnAddrs,
  1147. "haveVpnNetworks", vpnNetworks,
  1148. "from", via,
  1149. "certName", remoteCert.Certificate.Name(),
  1150. "certVersion", remoteCert.Certificate.Version(),
  1151. "fingerprint", remoteCert.Fingerprint,
  1152. "issuer", remoteCert.Certificate.Issuer(),
  1153. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  1154. )
  1155. if hostinfo.isLane() {
  1156. // No restart dance for lanes: close what the peer completed,
  1157. // release the slot with backoff, and let ensureLanes retry.
  1158. hm.deletePendingHostInfo(hostinfo)
  1159. hostinfo.vpnAddrs = vpnAddrs
  1160. f.sendCloseTunnel(hostinfo)
  1161. return
  1162. }
  1163. hm.DeleteHostInfo(hostinfo)
  1164. hm.StartHandshake(hostinfo.vpnAddrs[0], func(newHH *HandshakeHostInfo) {
  1165. newHH.hostinfo.remotes = hostinfo.remotes
  1166. newHH.hostinfo.remotes.BlockRemote(via)
  1167. newHH.packetStore = hh.packetStore
  1168. hh.packetStore = []*cachedPacket{}
  1169. hostinfo.vpnAddrs = vpnAddrs
  1170. f.sendCloseTunnel(hostinfo)
  1171. })
  1172. return
  1173. }
  1174. duration := time.Since(hh.startTime).Nanoseconds()
  1175. msg := "Handshake message received"
  1176. if !anyVpnAddrsInCommon {
  1177. msg = "Handshake message received, but no vpnNetworks in common."
  1178. }
  1179. f.l.Info(msg,
  1180. "vpnAddrs", vpnAddrs,
  1181. "from", via,
  1182. "certName", remoteCert.Certificate.Name(),
  1183. "certVersion", remoteCert.Certificate.Version(),
  1184. "fingerprint", remoteCert.Fingerprint,
  1185. "issuer", remoteCert.Certificate.Issuer(),
  1186. "initiatorIndex", result.LocalIndex,
  1187. "responderIndex", result.RemoteIndex,
  1188. "handshake", m{"stage": uint64(machine.MessageIndex()), "style": header.SubTypeName(header.Handshake, machine.Subtype())},
  1189. "durationNs", duration,
  1190. "sentCachedPackets", len(hh.packetStore),
  1191. )
  1192. hostinfo.vpnAddrs = vpnAddrs
  1193. hostinfo.buildNetworks(f.myVpnNetworksTable, remoteCert.Certificate)
  1194. if hostinfo.isLane() {
  1195. hm.completeLane(hostinfo, f)
  1196. // Publish to the data plane only after the lane is registered and its
  1197. // ConnectionState is fully populated; a routine that Loads non-nil
  1198. // must always see a usable tunnel.
  1199. ls := hostinfo.parent.lanes
  1200. i := int(hostinfo.laneIndex)
  1201. ls.Lock()
  1202. if i < len(ls.txPending) {
  1203. ls.txPending[i] = false
  1204. ls.txFails[i] = 0
  1205. }
  1206. ls.Unlock()
  1207. if i < len(ls.txLanes) {
  1208. ls.txLanes[i].Store(hostinfo)
  1209. }
  1210. f.metricHandshakes.Update(duration)
  1211. return
  1212. }
  1213. hm.maybeAllocLaneState(hostinfo, result)
  1214. hm.Complete(hostinfo, f)
  1215. hm.EnsureLanes(hostinfo)
  1216. if len(hh.packetStore) > 0 {
  1217. if f.l.Enabled(context.Background(), slog.LevelDebug) {
  1218. hostinfo.logger(f.l).Debug("Sending stored packets", "count", len(hh.packetStore))
  1219. }
  1220. nb := make([]byte, 12, 12)
  1221. out := make([]byte, mtu)
  1222. for _, cp := range hh.packetStore {
  1223. //todo use a sendbatcher
  1224. cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
  1225. }
  1226. f.cachedPacketMetrics.sent.Inc(int64(len(hh.packetStore)))
  1227. }
  1228. hostinfo.remotes.RefreshFromHandshake(vpnAddrs)
  1229. f.metricHandshakes.Update(duration)
  1230. // Don't wait for UpdateWorker
  1231. if f.lightHouse.IsAnyLighthouseAddr(vpnAddrs) {
  1232. f.lightHouse.TriggerUpdate()
  1233. }
  1234. }
  1235. // validatePeerCert checks the peer certificate for self-connection and remote allow list.
  1236. // Returns the VPN addrs, whether any of them fall within one of our own VPN
  1237. // networks, and true if valid; false if rejected.
  1238. func (hm *HandshakeManager) validatePeerCert(via ViaSender, remoteCert *cert.CachedCertificate) ([]netip.Addr, bool, bool) {
  1239. f := hm.f
  1240. vpnNetworks := remoteCert.Certificate.Networks()
  1241. // The cert package rejects host certs with no networks at parse time, so
  1242. // reaching this state would mean an invariant was bypassed elsewhere.
  1243. // Refuse explicitly so downstream code (which indexes vpnAddrs[0]) can't
  1244. // panic if that invariant ever changes.
  1245. if len(vpnNetworks) == 0 {
  1246. f.l.Info("No networks in certificate",
  1247. "from", via, "cert", remoteCert)
  1248. return nil, false, false
  1249. }
  1250. vpnAddrs := make([]netip.Addr, len(vpnNetworks))
  1251. anyVpnAddrsInCommon := false
  1252. for i, network := range vpnNetworks {
  1253. if f.myVpnAddrsTable.Contains(network.Addr()) {
  1254. f.l.Error("Refusing to handshake with myself",
  1255. "vpnNetworks", vpnNetworks,
  1256. "from", via,
  1257. "certName", remoteCert.Certificate.Name(),
  1258. "certVersion", remoteCert.Certificate.Version(),
  1259. "fingerprint", remoteCert.Fingerprint,
  1260. "issuer", remoteCert.Certificate.Issuer(),
  1261. )
  1262. return nil, false, false
  1263. }
  1264. vpnAddrs[i] = network.Addr()
  1265. if f.myVpnNetworksTable.Contains(network.Addr()) {
  1266. anyVpnAddrsInCommon = true
  1267. }
  1268. }
  1269. if !via.IsRelayed {
  1270. if !f.lightHouse.GetRemoteAllowList().AllowAll(vpnAddrs, via.UdpAddr.Addr()) {
  1271. f.l.Debug("lighthouse.remote_allow_list denied incoming handshake",
  1272. "vpnAddrs", vpnAddrs, "from", via)
  1273. return nil, false, false
  1274. }
  1275. }
  1276. return vpnAddrs, anyVpnAddrsInCommon, true
  1277. }
  1278. // sendHandshakeResponse sends a handshake response via the appropriate transport.
  1279. // cached is true when msg is a stored response being retransmitted because
  1280. // the peer's stage-1 retransmit landed (the ErrAlreadySeen path); false on a
  1281. // fresh response.
  1282. func (hm *HandshakeManager) sendHandshakeResponse(via ViaSender, msg []byte, hostinfo *HostInfo, cached bool) {
  1283. if msg == nil {
  1284. return
  1285. }
  1286. f := hm.f
  1287. f.messageMetrics.Tx(header.Handshake, header.MessageSubType(msg[1]), 1)
  1288. // Common log fields. peerCert may be nil during intermediate
  1289. // multi-message flows (handshake hasn't completed yet); skip the cert
  1290. // block if so.
  1291. logFields := []any{
  1292. "vpnAddrs", hostinfo.vpnAddrs,
  1293. "handshake", m{"stage": uint64(2), "style": header.SubTypeName(header.Handshake, header.HandshakeIXPSK0)},
  1294. "cached", cached,
  1295. "initiatorIndex", hostinfo.remoteIndexId,
  1296. "responderIndex", hostinfo.localIndexId,
  1297. }
  1298. if peerCert := hostinfo.ConnectionState.peerCert; peerCert != nil {
  1299. logFields = append(logFields,
  1300. "certName", peerCert.Certificate.Name(),
  1301. "certVersion", peerCert.Certificate.Version(),
  1302. "fingerprint", peerCert.Fingerprint,
  1303. "issuer", peerCert.Certificate.Issuer(),
  1304. )
  1305. }
  1306. if !via.IsRelayed {
  1307. fields := append(logFields, "from", via)
  1308. // Reply from the socket the handshake arrived on so the initiator sees
  1309. // the source port it targeted. Identical to f.outside under vanilla
  1310. // config (all writers share one port); required for multiport lanes.
  1311. err := f.writers[via.SockIdx].WriteTo(msg, via.UdpAddr)
  1312. if err != nil {
  1313. f.l.Error("Failed to send handshake message", append(fields, "error", err)...)
  1314. } else {
  1315. f.l.Info("Handshake message sent", fields...)
  1316. }
  1317. } else {
  1318. if via.relay == nil {
  1319. f.l.Error("Handshake send failed: both addr and via.relay are nil.")
  1320. return
  1321. }
  1322. hostinfo.relayState.InsertRelayTo(via.relayHI.vpnAddrs[0])
  1323. // We received a valid handshake on this relay, so make sure the relay
  1324. // state reflects that, in case it had been marked Disestablished.
  1325. via.relayHI.relayState.UpdateRelayForByIdxState(via.relay.LocalIndex, Established)
  1326. f.SendVia(via.relayHI, via.relay, msg, make([]byte, 12), make([]byte, mtu), false)
  1327. f.l.Info("Handshake message sent", append(logFields, "relay", via.relayHI.vpnAddrs[0])...)
  1328. }
  1329. }
  1330. // handleCheckAndCompleteError handles errors from CheckAndComplete.
  1331. // This only fires from the responder-side beginHandshake path, after the
  1332. // peer cert has been validated and ConnectionState populated, so peerCert
  1333. // is always non-nil for the cases that log it.
  1334. func (hm *HandshakeManager) handleCheckAndCompleteError(err error, existing, hostinfo *HostInfo, via ViaSender) {
  1335. f := hm.f
  1336. peerCert := hostinfo.ConnectionState.peerCert
  1337. hsFields := m{"stage": uint64(1), "style": header.SubTypeName(header.Handshake, header.HandshakeIXPSK0)}
  1338. switch err {
  1339. case ErrAlreadySeen:
  1340. if existing.SetRemoteIfPreferred(f.hostMap, via) {
  1341. f.SendMessageToVpnAddr(header.Test, header.TestRequest, hostinfo.vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  1342. }
  1343. // Resend the original response. The peer is committed to that response's
  1344. // ephemeral keys; a freshly-built one would have different keys and break
  1345. // the tunnel even though both sides "completed" the handshake.
  1346. if msg := existing.HandshakePacket[handshakePacketStage2]; msg != nil {
  1347. hm.sendHandshakeResponse(via, msg, existing, true)
  1348. }
  1349. case ErrExistingHostInfo:
  1350. f.l.Info("Handshake too old",
  1351. "vpnAddrs", hostinfo.vpnAddrs,
  1352. "from", via,
  1353. "certName", peerCert.Certificate.Name(),
  1354. "certVersion", peerCert.Certificate.Version(),
  1355. "fingerprint", peerCert.Fingerprint,
  1356. "issuer", peerCert.Certificate.Issuer(),
  1357. "oldHandshakeTime", existing.lastHandshakeTime,
  1358. "newHandshakeTime", hostinfo.lastHandshakeTime,
  1359. "initiatorIndex", hostinfo.remoteIndexId,
  1360. "responderIndex", hostinfo.localIndexId,
  1361. "handshake", hsFields,
  1362. )
  1363. f.SendMessageToVpnAddr(header.Test, header.TestRequest, hostinfo.vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  1364. case ErrLocalIndexCollision:
  1365. f.l.Error("Failed to add HostInfo due to localIndex collision",
  1366. "vpnAddrs", hostinfo.vpnAddrs,
  1367. "from", via,
  1368. "certName", peerCert.Certificate.Name(),
  1369. "certVersion", peerCert.Certificate.Version(),
  1370. "fingerprint", peerCert.Fingerprint,
  1371. "issuer", peerCert.Certificate.Issuer(),
  1372. "localIndex", hostinfo.localIndexId,
  1373. "initiatorIndex", hostinfo.remoteIndexId,
  1374. "responderIndex", hostinfo.localIndexId,
  1375. "handshake", hsFields,
  1376. )
  1377. default:
  1378. f.l.Error("Failed to add HostInfo to HostMap",
  1379. "vpnAddrs", hostinfo.vpnAddrs,
  1380. "from", via,
  1381. "error", err,
  1382. "certName", peerCert.Certificate.Name(),
  1383. "certVersion", peerCert.Certificate.Version(),
  1384. "fingerprint", peerCert.Fingerprint,
  1385. "issuer", peerCert.Certificate.Issuer(),
  1386. "initiatorIndex", hostinfo.remoteIndexId,
  1387. "responderIndex", hostinfo.localIndexId,
  1388. "handshake", hsFields,
  1389. )
  1390. }
  1391. }
  1392. // certVerifier returns a CertVerifier that validates certs against the current CA pool.
  1393. func (hm *HandshakeManager) certVerifier() handshake.CertVerifier {
  1394. return func(c cert.Certificate) (*cert.CachedCertificate, error) {
  1395. return hm.f.pki.GetCAPool().VerifyCertificate(time.Now(), c)
  1396. }
  1397. }