From 24ae61de3ed99a7b21dd6d4598e296df0b3e952d Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Mon, 13 May 2019 14:16:07 +0300 Subject: [PATCH 1/3] + dnsfilter: cache IP addresses of safebrowsing and parental control servers --- dnsfilter/dnsfilter.go | 44 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index c46c3e97..3396fb7c 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -157,6 +157,7 @@ const ( // these variables need to survive coredns reload var ( stats Stats + securityCache gcache.Cache // "host" -> "IP" cache for safebrowsing and parental control servers safebrowsingCache gcache.Cache parentalCache gcache.Cache safeSearchCache gcache.Cache @@ -972,10 +973,34 @@ func (d *Dnsfilter) matchHost(host string) (Result, error) { // lifecycle helper functions // +// Return TRUE if this host's IP should be cached +func (d *Dnsfilter) shouldCache(host string) bool { + return host == d.safeBrowsingServer || + host == d.parentalServer +} + +// Search for an IP address by host name +func searchInCache(host string) string { + rawValue, err := securityCache.Get(host) + if err != nil { + return "" + } + + ip, _ := rawValue.(string) + log.Debug("Found in cache: %s -> %s", host, ip) + return ip +} + +// Add "hostname" -> "IP address" entry to cache +func addToCache(host, ip string) { + securityCache.Set(host, ip) + log.Debug("Added to cache: %s -> %s", host, ip) +} + type dialFunctionType func(ctx context.Context, network, addr string) (net.Conn, error) // Connect to a remote server resolving hostname using our own DNS server -func createCustomDialContext(resolverAddr string) dialFunctionType { +func (d *Dnsfilter) createCustomDialContext(resolverAddr string) dialFunctionType { return func(ctx context.Context, network, addr string) (net.Conn, error) { log.Tracef("network:%v addr:%v", network, addr) @@ -993,6 +1018,15 @@ func createCustomDialContext(resolverAddr string) dialFunctionType { return con, err } + cache := d.shouldCache(host) + if cache { + ip := searchInCache(host) + if len(ip) != 0 { + addr = fmt.Sprintf("%s:%s", ip, port) + return dialer.DialContext(ctx, network, addr) + } + } + r := upstream.NewResolver(resolverAddr, 30*time.Second) addrs, e := r.LookupIPAddr(ctx, host) log.Tracef("LookupIPAddr: %s: %v", host, addrs) @@ -1011,6 +1045,11 @@ func createCustomDialContext(resolverAddr string) dialFunctionType { } continue } + + if cache { + addToCache(host, a.String()) + } + return con, err } return nil, firstErr @@ -1037,7 +1076,8 @@ func New(c *Config) *Dnsfilter { ExpectContinueTimeout: 1 * time.Second, } if c != nil && len(c.ResolverAddress) != 0 { - d.transport.DialContext = createCustomDialContext(c.ResolverAddress) + securityCache = gcache.New(2).LRU().Expiration(defaultCacheTime).Build() + d.transport.DialContext = d.createCustomDialContext(c.ResolverAddress) } d.client = http.Client{ Transport: d.transport, From b3461d37caa1003acd7a49239245cc2e26d98ee2 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Mon, 13 May 2019 14:47:55 +0300 Subject: [PATCH 2/3] rename functions and container --- dnsfilter/dnsfilter.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index 3396fb7c..d474930b 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -157,7 +157,7 @@ const ( // these variables need to survive coredns reload var ( stats Stats - securityCache gcache.Cache // "host" -> "IP" cache for safebrowsing and parental control servers + dialCache gcache.Cache // "host" -> "IP" cache for safebrowsing and parental control servers safebrowsingCache gcache.Cache parentalCache gcache.Cache safeSearchCache gcache.Cache @@ -974,14 +974,14 @@ func (d *Dnsfilter) matchHost(host string) (Result, error) { // // Return TRUE if this host's IP should be cached -func (d *Dnsfilter) shouldCache(host string) bool { +func (d *Dnsfilter) shouldBeInDialCache(host string) bool { return host == d.safeBrowsingServer || host == d.parentalServer } // Search for an IP address by host name -func searchInCache(host string) string { - rawValue, err := securityCache.Get(host) +func searchInDialCache(host string) string { + rawValue, err := dialCache.Get(host) if err != nil { return "" } @@ -992,8 +992,8 @@ func searchInCache(host string) string { } // Add "hostname" -> "IP address" entry to cache -func addToCache(host, ip string) { - securityCache.Set(host, ip) +func addToDialCache(host, ip string) { + dialCache.Set(host, ip) log.Debug("Added to cache: %s -> %s", host, ip) } @@ -1018,9 +1018,9 @@ func (d *Dnsfilter) createCustomDialContext(resolverAddr string) dialFunctionTyp return con, err } - cache := d.shouldCache(host) + cache := d.shouldBeInDialCache(host) if cache { - ip := searchInCache(host) + ip := searchInDialCache(host) if len(ip) != 0 { addr = fmt.Sprintf("%s:%s", ip, port) return dialer.DialContext(ctx, network, addr) @@ -1047,7 +1047,7 @@ func (d *Dnsfilter) createCustomDialContext(resolverAddr string) dialFunctionTyp } if cache { - addToCache(host, a.String()) + addToDialCache(host, a.String()) } return con, err @@ -1076,7 +1076,7 @@ func New(c *Config) *Dnsfilter { ExpectContinueTimeout: 1 * time.Second, } if c != nil && len(c.ResolverAddress) != 0 { - securityCache = gcache.New(2).LRU().Expiration(defaultCacheTime).Build() + dialCache = gcache.New(2).LRU().Expiration(defaultCacheTime).Build() d.transport.DialContext = d.createCustomDialContext(c.ResolverAddress) } d.client = http.Client{ From d918e5b418de232d95ba1e3d642dca00664f0304 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Wed, 15 May 2019 12:03:20 +0300 Subject: [PATCH 3/3] use maxDialCacheSize constant --- dnsfilter/dnsfilter.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index d474930b..b780c9f2 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -33,6 +33,7 @@ const defaultSafebrowsingServer = "sb.adtidy.org" const defaultSafebrowsingURL = "http://%s/safebrowsing-lookup-hash.html?prefixes=%s" const defaultParentalServer = "pctrl.adguard.com" const defaultParentalURL = "http://%s/check-parental-control-hash?prefixes=%s&sensitivity=%d" +const maxDialCacheSize = 2 // the number of host names for safebrowsing and parental control // ErrInvalidSyntax is returned by AddRule when the rule is invalid var ErrInvalidSyntax = errors.New("dnsfilter: invalid rule syntax") @@ -1076,7 +1077,7 @@ func New(c *Config) *Dnsfilter { ExpectContinueTimeout: 1 * time.Second, } if c != nil && len(c.ResolverAddress) != 0 { - dialCache = gcache.New(2).LRU().Expiration(defaultCacheTime).Build() + dialCache = gcache.New(maxDialCacheSize).LRU().Expiration(defaultCacheTime).Build() d.transport.DialContext = d.createCustomDialContext(c.ResolverAddress) } d.client = http.Client{