Support multiple fallback resolvers

This commit is contained in:
Frank Denis 2020-01-15 19:58:14 +01:00
parent f1bd4bf420
commit 7ada3fcfb8
3 changed files with 43 additions and 20 deletions

View File

@ -76,6 +76,7 @@ type Config struct {
SourceIPv6 bool `toml:"ipv6_servers"`
MaxClients uint32 `toml:"max_clients"`
FallbackResolver string `toml:"fallback_resolver"`
FallbackResolvers []string `toml:"fallback_resolvers"`
IgnoreSystemDNS bool `toml:"ignore_system_dns"`
AllWeeklyRanges map[string]WeeklyRangesStr `toml:"schedules"`
LogMaxSize int `toml:"log_files_max_size"`
@ -119,7 +120,7 @@ func newConfig() Config {
SourceDNSCrypt: true,
SourceDoH: true,
MaxClients: 250,
FallbackResolver: DefaultFallbackResolver,
FallbackResolvers: []string{DefaultFallbackResolver},
IgnoreSystemDNS: false,
LogMaxSize: 10,
LogMaxAge: 7,
@ -287,12 +288,17 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
proxy.xTransport.tlsCipherSuite = config.TLSCipherSuite
proxy.xTransport.mainProto = proxy.mainProto
if len(config.FallbackResolver) > 0 {
if err := isIPAndPort(config.FallbackResolver); err != nil {
dlog.Fatalf("fallback_resolver [%v]", err)
config.FallbackResolvers = []string{config.FallbackResolver}
}
if len(config.FallbackResolvers) > 0 {
for _, resolver := range config.FallbackResolvers {
if err := isIPAndPort(resolver); err != nil {
dlog.Fatalf("Fallback resolver [%v]: %v", resolver, err)
}
}
proxy.xTransport.ignoreSystemDNS = config.IgnoreSystemDNS
}
proxy.xTransport.fallbackResolver = config.FallbackResolver
proxy.xTransport.fallbackResolvers = config.FallbackResolvers
proxy.xTransport.useIPv4 = config.SourceIPv4
proxy.xTransport.useIPv6 = config.SourceIPv6
proxy.xTransport.keepAlive = time.Duration(config.KeepAlive) * time.Second
@ -489,8 +495,8 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
netprobeAddress := DefaultNetprobeAddress
if len(config.NetprobeAddress) > 0 {
netprobeAddress = config.NetprobeAddress
} else if len(config.FallbackResolver) > 0 {
netprobeAddress = config.FallbackResolver
} else if len(config.FallbackResolvers) > 0 {
netprobeAddress = config.FallbackResolvers[0]
}
proxy.showCerts = *flags.ShowCerts || len(os.Getenv("SHOW_CERTS")) > 0
if proxy.showCerts {

View File

@ -183,21 +183,23 @@ cert_refresh_delay = 240
# tls_cipher_suite = [52392, 49199]
## Fallback resolver
## This is a normal, non-encrypted DNS resolver, that will be only used
## Fallback resolvers
## These are normal, non-encrypted DNS resolvers, that will be only used
## for one-shot queries when retrieving the initial resolvers list, and
## only if the system DNS configuration doesn't work.
## No user application queries will ever be leaked through this resolver,
## and it will not be used after IP addresses of resolvers URLs have been found.
## It will never be used if lists have already been cached, and if stamps
## No user application queries will ever be leaked through these resolvers,
## and they will not be used after IP addresses of resolvers URLs have been found.
## They will never be used if lists have already been cached, and if stamps
## don't include host names without IP addresses.
## It will not be used if the configured system DNS works.
## A resolver supporting DNSSEC is recommended.
## They will not be used if the configured system DNS works.
## Resolver supporting DNSSEC are recommended.
##
## People in China may need to use 114.114.114.114:53 here.
## Other popular options include 8.8.8.8 and 1.1.1.1.
##
## If more than one resolver are specified, they will be tried in sequence.
fallback_resolver = '9.9.9.9:53'
fallback_resolvers = ['9.9.9.9:53', '8.8.8.8:53']
## Always use the fallback resolver before the system DNS settings.

View File

@ -49,7 +49,7 @@ type XTransport struct {
keepAlive time.Duration
timeout time.Duration
cachedIPs CachedIPs
fallbackResolver string
fallbackResolvers []string
mainProto string
ignoreSystemDNS bool
useIPv4 bool
@ -68,7 +68,7 @@ func NewXTransport() *XTransport {
cachedIPs: CachedIPs{cache: make(map[string]*CachedIPItem)},
keepAlive: DefaultKeepAlive,
timeout: DefaultTimeout,
fallbackResolver: DefaultFallbackResolver,
fallbackResolvers: []string{DefaultFallbackResolver},
mainProto: "",
ignoreSystemDNS: true,
useIPv4: true,
@ -245,6 +245,21 @@ func (xTransport *XTransport) resolveUsingResolver(proto, host string, resolver
return
}
func (xTransport *XTransport) resolveUsingResolvers(proto, host string, resolvers []string) (ip net.IP, ttl time.Duration, err error) {
for i, resolver := range resolvers {
ip, ttl, err = xTransport.resolveUsingResolver(proto, host, resolver)
if err == nil {
if i > 0 {
dlog.Infof("Resolution succeeded with fallback resolver %s[%s]", proto, resolver)
resolvers[0], resolvers[i] = resolvers[i], resolvers[0]
}
break
}
dlog.Infof("Unable to resolve [%s] using fallback resolver %s[%s]: %v", host, proto, resolver, err)
}
return
}
// If a name is not present in the cache, resolve the name and update the cache
func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
if xTransport.proxyDialer != nil || xTransport.httpProxyFunction != nil {
@ -270,18 +285,18 @@ func (xTransport *XTransport) resolveAndUpdateCache(host string) error {
}
for _, proto := range protos {
if err != nil {
dlog.Noticef("System DNS configuration not usable yet, exceptionally resolving [%s] using resolver [%s] over %s", host, xTransport.fallbackResolver, proto)
dlog.Noticef("System DNS configuration not usable yet, exceptionally resolving [%s] using fallback resolvers over %s", host, proto)
} else {
dlog.Debugf("Resolving [%s] using resolver %s[%s]", host, proto, xTransport.fallbackResolver)
dlog.Debugf("Resolving [%s] using fallback resolvers over %s", host, proto)
}
foundIP, ttl, err = xTransport.resolveUsingResolver(proto, host, xTransport.fallbackResolver)
foundIP, ttl, err = xTransport.resolveUsingResolvers(proto, host, xTransport.fallbackResolvers)
if err == nil {
break
}
}
}
if err != nil && xTransport.ignoreSystemDNS {
dlog.Noticef("Fallback resolver [%v] didn't respond - Trying with the system resolver as a last resort", xTransport.fallbackResolver)
dlog.Noticef("Fallback resolvers didn't respond - Trying with the system resolver as a last resort")
foundIP, ttl, err = xTransport.resolveUsingSystem(host)
}
if ttl < MinResolverIPTTL {