fix-probe-resolver-ports
Isolation probe: no netlink; "resolver is not the box's own address" moves root-side (#126)
This blocks production. After v0.25.0 rolled, every dev box reported ready: false, so nested-by-default never fired. The one failing line was:
resolver-ports fail interface addresses: route ip+net: netlinkrib: address family not supported by protocol
The probe called net.InterfaceAddrs, which uses netlink. carlos-instance-probe.service has RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX, the same as every instance unit, so that call could never succeed.
What changes
- Root side (
internal/instancectl):resolverAllownow takes the box's local prefixes and leaves out any nameserver inside one. The rule is enforced where the allow is written. - The control unit isRestrictAddressFamilies=AF_UNIX, so it can't use netlink either (the brief's premise that it isn't restricted is wrong). It reads procfs instead:/proc/net/fib_triefor IPv4 LOCAL routes, including whole local ranges like 127.0.0.0/8, and/proc/net/if_inet6. Reading a file needs no socket. - A refused resolver shows up as a new failingresolver-localline in the probe report, so the box stays not ready, the same outcome as before. - If the addresses can't be read, the allow is reset to empty andresolver-allowfails. An allow that might name the box is never written. A nilLocalAddrsalso closes every resolver. - Probe (
internal/instanceexec):localAddrsandinterfaceAddrsare gone.resolver-portskeeps only what it can test from inside the unit: an allowed resolver doesn't answer on TCP 22. - No unit changes. Nothing gains AF_NETLINK: not the instance templates, not the probe unit, not the control unit.
- Spec §egress paragraph updated.
Can the same thing hit instance units at runtime?
No.
- New test
TestInstanceCodeOpensOnlyTheUnitsAddressFamilieswalks every platform package that instanceexec builds from (probe, trampolineinstance-exec,instance-exit, instancectl, and their platform imports), as linux sees them. - It refusesnet.Interfaces,net.InterfaceAddrsandnet.InterfaceBy*,syscall.NetlinkRIB, and anyAF_*outside INET, INET6, UNIX and UNSPEC. - It fails on main withprobe.go: net.InterfaceAddrs. - Third-party code, checked by hand: the only such call is google/uuid's
net.Interfaces, reached only for v1/v6 UUIDs, and nothing here makes those. - The binary is
CGO_ENABLED=0, so DNS never goes through glibc's netlink use. - Go's IPv6 zone cache only touches netlink for zoned addresses. Those are link-local, which the fence denies anyway, and on failure it falls back to the numeric zone.
How tested
- Red first, on main: a probe run with interface listing failing exactly as on the fleet gave
resolver-ports fail interface addresses: route ip+net: netlinkrib: .... That seam no longer exists. The lasting red-on-main test is the walk above. - New instancectl tests: - the box's own address is refused, including inside a local range -
RunProbewith a local resolver: the allow is written empty and the report is not ready, with aresolver-localfail line - a good resolver gives an ok line - address listing erroring, or nil: the allow is reset andresolver-allowfails - fibtrie and ifinet6 parsing from an EC2-shaped fixture; a missing ifinet6 means no v6; a fibtrie with no LOCAL route is refused - Sanity checks on a real Debian 13 host: -
localPrefixesagainst the live procfs matches the interface addresses. - In a transient user unit withRestrictAddressFamilies=AF_UNIX ProtectKernelTunables=yes ProtectSystem=strict PrivateDevices=yes,ip addrfails with "Cannot open netlink socket: Address family not supported by protocol", while both procfs files read fine. - Caveat: that was the user manager, not the system one. - Gate: gofmt clean, build and vet clean,
make test: everything passes except known environment failures: - socket-path length (bind/connect EINVAL) in instanceexec, activator, edge and host - the root package reading ~/.carlos/config
Deliberately not done
- No AF_NETLINK anywhere.
- IPv6 local ranges, such as AnyIP routes, aren't read; only IPv6 interface addresses are. That is the same coverage the probe had.
- The probe's
dnsline also fails for a refused local resolver, because sendto gets EPERM. That is expected:resolver-localgives the reason.
Needs a release and roll to reach the fleet. A box becomes ready on its next probe after the control service restarts on the new binary.
Commits
0
Discussions
0
0 open
Tasks
0/0
done
Discussions
- No discussions on this branch yet.
Tasks
- No tasks yet.
Activity
- No activity yet.