Advertise underlay addresses on Android

On Android 11+ the app sandbox denies bind() on netlink_route_socket, so
the stdlib's net.Interfaces fails with EACCES. localAddrs discarded that
error and returned an empty slice, so the node advertised no underlay
addresses and peers could only ever reach it at the address a lighthouse
observed. A device on the same LAN as a peer was unreachable at its LAN
address.

Split interface enumeration behind a build-tagged seam and use
github.com/wlynxg/anet on Android, which reads RTM_GETADDR from an
unbound socket. Interface addresses have to come from anet as well, since
net.Interface.Addrs goes back through the same denied path. Every other
platform keeps the net package implementation.

Stop discarding the enumeration errors, which are exceptional now that
the sandbox case is handled.

anet needs -ldflags=-checklinkname=0 on Go 1.23+. Nebula ships no Android
binaries, so build-test-mobile is unaffected, but consumers linking
Android artifacts will need the flag.
This commit is contained in:
John Maguire
2026-07-24 15:06:29 -04:00
parent 72bf111209
commit 8cbee0e965
6 changed files with 161 additions and 2 deletions
+28 -2
View File
@@ -869,9 +869,27 @@ func (i *HostInfo) logger(l *slog.Logger) *slog.Logger {
// Utility functions
func localAddrs(l *slog.Logger, allowList *LocalAllowList) []netip.Addr {
return collectLocalAddrs(l, allowList, localInterfaces, localInterfaceAddrs)
}
// collectLocalAddrs takes its enumerators as arguments so tests can drive the filtering and the
// failure branches without depending on the addresses of whatever host they run on.
func collectLocalAddrs(
l *slog.Logger,
allowList *LocalAllowList,
interfaces func() ([]net.Interface, error),
interfaceAddrs func(*net.Interface) ([]net.Addr, error),
) []netip.Addr {
//FIXME: This function is pretty garbage
var finalAddrs []netip.Addr
ifaces, _ := net.Interfaces()
ifaces, err := interfaces()
if err != nil {
l.Warn("Failed to enumerate local interfaces, no underlay addresses will be advertised to lighthouses",
"error", err,
)
return nil
}
for _, i := range ifaces {
allow := allowList.AllowName(i.Name)
if l.Enabled(context.Background(), logging.LevelTrace) {
@@ -884,7 +902,15 @@ func localAddrs(l *slog.Logger, allowList *LocalAllowList) []netip.Addr {
if !allow {
continue
}
addrs, _ := i.Addrs()
addrs, err := interfaceAddrs(&i)
if err != nil {
l.Warn("Failed to get addresses for local interface",
"error", err,
"interfaceName", i.Name,
)
continue
}
for _, rawAddr := range addrs {
var addr netip.Addr
switch v := rawAddr.(type) {