lighthouse.go 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  1. package nebula
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "log/slog"
  8. "net"
  9. "net/netip"
  10. "slices"
  11. "strconv"
  12. "sync"
  13. "sync/atomic"
  14. "time"
  15. "github.com/gaissmai/bart"
  16. "github.com/slackhq/nebula/cert"
  17. "github.com/slackhq/nebula/config"
  18. "github.com/slackhq/nebula/header"
  19. "github.com/slackhq/nebula/logging"
  20. "github.com/slackhq/nebula/udp"
  21. "github.com/slackhq/nebula/util"
  22. )
  23. var ErrHostNotKnown = errors.New("host not known")
  24. var ErrBadDetailsVpnAddr = errors.New("invalid packet, malformed detailsVpnAddr")
  25. type LightHouse struct {
  26. //TODO: We need a timer wheel to kick out vpnAddrs that haven't reported in a long time
  27. sync.RWMutex //Because we concurrently read and write to our maps
  28. ctx context.Context
  29. amLighthouse bool
  30. myVpnNetworks []netip.Prefix
  31. myVpnNetworksTable *bart.Lite
  32. // myVpnAddrsTable contains our overlay host addrs, as opposed to the overlay networks
  33. myVpnAddrsTable *bart.Lite
  34. punchy *Punchy
  35. // localAddrsFn enumerates the underlay addresses we advertise. It is a field so tests can supply simulated
  36. // addresses rather than whatever this machine's NICs happen to be. Set it before Start.
  37. localAddrsFn func(*LocalAllowList) []netip.Addr
  38. // Local cache of answers from light houses
  39. // map of vpn addr to answers
  40. addrMap map[netip.Addr]*RemoteList
  41. // filters remote addresses allowed for each host
  42. // - When we are a lighthouse, this filters what addresses we store and
  43. // respond with.
  44. // - When we are not a lighthouse, this filters which addresses we accept
  45. // from lighthouses.
  46. remoteAllowList atomic.Pointer[RemoteAllowList]
  47. // filters local addresses that we advertise to lighthouses
  48. localAllowList atomic.Pointer[LocalAllowList]
  49. // used to trigger the HandshakeManager when we receive HostQueryReply
  50. handshakeTrigger chan<- netip.Addr
  51. // staticList exists to avoid having a bool in each addrMap entry
  52. // since static should be rare
  53. staticList atomic.Pointer[map[netip.Addr]struct{}]
  54. lighthouses atomic.Pointer[[]netip.Addr]
  55. interval atomic.Int64
  56. updateCancel context.CancelFunc
  57. ifce EncWriter
  58. nebulaPort uint32 // 32 bits because protobuf does not have a uint16
  59. advertiseAddrs atomic.Pointer[[]netip.AddrPort]
  60. // Addr's of relays that can be used by peers to access me
  61. relaysForMe atomic.Pointer[[]netip.Addr]
  62. updateTrigger chan struct{}
  63. queryChan chan netip.Addr
  64. calculatedRemotes atomic.Pointer[bart.Table[[]*calculatedRemote]] // Maps VpnAddr to []*calculatedRemote
  65. metrics *MessageMetrics
  66. l *slog.Logger
  67. }
  68. // NewLightHouseFromConfig will build a Lighthouse struct from the values provided in the config object
  69. // addrMap should be nil unless this is during a config reload
  70. func NewLightHouseFromConfig(ctx context.Context, l *slog.Logger, c *config.C, cs *CertState, pc udp.Conn, p *Punchy) (*LightHouse, error) {
  71. amLighthouse := c.GetBool("lighthouse.am_lighthouse", false)
  72. nebulaPort := uint32(c.GetInt("listen.port", 0))
  73. if amLighthouse && nebulaPort == 0 {
  74. return nil, util.NewContextualError("lighthouse.am_lighthouse enabled on node but no port number is set in config", nil, nil)
  75. }
  76. // If port is dynamic, discover it
  77. if nebulaPort == 0 && pc != nil {
  78. uPort, err := pc.LocalAddr()
  79. if err != nil {
  80. return nil, util.NewContextualError("Failed to get listening port", nil, err)
  81. }
  82. nebulaPort = uint32(uPort.Port())
  83. }
  84. h := LightHouse{
  85. ctx: ctx,
  86. amLighthouse: amLighthouse,
  87. myVpnNetworks: cs.myVpnNetworks,
  88. myVpnNetworksTable: cs.myVpnNetworksTable,
  89. myVpnAddrsTable: cs.myVpnAddrsTable,
  90. addrMap: make(map[netip.Addr]*RemoteList),
  91. nebulaPort: nebulaPort,
  92. punchy: p,
  93. updateTrigger: make(chan struct{}, 1),
  94. queryChan: make(chan netip.Addr, c.GetUint32("handshakes.query_buffer", 64)),
  95. l: l,
  96. }
  97. h.localAddrsFn = func(al *LocalAllowList) []netip.Addr {
  98. return localAddrs(h.l, al)
  99. }
  100. lighthouses := make([]netip.Addr, 0)
  101. h.lighthouses.Store(&lighthouses)
  102. staticList := make(map[netip.Addr]struct{})
  103. h.staticList.Store(&staticList)
  104. if c.GetBool("stats.lighthouse_metrics", false) {
  105. h.metrics = newLighthouseMetrics()
  106. }
  107. err := h.reload(c, true)
  108. if err != nil {
  109. return nil, err
  110. }
  111. c.RegisterReloadCallback(func(c *config.C) {
  112. err := h.reload(c, false)
  113. switch v := err.(type) {
  114. case *util.ContextualError:
  115. v.Log(l)
  116. case error:
  117. l.Error("failed to reload lighthouse", "error", err)
  118. }
  119. })
  120. h.startQueryWorker()
  121. return &h, nil
  122. }
  123. func (lh *LightHouse) GetStaticHostList() map[netip.Addr]struct{} {
  124. return *lh.staticList.Load()
  125. }
  126. func (lh *LightHouse) GetLighthouses() []netip.Addr {
  127. return *lh.lighthouses.Load()
  128. }
  129. func (lh *LightHouse) GetRemoteAllowList() *RemoteAllowList {
  130. return lh.remoteAllowList.Load()
  131. }
  132. func (lh *LightHouse) GetLocalAllowList() *LocalAllowList {
  133. return lh.localAllowList.Load()
  134. }
  135. func (lh *LightHouse) GetAdvertiseAddrs() []netip.AddrPort {
  136. return *lh.advertiseAddrs.Load()
  137. }
  138. func (lh *LightHouse) GetRelaysForMe() []netip.Addr {
  139. return *lh.relaysForMe.Load()
  140. }
  141. func (lh *LightHouse) getCalculatedRemotes() *bart.Table[[]*calculatedRemote] {
  142. return lh.calculatedRemotes.Load()
  143. }
  144. func (lh *LightHouse) GetUpdateInterval() int64 {
  145. return lh.interval.Load()
  146. }
  147. func (lh *LightHouse) reload(c *config.C, initial bool) error {
  148. if initial || c.HasChanged("lighthouse.advertise_addrs") {
  149. rawAdvAddrs := c.GetStringSlice("lighthouse.advertise_addrs", []string{})
  150. advAddrs := make([]netip.AddrPort, 0)
  151. for i, rawAddr := range rawAdvAddrs {
  152. host, sport, err := net.SplitHostPort(rawAddr)
  153. if err != nil {
  154. return util.NewContextualError("Unable to parse lighthouse.advertise_addrs entry", m{"addr": rawAddr, "entry": i + 1}, err)
  155. }
  156. addrs, err := net.DefaultResolver.LookupNetIP(context.Background(), "ip", host)
  157. if err != nil {
  158. return util.NewContextualError("Unable to lookup lighthouse.advertise_addrs entry", m{"addr": rawAddr, "entry": i + 1}, err)
  159. }
  160. if len(addrs) == 0 {
  161. return util.NewContextualError("Unable to lookup lighthouse.advertise_addrs entry", m{"addr": rawAddr, "entry": i + 1}, nil)
  162. }
  163. port, err := strconv.Atoi(sport)
  164. if err != nil {
  165. return util.NewContextualError("Unable to parse port in lighthouse.advertise_addrs entry", m{"addr": rawAddr, "entry": i + 1}, err)
  166. }
  167. if port == 0 {
  168. port = int(lh.nebulaPort)
  169. }
  170. //TODO: we could technically insert all returned addrs instead of just the first one if a dns lookup was used
  171. addr := addrs[0].Unmap()
  172. if lh.myVpnNetworksTable.Contains(addr) {
  173. lh.l.Warn("Ignoring lighthouse.advertise_addrs report because it is within the nebula network range",
  174. "addr", rawAddr,
  175. "entry", i+1,
  176. )
  177. continue
  178. }
  179. advAddrs = append(advAddrs, netip.AddrPortFrom(addr, uint16(port)))
  180. }
  181. lh.advertiseAddrs.Store(&advAddrs)
  182. if !initial {
  183. lh.l.Info("lighthouse.advertise_addrs has changed")
  184. }
  185. }
  186. if initial || c.HasChanged("lighthouse.interval") {
  187. lh.interval.Store(int64(c.GetInt("lighthouse.interval", 10)))
  188. if !initial {
  189. lh.l.Info("lighthouse.interval changed",
  190. "interval", lh.interval.Load(),
  191. )
  192. if lh.updateCancel != nil {
  193. // May not always have a running routine
  194. lh.updateCancel()
  195. }
  196. lh.StartUpdateWorker()
  197. }
  198. }
  199. if initial || c.HasChanged("lighthouse.remote_allow_list") || c.HasChanged("lighthouse.remote_allow_ranges") {
  200. ral, err := NewRemoteAllowListFromConfig(c, "lighthouse.remote_allow_list", "lighthouse.remote_allow_ranges")
  201. if err != nil {
  202. return util.NewContextualError("Invalid lighthouse.remote_allow_list", nil, err)
  203. }
  204. lh.remoteAllowList.Store(ral)
  205. if !initial {
  206. lh.l.Info("lighthouse.remote_allow_list and/or lighthouse.remote_allow_ranges has changed")
  207. }
  208. }
  209. if initial || c.HasChanged("lighthouse.local_allow_list") {
  210. lal, err := NewLocalAllowListFromConfig(c, "lighthouse.local_allow_list")
  211. if err != nil {
  212. return util.NewContextualError("Invalid lighthouse.local_allow_list", nil, err)
  213. }
  214. lh.localAllowList.Store(lal)
  215. if !initial {
  216. lh.l.Info("lighthouse.local_allow_list has changed")
  217. }
  218. }
  219. if initial || c.HasChanged("lighthouse.calculated_remotes") {
  220. cr, err := NewCalculatedRemotesFromConfig(c, "lighthouse.calculated_remotes")
  221. if err != nil {
  222. return util.NewContextualError("Invalid lighthouse.calculated_remotes", nil, err)
  223. }
  224. lh.calculatedRemotes.Store(cr)
  225. if !initial {
  226. lh.l.Info("lighthouse.calculated_remotes has changed")
  227. }
  228. }
  229. //NOTE: many things will get much simpler when we combine static_host_map and lighthouse.hosts in config
  230. if initial || c.HasChanged("static_host_map") || c.HasChanged("static_map.cadence") || c.HasChanged("static_map.network") || c.HasChanged("static_map.lookup_timeout") {
  231. // Clean up. Entries still in the static_host_map will be re-built.
  232. ourselves := lh.myVpnNetworks[0].Addr()
  233. oldStaticList := lh.staticList.Load()
  234. if oldStaticList != nil {
  235. lh.RLock()
  236. for staticVpnAddr := range *oldStaticList {
  237. if am, ok := lh.addrMap[staticVpnAddr]; ok && am != nil {
  238. am.ResetForOwner(ourselves)
  239. }
  240. }
  241. lh.RUnlock()
  242. }
  243. // Build a new list based on current config.
  244. staticList := make(map[netip.Addr]struct{})
  245. err := lh.loadStaticMap(c, staticList)
  246. if err != nil {
  247. return err
  248. }
  249. // For entries removed from static_host_map, stop the DNS goroutine and drop the cached addrs.
  250. // All addrs must come from the lighthouses now that it's no longer a static host.
  251. if oldStaticList != nil {
  252. lh.RLock()
  253. for staticVpnAddr := range *oldStaticList {
  254. if _, stillStatic := staticList[staticVpnAddr]; stillStatic {
  255. continue
  256. }
  257. if am, ok := lh.addrMap[staticVpnAddr]; ok && am != nil {
  258. am.ClearHostnameResults()
  259. }
  260. }
  261. lh.RUnlock()
  262. }
  263. lh.staticList.Store(&staticList)
  264. if !initial {
  265. if c.HasChanged("static_host_map") {
  266. lh.l.Info("static_host_map has changed")
  267. }
  268. if c.HasChanged("static_map.cadence") {
  269. lh.l.Info("static_map.cadence has changed")
  270. }
  271. if c.HasChanged("static_map.network") {
  272. lh.l.Info("static_map.network has changed")
  273. }
  274. if c.HasChanged("static_map.lookup_timeout") {
  275. lh.l.Info("static_map.lookup_timeout has changed")
  276. }
  277. }
  278. }
  279. if initial || c.HasChanged("lighthouse.hosts") {
  280. lhList, err := lh.parseLighthouses(c)
  281. if err != nil {
  282. return err
  283. }
  284. lh.lighthouses.Store(&lhList)
  285. if !initial {
  286. //NOTE: we are not tearing down existing lighthouse connections because they might be used for non lighthouse traffic
  287. lh.l.Info("lighthouse.hosts has changed")
  288. lh.TriggerUpdate()
  289. }
  290. }
  291. if initial || c.HasChanged("relay.relays") {
  292. switch c.GetBool("relay.am_relay", false) {
  293. case true:
  294. // Relays aren't allowed to specify other relays
  295. if len(c.GetStringSlice("relay.relays", nil)) > 0 {
  296. lh.l.Info("Ignoring relays from config because am_relay is true")
  297. }
  298. relaysForMe := []netip.Addr{}
  299. lh.relaysForMe.Store(&relaysForMe)
  300. case false:
  301. relaysForMe := []netip.Addr{}
  302. for _, v := range c.GetStringSlice("relay.relays", nil) {
  303. configRIP, err := netip.ParseAddr(v)
  304. if err != nil {
  305. lh.l.Warn("Parse relay from config failed",
  306. "relay", v,
  307. "error", err,
  308. )
  309. } else {
  310. lh.l.Info("Read relay from config", "relay", v)
  311. relaysForMe = append(relaysForMe, configRIP)
  312. }
  313. }
  314. lh.relaysForMe.Store(&relaysForMe)
  315. }
  316. }
  317. return nil
  318. }
  319. func (lh *LightHouse) parseLighthouses(c *config.C) ([]netip.Addr, error) {
  320. lhs := c.GetStringSlice("lighthouse.hosts", []string{})
  321. if lh.amLighthouse && len(lhs) != 0 {
  322. lh.l.Warn("lighthouse.am_lighthouse enabled on node but upstream lighthouses exist in config")
  323. }
  324. out := make([]netip.Addr, len(lhs))
  325. for i, host := range lhs {
  326. addr, err := netip.ParseAddr(host)
  327. if err != nil {
  328. return nil, util.NewContextualError("Unable to parse lighthouse host entry", m{"host": host, "entry": i + 1}, err)
  329. }
  330. if !lh.myVpnNetworksTable.Contains(addr) {
  331. lh.l.Warn("lighthouse host is not within our networks, lighthouse functionality will work but layer 3 network traffic to the lighthouse will not",
  332. "vpnAddr", addr,
  333. "networks", lh.myVpnNetworks,
  334. )
  335. }
  336. out[i] = addr
  337. }
  338. if !lh.amLighthouse && len(out) == 0 {
  339. lh.l.Warn("No lighthouse.hosts configured, this host will only be able to initiate tunnels with static_host_map entries")
  340. }
  341. staticList := lh.GetStaticHostList()
  342. for i := range out {
  343. if _, ok := staticList[out[i]]; !ok {
  344. return nil, fmt.Errorf("lighthouse %s does not have a static_host_map entry", out[i])
  345. }
  346. }
  347. return out, nil
  348. }
  349. func getStaticMapCadence(c *config.C) (time.Duration, error) {
  350. cadence := c.GetString("static_map.cadence", "30s")
  351. d, err := time.ParseDuration(cadence)
  352. if err != nil {
  353. return 0, err
  354. }
  355. return d, nil
  356. }
  357. func getStaticMapLookupTimeout(c *config.C) (time.Duration, error) {
  358. lookupTimeout := c.GetString("static_map.lookup_timeout", "250ms")
  359. d, err := time.ParseDuration(lookupTimeout)
  360. if err != nil {
  361. return 0, err
  362. }
  363. return d, nil
  364. }
  365. func getStaticMapNetwork(c *config.C) (string, error) {
  366. network := c.GetString("static_map.network", "ip4")
  367. if network != "ip" && network != "ip4" && network != "ip6" {
  368. return "", fmt.Errorf("static_map.network must be one of ip, ip4, or ip6")
  369. }
  370. return network, nil
  371. }
  372. func (lh *LightHouse) loadStaticMap(c *config.C, staticList map[netip.Addr]struct{}) error {
  373. d, err := getStaticMapCadence(c)
  374. if err != nil {
  375. return err
  376. }
  377. network, err := getStaticMapNetwork(c)
  378. if err != nil {
  379. return err
  380. }
  381. lookupTimeout, err := getStaticMapLookupTimeout(c)
  382. if err != nil {
  383. return err
  384. }
  385. shm := c.GetMap("static_host_map", map[string]any{})
  386. i := 0
  387. for k, v := range shm {
  388. vpnAddr, err := netip.ParseAddr(fmt.Sprintf("%v", k))
  389. if err != nil {
  390. return util.NewContextualError("Unable to parse static_host_map entry", m{"host": k, "entry": i + 1}, err)
  391. }
  392. if !lh.myVpnNetworksTable.Contains(vpnAddr) {
  393. lh.l.Warn("static_host_map key is not within our networks, layer 3 network traffic to this host will not work",
  394. "vpnAddr", vpnAddr,
  395. "networks", lh.myVpnNetworks,
  396. "entry", i+1,
  397. )
  398. }
  399. vals, ok := v.([]any)
  400. if !ok {
  401. vals = []any{v}
  402. }
  403. remoteAddrs := []string{}
  404. for _, v := range vals {
  405. remoteAddrs = append(remoteAddrs, fmt.Sprintf("%v", v))
  406. }
  407. err = lh.addStaticRemotes(i, d, network, lookupTimeout, vpnAddr, remoteAddrs, staticList)
  408. if err != nil {
  409. return err
  410. }
  411. i++
  412. }
  413. return nil
  414. }
  415. func (lh *LightHouse) Query(vpnAddr netip.Addr) *RemoteList {
  416. if !lh.IsLighthouseAddr(vpnAddr) {
  417. lh.QueryServer(vpnAddr)
  418. }
  419. lh.RLock()
  420. if v, ok := lh.addrMap[vpnAddr]; ok {
  421. lh.RUnlock()
  422. return v
  423. }
  424. lh.RUnlock()
  425. return nil
  426. }
  427. // QueryServer is asynchronous so no reply should be expected
  428. func (lh *LightHouse) QueryServer(vpnAddr netip.Addr) {
  429. // Don't put lighthouse addrs in the query channel because we can't query lighthouses about lighthouses
  430. if lh.amLighthouse || lh.IsLighthouseAddr(vpnAddr) {
  431. return
  432. }
  433. lh.queryChan <- vpnAddr
  434. }
  435. func (lh *LightHouse) QueryCache(vpnAddrs []netip.Addr) *RemoteList {
  436. lh.RLock()
  437. if v, ok := lh.addrMap[vpnAddrs[0]]; ok {
  438. lh.RUnlock()
  439. return v
  440. }
  441. lh.RUnlock()
  442. lh.Lock()
  443. defer lh.Unlock()
  444. // Add an entry if we don't already have one
  445. return lh.unlockedGetRemoteList(vpnAddrs) //todo CERT-V2 this contains addrmap lookups we could potentially skip
  446. }
  447. // queryAndPrepMessage is a lock helper on RemoteList, assisting the caller to build a lighthouse message containing
  448. // details from the remote list. It looks for a hit in the addrMap and a hit in the RemoteList under the owner vpnAddr
  449. // If one is found then f() is called with proper locking, f() must return result of n.MarshalTo()
  450. func (lh *LightHouse) queryAndPrepMessage(vpnAddr netip.Addr, f func(*cache) (int, error)) (bool, int, error) {
  451. lh.RLock()
  452. // Do we have an entry in the main cache?
  453. if v, ok := lh.addrMap[vpnAddr]; ok {
  454. // Swap lh lock for remote list lock
  455. v.RLock()
  456. defer v.RUnlock()
  457. lh.RUnlock()
  458. // We may be asking about a non primary address so lets get the primary address
  459. if slices.Contains(v.vpnAddrs, vpnAddr) {
  460. vpnAddr = v.vpnAddrs[0]
  461. }
  462. c := v.cache[vpnAddr]
  463. // Make sure we have
  464. if c != nil {
  465. n, err := f(c)
  466. return true, n, err
  467. }
  468. return false, 0, nil
  469. }
  470. lh.RUnlock()
  471. return false, 0, nil
  472. }
  473. func (lh *LightHouse) DeleteVpnAddrs(allVpnAddrs []netip.Addr) {
  474. // First we check the static host map. If any of the VpnAddrs to be deleted are present, do nothing.
  475. staticList := lh.GetStaticHostList()
  476. for _, addr := range allVpnAddrs {
  477. if _, ok := staticList[addr]; ok {
  478. return
  479. }
  480. }
  481. // None of the VpnAddrs were present. Now we can do the deletes.
  482. lh.Lock()
  483. rm, ok := lh.addrMap[allVpnAddrs[0]]
  484. if ok {
  485. debugEnabled := lh.l.Enabled(context.Background(), slog.LevelDebug)
  486. for _, addr := range allVpnAddrs {
  487. srm := lh.addrMap[addr]
  488. if srm == rm {
  489. delete(lh.addrMap, addr)
  490. if debugEnabled {
  491. lh.l.Debug("deleting from lighthouse", "vpnAddr", addr)
  492. }
  493. }
  494. }
  495. }
  496. lh.Unlock()
  497. }
  498. // AddStaticRemote adds a static host entry for vpnAddr as ourselves as the owner
  499. // We are the owner because we don't want a lighthouse server to advertise for static hosts it was configured with
  500. // And we don't want a lighthouse query reply to interfere with our learned cache if we are a client
  501. // NOTE: this function should not interact with any hot path objects, like lh.staticList, the caller should handle it
  502. func (lh *LightHouse) addStaticRemotes(i int, d time.Duration, network string, timeout time.Duration, vpnAddr netip.Addr, toAddrs []string, staticList map[netip.Addr]struct{}) error {
  503. lh.Lock()
  504. am := lh.unlockedGetRemoteList([]netip.Addr{vpnAddr})
  505. am.Lock()
  506. defer am.Unlock()
  507. ctx := lh.ctx
  508. lh.Unlock()
  509. hr, err := NewHostnameResults(ctx, lh.l, d, network, timeout, toAddrs, func() {
  510. // This callback runs whenever the DNS hostname resolver finds a different set of addr's
  511. // in its resolution for hostnames.
  512. am.Lock()
  513. defer am.Unlock()
  514. am.shouldRebuild = true
  515. })
  516. if err != nil {
  517. return util.NewContextualError("Static host address could not be parsed", m{"vpnAddr": vpnAddr, "entry": i + 1}, err)
  518. }
  519. am.unlockedSetHostnamesResults(hr)
  520. for _, addrPort := range hr.GetAddrs() {
  521. if !lh.shouldAdd([]netip.Addr{vpnAddr}, addrPort.Addr()) {
  522. continue
  523. }
  524. switch {
  525. case addrPort.Addr().Is4():
  526. am.unlockedPrependV4(lh.myVpnNetworks[0].Addr(), netAddrToProtoV4AddrPort(addrPort.Addr(), addrPort.Port()))
  527. case addrPort.Addr().Is6():
  528. am.unlockedPrependV6(lh.myVpnNetworks[0].Addr(), netAddrToProtoV6AddrPort(addrPort.Addr(), addrPort.Port()))
  529. }
  530. }
  531. // Mark it as static in the caller provided map
  532. staticList[vpnAddr] = struct{}{}
  533. return nil
  534. }
  535. // addCalculatedRemotes adds any calculated remotes based on the
  536. // lighthouse.calculated_remotes configuration. It returns true if any
  537. // calculated remotes were added
  538. func (lh *LightHouse) addCalculatedRemotes(vpnAddr netip.Addr) bool {
  539. tree := lh.getCalculatedRemotes()
  540. if tree == nil {
  541. return false
  542. }
  543. calculatedRemotes, ok := tree.Lookup(vpnAddr)
  544. if !ok {
  545. return false
  546. }
  547. var calculatedV4 []*V4AddrPort
  548. var calculatedV6 []*V6AddrPort
  549. for _, cr := range calculatedRemotes {
  550. if vpnAddr.Is4() {
  551. c := cr.ApplyV4(vpnAddr)
  552. if c != nil {
  553. calculatedV4 = append(calculatedV4, c)
  554. }
  555. } else if vpnAddr.Is6() {
  556. c := cr.ApplyV6(vpnAddr)
  557. if c != nil {
  558. calculatedV6 = append(calculatedV6, c)
  559. }
  560. }
  561. }
  562. lh.Lock()
  563. am := lh.unlockedGetRemoteList([]netip.Addr{vpnAddr})
  564. am.Lock()
  565. defer am.Unlock()
  566. lh.Unlock()
  567. if len(calculatedV4) > 0 {
  568. am.unlockedSetV4(lh.myVpnNetworks[0].Addr(), vpnAddr, calculatedV4, lh.unlockedShouldAddV4)
  569. }
  570. if len(calculatedV6) > 0 {
  571. am.unlockedSetV6(lh.myVpnNetworks[0].Addr(), vpnAddr, calculatedV6, lh.unlockedShouldAddV6)
  572. }
  573. return len(calculatedV4) > 0 || len(calculatedV6) > 0
  574. }
  575. // unlockedGetRemoteList assumes you have the lh lock
  576. func (lh *LightHouse) unlockedGetRemoteList(allAddrs []netip.Addr) *RemoteList {
  577. // before we go and make a new remotelist, we need to make sure we don't have one for any of this set of vpnaddrs yet
  578. for i, addr := range allAddrs {
  579. am, ok := lh.addrMap[addr]
  580. if ok {
  581. if i != 0 {
  582. lh.addrMap[allAddrs[0]] = am
  583. }
  584. return am
  585. }
  586. }
  587. am := NewRemoteList(allAddrs, lh.shouldAdd)
  588. for _, addr := range allAddrs {
  589. lh.addrMap[addr] = am
  590. }
  591. return am
  592. }
  593. func (lh *LightHouse) shouldAdd(vpnAddrs []netip.Addr, to netip.Addr) bool {
  594. allow := lh.GetRemoteAllowList().AllowAll(vpnAddrs, to)
  595. if lh.l.Enabled(context.Background(), logging.LevelTrace) {
  596. lh.l.Log(context.Background(), logging.LevelTrace, "remoteAllowList.Allow",
  597. "vpnAddrs", vpnAddrs,
  598. "udpAddr", to,
  599. "allow", allow,
  600. )
  601. }
  602. if !allow {
  603. return false
  604. }
  605. if lh.myVpnNetworksTable.Contains(to) {
  606. return false
  607. }
  608. return true
  609. }
  610. // unlockedShouldAddV4 checks if to is allowed by our allow list
  611. func (lh *LightHouse) unlockedShouldAddV4(vpnAddr netip.Addr, to *V4AddrPort) bool {
  612. udpAddr := protoV4AddrPortToNetAddrPort(to)
  613. allow := lh.GetRemoteAllowList().Allow(vpnAddr, udpAddr.Addr())
  614. if lh.l.Enabled(context.Background(), logging.LevelTrace) {
  615. lh.l.Log(context.Background(), logging.LevelTrace, "remoteAllowList.Allow",
  616. "vpnAddr", vpnAddr,
  617. "udpAddr", udpAddr,
  618. "allow", allow,
  619. )
  620. }
  621. if !allow {
  622. return false
  623. }
  624. if lh.myVpnNetworksTable.Contains(udpAddr.Addr()) {
  625. return false
  626. }
  627. return true
  628. }
  629. // unlockedShouldAddV6 checks if to is allowed by our allow list
  630. func (lh *LightHouse) unlockedShouldAddV6(vpnAddr netip.Addr, to *V6AddrPort) bool {
  631. udpAddr := protoV6AddrPortToNetAddrPort(to)
  632. allow := lh.GetRemoteAllowList().Allow(vpnAddr, udpAddr.Addr())
  633. if lh.l.Enabled(context.Background(), logging.LevelTrace) {
  634. lh.l.Log(context.Background(), logging.LevelTrace, "remoteAllowList.Allow",
  635. "vpnAddr", vpnAddr,
  636. "udpAddr", udpAddr,
  637. "allow", allow,
  638. )
  639. }
  640. if !allow {
  641. return false
  642. }
  643. if lh.myVpnNetworksTable.Contains(udpAddr.Addr()) {
  644. return false
  645. }
  646. return true
  647. }
  648. func (lh *LightHouse) IsLighthouseAddr(vpnAddr netip.Addr) bool {
  649. l := lh.GetLighthouses()
  650. return slices.Contains(l, vpnAddr)
  651. }
  652. func (lh *LightHouse) IsAnyLighthouseAddr(vpnAddrs []netip.Addr) bool {
  653. l := lh.GetLighthouses()
  654. for i := range vpnAddrs {
  655. if slices.Contains(l, vpnAddrs[i]) {
  656. return true
  657. }
  658. }
  659. return false
  660. }
  661. func (lh *LightHouse) startQueryWorker() {
  662. if lh.amLighthouse {
  663. return
  664. }
  665. go func() {
  666. nb := make([]byte, 12, 12)
  667. out := make([]byte, mtu)
  668. for {
  669. select {
  670. case <-lh.ctx.Done():
  671. return
  672. case addr := <-lh.queryChan:
  673. lh.innerQueryServer(addr, nb, out)
  674. }
  675. }
  676. }()
  677. }
  678. func (lh *LightHouse) innerQueryServer(addr netip.Addr, nb, out []byte) {
  679. if lh.IsLighthouseAddr(addr) {
  680. return
  681. }
  682. msg := &NebulaMeta{
  683. Type: NebulaMeta_HostQuery,
  684. Details: &NebulaMetaDetails{},
  685. }
  686. var v1Query, v2Query []byte
  687. var err error
  688. var v cert.Version
  689. queried := 0
  690. lighthouses := lh.GetLighthouses()
  691. for _, lhVpnAddr := range lighthouses {
  692. hi := lh.ifce.GetHostInfo(lhVpnAddr)
  693. if hi != nil {
  694. v = hi.ConnectionState.myCert.Version()
  695. } else {
  696. v = lh.ifce.GetCertState().initiatingVersion
  697. }
  698. if v == cert.Version1 {
  699. if !addr.Is4() {
  700. lh.l.Error("Can't query lighthouse for v6 address using a v1 protocol",
  701. "queryVpnAddr", addr,
  702. "lighthouseAddr", lhVpnAddr,
  703. )
  704. continue
  705. }
  706. if v1Query == nil {
  707. b := addr.As4()
  708. msg.Details.VpnAddr = nil
  709. msg.Details.OldVpnAddr = binary.BigEndian.Uint32(b[:])
  710. v1Query, err = msg.Marshal()
  711. if err != nil {
  712. lh.l.Error("Failed to marshal lighthouse v1 query payload",
  713. "error", err,
  714. "queryVpnAddr", addr,
  715. "lighthouseAddr", lhVpnAddr,
  716. )
  717. continue
  718. }
  719. }
  720. lh.ifce.SendMessageToVpnAddr(header.LightHouse, 0, lhVpnAddr, v1Query, nb, out)
  721. queried++
  722. } else if v == cert.Version2 {
  723. if v2Query == nil {
  724. msg.Details.OldVpnAddr = 0
  725. msg.Details.VpnAddr = netAddrToProtoAddr(addr)
  726. v2Query, err = msg.Marshal()
  727. if err != nil {
  728. lh.l.Error("Failed to marshal lighthouse v2 query payload",
  729. "error", err,
  730. "queryVpnAddr", addr,
  731. "lighthouseAddr", lhVpnAddr,
  732. )
  733. continue
  734. }
  735. }
  736. lh.ifce.SendMessageToVpnAddr(header.LightHouse, 0, lhVpnAddr, v2Query, nb, out)
  737. queried++
  738. } else {
  739. lh.l.Debug("unsupported protocol version",
  740. "op", "query",
  741. "queryVpnAddr", addr,
  742. "version", v,
  743. )
  744. continue
  745. }
  746. }
  747. lh.metricTx(NebulaMeta_HostQuery, int64(queried))
  748. }
  749. func (lh *LightHouse) StartUpdateWorker() {
  750. interval := lh.GetUpdateInterval()
  751. if lh.amLighthouse || interval == 0 {
  752. return
  753. }
  754. clockSource := time.NewTicker(time.Second * time.Duration(interval))
  755. updateCtx, cancel := context.WithCancel(lh.ctx)
  756. lh.updateCancel = cancel
  757. go func() {
  758. defer clockSource.Stop()
  759. for {
  760. lh.SendUpdate()
  761. select {
  762. case <-updateCtx.Done():
  763. return
  764. case <-clockSource.C:
  765. continue
  766. case <-lh.updateTrigger:
  767. continue
  768. }
  769. }
  770. }()
  771. }
  772. // TriggerUpdate requests an immediate lighthouse update. This is a non-blocking
  773. // operation intended to be called after a handshake completes with a lighthouse,
  774. // so the lighthouse has our current addresses without waiting for the next
  775. // periodic update.
  776. func (lh *LightHouse) TriggerUpdate() {
  777. select {
  778. case lh.updateTrigger <- struct{}{}:
  779. default:
  780. }
  781. }
  782. func (lh *LightHouse) SendUpdate() {
  783. var v4 []*V4AddrPort
  784. var v6 []*V6AddrPort
  785. for _, e := range lh.GetAdvertiseAddrs() {
  786. if e.Addr().Is4() {
  787. v4 = append(v4, netAddrToProtoV4AddrPort(e.Addr(), e.Port()))
  788. } else {
  789. v6 = append(v6, netAddrToProtoV6AddrPort(e.Addr(), e.Port()))
  790. }
  791. }
  792. lal := lh.GetLocalAllowList()
  793. for _, e := range lh.localAddrsFn(lal) {
  794. if lh.myVpnNetworksTable.Contains(e) {
  795. continue
  796. }
  797. // Only add addrs that aren't my VPN/tun networks
  798. if e.Is4() {
  799. v4 = append(v4, netAddrToProtoV4AddrPort(e, uint16(lh.nebulaPort)))
  800. } else {
  801. v6 = append(v6, netAddrToProtoV6AddrPort(e, uint16(lh.nebulaPort)))
  802. }
  803. }
  804. nb := make([]byte, 12, 12)
  805. out := make([]byte, mtu)
  806. var v1Update, v2Update []byte
  807. var err error
  808. updated := 0
  809. lighthouses := lh.GetLighthouses()
  810. for _, lhVpnAddr := range lighthouses {
  811. var v cert.Version
  812. hi := lh.ifce.GetHostInfo(lhVpnAddr)
  813. if hi != nil {
  814. v = hi.ConnectionState.myCert.Version()
  815. } else {
  816. v = lh.ifce.GetCertState().initiatingVersion
  817. }
  818. if v == cert.Version1 {
  819. if v1Update == nil {
  820. if !lh.myVpnNetworks[0].Addr().Is4() {
  821. lh.l.Warn("cannot update lighthouse using v1 protocol without an IPv4 address",
  822. "lighthouseAddr", lhVpnAddr,
  823. )
  824. continue
  825. }
  826. var relays []uint32
  827. for _, r := range lh.GetRelaysForMe() {
  828. if !r.Is4() {
  829. continue
  830. }
  831. b := r.As4()
  832. relays = append(relays, binary.BigEndian.Uint32(b[:]))
  833. }
  834. b := lh.myVpnNetworks[0].Addr().As4()
  835. msg := NebulaMeta{
  836. Type: NebulaMeta_HostUpdateNotification,
  837. Details: &NebulaMetaDetails{
  838. V4AddrPorts: v4,
  839. V6AddrPorts: v6,
  840. OldRelayVpnAddrs: relays,
  841. OldVpnAddr: binary.BigEndian.Uint32(b[:]),
  842. },
  843. }
  844. v1Update, err = msg.Marshal()
  845. if err != nil {
  846. lh.l.Error("Error while marshaling for lighthouse v1 update",
  847. "error", err,
  848. "lighthouseAddr", lhVpnAddr,
  849. )
  850. continue
  851. }
  852. }
  853. lh.ifce.SendMessageToVpnAddr(header.LightHouse, 0, lhVpnAddr, v1Update, nb, out)
  854. updated++
  855. } else if v == cert.Version2 {
  856. if v2Update == nil {
  857. var relays []*Addr
  858. for _, r := range lh.GetRelaysForMe() {
  859. relays = append(relays, netAddrToProtoAddr(r))
  860. }
  861. msg := NebulaMeta{
  862. Type: NebulaMeta_HostUpdateNotification,
  863. Details: &NebulaMetaDetails{
  864. V4AddrPorts: v4,
  865. V6AddrPorts: v6,
  866. RelayVpnAddrs: relays,
  867. },
  868. }
  869. v2Update, err = msg.Marshal()
  870. if err != nil {
  871. lh.l.Error("Error while marshaling for lighthouse v2 update",
  872. "error", err,
  873. "lighthouseAddr", lhVpnAddr,
  874. )
  875. continue
  876. }
  877. }
  878. lh.ifce.SendMessageToVpnAddr(header.LightHouse, 0, lhVpnAddr, v2Update, nb, out)
  879. updated++
  880. } else {
  881. lh.l.Debug("unsupported protocol version",
  882. "op", "update",
  883. "version", v,
  884. )
  885. continue
  886. }
  887. }
  888. lh.metricTx(NebulaMeta_HostUpdateNotification, int64(updated))
  889. }
  890. type LightHouseHandler struct {
  891. lh *LightHouse
  892. nb []byte
  893. out []byte
  894. pb []byte
  895. meta *NebulaMeta
  896. l *slog.Logger
  897. }
  898. func (lh *LightHouse) NewRequestHandler() *LightHouseHandler {
  899. lhh := &LightHouseHandler{
  900. lh: lh,
  901. nb: make([]byte, 12, 12),
  902. out: make([]byte, mtu),
  903. l: lh.l,
  904. pb: make([]byte, mtu),
  905. meta: &NebulaMeta{
  906. Details: &NebulaMetaDetails{},
  907. },
  908. }
  909. return lhh
  910. }
  911. func (lh *LightHouse) metricRx(t NebulaMeta_MessageType, i int64) {
  912. lh.metrics.Rx(header.MessageType(t), 0, i)
  913. }
  914. func (lh *LightHouse) metricTx(t NebulaMeta_MessageType, i int64) {
  915. lh.metrics.Tx(header.MessageType(t), 0, i)
  916. }
  917. // This method is similar to Reset(), but it re-uses the pointer structs
  918. // so that we don't have to re-allocate them
  919. func (lhh *LightHouseHandler) resetMeta() *NebulaMeta {
  920. details := lhh.meta.Details
  921. lhh.meta.Reset()
  922. // Keep the array memory around
  923. details.V4AddrPorts = details.V4AddrPorts[:0]
  924. details.V6AddrPorts = details.V6AddrPorts[:0]
  925. details.RelayVpnAddrs = details.RelayVpnAddrs[:0]
  926. details.OldRelayVpnAddrs = details.OldRelayVpnAddrs[:0]
  927. details.OldVpnAddr = 0
  928. details.VpnAddr = nil
  929. lhh.meta.Details = details
  930. return lhh.meta
  931. }
  932. func (lhh *LightHouseHandler) HandleRequest(rAddr netip.AddrPort, fromVpnAddrs []netip.Addr, p []byte, w EncWriter) {
  933. n := lhh.resetMeta()
  934. err := n.Unmarshal(p)
  935. if err != nil {
  936. lhh.l.Error("Failed to unmarshal lighthouse packet",
  937. "error", err,
  938. "vpnAddrs", fromVpnAddrs,
  939. "udpAddr", rAddr,
  940. )
  941. return
  942. }
  943. if n.Details == nil {
  944. lhh.l.Error("Invalid lighthouse update",
  945. "vpnAddrs", fromVpnAddrs,
  946. "udpAddr", rAddr,
  947. )
  948. return
  949. }
  950. lhh.lh.metricRx(n.Type, 1)
  951. switch n.Type {
  952. case NebulaMeta_HostQuery:
  953. lhh.handleHostQuery(n, fromVpnAddrs, rAddr, w)
  954. case NebulaMeta_HostQueryReply:
  955. lhh.handleHostQueryReply(n, fromVpnAddrs)
  956. case NebulaMeta_HostUpdateNotification:
  957. lhh.handleHostUpdateNotification(n, fromVpnAddrs, w)
  958. case NebulaMeta_HostMovedNotification:
  959. case NebulaMeta_HostPunchNotification:
  960. lhh.handleHostPunchNotification(n, fromVpnAddrs, w)
  961. case NebulaMeta_HostUpdateNotificationAck:
  962. // noop
  963. }
  964. }
  965. func (lhh *LightHouseHandler) handleHostQuery(n *NebulaMeta, fromVpnAddrs []netip.Addr, addr netip.AddrPort, w EncWriter) {
  966. // Exit if we don't answer queries
  967. if !lhh.lh.amLighthouse {
  968. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  969. lhh.l.Debug("I don't answer queries, but received one", "from", addr)
  970. }
  971. return
  972. }
  973. queryVpnAddr, useVersion, err := n.Details.GetVpnAddrAndVersion()
  974. if err != nil {
  975. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  976. lhh.l.Debug("Dropping malformed HostQuery",
  977. "from", fromVpnAddrs,
  978. "details", n.Details,
  979. )
  980. }
  981. return
  982. }
  983. if useVersion == cert.Version1 && queryVpnAddr.Is6() {
  984. // this case really shouldn't be possible to represent, but reject it anyway.
  985. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  986. lhh.l.Debug("invalid vpn addr for v1 handleHostQuery",
  987. "vpnAddrs", fromVpnAddrs,
  988. "queryVpnAddr", queryVpnAddr,
  989. )
  990. }
  991. return
  992. }
  993. // Don't respond to requests for us.
  994. if lhh.lh.myVpnAddrsTable.Contains(queryVpnAddr) {
  995. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  996. lhh.l.Debug("Ignoring HostQuery for one of my own addresses",
  997. "fromVpnAddrs", fromVpnAddrs,
  998. "queryVpnAddr", queryVpnAddr,
  999. )
  1000. }
  1001. return
  1002. }
  1003. found, ln, err := lhh.lh.queryAndPrepMessage(queryVpnAddr, func(c *cache) (int, error) {
  1004. n = lhh.resetMeta()
  1005. n.Type = NebulaMeta_HostQueryReply
  1006. if useVersion == cert.Version1 {
  1007. b := queryVpnAddr.As4()
  1008. n.Details.OldVpnAddr = binary.BigEndian.Uint32(b[:])
  1009. } else {
  1010. n.Details.VpnAddr = netAddrToProtoAddr(queryVpnAddr)
  1011. }
  1012. lhh.coalesceAnswers(useVersion, c, n)
  1013. return n.MarshalTo(lhh.pb)
  1014. })
  1015. if !found {
  1016. return
  1017. }
  1018. if err != nil {
  1019. lhh.l.Error("Failed to marshal lighthouse host query reply",
  1020. "error", err,
  1021. "vpnAddrs", fromVpnAddrs,
  1022. )
  1023. return
  1024. }
  1025. lhh.lh.metricTx(NebulaMeta_HostQueryReply, 1)
  1026. w.SendMessageToVpnAddr(header.LightHouse, 0, fromVpnAddrs[0], lhh.pb[:ln], lhh.nb, lhh.out[:0])
  1027. lhh.sendHostPunchNotification(n, fromVpnAddrs, queryVpnAddr, w)
  1028. }
  1029. // sendHostPunchNotification signals the other side to punch some zero byte udp packets
  1030. func (lhh *LightHouseHandler) sendHostPunchNotification(n *NebulaMeta, fromVpnAddrs []netip.Addr, punchNotifDest netip.Addr, w EncWriter) {
  1031. whereToPunch := fromVpnAddrs[0]
  1032. found, ln, err := lhh.lh.queryAndPrepMessage(whereToPunch, func(c *cache) (int, error) {
  1033. n = lhh.resetMeta()
  1034. n.Type = NebulaMeta_HostPunchNotification
  1035. targetHI := lhh.lh.ifce.GetHostInfo(punchNotifDest)
  1036. var useVersion cert.Version
  1037. if targetHI == nil {
  1038. useVersion = lhh.lh.ifce.GetCertState().initiatingVersion
  1039. } else {
  1040. crt := targetHI.GetCert().Certificate
  1041. useVersion = crt.Version()
  1042. // we can only retarget if we have a hostinfo
  1043. newDest, ok := findNetworkUnion(crt.Networks(), fromVpnAddrs)
  1044. if ok {
  1045. whereToPunch = newDest
  1046. } else {
  1047. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1048. lhh.l.Debug("unable to punch to host, no addresses in common",
  1049. "to", crt.Networks(),
  1050. )
  1051. }
  1052. }
  1053. }
  1054. if useVersion == cert.Version1 {
  1055. if !whereToPunch.Is4() {
  1056. return 0, fmt.Errorf("invalid vpn addr for v1 handleHostQuery")
  1057. }
  1058. b := whereToPunch.As4()
  1059. n.Details.OldVpnAddr = binary.BigEndian.Uint32(b[:])
  1060. } else if useVersion == cert.Version2 {
  1061. n.Details.VpnAddr = netAddrToProtoAddr(whereToPunch)
  1062. } else {
  1063. return 0, errors.New("unsupported version")
  1064. }
  1065. lhh.coalesceAnswers(useVersion, c, n)
  1066. return n.MarshalTo(lhh.pb)
  1067. })
  1068. if !found {
  1069. return
  1070. }
  1071. if err != nil {
  1072. lhh.l.Error("Failed to marshal lighthouse host was queried for",
  1073. "error", err,
  1074. "vpnAddrs", fromVpnAddrs,
  1075. )
  1076. return
  1077. }
  1078. lhh.lh.metricTx(NebulaMeta_HostPunchNotification, 1)
  1079. w.SendMessageToVpnAddr(header.LightHouse, 0, punchNotifDest, lhh.pb[:ln], lhh.nb, lhh.out[:0])
  1080. }
  1081. func (lhh *LightHouseHandler) coalesceAnswers(v cert.Version, c *cache, n *NebulaMeta) {
  1082. if c.v4 != nil {
  1083. if c.v4.learned != nil {
  1084. n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.learned)
  1085. }
  1086. if c.v4.reported != nil && len(c.v4.reported) > 0 {
  1087. n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.reported...)
  1088. }
  1089. }
  1090. if c.v6 != nil {
  1091. if c.v6.learned != nil {
  1092. n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.learned)
  1093. }
  1094. if c.v6.reported != nil && len(c.v6.reported) > 0 {
  1095. n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.reported...)
  1096. }
  1097. }
  1098. if c.relay != nil {
  1099. if v == cert.Version1 {
  1100. b := [4]byte{}
  1101. for _, r := range c.relay.relay {
  1102. if !r.Is4() {
  1103. continue
  1104. }
  1105. b = r.As4()
  1106. n.Details.OldRelayVpnAddrs = append(n.Details.OldRelayVpnAddrs, binary.BigEndian.Uint32(b[:]))
  1107. }
  1108. } else if v == cert.Version2 {
  1109. for _, r := range c.relay.relay {
  1110. n.Details.RelayVpnAddrs = append(n.Details.RelayVpnAddrs, netAddrToProtoAddr(r))
  1111. }
  1112. } else {
  1113. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1114. lhh.l.Debug("unsupported protocol version",
  1115. "op", "coalesceAnswers",
  1116. "version", v,
  1117. )
  1118. }
  1119. }
  1120. }
  1121. }
  1122. func (lhh *LightHouseHandler) handleHostQueryReply(n *NebulaMeta, fromVpnAddrs []netip.Addr) {
  1123. if !lhh.lh.IsAnyLighthouseAddr(fromVpnAddrs) {
  1124. return
  1125. }
  1126. certVpnAddr, _, err := n.Details.GetVpnAddrAndVersion()
  1127. if err != nil {
  1128. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1129. lhh.l.Error("dropping malformed HostQueryReply",
  1130. "error", err,
  1131. "vpnAddrs", fromVpnAddrs,
  1132. )
  1133. }
  1134. return
  1135. }
  1136. relays := n.Details.GetRelays()
  1137. lhh.lh.Lock()
  1138. am := lhh.lh.unlockedGetRemoteList([]netip.Addr{certVpnAddr})
  1139. am.Lock()
  1140. lhh.lh.Unlock()
  1141. am.unlockedSetV4(fromVpnAddrs[0], certVpnAddr, n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4)
  1142. am.unlockedSetV6(fromVpnAddrs[0], certVpnAddr, n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6)
  1143. am.unlockedSetRelay(fromVpnAddrs[0], relays)
  1144. am.Unlock()
  1145. // Non-blocking attempt to trigger, skip if it would block
  1146. select {
  1147. case lhh.lh.handshakeTrigger <- certVpnAddr:
  1148. default:
  1149. }
  1150. }
  1151. func (lhh *LightHouseHandler) handleHostUpdateNotification(n *NebulaMeta, fromVpnAddrs []netip.Addr, w EncWriter) {
  1152. if !lhh.lh.amLighthouse {
  1153. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1154. lhh.l.Debug("I am not a lighthouse, do not take host updates", "from", fromVpnAddrs)
  1155. }
  1156. return
  1157. }
  1158. // not using GetVpnAddrAndVersion because we don't want to error on a blank detailsVpnAddr
  1159. var detailsVpnAddr netip.Addr
  1160. var useVersion cert.Version
  1161. if n.Details.OldVpnAddr != 0 { //v1 always sets this field
  1162. b := [4]byte{}
  1163. binary.BigEndian.PutUint32(b[:], n.Details.OldVpnAddr)
  1164. detailsVpnAddr = netip.AddrFrom4(b)
  1165. useVersion = cert.Version1
  1166. } else if n.Details.VpnAddr != nil { //this field is "optional" in v2, but if it's set, we should enforce it
  1167. detailsVpnAddr = protoAddrToNetAddr(n.Details.VpnAddr)
  1168. useVersion = cert.Version2
  1169. } else {
  1170. detailsVpnAddr = netip.Addr{}
  1171. useVersion = cert.Version2
  1172. }
  1173. //Simple check that the host sent this not someone else, if detailsVpnAddr is filled
  1174. if detailsVpnAddr.IsValid() && !slices.Contains(fromVpnAddrs, detailsVpnAddr) {
  1175. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1176. lhh.l.Debug("Host sent invalid update",
  1177. "vpnAddrs", fromVpnAddrs,
  1178. "answer", detailsVpnAddr,
  1179. )
  1180. }
  1181. return
  1182. }
  1183. relays := n.Details.GetRelays()
  1184. lhh.lh.Lock()
  1185. am := lhh.lh.unlockedGetRemoteList(fromVpnAddrs)
  1186. am.Lock()
  1187. lhh.lh.Unlock()
  1188. am.unlockedSetV4(fromVpnAddrs[0], fromVpnAddrs[0], n.Details.V4AddrPorts, lhh.lh.unlockedShouldAddV4)
  1189. am.unlockedSetV6(fromVpnAddrs[0], fromVpnAddrs[0], n.Details.V6AddrPorts, lhh.lh.unlockedShouldAddV6)
  1190. am.unlockedSetRelay(fromVpnAddrs[0], relays)
  1191. am.Unlock()
  1192. n = lhh.resetMeta()
  1193. n.Type = NebulaMeta_HostUpdateNotificationAck
  1194. switch useVersion {
  1195. case cert.Version1:
  1196. if !fromVpnAddrs[0].Is4() {
  1197. lhh.l.Error("Can not send HostUpdateNotificationAck for a ipv6 vpn ip in a v1 message",
  1198. "vpnAddrs", fromVpnAddrs,
  1199. )
  1200. return
  1201. }
  1202. vpnAddrB := fromVpnAddrs[0].As4()
  1203. n.Details.OldVpnAddr = binary.BigEndian.Uint32(vpnAddrB[:])
  1204. case cert.Version2:
  1205. // do nothing, we want to send a blank message
  1206. default:
  1207. lhh.l.Error("invalid protocol version", "useVersion", useVersion)
  1208. return
  1209. }
  1210. ln, err := n.MarshalTo(lhh.pb)
  1211. if err != nil {
  1212. lhh.l.Error("Failed to marshal lighthouse host update ack",
  1213. "error", err,
  1214. "vpnAddrs", fromVpnAddrs,
  1215. )
  1216. return
  1217. }
  1218. lhh.lh.metricTx(NebulaMeta_HostUpdateNotificationAck, 1)
  1219. w.SendMessageToVpnAddr(header.LightHouse, 0, fromVpnAddrs[0], lhh.pb[:ln], lhh.nb, lhh.out[:0])
  1220. }
  1221. func (lhh *LightHouseHandler) handleHostPunchNotification(n *NebulaMeta, fromVpnAddrs []netip.Addr, w EncWriter) {
  1222. //It's possible the lighthouse is communicating with us using a non primary vpn addr,
  1223. //which means we need to compare all fromVpnAddrs against all configured lighthouse vpn addrs.
  1224. if !lhh.lh.IsAnyLighthouseAddr(fromVpnAddrs) {
  1225. return
  1226. }
  1227. detailsVpnAddr, _, err := n.Details.GetVpnAddrAndVersion()
  1228. if err != nil {
  1229. if lhh.l.Enabled(context.Background(), slog.LevelDebug) {
  1230. lhh.l.Debug("dropping invalid HostPunchNotification",
  1231. "details", n.Details,
  1232. "error", err,
  1233. )
  1234. }
  1235. return
  1236. }
  1237. remoteAllowList := lhh.lh.GetRemoteAllowList()
  1238. for _, a := range n.Details.V4AddrPorts {
  1239. if a == nil {
  1240. continue
  1241. }
  1242. b := protoV4AddrPortToNetAddrPort(a)
  1243. if remoteAllowList.Allow(detailsVpnAddr, b.Addr()) {
  1244. lhh.lh.punchy.Schedule(b, detailsVpnAddr)
  1245. }
  1246. }
  1247. for _, a := range n.Details.V6AddrPorts {
  1248. if a == nil {
  1249. continue
  1250. }
  1251. b := protoV6AddrPortToNetAddrPort(a)
  1252. if remoteAllowList.Allow(detailsVpnAddr, b.Addr()) {
  1253. lhh.lh.punchy.Schedule(b, detailsVpnAddr)
  1254. }
  1255. }
  1256. // This sends a nebula test packet to the host trying to contact us. In the case
  1257. // of a double nat or other difficult scenario, this may help establish
  1258. // a tunnel. ScheduleRespond is a no-op when punchy.respond is disabled.
  1259. lhh.lh.punchy.ScheduleRespond(detailsVpnAddr)
  1260. }
  1261. func protoAddrToNetAddr(addr *Addr) netip.Addr {
  1262. b := [16]byte{}
  1263. binary.BigEndian.PutUint64(b[:8], addr.Hi)
  1264. binary.BigEndian.PutUint64(b[8:], addr.Lo)
  1265. return netip.AddrFrom16(b).Unmap()
  1266. }
  1267. func protoV4AddrPortToNetAddrPort(ap *V4AddrPort) netip.AddrPort {
  1268. b := [4]byte{}
  1269. binary.BigEndian.PutUint32(b[:], ap.Addr)
  1270. return netip.AddrPortFrom(netip.AddrFrom4(b), uint16(ap.Port))
  1271. }
  1272. func protoV6AddrPortToNetAddrPort(ap *V6AddrPort) netip.AddrPort {
  1273. b := [16]byte{}
  1274. binary.BigEndian.PutUint64(b[:8], ap.Hi)
  1275. binary.BigEndian.PutUint64(b[8:], ap.Lo)
  1276. return netip.AddrPortFrom(netip.AddrFrom16(b).Unmap(), uint16(ap.Port))
  1277. }
  1278. func netAddrToProtoAddr(addr netip.Addr) *Addr {
  1279. b := addr.As16()
  1280. return &Addr{
  1281. Hi: binary.BigEndian.Uint64(b[:8]),
  1282. Lo: binary.BigEndian.Uint64(b[8:]),
  1283. }
  1284. }
  1285. func netAddrToProtoV4AddrPort(addr netip.Addr, port uint16) *V4AddrPort {
  1286. v4Addr := addr.As4()
  1287. return &V4AddrPort{
  1288. Addr: binary.BigEndian.Uint32(v4Addr[:]),
  1289. Port: uint32(port),
  1290. }
  1291. }
  1292. func netAddrToProtoV6AddrPort(addr netip.Addr, port uint16) *V6AddrPort {
  1293. v6Addr := addr.As16()
  1294. return &V6AddrPort{
  1295. Hi: binary.BigEndian.Uint64(v6Addr[:8]),
  1296. Lo: binary.BigEndian.Uint64(v6Addr[8:]),
  1297. Port: uint32(port),
  1298. }
  1299. }
  1300. func (d *NebulaMetaDetails) GetRelays() []netip.Addr {
  1301. var relays []netip.Addr
  1302. if len(d.OldRelayVpnAddrs) > 0 {
  1303. b := [4]byte{}
  1304. for _, r := range d.OldRelayVpnAddrs {
  1305. binary.BigEndian.PutUint32(b[:], r)
  1306. relays = append(relays, netip.AddrFrom4(b))
  1307. }
  1308. }
  1309. if len(d.RelayVpnAddrs) > 0 {
  1310. for _, r := range d.RelayVpnAddrs {
  1311. if r != nil {
  1312. relays = append(relays, protoAddrToNetAddr(r))
  1313. }
  1314. }
  1315. }
  1316. return relays
  1317. }
  1318. // FindNetworkUnion returns the first netip.Addr contained in the list of provided netip.Prefix, if able
  1319. func findNetworkUnion(prefixes []netip.Prefix, addrs []netip.Addr) (netip.Addr, bool) {
  1320. for i := range prefixes {
  1321. for j := range addrs {
  1322. if prefixes[i].Contains(addrs[j]) {
  1323. return addrs[j], true
  1324. }
  1325. }
  1326. }
  1327. return netip.Addr{}, false
  1328. }
  1329. func (d *NebulaMetaDetails) GetVpnAddrAndVersion() (netip.Addr, cert.Version, error) {
  1330. if d.OldVpnAddr != 0 {
  1331. b := [4]byte{}
  1332. binary.BigEndian.PutUint32(b[:], d.OldVpnAddr)
  1333. detailsVpnAddr := netip.AddrFrom4(b)
  1334. return detailsVpnAddr, cert.Version1, nil
  1335. } else if d.VpnAddr != nil {
  1336. detailsVpnAddr := protoAddrToNetAddr(d.VpnAddr)
  1337. return detailsVpnAddr, cert.Version2, nil
  1338. } else {
  1339. return netip.Addr{}, cert.Version1, ErrBadDetailsVpnAddr
  1340. }
  1341. }