From 8d2a9ce923eae4673a74f4c4a7e1d9ef840f04d2 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 9 Jan 2020 19:31:14 +0300 Subject: [PATCH] * dnsfilter: change DNS answer for host rules When matched by a host rule, return only the IP address specified in rule. Respond with an empty IP list to another request type. :: host -- return nothing to A, return :: to AAAA request 0.0.0.0 host -- return 0.0.0.0 to A, return nothing to AAAA request --- dnsfilter/dnsfilter.go | 18 ++++-------------- dnsfilter/dnsfilter_test.go | 19 +++++++++++++------ dnsforward/dnsforward.go | 3 ++- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index 7f7034a8..25ca9fa1 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -1,7 +1,6 @@ package dnsfilter import ( - "bytes" "fmt" "io/ioutil" "net" @@ -538,24 +537,15 @@ func (d *Dnsfilter) matchHost(host string, qtype uint16) (Result, error) { } else if hostRule, ok := rule.(*rules.HostRule); ok { + res.IP = net.IP{} if qtype == dns.TypeA && hostRule.IP.To4() != nil { // either IPv4 or IPv4-mapped IPv6 address res.IP = hostRule.IP.To4() - return res, nil - } else if qtype == dns.TypeAAAA { - ip4 := hostRule.IP.To4() - if ip4 == nil { - res.IP = hostRule.IP - return res, nil - } - if bytes.Equal(ip4, []byte{0, 0, 0, 0}) { - // send IP="::" response for a rule "0.0.0.0 blockdomain" - res.IP = net.IPv6zero - return res, nil - } + } else if qtype == dns.TypeAAAA && hostRule.IP.To4() == nil { + res.IP = hostRule.IP } - continue + return res, nil } else { log.Tracef("Rule type is unsupported: '%s' list_id: %d", diff --git a/dnsfilter/dnsfilter_test.go b/dnsfilter/dnsfilter_test.go index 02176539..2881d0bf 100644 --- a/dnsfilter/dnsfilter_test.go +++ b/dnsfilter/dnsfilter_test.go @@ -98,7 +98,7 @@ func (d *Dnsfilter) checkMatchEmpty(t *testing.T, hostname string) { func TestEtcHostsMatching(t *testing.T) { addr := "216.239.38.120" addr6 := "::1" - text := fmt.Sprintf(" %s google.com www.google.com # enforce google's safesearch \n%s google.com\n0.0.0.0 block.com\n", + text := fmt.Sprintf(" %s google.com www.google.com # enforce google's safesearch \n%s ipv6.com\n0.0.0.0 block.com\n", addr, addr6) filters := make(map[int]string) filters[0] = text @@ -110,12 +110,19 @@ func TestEtcHostsMatching(t *testing.T) { d.checkMatchEmpty(t, "subdomain.google.com") d.checkMatchEmpty(t, "example.org") - // IPv6 address - d.checkMatchIP(t, "google.com", addr6, dns.TypeAAAA) - - // block both IPv4 and IPv6 + // IPv4 d.checkMatchIP(t, "block.com", "0.0.0.0", dns.TypeA) - d.checkMatchIP(t, "block.com", "::", dns.TypeAAAA) + + // ...but empty IPv6 + ret, err := d.CheckHost("block.com", dns.TypeAAAA, &setts) + assert.True(t, err == nil && ret.IsFiltered && ret.IP != nil && len(ret.IP) == 0) + + // IPv6 + d.checkMatchIP(t, "ipv6.com", addr6, dns.TypeAAAA) + + // ...but empty IPv4 + ret, err = d.CheckHost("ipv6.com", dns.TypeA, &setts) + assert.True(t, err == nil && ret.IsFiltered && ret.IP != nil && len(ret.IP) == 0) } // SAFE BROWSING diff --git a/dnsforward/dnsforward.go b/dnsforward/dnsforward.go index a2cf5b65..f14845a8 100644 --- a/dnsforward/dnsforward.go +++ b/dnsforward/dnsforward.go @@ -788,7 +788,8 @@ func (s *Server) genAAAAAnswer(req *dns.Msg, ip net.IP) *dns.AAAA { func (s *Server) genResponseWithIP(req *dns.Msg, ip net.IP) *dns.Msg { if req.Question[0].Qtype == dns.TypeA && ip.To4() != nil { return s.genARecord(req, ip.To4()) - } else if req.Question[0].Qtype == dns.TypeAAAA && ip.To4() == nil { + } else if req.Question[0].Qtype == dns.TypeAAAA && + len(ip) == net.IPv6len && ip.To4() == nil { return s.genAAAARecord(req, ip) }