Using ControlD bootstrap DNS again

So on system where there's no available DNS, non-ControlD upstreams
could be bootstrapped like before.

While at it, also improving lookupIP to not initializing OS resolver
anymore, removing the un-necessary contention for accquiring/releasing
OS resolver mutex.
This commit is contained in:
Cuong Manh Le authored and Cuong Manh Le committed 2025-04-17 17:15:15 +07:00
1 parent 8d6ea91f35
commit 0c2cc00c4f
2 files changed
+24 -13

No files matched your search

+13 -1
View File
@@ -427,11 +427,18 @@ func (uc *UpstreamConfig) UID() string {
// SetupBootstrapIP manually find all available IPs of the upstream. // SetupBootstrapIP manually find all available IPs of the upstream.
// The first usable IP will be used as bootstrap IP of the upstream. // The first usable IP will be used as bootstrap IP of the upstream.
// The upstream domain will be looked up using following orders:
//
// - Current system DNS settings.
// - Direct IPs table for ControlD upstreams.
// - ControlD Bootstrap DNS 76.76.2.22
//
// The setup process will block until there's usable IPs found.
func (uc *UpstreamConfig) SetupBootstrapIP() { func (uc *UpstreamConfig) SetupBootstrapIP() {
b := backoff.NewBackoff("setupBootstrapIP", func(format string, args ...any) {}, 10*time.Second) b := backoff.NewBackoff("setupBootstrapIP", func(format string, args ...any) {}, 10*time.Second)
isControlD := uc.IsControlD() isControlD := uc.IsControlD()
for { for {
uc.bootstrapIPs = lookupIP(uc.Domain, uc.Timeout) uc.bootstrapIPs = lookupIP(uc.Domain, uc.Timeout, defaultNameservers())
// For ControlD upstream, the bootstrap IPs could not be RFC 1918 addresses, // For ControlD upstream, the bootstrap IPs could not be RFC 1918 addresses,
// filtering them out here to prevent weird behavior. // filtering them out here to prevent weird behavior.
if isControlD { if isControlD {
@@ -449,6 +456,11 @@ func (uc *UpstreamConfig) SetupBootstrapIP() {
ProxyLogger.Load().Warn().Msgf("no record found for %q, lookup from direct IP table", uc.Domain) ProxyLogger.Load().Warn().Msgf("no record found for %q, lookup from direct IP table", uc.Domain)
} }
} }
if len(uc.bootstrapIPs) == 0 {
ProxyLogger.Load().Warn().Msgf("no record found for %q, using bootstrap server: %s", uc.Domain, PremiumDNSBoostrapIP)
uc.bootstrapIPs = lookupIP(uc.Domain, uc.Timeout, []string{net.JoinHostPort(PremiumDNSBoostrapIP, "53")})
}
if len(uc.bootstrapIPs) > 0 { if len(uc.bootstrapIPs) > 0 {
break break
} }
+11 -12
View File
@@ -466,27 +466,26 @@ func (d dummyResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, err
return ans, nil return ans, nil
} }
// LookupIP looks up host using OS resolver. // LookupIP looks up domain using current system nameservers settings.
// It returns a slice of that host's IPv4 and IPv6 addresses. // It returns a slice of that host's IPv4 and IPv6 addresses.
func LookupIP(domain string) []string { func LookupIP(domain string) []string {
return lookupIP(domain, -1) return lookupIP(domain, -1, defaultNameservers())
} }
func lookupIP(domain string, timeout int) (ips []string) { // lookupIP looks up domain with given timeout and bootstrapDNS.
// If timeout is negative, default timeout 2000 ms will be used.
// It returns nil if bootstrapDNS is nil or empty.
func lookupIP(domain string, timeout int, bootstrapDNS []string) (ips []string) {
if net.ParseIP(domain) != nil { if net.ParseIP(domain) != nil {
return []string{domain} return []string{domain}
} }
resolverMutex.Lock() if bootstrapDNS == nil {
if or == nil { ProxyLogger.Load().Debug().Msgf("empty bootstrap DNS")
ProxyLogger.Load().Debug().Msgf("Initialize OS resolver in lookupIP") return nil
or = newResolverWithNameserver(defaultNameservers())
} }
nss := *or.lanServers.Load()
nss = append(nss, *or.publicServers.Load()...)
resolverMutex.Unlock()
resolver := newResolverWithNameserver(nss) resolver := newResolverWithNameserver(bootstrapDNS)
ProxyLogger.Load().Debug().Msgf("resolving %q using bootstrap DNS %q", domain, nss) ProxyLogger.Load().Debug().Msgf("resolving %q using bootstrap DNS %q", domain, bootstrapDNS)
timeoutMs := 2000 timeoutMs := 2000
if timeout > 0 && timeout < timeoutMs { if timeout > 0 && timeout < timeoutMs {
timeoutMs = timeout timeoutMs = timeout