Skip to content

LightHouse addrMap

John Maguire edited this page Oct 23, 2024 · 3 revisions

This is an incomplete, point-in-time, high-level overview of how LightHouse.addrMap is maintained in Nebula.

When Nebula starts, it constructs a single LightHouse struct used for the duration of the process. It persists across reloads.

A LightHouse contains an addrMap (map[iputil.VpnIp]*RemoteList) mapping all of the VPN IPs it is tracking to their associated underlays. addrMap lives for the duration of the process.

RemoteList structs contains a deduplicated set of addresses (addrs) and relays (relays) that can be used to talk to a given VPN IP. These two fields are populated by unlockedCollect and deduped by unlockedSort, based on the cache and hostnameResults objects).) RemoteList entries are deleted by DeleteVpnIp when a tunnel is closed or detected dead (unless the VPN IP is in the static host map - we can't delete these or we wouldn't learn them again until Nebula is reloaded!) They are created on the fly by unlockedGetRemoteList if they don't already exist for a given VPN IP, e.g. inside addStaticRemotes , QueryCache, addCalculatedRemotes, handleHostUpdateInformation, handleHostQueryReply, etc.

RemoteList.cache (map[iputil.VpnIp]*cache) maps an "owner" or "source" of an underlay IP address (i.e. a Lighthouse IP or our own IP if the underlay IP was discovered via an incoming handshake) to possible IPv4/relay, IPv6/relay, direct IPv4 and direct IPv6 underlay addresses. This is where

RemoteList.hr (*hostnamesResults ) is a struct used by RemoteList primarily to manage a background goroutine polling for DNS updates to static_host_map entries. When LightHouse is (re-)loaded addStaticRemotes iterates all the entries and calls NewHostnameResults for each VPN IP listed. During construction, Nebula separates ip:port entries from host:port entries. The ip:port entries are immediately stored in the hostnameResults and returned. Meanwhile a background goroutine begins to poll the configured DNS server for hostnames on a configured cadence.

The background goroutine loop attempts to resolve all known DNS names and IP addresses (which are returned unmodified.) DNS resolution errors are logged but otherwise ignored. When the goroutine finishes, the previous list of ip:port entries is combined against the new list of ip:port entries. If there is any difference, the old list is replaced with the new list. This means that any temporary DNS failures will result in temporarily "forgetting" an ip:port combination. If all DNS queries fail, Nebula will forget all associated ip:port combinations. Normally this is not an issue as the static_host_map is mainly used to connect to the Lighthouse, and connections to the Lighthouse tend to be persistent once established.

Untitled Diagram drawio(2)

Clone this wiki locally