lighthouse.go 42 KB

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