logpolicy: extend the gokrazy/natlab wait-for-network delay for IPv6

Really we need to fix logpolicy + bootstrapDNS to not be so aggressive,
but this is a quick workaround meanwhile.

Without this, tailscaled starts immediately while IPv6 DAD is
happening for a couple seconds and logpolicy freaks out without the
network available and starts spamming stderr about bootstrap DNS
options. But we see that regularly anyway from people whose wifi is
down. So we need to fix the general case. This is not that fix.

Updates #13038

Change-Id: Iba7e536d08e59d34abded1d279f88fdc9c46d94d
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-08-25 20:37:25 -07:00 committed by Brad Fitzpatrick
parent 2636a83d0e
commit 9f7683e2a1

View File

@ -18,6 +18,7 @@
"log" "log"
"net" "net"
"net/http" "net/http"
"net/netip"
"net/url" "net/url"
"os" "os"
"os/exec" "os/exec"
@ -835,8 +836,20 @@ func awaitGokrazyNetwork() {
// Before DHCP finishes, the /etc/resolv.conf file has just "#MANUAL". // Before DHCP finishes, the /etc/resolv.conf file has just "#MANUAL".
all, _ := os.ReadFile("/etc/resolv.conf") all, _ := os.ReadFile("/etc/resolv.conf")
if bytes.Contains(all, []byte("nameserver ")) { if bytes.Contains(all, []byte("nameserver ")) {
good := true
firstLine, _, ok := strings.Cut(string(all), "\n")
if ok {
ns, ok := strings.CutPrefix(firstLine, "nameserver ")
if ok {
if ip, err := netip.ParseAddr(ns); err == nil && ip.Is6() && !ip.IsLinkLocalUnicast() {
good = haveGlobalUnicastIPv6()
}
}
}
if good {
return return
} }
}
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
@ -844,3 +857,27 @@ func awaitGokrazyNetwork() {
} }
} }
} }
// haveGlobalUnicastIPv6 reports whether the machine has a IPv6 non-private
// (non-ULA) global unicast address.
//
// It's only intended for use in natlab integration tests so only works on
// Linux/macOS now and not environments (such as Android) where net.Interfaces
// doesn't work directly.
func haveGlobalUnicastIPv6() bool {
ifs, _ := net.Interfaces()
for _, ni := range ifs {
aa, _ := ni.Addrs()
for _, a := range aa {
ipn, ok := a.(*net.IPNet)
if !ok {
continue
}
ip, _ := netip.AddrFromSlice(ipn.IP)
if ip.Is6() && ip.IsGlobalUnicast() && !ip.IsPrivate() {
return true
}
}
}
return false
}