Add an option to always ignore the system resolver

This makes startup faster when DoH resolvers without a static IP
are used (Google).
This commit is contained in:
Frank Denis 2018-01-30 17:37:35 +01:00
parent 931916097e
commit 1d35e249c9
3 changed files with 57 additions and 36 deletions

View File

@ -42,6 +42,7 @@ type Config struct {
SourceIPv6 bool `toml:"ipv6_servers"` SourceIPv6 bool `toml:"ipv6_servers"`
MaxClients uint32 `toml:"max_clients"` MaxClients uint32 `toml:"max_clients"`
FallbackResolver string `toml:"fallback_resolver"` FallbackResolver string `toml:"fallback_resolver"`
IgnoreSystemDNS bool `toml:"ignore_system_dns"`
} }
func newConfig() Config { func newConfig() Config {
@ -61,6 +62,7 @@ func newConfig() Config {
SourceIPv6: false, SourceIPv6: false,
MaxClients: 100, MaxClients: 100,
FallbackResolver: DefaultFallbackResolver, FallbackResolver: DefaultFallbackResolver,
IgnoreSystemDNS: false,
} }
} }
@ -132,6 +134,9 @@ func ConfigLoad(proxy *Proxy, svcFlag *string, config_file string) error {
dlog.UseLogFile(*config.LogFile) dlog.UseLogFile(*config.LogFile)
} }
proxy.xTransport.fallbackResolver = config.FallbackResolver proxy.xTransport.fallbackResolver = config.FallbackResolver
if len(config.FallbackResolver) > 0 {
proxy.xTransport.ignoreSystemDNS = config.IgnoreSystemDNS
}
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
proxy.maxClients = config.MaxClients proxy.maxClients = config.MaxClients
proxy.mainProto = "udp" proxy.mainProto = "udp"

View File

@ -93,6 +93,11 @@ cert_refresh_delay = 30
fallback_resolver = "9.9.9.9:53" fallback_resolver = "9.9.9.9:53"
## Never try to use the system DNS settings; unconditionally use the
## fallback resolver.
ignore_system_dns = false
######################### #########################
# Filters # # Filters #

View File

@ -30,6 +30,7 @@ type XTransport struct {
timeout time.Duration timeout time.Duration
cachedIPs CachedIPs cachedIPs CachedIPs
fallbackResolver string fallbackResolver string
ignoreSystemDNS bool
} }
func NewXTransport(timeout time.Duration) *XTransport { func NewXTransport(timeout time.Duration) *XTransport {
@ -37,6 +38,7 @@ func NewXTransport(timeout time.Duration) *XTransport {
cachedIPs: CachedIPs{cache: make(map[string]string)}, cachedIPs: CachedIPs{cache: make(map[string]string)},
timeout: timeout, timeout: timeout,
fallbackResolver: DefaultFallbackResolver, fallbackResolver: DefaultFallbackResolver,
ignoreSystemDNS: false,
} }
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true} dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
transport := &http.Transport{ transport := &http.Transport{
@ -87,6 +89,12 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
if body != nil { if body != nil {
req.Body = *body req.Body = *body
} }
var err error
host := url.Host
xTransport.cachedIPs.RLock()
cachedIP := xTransport.cachedIPs.cache[host]
xTransport.cachedIPs.RUnlock()
if !xTransport.ignoreSystemDNS || len(cachedIP) > 0 {
start := time.Now() start := time.Now()
resp, err := client.Do(req) resp, err := client.Do(req)
rtt := time.Since(start) rtt := time.Since(start)
@ -98,13 +106,13 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
} }
return resp, rtt, err return resp, rtt, err
} }
host := url.Host dlog.Debugf("[%s]: [%s]", req.URL, err)
xTransport.cachedIPs.RLock() } else {
cachedIP := xTransport.cachedIPs.cache[host] dlog.Debug("Ignoring system DNS")
xTransport.cachedIPs.RUnlock() }
if len(cachedIP) > 0 { if len(cachedIP) > 0 && err != nil {
dlog.Debugf("IP for [%s] was cached to [%s], but connection failed: [%s]", host, cachedIP, err) dlog.Debugf("IP for [%s] was cached to [%s], but connection failed: [%s]", host, cachedIP, err)
return resp, rtt, err return nil, 0, err
} }
dnsClient := new(dns.Client) dnsClient := new(dns.Client)
msg := new(dns.Msg) msg := new(dns.Msg)
@ -113,10 +121,10 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
dlog.Noticef("System DNS configuration not usable yet, exceptionally resolving [%s] using fallback resolver [%s]", host, xTransport.fallbackResolver) dlog.Noticef("System DNS configuration not usable yet, exceptionally resolving [%s] using fallback resolver [%s]", host, xTransport.fallbackResolver)
in, _, err := dnsClient.Exchange(msg, xTransport.fallbackResolver) in, _, err := dnsClient.Exchange(msg, xTransport.fallbackResolver)
if err != nil { if err != nil {
return resp, rtt, err return nil, 0, err
} }
if len(in.Answer) <= 0 { if len(in.Answer) <= 0 {
return resp, rtt, fmt.Errorf("No IP found for [%s]", host) return nil, 0, fmt.Errorf("No IP found for [%s]", host)
} }
foundIP := in.Answer[0].(*dns.A).A.String() foundIP := in.Answer[0].(*dns.A).A.String()
xTransport.cachedIPs.Lock() xTransport.cachedIPs.Lock()
@ -124,9 +132,9 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
xTransport.cachedIPs.Unlock() xTransport.cachedIPs.Unlock()
dlog.Debugf("[%s] IP address [%s] added to the cache", host, foundIP) dlog.Debugf("[%s] IP address [%s] added to the cache", host, foundIP)
start = time.Now() start := time.Now()
resp, err = client.Do(req) resp, err := client.Do(req)
rtt = time.Since(start) rtt := time.Since(start)
if err == nil { if err == nil {
if resp == nil { if resp == nil {
err = errors.New("Webserver returned an error") err = errors.New("Webserver returned an error")
@ -134,6 +142,9 @@ func (xTransport *XTransport) Fetch(method string, url *url.URL, accept string,
err = fmt.Errorf("Webserver returned code %d", resp.StatusCode) err = fmt.Errorf("Webserver returned code %d", resp.StatusCode)
} }
} }
if err != nil {
dlog.Debugf("[%s]: [%s]", req.URL, err)
}
return resp, rtt, err return resp, rtt, err
} }