remote_list.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. package nebula
  2. import (
  3. "context"
  4. "log/slog"
  5. "net"
  6. "net/netip"
  7. "slices"
  8. "sort"
  9. "strconv"
  10. "sync"
  11. "sync/atomic"
  12. "time"
  13. "github.com/slackhq/nebula/cert"
  14. )
  15. // forEachFunc is used to benefit folks that want to do work inside the lock
  16. type forEachFunc func(addr netip.AddrPort, preferred bool)
  17. // The checkFuncs here are to simplify bulk importing LH query response logic into a single function (reset slice and iterate)
  18. type checkFuncV4 func(vpnIp netip.Addr, to *V4AddrPort) bool
  19. type checkFuncV6 func(vpnIp netip.Addr, to *V6AddrPort) bool
  20. // CacheMap is a struct that better represents the lighthouse cache for humans
  21. // The string key is the owners vpnIp
  22. type CacheMap map[string]*Cache
  23. // Cache is the other part of CacheMap to better represent the lighthouse cache for humans
  24. // We don't reason about ipv4 vs ipv6 here
  25. type Cache struct {
  26. Learned []netip.AddrPort `json:"learned,omitempty"`
  27. Reported []netip.AddrPort `json:"reported,omitempty"`
  28. Relay []netip.Addr `json:"relay"`
  29. }
  30. // cache is an internal struct that splits v4 and v6 addresses inside the cache map
  31. type cache struct {
  32. v4 *cacheV4
  33. v6 *cacheV6
  34. relay *cacheRelay
  35. }
  36. type cacheRelay struct {
  37. relay []netip.Addr
  38. }
  39. // cacheV4 stores learned and reported ipv4 records under cache
  40. type cacheV4 struct {
  41. learned *V4AddrPort
  42. reported []*V4AddrPort
  43. }
  44. // cacheV4 stores learned and reported ipv6 records under cache
  45. type cacheV6 struct {
  46. learned *V6AddrPort
  47. reported []*V6AddrPort
  48. }
  49. type hostnamePort struct {
  50. name string
  51. port uint16
  52. }
  53. type hostnamesResults struct {
  54. hostnames []hostnamePort
  55. network string
  56. lookupTimeout time.Duration
  57. cancelFn func()
  58. l *slog.Logger
  59. ips atomic.Pointer[map[netip.AddrPort]struct{}]
  60. }
  61. func NewHostnameResults(ctx context.Context, l *slog.Logger, d time.Duration, network string, timeout time.Duration, hostPorts []string, onUpdate func()) (*hostnamesResults, error) {
  62. r := &hostnamesResults{
  63. hostnames: make([]hostnamePort, len(hostPorts)),
  64. network: network,
  65. lookupTimeout: timeout,
  66. l: l,
  67. }
  68. // Fastrack IP addresses to ensure they're immediately available for use.
  69. // DNS lookups for hostnames that aren't hardcoded IP's will happen in a background goroutine.
  70. performBackgroundLookup := false
  71. ips := map[netip.AddrPort]struct{}{}
  72. for idx, hostPort := range hostPorts {
  73. rIp, sPort, err := net.SplitHostPort(hostPort)
  74. if err != nil {
  75. return nil, err
  76. }
  77. iPort, err := strconv.Atoi(sPort)
  78. if err != nil {
  79. return nil, err
  80. }
  81. r.hostnames[idx] = hostnamePort{name: rIp, port: uint16(iPort)}
  82. addr, err := netip.ParseAddr(rIp)
  83. if err != nil {
  84. // This address is a hostname, not an IP address
  85. performBackgroundLookup = true
  86. continue
  87. }
  88. // Save the IP address immediately
  89. ips[netip.AddrPortFrom(addr, uint16(iPort))] = struct{}{}
  90. }
  91. r.ips.Store(&ips)
  92. // Time for the DNS lookup goroutine
  93. if performBackgroundLookup {
  94. newCtx, cancel := context.WithCancel(ctx)
  95. r.cancelFn = cancel
  96. ticker := time.NewTicker(d)
  97. go func() {
  98. defer ticker.Stop()
  99. for {
  100. netipAddrs := map[netip.AddrPort]struct{}{}
  101. for _, hostPort := range r.hostnames {
  102. timeoutCtx, timeoutCancel := context.WithTimeout(ctx, r.lookupTimeout)
  103. addrs, err := net.DefaultResolver.LookupNetIP(timeoutCtx, r.network, hostPort.name)
  104. timeoutCancel()
  105. if err != nil {
  106. l.Error("DNS resolution failed for static_map host",
  107. "hostname", hostPort.name,
  108. "network", r.network,
  109. "error", err,
  110. )
  111. continue
  112. }
  113. for _, a := range addrs {
  114. netipAddrs[netip.AddrPortFrom(a.Unmap(), hostPort.port)] = struct{}{}
  115. }
  116. }
  117. origSet := r.ips.Load()
  118. different := false
  119. for a := range *origSet {
  120. if _, ok := netipAddrs[a]; !ok {
  121. different = true
  122. break
  123. }
  124. }
  125. if !different {
  126. for a := range netipAddrs {
  127. if _, ok := (*origSet)[a]; !ok {
  128. different = true
  129. break
  130. }
  131. }
  132. }
  133. if different {
  134. l.Info("DNS results changed for host list",
  135. "origSet", origSet,
  136. "newSet", netipAddrs,
  137. )
  138. r.ips.Store(&netipAddrs)
  139. onUpdate()
  140. }
  141. select {
  142. case <-newCtx.Done():
  143. return
  144. case <-ticker.C:
  145. continue
  146. }
  147. }
  148. }()
  149. }
  150. return r, nil
  151. }
  152. func (hr *hostnamesResults) Cancel() {
  153. if hr != nil && hr.cancelFn != nil {
  154. hr.cancelFn()
  155. }
  156. }
  157. func (hr *hostnamesResults) GetAddrs() []netip.AddrPort {
  158. var retSlice []netip.AddrPort
  159. if hr != nil {
  160. p := hr.ips.Load()
  161. if p != nil {
  162. for k := range *p {
  163. retSlice = append(retSlice, k)
  164. }
  165. }
  166. }
  167. return retSlice
  168. }
  169. // RemoteList is a unifying concept for lighthouse servers and clients as well as hostinfos.
  170. // It serves as a local cache of query replies, host update notifications, and locally learned addresses
  171. type RemoteList struct {
  172. // Every interaction with internals requires a lock!
  173. sync.RWMutex
  174. // The full list of vpn addresses assigned to this host
  175. vpnAddrs []netip.Addr
  176. // A deduplicated set of underlay addresses. Any accessor should lock beforehand.
  177. addrs []netip.AddrPort
  178. // A set of relay addresses. VpnIp addresses that the remote identified as relays.
  179. relays []netip.Addr
  180. // These are maps to store v4 and v6 addresses per lighthouse
  181. // Map key is the vpnIp of the person that told us about this the cached entries underneath.
  182. // For learned addresses, this is the vpnIp that sent the packet
  183. cache map[netip.Addr]*cache
  184. hr *hostnamesResults
  185. // shouldAdd is a nillable function that decides if x should be added to addrs.
  186. shouldAdd func(vpnAddrs []netip.Addr, x netip.Addr) bool
  187. // This is a list of remotes that we have tried to handshake with and have returned from the wrong vpn ip.
  188. // They should not be tried again during a handshake
  189. badRemotes []netip.AddrPort
  190. // A flag that the cache may have changed and addrs needs to be rebuilt
  191. shouldRebuild bool
  192. }
  193. // NewRemoteList creates a new empty RemoteList
  194. func NewRemoteList(vpnAddrs []netip.Addr, shouldAdd func([]netip.Addr, netip.Addr) bool) *RemoteList {
  195. r := &RemoteList{
  196. vpnAddrs: make([]netip.Addr, len(vpnAddrs)),
  197. addrs: make([]netip.AddrPort, 0),
  198. relays: make([]netip.Addr, 0),
  199. cache: make(map[netip.Addr]*cache),
  200. shouldAdd: shouldAdd,
  201. }
  202. copy(r.vpnAddrs, vpnAddrs)
  203. return r
  204. }
  205. func (r *RemoteList) unlockedSetHostnamesResults(hr *hostnamesResults) {
  206. // Cancel any existing hostnamesResults DNS goroutine to release resources
  207. r.hr.Cancel()
  208. r.hr = hr
  209. }
  210. // ResetForOwner zeros the reported address slices for the given owner and marks the addrs list dirty.
  211. // Any pending hostname resolution will be canceled.
  212. func (r *RemoteList) ResetForOwner(ownerVpnAddr netip.Addr) {
  213. r.Lock()
  214. defer r.Unlock()
  215. r.hr.Cancel()
  216. if c, ok := r.cache[ownerVpnAddr]; ok {
  217. if c.v4 != nil {
  218. c.v4.reported = c.v4.reported[:0]
  219. }
  220. if c.v6 != nil {
  221. c.v6.reported = c.v6.reported[:0]
  222. }
  223. }
  224. r.shouldRebuild = true
  225. }
  226. // ClearHostnameResults cancels the in-flight DNS resolver goroutine (if any) and drops the resolved IP cache.
  227. func (r *RemoteList) ClearHostnameResults() {
  228. r.Lock()
  229. defer r.Unlock()
  230. r.unlockedSetHostnamesResults(nil)
  231. r.shouldRebuild = true
  232. }
  233. // Len locks and reports the size of the deduplicated address list
  234. // The deduplication work may need to occur here, so you must pass preferredRanges
  235. func (r *RemoteList) Len(preferredRanges []netip.Prefix) int {
  236. r.Rebuild(preferredRanges)
  237. r.RLock()
  238. defer r.RUnlock()
  239. return len(r.addrs)
  240. }
  241. // ForEach locks and will call the forEachFunc for every deduplicated address in the list
  242. // The deduplication work may need to occur here, so you must pass preferredRanges
  243. func (r *RemoteList) ForEach(preferredRanges []netip.Prefix, forEach forEachFunc) {
  244. r.Rebuild(preferredRanges)
  245. r.RLock()
  246. for _, v := range r.addrs {
  247. forEach(v, isPreferred(v.Addr(), preferredRanges))
  248. }
  249. r.RUnlock()
  250. }
  251. // CopyAddrs locks and makes a deep copy of the deduplicated address list
  252. // The deduplication work may need to occur here, so you must pass preferredRanges
  253. func (r *RemoteList) CopyAddrs(preferredRanges []netip.Prefix) []netip.AddrPort {
  254. if r == nil {
  255. return nil
  256. }
  257. r.Rebuild(preferredRanges)
  258. r.RLock()
  259. defer r.RUnlock()
  260. c := make([]netip.AddrPort, len(r.addrs))
  261. for i, v := range r.addrs {
  262. c[i] = v
  263. }
  264. return c
  265. }
  266. // LearnRemote locks and sets the learned slot for the owner vpn ip to the provided addr
  267. // Currently this is only needed when HostInfo.SetRemote is called as that should cover both handshaking and roaming.
  268. // It will mark the deduplicated address list as dirty, so do not call it unless new information is available
  269. func (r *RemoteList) LearnRemote(ownerVpnIp netip.Addr, remote netip.AddrPort) {
  270. r.Lock()
  271. defer r.Unlock()
  272. if remote.Addr().Is4() {
  273. r.unlockedSetLearnedV4(ownerVpnIp, netAddrToProtoV4AddrPort(remote.Addr(), remote.Port()))
  274. } else {
  275. r.unlockedSetLearnedV6(ownerVpnIp, netAddrToProtoV6AddrPort(remote.Addr(), remote.Port()))
  276. }
  277. }
  278. // CopyCache locks and creates a more human friendly form of the internal address cache.
  279. // This may contain duplicates and blocked addresses
  280. func (r *RemoteList) CopyCache() *CacheMap {
  281. r.RLock()
  282. defer r.RUnlock()
  283. cm := make(CacheMap)
  284. getOrMake := func(vpnIp string) *Cache {
  285. c := cm[vpnIp]
  286. if c == nil {
  287. c = &Cache{
  288. Learned: make([]netip.AddrPort, 0),
  289. Reported: make([]netip.AddrPort, 0),
  290. Relay: make([]netip.Addr, 0),
  291. }
  292. cm[vpnIp] = c
  293. }
  294. return c
  295. }
  296. for owner, mc := range r.cache {
  297. c := getOrMake(owner.String())
  298. if mc.v4 != nil {
  299. if mc.v4.learned != nil {
  300. c.Learned = append(c.Learned, protoV4AddrPortToNetAddrPort(mc.v4.learned))
  301. }
  302. for _, a := range mc.v4.reported {
  303. if a == nil {
  304. continue
  305. }
  306. c.Reported = append(c.Reported, protoV4AddrPortToNetAddrPort(a))
  307. }
  308. }
  309. if mc.v6 != nil {
  310. if mc.v6.learned != nil {
  311. c.Learned = append(c.Learned, protoV6AddrPortToNetAddrPort(mc.v6.learned))
  312. }
  313. for _, a := range mc.v6.reported {
  314. if a == nil {
  315. continue
  316. }
  317. c.Reported = append(c.Reported, protoV6AddrPortToNetAddrPort(a))
  318. }
  319. }
  320. if mc.relay != nil {
  321. for _, a := range mc.relay.relay {
  322. c.Relay = append(c.Relay, a)
  323. }
  324. }
  325. }
  326. return &cm
  327. }
  328. // BlockRemote locks and records the address as bad, it will be excluded from the deduplicated address list
  329. func (r *RemoteList) BlockRemote(bad ViaSender) {
  330. if bad.IsRelayed {
  331. return
  332. }
  333. r.Lock()
  334. defer r.Unlock()
  335. // Check if we already blocked this addr
  336. if r.unlockedIsBad(bad.UdpAddr) {
  337. return
  338. }
  339. // We copy here because we are taking something else's memory and we can't trust everything
  340. r.badRemotes = append(r.badRemotes, bad.UdpAddr)
  341. // Mark the next interaction must recollect/dedupe
  342. r.shouldRebuild = true
  343. }
  344. // CopyBlockedRemotes locks and makes a deep copy of the blocked remotes list
  345. func (r *RemoteList) CopyBlockedRemotes() []netip.AddrPort {
  346. r.RLock()
  347. defer r.RUnlock()
  348. c := make([]netip.AddrPort, len(r.badRemotes))
  349. for i, v := range r.badRemotes {
  350. c[i] = v
  351. }
  352. return c
  353. }
  354. // RefreshFromHandshake locks and updates the RemoteList to account for data learned upon a completed handshake
  355. func (r *RemoteList) RefreshFromHandshake(vpnAddrs []netip.Addr, v cert.Version) {
  356. r.Lock()
  357. r.badRemotes = nil
  358. if v != cert.Version1 {
  359. // a handshake from a v1 cert can never expand our knowledge of the number of addresses a host has,
  360. // and, because v2 certs exist, it can also never contract it. So, only update this for non-v1 certs.
  361. r.vpnAddrs = make([]netip.Addr, len(vpnAddrs))
  362. copy(r.vpnAddrs, vpnAddrs)
  363. }
  364. r.Unlock()
  365. }
  366. // ResetBlockedRemotes locks and clears the blocked remotes list
  367. func (r *RemoteList) ResetBlockedRemotes() {
  368. r.Lock()
  369. r.badRemotes = nil
  370. r.Unlock()
  371. }
  372. // Rebuild locks and generates the deduplicated address list only if there is work to be done
  373. // There is generally no reason to call this directly but it is safe to do so
  374. func (r *RemoteList) Rebuild(preferredRanges []netip.Prefix) {
  375. r.Lock()
  376. defer r.Unlock()
  377. // Only rebuild if the cache changed
  378. if r.shouldRebuild {
  379. r.unlockedCollect()
  380. r.shouldRebuild = false
  381. }
  382. // Always re-sort, preferredRanges can change via HUP
  383. r.unlockedSort(preferredRanges)
  384. }
  385. // unlockedIsBad assumes you have the write lock and checks if the remote matches any entry in the blocked address list
  386. func (r *RemoteList) unlockedIsBad(remote netip.AddrPort) bool {
  387. return slices.Contains(r.badRemotes, remote)
  388. }
  389. // unlockedSetLearnedV4 assumes you have the write lock and sets the current learned address for this owner and marks the
  390. // deduplicated address list as dirty
  391. func (r *RemoteList) unlockedSetLearnedV4(ownerVpnIp netip.Addr, to *V4AddrPort) {
  392. r.shouldRebuild = true
  393. r.unlockedGetOrMakeV4(ownerVpnIp).learned = to
  394. }
  395. // unlockedSetV4 assumes you have the write lock and resets the reported list of ips for this owner to the list provided
  396. // and marks the deduplicated address list as dirty
  397. func (r *RemoteList) unlockedSetV4(ownerVpnIp, vpnIp netip.Addr, to []*V4AddrPort, check checkFuncV4) {
  398. r.shouldRebuild = true
  399. c := r.unlockedGetOrMakeV4(ownerVpnIp)
  400. // Reset the slice
  401. c.reported = c.reported[:0]
  402. // We can't take their array but we can take their pointers
  403. for _, v := range to[:minInt(len(to), MaxRemotes)] {
  404. if check(vpnIp, v) {
  405. c.reported = append(c.reported, v)
  406. }
  407. }
  408. }
  409. func (r *RemoteList) unlockedSetRelay(ownerVpnIp netip.Addr, to []netip.Addr) {
  410. r.shouldRebuild = true
  411. c := r.unlockedGetOrMakeRelay(ownerVpnIp)
  412. // Reset the slice
  413. c.relay = c.relay[:0]
  414. // We can't take their array but we can take their pointers
  415. c.relay = append(c.relay, to[:minInt(len(to), MaxRemotes)]...)
  416. }
  417. // unlockedPrependV4 assumes you have the write lock and prepends the address in the reported list for this owner
  418. // This is only useful for establishing static hosts
  419. func (r *RemoteList) unlockedPrependV4(ownerVpnIp netip.Addr, to *V4AddrPort) {
  420. r.shouldRebuild = true
  421. c := r.unlockedGetOrMakeV4(ownerVpnIp)
  422. // We are doing the easy append because this is rarely called
  423. c.reported = append([]*V4AddrPort{to}, c.reported...)
  424. if len(c.reported) > MaxRemotes {
  425. c.reported = c.reported[:MaxRemotes]
  426. }
  427. }
  428. // unlockedSetLearnedV6 assumes you have the write lock and sets the current learned address for this owner and marks the
  429. // deduplicated address list as dirty
  430. func (r *RemoteList) unlockedSetLearnedV6(ownerVpnIp netip.Addr, to *V6AddrPort) {
  431. r.shouldRebuild = true
  432. r.unlockedGetOrMakeV6(ownerVpnIp).learned = to
  433. }
  434. // unlockedSetV6 assumes you have the write lock and resets the reported list of ips for this owner to the list provided
  435. // and marks the deduplicated address list as dirty
  436. func (r *RemoteList) unlockedSetV6(ownerVpnIp, vpnIp netip.Addr, to []*V6AddrPort, check checkFuncV6) {
  437. r.shouldRebuild = true
  438. c := r.unlockedGetOrMakeV6(ownerVpnIp)
  439. // Reset the slice
  440. c.reported = c.reported[:0]
  441. // We can't take their array but we can take their pointers
  442. for _, v := range to[:minInt(len(to), MaxRemotes)] {
  443. if check(vpnIp, v) {
  444. c.reported = append(c.reported, v)
  445. }
  446. }
  447. }
  448. // unlockedPrependV6 assumes you have the write lock and prepends the address in the reported list for this owner
  449. // This is only useful for establishing static hosts
  450. func (r *RemoteList) unlockedPrependV6(ownerVpnIp netip.Addr, to *V6AddrPort) {
  451. r.shouldRebuild = true
  452. c := r.unlockedGetOrMakeV6(ownerVpnIp)
  453. // We are doing the easy append because this is rarely called
  454. c.reported = append([]*V6AddrPort{to}, c.reported...)
  455. if len(c.reported) > MaxRemotes {
  456. c.reported = c.reported[:MaxRemotes]
  457. }
  458. }
  459. func (r *RemoteList) unlockedGetOrMakeRelay(ownerVpnIp netip.Addr) *cacheRelay {
  460. am := r.cache[ownerVpnIp]
  461. if am == nil {
  462. am = &cache{}
  463. r.cache[ownerVpnIp] = am
  464. }
  465. // Avoid occupying memory for relay if we never have any
  466. if am.relay == nil {
  467. am.relay = &cacheRelay{}
  468. }
  469. return am.relay
  470. }
  471. // unlockedGetOrMakeV4 assumes you have the write lock and builds the cache and owner entry. Only the v4 pointer is established.
  472. // The caller must dirty the learned address cache if required
  473. func (r *RemoteList) unlockedGetOrMakeV4(ownerVpnIp netip.Addr) *cacheV4 {
  474. am := r.cache[ownerVpnIp]
  475. if am == nil {
  476. am = &cache{}
  477. r.cache[ownerVpnIp] = am
  478. }
  479. // Avoid occupying memory for v6 addresses if we never have any
  480. if am.v4 == nil {
  481. am.v4 = &cacheV4{}
  482. }
  483. return am.v4
  484. }
  485. // unlockedGetOrMakeV6 assumes you have the write lock and builds the cache and owner entry. Only the v6 pointer is established.
  486. // The caller must dirty the learned address cache if required
  487. func (r *RemoteList) unlockedGetOrMakeV6(ownerVpnIp netip.Addr) *cacheV6 {
  488. am := r.cache[ownerVpnIp]
  489. if am == nil {
  490. am = &cache{}
  491. r.cache[ownerVpnIp] = am
  492. }
  493. // Avoid occupying memory for v4 addresses if we never have any
  494. if am.v6 == nil {
  495. am.v6 = &cacheV6{}
  496. }
  497. return am.v6
  498. }
  499. // unlockedCollect assumes you have the write lock and collects/transforms the cache into the deduped address list.
  500. // The result of this function can contain duplicates. unlockedSort handles cleaning it.
  501. func (r *RemoteList) unlockedCollect() {
  502. addrs := r.addrs[:0]
  503. relays := r.relays[:0]
  504. for _, c := range r.cache {
  505. if c.v4 != nil {
  506. if c.v4.learned != nil {
  507. u := protoV4AddrPortToNetAddrPort(c.v4.learned)
  508. if !r.unlockedIsBad(u) {
  509. addrs = append(addrs, u)
  510. }
  511. }
  512. for _, v := range c.v4.reported {
  513. if v == nil {
  514. continue
  515. }
  516. u := protoV4AddrPortToNetAddrPort(v)
  517. if !r.unlockedIsBad(u) {
  518. addrs = append(addrs, u)
  519. }
  520. }
  521. }
  522. if c.v6 != nil {
  523. if c.v6.learned != nil {
  524. u := protoV6AddrPortToNetAddrPort(c.v6.learned)
  525. if !r.unlockedIsBad(u) {
  526. addrs = append(addrs, u)
  527. }
  528. }
  529. for _, v := range c.v6.reported {
  530. if v == nil {
  531. continue
  532. }
  533. u := protoV6AddrPortToNetAddrPort(v)
  534. if !r.unlockedIsBad(u) {
  535. addrs = append(addrs, u)
  536. }
  537. }
  538. }
  539. if c.relay != nil {
  540. for _, v := range c.relay.relay {
  541. relays = append(relays, v)
  542. }
  543. }
  544. }
  545. dnsAddrs := r.hr.GetAddrs()
  546. for _, addr := range dnsAddrs {
  547. if r.shouldAdd == nil || r.shouldAdd(r.vpnAddrs, addr.Addr()) {
  548. if !r.unlockedIsBad(addr) {
  549. addrs = append(addrs, addr)
  550. }
  551. }
  552. }
  553. r.addrs = addrs
  554. r.relays = relays
  555. }
  556. // unlockedSort assumes you have the write lock and performs the deduping and sorting of the address list
  557. func (r *RemoteList) unlockedSort(preferredRanges []netip.Prefix) {
  558. // Use a map to deduplicate any relay addresses
  559. dedupedRelays := map[netip.Addr]struct{}{}
  560. for _, relay := range r.relays {
  561. dedupedRelays[relay] = struct{}{}
  562. }
  563. r.relays = r.relays[:0]
  564. for relay := range dedupedRelays {
  565. r.relays = append(r.relays, relay)
  566. }
  567. // Put them in a somewhat consistent order after de-duplication
  568. slices.SortFunc(r.relays, func(a, b netip.Addr) int {
  569. return a.Compare(b)
  570. })
  571. // Now the addrs
  572. n := len(r.addrs)
  573. if n < 2 {
  574. return
  575. }
  576. lessFunc := func(i, j int) bool {
  577. a := r.addrs[i]
  578. b := r.addrs[j]
  579. // Preferred addresses first
  580. aPref := isPreferred(a.Addr(), preferredRanges)
  581. bPref := isPreferred(b.Addr(), preferredRanges)
  582. switch {
  583. case aPref && !bPref:
  584. // If i is preferred and j is not, i is less than j
  585. return true
  586. case !aPref && bPref:
  587. // If j is preferred then i is not due to the else, i is not less than j
  588. return false
  589. default:
  590. // Both i an j are either preferred or not, sort within that
  591. }
  592. // ipv6 addresses 2nd
  593. a4 := a.Addr().Is4()
  594. b4 := b.Addr().Is4()
  595. switch {
  596. case a4 == false && b4 == true:
  597. // If i is v6 and j is v4, i is less than j
  598. return true
  599. case a4 == true && b4 == false:
  600. // If j is v6 and i is v4, i is not less than j
  601. return false
  602. case a4 == true && b4 == true:
  603. // i and j are both ipv4
  604. aPrivate := a.Addr().IsPrivate()
  605. bPrivate := b.Addr().IsPrivate()
  606. switch {
  607. case !aPrivate && bPrivate:
  608. // If i is a public ip (not private) and j is a private ip, i is less then j
  609. return true
  610. case aPrivate && !bPrivate:
  611. // If j is public (not private) then i is private due to the else, i is not less than j
  612. return false
  613. default:
  614. // Both i an j are either public or private, sort within that
  615. }
  616. default:
  617. // Both i an j are either ipv4 or ipv6, sort within that
  618. }
  619. // lexical order of ips 3rd
  620. c := a.Addr().Compare(b.Addr())
  621. if c == 0 {
  622. // Ips are the same, Lexical order of ports 4th
  623. return a.Port() < b.Port()
  624. }
  625. // Ip wasn't the same
  626. return c < 0
  627. }
  628. // Sort it
  629. sort.Slice(r.addrs, lessFunc)
  630. // Deduplicate
  631. a, b := 0, 1
  632. for b < n {
  633. if r.addrs[a] != r.addrs[b] {
  634. a++
  635. if a != b {
  636. r.addrs[a], r.addrs[b] = r.addrs[b], r.addrs[a]
  637. }
  638. }
  639. b++
  640. }
  641. r.addrs = r.addrs[:a+1]
  642. return
  643. }
  644. // minInt returns the minimum integer of a or b
  645. func minInt(a, b int) int {
  646. if a < b {
  647. return a
  648. }
  649. return b
  650. }
  651. // isPreferred returns true of the ip is contained in the preferredRanges list
  652. func isPreferred(ip netip.Addr, preferredRanges []netip.Prefix) bool {
  653. for _, p := range preferredRanges {
  654. if p.Contains(ip) {
  655. return true
  656. }
  657. }
  658. return false
  659. }