Pull request: 3185 detecting recursion

Merge in DNS/adguard-home from 3185-recursion to master

Closes #3185.

Squashed commit of the following:

commit 2fa44223f533c471f2b8c0e17d8550bf4ff73c7b
Merge: 7975957c 7a48e92e
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Thu May 27 19:04:44 2021 +0300

    Merge branch 'master' into 3185-recursion

commit 7975957cceb840f76eef0e2e434f4163a122ac34
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Thu May 27 17:36:22 2021 +0300

    dnsforward: imp docs

commit 1af7131a5b7c1fefed2d1eb8ee24ebfd3602dc77
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Thu May 27 17:15:00 2021 +0300

    dnsforward: imp code, tests, docs

commit f3f9145fb5e1174fab87ca6890da9df722cfebf0
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Thu May 27 15:45:44 2021 +0300

    dnsforward: add recursion detector
This commit is contained in:
Eugene Burkov
2021-05-27 19:19:19 +03:00
parent 7a48e92e4d
commit 48b8579703
6 changed files with 324 additions and 23 deletions

View File

@@ -76,6 +76,7 @@ type Server struct {
ipset ipsetCtx
subnetDetector *aghnet.SubnetDetector
localResolvers *proxy.Proxy
recDetector *recursionDetector
tableHostToIP hostToIPTable
tableHostToIPLock sync.Mutex
@@ -121,6 +122,14 @@ func domainNameToSuffix(tld string) (suffix string) {
return string(b)
}
const (
// recursionTTL is the time recursive request is cached for.
recursionTTL = 5 * time.Second
// cachedRecurrentReqNum is the maximum number of cached recurrent
// requests.
cachedRecurrentReqNum = 1000
)
// NewServer creates a new instance of the dnsforward.Server
// Note: this function must be called only once
func NewServer(p DNSCreateParams) (s *Server, err error) {
@@ -142,6 +151,7 @@ func NewServer(p DNSCreateParams) (s *Server, err error) {
queryLog: p.QueryLog,
subnetDetector: p.SubnetDetector,
localDomainSuffix: localDomainSuffix,
recDetector: newRecursionDetector(recursionTTL, cachedRecurrentReqNum),
}
if p.DHCPServer != nil {
@@ -160,7 +170,9 @@ func NewServer(p DNSCreateParams) (s *Server, err error) {
// NewCustomServer creates a new instance of *Server with custom internal proxy.
func NewCustomServer(internalProxy *proxy.Proxy) *Server {
s := &Server{}
s := &Server{
recDetector: newRecursionDetector(0, 1),
}
if internalProxy != nil {
s.internalProxy = internalProxy
}
@@ -278,14 +290,13 @@ func (s *Server) Exchange(ip net.IP) (host string, err error) {
Req: req,
StartTime: time.Now(),
}
var resp *dns.Msg
err = resolver.Resolve(ctx)
if err != nil {
s.recDetector.add(*req)
if err = resolver.Resolve(ctx); err != nil {
return "", err
}
resp = ctx.Res
resp := ctx.Res
if len(resp.Answer) == 0 {
return "", fmt.Errorf("lookup for %q: %w", arpa, rDNSEmptyAnswerErr)
}
@@ -490,6 +501,8 @@ func (s *Server) Prepare(config *ServerConfig) error {
return fmt.Errorf("setting up resolvers: %w", err)
}
s.recDetector.clear()
return nil
}