hostmap.go 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  1. package nebula
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "hash/fnv"
  8. "log/slog"
  9. "net"
  10. "net/netip"
  11. "slices"
  12. "sync"
  13. "sync/atomic"
  14. "time"
  15. "github.com/gaissmai/bart"
  16. "github.com/rcrowley/go-metrics"
  17. "github.com/slackhq/nebula/cert"
  18. "github.com/slackhq/nebula/config"
  19. "github.com/slackhq/nebula/header"
  20. "github.com/slackhq/nebula/logging"
  21. )
  22. const defaultPromoteEvery = 1000 // Count of packets sent before we try moving a tunnel to a preferred underlay ip address
  23. const defaultReQueryEvery = 5000 // Count of packets sent before re-querying a hostinfo to the lighthouse
  24. const defaultReQueryWait = time.Minute // Minimum amount of seconds to wait before re-querying a hostinfo the lighthouse. Evaluated every ReQueryEvery
  25. const MaxRemotes = 10
  26. // MaxHostInfosPerVpnIp is the max number of hostinfos we will track for a given vpn ip
  27. // 5 allows for an initial handshake and each host pair re-handshaking twice
  28. const MaxHostInfosPerVpnIp = 5
  29. // How long we should prevent roaming back to the previous IP.
  30. // This helps prevent flapping due to packets already in flight
  31. const RoamingSuppressSeconds = 2
  32. const (
  33. Requested = iota
  34. PeerRequested
  35. Established
  36. Disestablished
  37. )
  38. const (
  39. Unknowntype = iota
  40. ForwardingType
  41. TerminalType
  42. )
  43. type Relay struct {
  44. Type int
  45. State int
  46. LocalIndex uint32
  47. RemoteIndex uint32
  48. PeerAddr netip.Addr
  49. }
  50. type HostMap struct {
  51. sync.RWMutex //Because we concurrently read and write to our maps
  52. Indexes map[uint32]*HostInfo
  53. Relays map[uint32]*HostInfo // Maps a Relay IDX to a Relay HostInfo object
  54. RemoteIndexes map[uint32]*HostInfo
  55. // Hosts maps a vpn address to its primary hostinfo, one entry per address we hold a tunnel
  56. // for. moreHosts only has an entry while an address is held by 2 or more hostinfos and stores
  57. // the full most-recent-first list; moreHosts[a][0] is always the same hostinfo as Hosts[a].
  58. // Each address gets its own independent list, so a hostinfo owning multiple addresses can
  59. // never corrupt another address's ordering the way the old shared next/prev chain could.
  60. // Entries in moreHosts are only ever written by unlockedSetHostsForAddr; Hosts is written
  61. // directly only in the single-hostinfo fast paths where moreHosts is known to have no entry,
  62. // and unlockedDeleteHostInfo swaps either map for a fresh one when it fully drains.
  63. Hosts map[netip.Addr]*HostInfo
  64. moreHosts map[netip.Addr][]*HostInfo
  65. preferredRanges atomic.Pointer[[]netip.Prefix]
  66. l *slog.Logger
  67. }
  68. // For synchronization, treat the pointed-to Relay struct as immutable. To edit the Relay
  69. // struct, make a copy of an existing value, edit the fileds in the copy, and
  70. // then store a pointer to the new copy in both realyForBy* maps.
  71. type RelayState struct {
  72. sync.RWMutex
  73. relays []netip.Addr // Ordered set of VpnAddrs of Hosts to use as relays to access this peer
  74. // For data race avoidance, the contents of a *Relay are treated immutably. To update a *Relay, copy the existing data,
  75. // modify what needs to be updated, and store the new modified copy in the relayForByIp and relayForByIdx maps (with
  76. // the RelayState Lock held)
  77. relayForByAddr map[netip.Addr]*Relay // Maps vpnAddr of peers for which this HostInfo is a relay to some Relay info
  78. relayForByIdx map[uint32]*Relay // Maps a local index to some Relay info
  79. }
  80. func (rs *RelayState) DeleteRelay(ip netip.Addr) {
  81. rs.Lock()
  82. defer rs.Unlock()
  83. for idx, val := range rs.relays {
  84. if val == ip {
  85. rs.relays = append(rs.relays[:idx], rs.relays[idx+1:]...)
  86. return
  87. }
  88. }
  89. }
  90. func (rs *RelayState) UpdateRelayForByIpState(vpnIp netip.Addr, state int) {
  91. rs.Lock()
  92. defer rs.Unlock()
  93. if r, ok := rs.relayForByAddr[vpnIp]; ok {
  94. newRelay := *r
  95. newRelay.State = state
  96. rs.relayForByAddr[newRelay.PeerAddr] = &newRelay
  97. rs.relayForByIdx[newRelay.LocalIndex] = &newRelay
  98. }
  99. }
  100. func (rs *RelayState) UpdateRelayForByIdxState(idx uint32, state int) {
  101. rs.Lock()
  102. defer rs.Unlock()
  103. if r, ok := rs.relayForByIdx[idx]; ok {
  104. newRelay := *r
  105. newRelay.State = state
  106. rs.relayForByAddr[newRelay.PeerAddr] = &newRelay
  107. rs.relayForByIdx[newRelay.LocalIndex] = &newRelay
  108. }
  109. }
  110. func (rs *RelayState) CopyAllRelayFor() []*Relay {
  111. rs.RLock()
  112. defer rs.RUnlock()
  113. ret := make([]*Relay, 0, len(rs.relayForByIdx))
  114. for _, r := range rs.relayForByIdx {
  115. ret = append(ret, r)
  116. }
  117. return ret
  118. }
  119. func (rs *RelayState) GetRelayForByAddr(addr netip.Addr) (*Relay, bool) {
  120. rs.RLock()
  121. defer rs.RUnlock()
  122. r, ok := rs.relayForByAddr[addr]
  123. return r, ok
  124. }
  125. func (rs *RelayState) InsertRelayTo(ip netip.Addr) {
  126. rs.Lock()
  127. defer rs.Unlock()
  128. if !slices.Contains(rs.relays, ip) {
  129. rs.relays = append(rs.relays, ip)
  130. }
  131. }
  132. func (rs *RelayState) CopyRelayIps() []netip.Addr {
  133. rs.RLock()
  134. defer rs.RUnlock()
  135. ret := make([]netip.Addr, len(rs.relays))
  136. copy(ret, rs.relays)
  137. return ret
  138. }
  139. func (rs *RelayState) CopyRelayForIps() []netip.Addr {
  140. rs.RLock()
  141. defer rs.RUnlock()
  142. currentRelays := make([]netip.Addr, 0, len(rs.relayForByAddr))
  143. for relayIp := range rs.relayForByAddr {
  144. currentRelays = append(currentRelays, relayIp)
  145. }
  146. return currentRelays
  147. }
  148. func (rs *RelayState) CopyRelayForIdxs() []uint32 {
  149. rs.RLock()
  150. defer rs.RUnlock()
  151. ret := make([]uint32, 0, len(rs.relayForByIdx))
  152. for i := range rs.relayForByIdx {
  153. ret = append(ret, i)
  154. }
  155. return ret
  156. }
  157. func (rs *RelayState) CompleteRelayByIP(vpnIp netip.Addr, remoteIdx uint32) bool {
  158. rs.Lock()
  159. defer rs.Unlock()
  160. r, ok := rs.relayForByAddr[vpnIp]
  161. if !ok {
  162. return false
  163. }
  164. newRelay := *r
  165. newRelay.State = Established
  166. newRelay.RemoteIndex = remoteIdx
  167. rs.relayForByIdx[r.LocalIndex] = &newRelay
  168. rs.relayForByAddr[r.PeerAddr] = &newRelay
  169. return true
  170. }
  171. func (rs *RelayState) CompleteRelayByIdx(localIdx uint32, remoteIdx uint32) (*Relay, bool) {
  172. rs.Lock()
  173. defer rs.Unlock()
  174. r, ok := rs.relayForByIdx[localIdx]
  175. if !ok {
  176. return nil, false
  177. }
  178. newRelay := *r
  179. newRelay.State = Established
  180. newRelay.RemoteIndex = remoteIdx
  181. rs.relayForByIdx[r.LocalIndex] = &newRelay
  182. rs.relayForByAddr[r.PeerAddr] = &newRelay
  183. return &newRelay, true
  184. }
  185. func (rs *RelayState) QueryRelayForByIp(vpnIp netip.Addr) (*Relay, bool) {
  186. rs.RLock()
  187. defer rs.RUnlock()
  188. r, ok := rs.relayForByAddr[vpnIp]
  189. return r, ok
  190. }
  191. func (rs *RelayState) QueryRelayForByIdx(idx uint32) (*Relay, bool) {
  192. rs.RLock()
  193. defer rs.RUnlock()
  194. r, ok := rs.relayForByIdx[idx]
  195. return r, ok
  196. }
  197. func (rs *RelayState) InsertRelay(ip netip.Addr, idx uint32, r *Relay) {
  198. rs.Lock()
  199. defer rs.Unlock()
  200. rs.relayForByAddr[ip] = r
  201. rs.relayForByIdx[idx] = r
  202. }
  203. type NetworkType uint8
  204. const (
  205. NetworkTypeUnknown NetworkType = iota
  206. // NetworkTypeVPN is a network that overlaps one or more of the vpnNetworks in our certificate
  207. NetworkTypeVPN
  208. // NetworkTypeVPNPeer is a network that does not overlap one of our networks
  209. NetworkTypeVPNPeer
  210. // NetworkTypeUnsafe is a network from Certificate.UnsafeNetworks()
  211. NetworkTypeUnsafe
  212. )
  213. type HostInfo struct {
  214. remote atomic.Pointer[netip.AddrPort]
  215. ConnectionState *ConnectionState
  216. // Traffic bits, pendingDeletion, and the rebind epoch we last sent under
  217. state atomic.Uint32
  218. promoteCounter atomic.Uint32
  219. remoteIndexId uint32
  220. localIndexId uint32
  221. remotes *RemoteList
  222. // vpnAddrs is a list of vpn addresses assigned to this host that are within our own vpn networks
  223. // The host may have other vpn addresses that are outside our
  224. // vpn networks but were removed because they are not usable
  225. vpnAddrs []netip.Addr
  226. // networks is a combination of specific vpn addresses (not prefixes!) and full unsafe networks assigned to this host.
  227. networks *bart.Table[NetworkType]
  228. relayState RelayState
  229. // HandshakePacket records the packets used to create this hostinfo
  230. // We need these to avoid replayed handshake packets creating new hostinfos which causes churn
  231. HandshakePacket map[uint8][]byte
  232. // nextLHQuery is the earliest we can ask the lighthouse for new information.
  233. // This is used to limit lighthouse re-queries in chatty clients
  234. nextLHQuery atomic.Int64
  235. // lastHandshakeTime records the time the remote side told us about at the stage when the handshake was completed locally
  236. // Stage 1 packet will contain it if I am a responder, stage 2 packet if I am an initiator
  237. // This is used to avoid an attack where a handshake packet is replayed after some time
  238. lastHandshakeTime uint64
  239. lastRoam time.Time
  240. lastRoamRemote netip.AddrPort
  241. // lastUsed tracks the last time ConnectionManager checked the tunnel and it was in use.
  242. // This value will be behind against actual tunnel utilization in the hot path.
  243. // This should only be used by the ConnectionManagers ticker routine.
  244. lastUsed time.Time
  245. // sockIdx is the index into Interface.writers of the socket every packet
  246. // on this tunnel egresses from (and, for lanes, arrives on). 0 for base
  247. // and vanilla tunnels — the zero value preserves stock behavior.
  248. sockIdx int
  249. // laneIndex is the owner's lane number for a lane tunnel; 0 for base.
  250. laneIndex uint16
  251. // laneOwned is true when we initiated this lane (it carries our TX data).
  252. laneOwned bool
  253. // parent points at the base tunnel a lane hangs off of; nil for base and
  254. // vanilla tunnels. Set before the lane is registered in hostmap.Indexes.
  255. parent *HostInfo
  256. // lanes is allocated on a base tunnel when multiport is enabled and the
  257. // peer advertised lane support; nil otherwise.
  258. lanes *laneState
  259. }
  260. // isLane reports whether this HostInfo is a lane tunnel rather than a base
  261. // (or vanilla) tunnel.
  262. func (i *HostInfo) isLane() bool {
  263. return i.parent != nil
  264. }
  265. // laneState hangs off a base HostInfo and tracks the multiport lane tunnels
  266. // associated with it. txLanes is read lock-free on the TX hot path; the Mutex
  267. // guards everything else.
  268. type laneState struct {
  269. sync.Mutex
  270. // peerPortCount/peerBasePort are the peer's advert from the base
  271. // handshake; portOffset is the per-pair rotation from lanePortOffset.
  272. // Lane i targets peerBasePort + ((i + portOffset) % peerPortCount).
  273. peerPortCount uint16
  274. peerBasePort uint16
  275. portOffset uint16
  276. // txLanes[i] is our established, initiator-owned lane for routine i, or
  277. // nil. Index 0 is always nil — the base tunnel is lane 0. A pointer is
  278. // only Stored once the lane's ConnectionState is fully populated, so a
  279. // data-plane routine that Loads non-nil always sees a usable tunnel.
  280. txLanes []atomic.Pointer[HostInfo]
  281. // txDemand[i] is set by the data plane when a routine riding slot i has
  282. // traffic for this peer and no established lane, and consumed when
  283. // EnsureLanes claims the slot. Lanes exist only where traffic asked for
  284. // one: a peer we exchange a trickle with never costs more than the base
  285. // tunnel, no matter how many routines are configured. Written without
  286. // the Mutex.
  287. txDemand []atomic.Bool
  288. // Under Mutex: per-slot handshake-in-flight flag, consecutive failure
  289. // count, and earliest next attempt, driving ensureLanes' backoff.
  290. txPending []bool
  291. txFails []uint8
  292. txRetryAt []time.Time
  293. // Under Mutex: responder-side records of peer-owned lanes, capped by
  294. // same-laneIndex replacement.
  295. peerLanes []*HostInfo
  296. }
  297. func newLaneState(laneCount int, peerPortCount, peerBasePort, portOffset uint16) *laneState {
  298. return &laneState{
  299. peerPortCount: peerPortCount,
  300. peerBasePort: peerBasePort,
  301. portOffset: portOffset,
  302. txLanes: make([]atomic.Pointer[HostInfo], laneCount),
  303. txDemand: make([]atomic.Bool, laneCount),
  304. txPending: make([]bool, laneCount),
  305. txFails: make([]uint8, laneCount),
  306. txRetryAt: make([]time.Time, laneCount),
  307. }
  308. }
  309. // noteLaneDemand records that a data-plane routine has traffic for lane slot
  310. // i but found the slot empty. Called from the TX hot path on every packet
  311. // that misses, so the store is load-guarded: once the flag is up, further
  312. // misses are plain reads and cannot ping-pong a cache line shared with the
  313. // neighbouring slots' flags. Slot 0 is the base tunnel and never a lane.
  314. func (ls *laneState) noteLaneDemand(i int) {
  315. if i <= 0 || i >= len(ls.txDemand) {
  316. return
  317. }
  318. if !ls.txDemand[i].Load() {
  319. ls.txDemand[i].Store(true)
  320. }
  321. }
  322. // takeLaneDemand consumes slot i's demand flag, reporting whether the data
  323. // plane had asked for the lane since the last time we looked.
  324. func (ls *laneState) takeLaneDemand(i int) bool {
  325. if i <= 0 || i >= len(ls.txDemand) {
  326. return false
  327. }
  328. return ls.txDemand[i].Swap(false)
  329. }
  330. // laneTargetPort returns the peer port that owned lane i handshakes to and
  331. // egresses toward. The caller must ensure peerPortCount != 0.
  332. func (ls *laneState) laneTargetPort(i int) uint16 {
  333. return ls.peerBasePort + uint16((i+int(ls.portOffset))%int(ls.peerPortCount))
  334. }
  335. // lanePortOffset returns the rotation applied to this pair's lane target
  336. // ports, in [0, peerPortCount). Without it every low-routine peer would aim
  337. // its few lanes at a big peer's first few ports, concentrating the big
  338. // peer's receive work on a couple of sockets; the hash spreads pairs across
  339. // the whole advertised range.
  340. //
  341. // Both sides hash the same sorted vpn-address pair and the higher address
  342. // negates the result, so when port counts match the two sides' rotations
  343. // cancel: our lane i's 4-tuple is still the reverse of a peer-owned lane's,
  344. // and each outbound lane handshake opens the conntrack entry its partner
  345. // arrives through. (The one lane a nonzero rotation lands on the peer's base
  346. // port has no partner lane; behind a port-restricted NAT it may not form and
  347. // its routine rides the base tunnel — the standard lane fallback.)
  348. func lanePortOffset(myAddr, peerAddr netip.Addr, peerPortCount uint16) uint16 {
  349. if peerPortCount == 0 {
  350. return 0
  351. }
  352. lo, hi := myAddr, peerAddr
  353. if hi.Less(lo) {
  354. lo, hi = hi, lo
  355. }
  356. h := fnv.New32a()
  357. b := lo.As16()
  358. h.Write(b[:])
  359. b = hi.As16()
  360. h.Write(b[:])
  361. o := uint16(h.Sum32() % uint32(peerPortCount))
  362. if myAddr == hi {
  363. o = (peerPortCount - o) % peerPortCount
  364. }
  365. return o
  366. }
  367. const (
  368. laneRetryBase = 5 * time.Second
  369. laneRetryMax = 60 * time.Second
  370. )
  371. // noteLaneFailure marks lane slot i as empty and pushes the next attempt out
  372. // with exponential backoff. Called when an owned lane dies or its handshake
  373. // times out.
  374. func (ls *laneState) noteLaneFailure(i int) {
  375. if i < 0 || i >= len(ls.txPending) {
  376. return
  377. }
  378. ls.Lock()
  379. ls.txPending[i] = false
  380. if ls.txFails[i] < 200 { // just avoid wrapping; the delay caps far earlier
  381. ls.txFails[i]++
  382. }
  383. d := laneRetryBase << min(ls.txFails[i], 4)
  384. if d > laneRetryMax {
  385. d = laneRetryMax
  386. }
  387. ls.txRetryAt[i] = time.Now().Add(d)
  388. ls.Unlock()
  389. }
  390. // noteOwnedLaneDeath detaches an established owned lane from its slot
  391. // (identity-checked, so a raced re-establishment is never clobbered) and
  392. // applies failure backoff.
  393. func (ls *laneState) noteOwnedLaneDeath(lane *HostInfo) {
  394. i := int(lane.laneIndex)
  395. if i >= len(ls.txLanes) {
  396. return
  397. }
  398. ls.txLanes[i].CompareAndSwap(lane, nil)
  399. ls.noteLaneFailure(i)
  400. }
  401. // removePeerLane drops a responder-side lane record by identity.
  402. func (ls *laneState) removePeerLane(lane *HostInfo) {
  403. ls.Lock()
  404. for n, h := range ls.peerLanes {
  405. if h == lane {
  406. ls.peerLanes = append(ls.peerLanes[:n], ls.peerLanes[n+1:]...)
  407. break
  408. }
  409. }
  410. ls.Unlock()
  411. }
  412. // snapshotLanes returns every lane hostinfo currently attached, used by the
  413. // base-delete cascade. Taken under the lock and returned as a copy so the
  414. // caller can delete without holding it.
  415. func (ls *laneState) snapshotLanes() []*HostInfo {
  416. ls.Lock()
  417. defer ls.Unlock()
  418. out := make([]*HostInfo, 0, len(ls.txLanes)+len(ls.peerLanes))
  419. for n := range ls.txLanes {
  420. if h := ls.txLanes[n].Load(); h != nil {
  421. out = append(out, h)
  422. }
  423. }
  424. out = append(out, ls.peerLanes...)
  425. return out
  426. }
  427. type ViaSender struct {
  428. UdpAddr netip.AddrPort
  429. relayHI *HostInfo // relayHI is the host info object of the relay
  430. relay *Relay // relay contains the rest of the relay information, including the PeerIP of the host trying to communicate with us.
  431. IsRelayed bool // IsRelayed is true if the packet was sent through a relay
  432. // SockIdx is the local socket (Interface.writers index) the packet
  433. // arrived on. Replies that must originate from the same 4-tuple egress
  434. // f.writers[SockIdx].
  435. SockIdx int
  436. }
  437. func (v ViaSender) String() string {
  438. if v.IsRelayed {
  439. return fmt.Sprintf("%s (relayed)", v.UdpAddr)
  440. }
  441. return v.UdpAddr.String()
  442. }
  443. func (v ViaSender) MarshalJSON() ([]byte, error) {
  444. if v.IsRelayed {
  445. return json.Marshal(m{"relay": v.UdpAddr})
  446. }
  447. return json.Marshal(m{"direct": v.UdpAddr})
  448. }
  449. type cachedPacket struct {
  450. messageType header.MessageType
  451. messageSubType header.MessageSubType
  452. callback packetCallback
  453. packet []byte
  454. }
  455. type packetCallback func(t header.MessageType, st header.MessageSubType, h *HostInfo, p, nb, out []byte)
  456. type cachedPacketMetrics struct {
  457. sent metrics.Counter
  458. dropped metrics.Counter
  459. }
  460. func NewHostMapFromConfig(l *slog.Logger, c *config.C) *HostMap {
  461. hm := newHostMap(l)
  462. hm.reload(c, true)
  463. c.RegisterReloadCallback(func(c *config.C) {
  464. hm.reload(c, false)
  465. })
  466. l.Info("Main HostMap created", "preferredRanges", hm.GetPreferredRanges())
  467. return hm
  468. }
  469. func newHostMap(l *slog.Logger) *HostMap {
  470. return &HostMap{
  471. Indexes: map[uint32]*HostInfo{},
  472. Relays: map[uint32]*HostInfo{},
  473. RemoteIndexes: map[uint32]*HostInfo{},
  474. Hosts: map[netip.Addr]*HostInfo{},
  475. moreHosts: map[netip.Addr][]*HostInfo{},
  476. l: l,
  477. }
  478. }
  479. func (hm *HostMap) reload(c *config.C, initial bool) {
  480. if initial || c.HasChanged("preferred_ranges") {
  481. var preferredRanges []netip.Prefix
  482. rawPreferredRanges := c.GetStringSlice("preferred_ranges", []string{})
  483. for _, rawPreferredRange := range rawPreferredRanges {
  484. preferredRange, err := netip.ParsePrefix(rawPreferredRange)
  485. if err != nil {
  486. hm.l.Warn("Failed to parse preferred ranges, ignoring",
  487. "error", err,
  488. "range", rawPreferredRanges,
  489. )
  490. continue
  491. }
  492. preferredRanges = append(preferredRanges, preferredRange)
  493. }
  494. oldRanges := hm.preferredRanges.Swap(&preferredRanges)
  495. if !initial {
  496. hm.l.Info("preferred_ranges changed",
  497. "oldPreferredRanges", *oldRanges,
  498. "newPreferredRanges", preferredRanges,
  499. )
  500. }
  501. }
  502. }
  503. // EmitStats reports host, index, and relay counts to the stats collection system
  504. func (hm *HostMap) EmitStats() {
  505. hm.RLock()
  506. hostLen := len(hm.Hosts)
  507. indexLen := len(hm.Indexes)
  508. remoteIndexLen := len(hm.RemoteIndexes)
  509. relaysLen := len(hm.Relays)
  510. hm.RUnlock()
  511. metrics.GetOrRegisterGauge("hostmap.main.hosts", nil).Update(int64(hostLen))
  512. metrics.GetOrRegisterGauge("hostmap.main.indexes", nil).Update(int64(indexLen))
  513. metrics.GetOrRegisterGauge("hostmap.main.remoteIndexes", nil).Update(int64(remoteIndexLen))
  514. metrics.GetOrRegisterGauge("hostmap.main.relayIndexes", nil).Update(int64(relaysLen))
  515. }
  516. // unlockedSetHostsForAddr stores the per-address hostinfo list (list[0] is the primary). An empty
  517. // list removes the address. This is the one place Hosts and moreHosts are written together, keep
  518. // it that way. Callers must hold the write lock.
  519. func (hm *HostMap) unlockedSetHostsForAddr(addr netip.Addr, list []*HostInfo) {
  520. if len(list) == 0 {
  521. delete(hm.Hosts, addr)
  522. delete(hm.moreHosts, addr)
  523. return
  524. }
  525. hm.Hosts[addr] = list[0]
  526. if len(list) > 1 {
  527. hm.moreHosts[addr] = list
  528. } else {
  529. delete(hm.moreHosts, addr)
  530. }
  531. }
  532. // unlockedGetHostList returns every hostinfo holding addr, primary first, or nil if we have no
  533. // tunnel for addr. The common single-hostinfo case builds a fresh one element list, so keep this
  534. // off the packet hot path; the primary is a direct Hosts read. Callers must hold the lock (read
  535. // or write).
  536. func (hm *HostMap) unlockedGetHostList(addr netip.Addr) []*HostInfo {
  537. if list, ok := hm.moreHosts[addr]; ok {
  538. return list
  539. }
  540. if h, ok := hm.Hosts[addr]; ok {
  541. return []*HostInfo{h}
  542. }
  543. return nil
  544. }
  545. // removeHostInfo returns list with hi removed (order preserved), or list unchanged if hi is
  546. // absent. It deletes in place: every mutator holds the hostmap write lock and no reader ever
  547. // retains a slice across a mutation (readers iterate under RLock), so there is no snapshot to
  548. // invalidate.
  549. func removeHostInfo(list []*HostInfo, hi *HostInfo) []*HostInfo {
  550. idx := slices.Index(list, hi)
  551. if idx < 0 {
  552. return list
  553. }
  554. return slices.Delete(list, idx, idx+1)
  555. }
  556. // DeleteHostInfo will fully unlink the hostinfo and return true if no other hostinfo still holds
  557. // any of its vpn addrs, meaning we no longer have a tunnel to the peer
  558. func (hm *HostMap) DeleteHostInfo(hostinfo *HostInfo) bool {
  559. // Delete the host itself, ensuring it's not modified anymore
  560. hm.Lock()
  561. final := hm.unlockedDeleteHostInfo(hostinfo)
  562. hm.Unlock()
  563. return final
  564. }
  565. func (hm *HostMap) MakePrimary(hostinfo *HostInfo) {
  566. hm.Lock()
  567. defer hm.Unlock()
  568. hm.unlockedMakePrimary(hostinfo)
  569. }
  570. // unlockedMakePrimary reports whether hostinfo is (now) the primary for each of its addresses,
  571. // false only when it is no longer in the hostmap at all.
  572. func (hm *HostMap) unlockedMakePrimary(hostinfo *HostInfo) bool {
  573. // A lane must never become a Hosts primary: it would start carrying all
  574. // traffic for the peer and become a relay candidate.
  575. if hostinfo.isLane() {
  576. return false
  577. }
  578. // A hostinfo that is no longer in the hostmap must not be re-inserted here. Callers can race
  579. // tunnel teardown, deciding to promote under the read lock and only taking the write lock
  580. // after a delete fully unlinked the hostinfo (connection manager swapPrimary, AddRelay). Every
  581. // live hostinfo is registered in Indexes by unlockedAddHostInfo, so this is a membership test.
  582. if hm.Indexes[hostinfo.localIndexId] != hostinfo {
  583. return false
  584. }
  585. // Move hostinfo to the front (primary) of each of its address lists. The lists are
  586. // independent per address, so this can never leave a dangling entry the way promoting
  587. // against a single shared chain could.
  588. for _, addr := range hostinfo.vpnAddrs {
  589. if hm.Hosts[addr] == hostinfo {
  590. // Already primary for this address, the list is already in the right order
  591. continue
  592. }
  593. list := removeHostInfo(hm.unlockedGetHostList(addr), hostinfo)
  594. list = append([]*HostInfo{hostinfo}, list...)
  595. hm.unlockedSetHostsForAddr(addr, list)
  596. }
  597. return true
  598. }
  599. // unlockedDeleteHostInfo removes hostinfo from every one of its address lists and from the index
  600. // maps. It returns true if this was the last hostinfo for all of its addresses (we no longer have
  601. // any tunnel to the peer), which the caller uses to decide whether to clear learned lighthouse
  602. // state and disestablish relays.
  603. func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo) bool {
  604. if hostinfo.isLane() {
  605. return hm.unlockedDeleteLane(hostinfo)
  606. }
  607. // A dying base takes its lanes with it. The peer converges symmetrically
  608. // when it processes the base's CloseTunnel, so lanes need no signaling of
  609. // their own. Depth-1 recursion: lanes have no children.
  610. if hostinfo.lanes != nil {
  611. for _, lane := range hostinfo.lanes.snapshotLanes() {
  612. hm.unlockedDeleteLane(lane)
  613. }
  614. }
  615. // Remove this hostinfo from each of its address lists. The lists are independent, so a
  616. // sibling is never promoted to an address it does not own and no other list is touched.
  617. final := true
  618. for _, addr := range hostinfo.vpnAddrs {
  619. if list, ok := hm.moreHosts[addr]; ok {
  620. list = removeHostInfo(list, hostinfo)
  621. hm.unlockedSetHostsForAddr(addr, list)
  622. if len(list) > 0 {
  623. final = false
  624. }
  625. } else if existing, ok := hm.Hosts[addr]; ok {
  626. if existing == hostinfo {
  627. // Common case, the only hostinfo for this address. moreHosts has no entry to clean up.
  628. delete(hm.Hosts, addr)
  629. } else {
  630. // We don't hold this address but another hostinfo does, we still have a tunnel to the peer
  631. final = false
  632. }
  633. }
  634. }
  635. // Go maps never shrink their buckets, replace fully drained maps so a node that churned
  636. // through a large peer count gives the memory back. Same idiom as the index maps below.
  637. if len(hm.Hosts) == 0 {
  638. hm.Hosts = map[netip.Addr]*HostInfo{}
  639. }
  640. if len(hm.moreHosts) == 0 {
  641. hm.moreHosts = map[netip.Addr][]*HostInfo{}
  642. }
  643. // The remote index uses index ids outside our control so lets make sure we are only removing
  644. // the remote index pointer here if it points to the hostinfo we are deleting
  645. hostinfo2, ok := hm.RemoteIndexes[hostinfo.remoteIndexId]
  646. if ok && hostinfo2 == hostinfo {
  647. delete(hm.RemoteIndexes, hostinfo.remoteIndexId)
  648. if len(hm.RemoteIndexes) == 0 {
  649. hm.RemoteIndexes = map[uint32]*HostInfo{}
  650. }
  651. }
  652. delete(hm.Indexes, hostinfo.localIndexId)
  653. if len(hm.Indexes) == 0 {
  654. hm.Indexes = map[uint32]*HostInfo{}
  655. }
  656. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  657. hm.l.Debug("Hostmap hostInfo deleted",
  658. "hostMap", m{"mapTotalSize": len(hm.Hosts),
  659. "vpnAddrs": hostinfo.vpnAddrs, "indexNumber": hostinfo.localIndexId, "remoteIndexNumber": hostinfo.remoteIndexId},
  660. )
  661. }
  662. if final {
  663. // I have lost connectivity to my peers. My relay tunnel is likely broken. Mark the next
  664. // hops as 'Requested' so that new relay tunnels are created in the future.
  665. hm.unlockedDisestablishVpnAddrRelayFor(hostinfo)
  666. }
  667. // Clean up any local relay indexes for which I am acting as a relay hop
  668. for _, localRelayIdx := range hostinfo.relayState.CopyRelayForIdxs() {
  669. delete(hm.Relays, localRelayIdx)
  670. }
  671. return final
  672. }
  673. func (hm *HostMap) QueryIndexCached(index uint32, cache map[uint32]*HostInfo) *HostInfo {
  674. if out, ok := cache[index]; ok {
  675. return out
  676. }
  677. out := hm.QueryIndex(index)
  678. if out != nil {
  679. cache[index] = out
  680. }
  681. return out
  682. }
  683. // unlockedDeleteLane removes a lane tunnel from the index maps and detaches it
  684. // from its base. Lanes never live in Hosts and their death never means "no
  685. // tunnel to the peer", so the return is always false (the lighthouse cache and
  686. // relays stay untouched). Idempotent: every step is identity-checked.
  687. func (hm *HostMap) unlockedDeleteLane(lane *HostInfo) bool {
  688. if ls := lane.parent.lanes; ls != nil {
  689. if lane.laneOwned {
  690. ls.noteOwnedLaneDeath(lane)
  691. } else {
  692. ls.removePeerLane(lane)
  693. }
  694. }
  695. if hostinfo2, ok := hm.RemoteIndexes[lane.remoteIndexId]; ok && hostinfo2 == lane {
  696. delete(hm.RemoteIndexes, lane.remoteIndexId)
  697. }
  698. if hostinfo2, ok := hm.Indexes[lane.localIndexId]; ok && hostinfo2 == lane {
  699. delete(hm.Indexes, lane.localIndexId)
  700. }
  701. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  702. hm.l.Debug("Hostmap lane deleted",
  703. "hostMap", m{"vpnAddrs": lane.vpnAddrs, "laneIndex": lane.laneIndex,
  704. "indexNumber": lane.localIndexId, "remoteIndexNumber": lane.remoteIndexId},
  705. )
  706. }
  707. return false
  708. }
  709. func (hm *HostMap) QueryIndex(index uint32) *HostInfo {
  710. hm.RLock()
  711. if h, ok := hm.Indexes[index]; ok {
  712. hm.RUnlock()
  713. return h
  714. } else {
  715. hm.RUnlock()
  716. return nil
  717. }
  718. }
  719. func (hm *HostMap) QueryRelayIndex(index uint32) *HostInfo {
  720. hm.RLock()
  721. if h, ok := hm.Relays[index]; ok {
  722. hm.RUnlock()
  723. return h
  724. } else {
  725. hm.RUnlock()
  726. return nil
  727. }
  728. }
  729. func (hm *HostMap) QueryReverseIndex(index uint32) *HostInfo {
  730. hm.RLock()
  731. if h, ok := hm.RemoteIndexes[index]; ok {
  732. hm.RUnlock()
  733. return h
  734. } else {
  735. hm.RUnlock()
  736. return nil
  737. }
  738. }
  739. func (hm *HostMap) QueryVpnAddr(vpnIp netip.Addr) *HostInfo {
  740. return hm.queryVpnAddr(vpnIp, nil)
  741. }
  742. func (hm *HostMap) QueryVpnAddrsRelayFor(targetIps []netip.Addr, relayHostIp netip.Addr) (*HostInfo, *Relay, error) {
  743. hm.RLock()
  744. defer hm.RUnlock()
  745. // This runs per relayed packet, so check the primary with a single map probe and only consult
  746. // moreHosts when the primary can't relay for us.
  747. h, ok := hm.Hosts[relayHostIp]
  748. if !ok {
  749. return nil, nil, errors.New("unable to find host")
  750. }
  751. for _, targetIp := range targetIps {
  752. r, ok := h.relayState.QueryRelayForByIp(targetIp)
  753. if ok && r.State == Established {
  754. return h, r, nil
  755. }
  756. }
  757. if list, ok := hm.moreHosts[relayHostIp]; ok {
  758. // list[0] is the primary we already checked
  759. for _, h := range list[1:] {
  760. for _, targetIp := range targetIps {
  761. r, ok := h.relayState.QueryRelayForByIp(targetIp)
  762. if ok && r.State == Established {
  763. return h, r, nil
  764. }
  765. }
  766. }
  767. }
  768. return nil, nil, errors.New("unable to find host with relay")
  769. }
  770. func (hm *HostMap) unlockedDisestablishVpnAddrRelayFor(hi *HostInfo) {
  771. for _, relayHostIp := range hi.relayState.CopyRelayIps() {
  772. for _, h := range hm.unlockedGetHostList(relayHostIp) {
  773. h.relayState.UpdateRelayForByIpState(hi.vpnAddrs[0], Disestablished)
  774. }
  775. }
  776. for _, rs := range hi.relayState.CopyAllRelayFor() {
  777. if rs.Type == ForwardingType {
  778. for _, h := range hm.unlockedGetHostList(rs.PeerAddr) {
  779. h.relayState.UpdateRelayForByIpState(hi.vpnAddrs[0], Disestablished)
  780. }
  781. }
  782. }
  783. }
  784. func (hm *HostMap) queryVpnAddr(vpnIp netip.Addr, promoteIfce *Interface) *HostInfo {
  785. hm.RLock()
  786. if h, ok := hm.Hosts[vpnIp]; ok {
  787. hm.RUnlock()
  788. // Do not attempt promotion if you are a lighthouse
  789. if promoteIfce != nil && !promoteIfce.lightHouse.amLighthouse {
  790. h.TryPromoteBest(hm.GetPreferredRanges(), promoteIfce)
  791. }
  792. return h
  793. }
  794. hm.RUnlock()
  795. return nil
  796. }
  797. // unlockedAddHostInfo assumes you have a write-lock and will add a hostinfo object to the hostmap Indexes and RemoteIndexes maps.
  798. // If an entry exists for the Hosts table (vpnIp -> hostinfo) then the provided hostinfo will be made primary
  799. func (hm *HostMap) unlockedAddHostInfo(hostinfo *HostInfo, f *Interface) {
  800. if f.dnsServer != nil {
  801. remoteCert := hostinfo.ConnectionState.peerCert
  802. f.dnsServer.Add(remoteCert.Certificate.Name()+".", hostinfo.vpnAddrs)
  803. }
  804. for _, addr := range hostinfo.vpnAddrs {
  805. hm.unlockedInnerAddHostInfo(addr, hostinfo, f)
  806. }
  807. hm.Indexes[hostinfo.localIndexId] = hostinfo
  808. hm.RemoteIndexes[hostinfo.remoteIndexId] = hostinfo
  809. hostinfo.markOut(f.rebindEpoch.Load())
  810. if f.connectionManager != nil { // f.connectionManager is only nil in some unit tests
  811. f.connectionManager.trafficTimer.Add(hostinfo.localIndexId, f.connectionManager.checkInterval)
  812. }
  813. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  814. hm.l.Debug("Hostmap vpnIp added",
  815. "hostMap", m{"vpnAddrs": hostinfo.vpnAddrs, "mapTotalSize": len(hm.Hosts),
  816. "hostinfo": m{"existing": true, "localIndexId": hostinfo.localIndexId, "vpnAddrs": hostinfo.vpnAddrs}},
  817. )
  818. }
  819. }
  820. // unlockedAddLane registers a lane tunnel in the index maps (RX demux and
  821. // recv_error need it there) without touching Hosts: lanes are never primary,
  822. // never dns-visible, and never subject to the MaxHostInfosPerVpnIp eviction.
  823. // The connection manager still tracks it for keepalive/death.
  824. func (hm *HostMap) unlockedAddLane(lane *HostInfo, f *Interface) {
  825. hm.Indexes[lane.localIndexId] = lane
  826. hm.RemoteIndexes[lane.remoteIndexId] = lane
  827. lane.markOutOnly()
  828. if f.connectionManager != nil { // f.connectionManager is only nil in some unit tests
  829. f.connectionManager.trafficTimer.Add(lane.localIndexId, f.connectionManager.checkInterval)
  830. }
  831. if hm.l.Enabled(context.Background(), slog.LevelDebug) {
  832. hm.l.Debug("Hostmap lane added",
  833. "hostMap", m{"vpnAddrs": lane.vpnAddrs, "laneIndex": lane.laneIndex,
  834. "indexNumber": lane.localIndexId, "remoteIndexNumber": lane.remoteIndexId},
  835. )
  836. }
  837. }
  838. func (hm *HostMap) unlockedInnerAddHostInfo(vpnAddr netip.Addr, hostinfo *HostInfo, f *Interface) {
  839. existing, ok := hm.Hosts[vpnAddr]
  840. if !ok {
  841. // Common case, the first hostinfo for this address. moreHosts stays empty.
  842. hm.Hosts[vpnAddr] = hostinfo
  843. return
  844. }
  845. // The new hostinfo becomes the primary for this address. Remove any stale copy of it first so
  846. // we never hold a duplicate, then prepend.
  847. list, ok := hm.moreHosts[vpnAddr]
  848. if !ok {
  849. list = []*HostInfo{existing}
  850. }
  851. list = removeHostInfo(list, hostinfo)
  852. list = append([]*HostInfo{hostinfo}, list...)
  853. hm.unlockedSetHostsForAddr(vpnAddr, list)
  854. // Enforce the per-address cap by fully retiring the oldest hostinfo once we exceed it.
  855. // Deleting it removes it from all of its addresses and the index maps, matching prior behavior.
  856. if len(list) > MaxHostInfosPerVpnIp {
  857. hm.unlockedDeleteHostInfo(list[len(list)-1])
  858. }
  859. }
  860. func (hm *HostMap) GetPreferredRanges() []netip.Prefix {
  861. //NOTE: if preferredRanges is ever not stored before a load this will fail to dereference a nil pointer
  862. return *hm.preferredRanges.Load()
  863. }
  864. func (hm *HostMap) ForEachVpnAddr(f controlEach) {
  865. hm.RLock()
  866. defer hm.RUnlock()
  867. for _, v := range hm.Hosts {
  868. f(v)
  869. }
  870. }
  871. func (hm *HostMap) ForEachIndex(f controlEach) {
  872. hm.RLock()
  873. defer hm.RUnlock()
  874. for _, v := range hm.Indexes {
  875. f(v)
  876. }
  877. }
  878. // TryPromoteBest handles re-querying lighthouses and probing for better paths
  879. // NOTE: It is an error to call this if you are a lighthouse since they should not roam clients!
  880. func (i *HostInfo) TryPromoteBest(preferredRanges []netip.Prefix, ifce *Interface) {
  881. c := i.promoteCounter.Add(1)
  882. if c%ifce.tryPromoteEvery.Load() == 0 {
  883. remote := i.GetRemote()
  884. // return early if we are already on a preferred remote
  885. if remote.IsValid() {
  886. rIP := remote.Addr()
  887. for _, l := range preferredRanges {
  888. if l.Contains(rIP) {
  889. return
  890. }
  891. }
  892. }
  893. i.remotes.ForEach(preferredRanges, func(addr netip.AddrPort, preferred bool) {
  894. if remote.IsValid() && (!addr.IsValid() || !preferred) {
  895. return
  896. }
  897. // Try to send a test packet to that host, this should
  898. // cause it to detect a roaming event and switch remotes
  899. ifce.sendTo(header.Test, header.TestRequest, i.ConnectionState, i, addr, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
  900. })
  901. }
  902. // Re query our lighthouses for new remotes occasionally
  903. if c%ifce.reQueryEvery.Load() == 0 && ifce.lightHouse != nil {
  904. now := time.Now().UnixNano()
  905. if now < i.nextLHQuery.Load() {
  906. return
  907. }
  908. i.nextLHQuery.Store(now + ifce.reQueryWait.Load())
  909. ifce.lightHouse.QueryServer(i.vpnAddrs[0])
  910. }
  911. }
  912. // Bits within HostInfo.state, everything above stateEpochShift is the epoch
  913. const (
  914. stateIn uint32 = 1 << iota
  915. stateOut
  916. statePendingDeletion
  917. stateFlags = stateIn | stateOut | statePendingDeletion
  918. // The epoch is the top 29 bits, it would take 2^29 rebinds to wrap and we will never get there
  919. stateEpochShift = 3
  920. )
  921. // markIn records inbound traffic
  922. func (i *HostInfo) markIn() {
  923. if i.state.Load()&stateIn == 0 {
  924. i.state.Or(stateIn)
  925. }
  926. }
  927. // markOut records a send and reports whether the epoch moved, meaning we want a punch from the far side
  928. func (i *HostInfo) markOut(epoch uint32) bool {
  929. e := epoch << stateEpochShift
  930. for {
  931. old := i.state.Load()
  932. if old&stateOut != 0 && old&^stateFlags == e {
  933. return false
  934. }
  935. if i.state.CompareAndSwap(old, old&stateFlags|stateOut|e) {
  936. return old&^stateFlags != e
  937. }
  938. }
  939. }
  940. // markOutOnly records a send without consuming the rebind epoch, for paths that cannot act on a requery
  941. func (i *HostInfo) markOutOnly() {
  942. if i.state.Load()&stateOut == 0 {
  943. i.state.Or(stateOut)
  944. }
  945. }
  946. // takeTraffic clears both traffic bits, leaving the epoch alone, and reports what they were
  947. func (i *HostInfo) takeTraffic() (in bool, out bool) {
  948. old := i.state.And(^(stateIn | stateOut))
  949. return old&stateIn != 0, old&stateOut != 0
  950. }
  951. func (i *HostInfo) setPendingDeletion(v bool) {
  952. if v {
  953. i.state.Or(statePendingDeletion)
  954. } else {
  955. i.state.And(^statePendingDeletion)
  956. }
  957. }
  958. func (i *HostInfo) isPendingDeletion() bool {
  959. return i.state.Load()&statePendingDeletion != 0
  960. }
  961. func (i *HostInfo) GetCert() *cert.CachedCertificate {
  962. if i.ConnectionState != nil {
  963. return i.ConnectionState.peerCert
  964. }
  965. return nil
  966. }
  967. func (i *HostInfo) GetRemote() netip.AddrPort {
  968. if p := i.remote.Load(); p != nil {
  969. return *p
  970. }
  971. return netip.AddrPort{}
  972. }
  973. // TODO: Maybe use ViaSender here?
  974. func (i *HostInfo) SetRemote(remote netip.AddrPort) {
  975. // We copy here because we likely got this remote from a source that reuses the object
  976. if i.GetRemote() != remote {
  977. i.remote.Store(&remote)
  978. i.remotes.LearnRemote(i.vpnAddrs[0], remote)
  979. }
  980. }
  981. // SetRemoteIfPreferred returns true if the remote was changed. The lastRoam
  982. // time on the HostInfo will also be updated.
  983. func (i *HostInfo) SetRemoteIfPreferred(hm *HostMap, via ViaSender) bool {
  984. if via.IsRelayed {
  985. return false
  986. }
  987. currentRemote := i.GetRemote()
  988. if !currentRemote.IsValid() {
  989. i.SetRemote(via.UdpAddr)
  990. return true
  991. }
  992. // NOTE: We do this loop here instead of calling `isPreferred` in
  993. // remote_list.go so that we only have to loop over preferredRanges once.
  994. newIsPreferred := false
  995. for _, l := range hm.GetPreferredRanges() {
  996. // return early if we are already on a preferred remote
  997. if l.Contains(currentRemote.Addr()) {
  998. return false
  999. }
  1000. if l.Contains(via.UdpAddr.Addr()) {
  1001. newIsPreferred = true
  1002. }
  1003. }
  1004. if newIsPreferred {
  1005. // Consider this a roaming event
  1006. i.lastRoam = time.Now()
  1007. i.lastRoamRemote = currentRemote
  1008. i.SetRemote(via.UdpAddr)
  1009. return true
  1010. }
  1011. return false
  1012. }
  1013. // buildNetworks fills in the networks field of HostInfo. It accepts a cert.Certificate so you never ever mix the network types up.
  1014. func (i *HostInfo) buildNetworks(myVpnNetworksTable *bart.Lite, c cert.Certificate) {
  1015. if len(c.Networks()) == 1 && len(c.UnsafeNetworks()) == 0 {
  1016. if myVpnNetworksTable.Contains(c.Networks()[0].Addr()) {
  1017. return // Simple case, no BART needed
  1018. }
  1019. }
  1020. i.networks = new(bart.Table[NetworkType])
  1021. for _, network := range c.Networks() {
  1022. nprefix := netip.PrefixFrom(network.Addr(), network.Addr().BitLen())
  1023. if myVpnNetworksTable.Contains(network.Addr()) {
  1024. i.networks.Insert(nprefix, NetworkTypeVPN)
  1025. } else {
  1026. i.networks.Insert(nprefix, NetworkTypeVPNPeer)
  1027. }
  1028. }
  1029. for _, network := range c.UnsafeNetworks() {
  1030. i.networks.Insert(network, NetworkTypeUnsafe)
  1031. }
  1032. }
  1033. // logger returns a derived slog.Logger with per-hostinfo fields pre-bound.
  1034. func (i *HostInfo) logger(l *slog.Logger) *slog.Logger {
  1035. if i == nil {
  1036. return l
  1037. }
  1038. li := l.With(
  1039. "vpnAddrs", i.vpnAddrs,
  1040. "localIndex", i.localIndexId,
  1041. "remoteIndex", i.remoteIndexId,
  1042. )
  1043. if connState := i.ConnectionState; connState != nil {
  1044. if peerCert := connState.peerCert; peerCert != nil {
  1045. li = li.With("certName", peerCert.Certificate.Name())
  1046. }
  1047. }
  1048. return li
  1049. }
  1050. // Utility functions
  1051. func localAddrs(l *slog.Logger, allowList *LocalAllowList) []netip.Addr {
  1052. //FIXME: This function is pretty garbage
  1053. var finalAddrs []netip.Addr
  1054. ifaces, _ := net.Interfaces()
  1055. for _, i := range ifaces {
  1056. allow := allowList.AllowName(i.Name)
  1057. if l.Enabled(context.Background(), logging.LevelTrace) {
  1058. l.Log(context.Background(), logging.LevelTrace, "localAllowList.AllowName",
  1059. "interfaceName", i.Name,
  1060. "allow", allow,
  1061. )
  1062. }
  1063. if !allow {
  1064. continue
  1065. }
  1066. addrs, _ := i.Addrs()
  1067. for _, rawAddr := range addrs {
  1068. var addr netip.Addr
  1069. switch v := rawAddr.(type) {
  1070. case *net.IPNet:
  1071. //continue
  1072. addr, _ = netip.AddrFromSlice(v.IP)
  1073. case *net.IPAddr:
  1074. addr, _ = netip.AddrFromSlice(v.IP)
  1075. }
  1076. if !addr.IsValid() {
  1077. if l.Enabled(context.Background(), slog.LevelDebug) {
  1078. l.Debug("addr was invalid", "localAddr", rawAddr)
  1079. }
  1080. continue
  1081. }
  1082. addr = addr.Unmap()
  1083. if addr.IsLoopback() == false && addr.IsLinkLocalUnicast() == false {
  1084. isAllowed := allowList.Allow(addr)
  1085. if l.Enabled(context.Background(), logging.LevelTrace) {
  1086. l.Log(context.Background(), logging.LevelTrace, "localAllowList.Allow",
  1087. "localAddr", addr,
  1088. "allowed", isAllowed,
  1089. )
  1090. }
  1091. if !isAllowed {
  1092. continue
  1093. }
  1094. finalAddrs = append(finalAddrs, addr)
  1095. }
  1096. }
  1097. }
  1098. return finalAddrs
  1099. }