|
|
|
@ -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()
|
|
|
|
|