net/dnsfallback: fix infinite loop and limit number of candidates

Updates #1455 (fixes the DNS spin part, but other things aren't ideal there)

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/1428/head
Brad Fitzpatrick 3 years ago
parent 63a9adeb6c
commit d37b3b02cd

@ -30,26 +30,40 @@ func Lookup(ctx context.Context, host string) ([]netaddr.IP, error) {
ip netaddr.IP
}
var cands []nameIP
dm := derpmap.Prod()
var cands4, cands6 []nameIP
for _, dr := range dm.Regions {
for _, n := range dr.Nodes {
if ip, err := netaddr.ParseIP(n.IPv4); err == nil {
cands = append(cands, nameIP{n.HostName, ip})
cands4 = append(cands4, nameIP{n.HostName, ip})
}
if ip, err := netaddr.ParseIP(n.IPv6); err == nil {
cands = append(cands, nameIP{n.HostName, ip})
cands6 = append(cands6, nameIP{n.HostName, ip})
}
}
}
rand.Shuffle(len(cands), func(i, j int) {
cands[i], cands[j] = cands[j], cands[i]
})
rand.Shuffle(len(cands4), func(i, j int) { cands4[i], cands4[j] = cands4[j], cands4[i] })
rand.Shuffle(len(cands6), func(i, j int) { cands6[i], cands6[j] = cands6[j], cands6[i] })
const maxCands = 6
var cands []nameIP // up to maxCands alternating v4/v6 as long as we have both
for (len(cands4) > 0 || len(cands6) > 0) && len(cands) < maxCands {
if len(cands4) > 0 {
cands = append(cands, cands4[0])
cands4 = cands4[1:]
}
if len(cands6) > 0 {
cands = append(cands, cands6[0])
cands6 = cands6[1:]
}
}
if len(cands) == 0 {
return nil, fmt.Errorf("no DNS fallback options for %q", host)
}
for ctx.Err() == nil && len(cands) > 0 {
cand := cands[0]
for _, cand := range cands {
if err := ctx.Err(); err != nil {
return nil, err
}
log.Printf("trying bootstrapDNS(%q, %q) for %q ...", cand.dnsName, cand.ip, host)
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()

Loading…
Cancel
Save