From 526c35869714da35a23bc19f947c169ae045140e Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Thu, 15 Dec 2022 12:13:14 +0700 Subject: [PATCH] all: rewrites --- internal/dnsforward/dnsforward_test.go | 18 ++++++-------- internal/filtering/filtering.go | 2 ++ internal/filtering/rewrite/storage.go | 29 ++++++++++++++-------- internal/filtering/rewrite/storage_test.go | 25 +++++++++++++++++++ 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/internal/dnsforward/dnsforward_test.go b/internal/dnsforward/dnsforward_test.go index 30723c70..60044e13 100644 --- a/internal/dnsforward/dnsforward_test.go +++ b/internal/dnsforward/dnsforward_test.go @@ -947,12 +947,11 @@ func TestRewrite(t *testing.T) { reply, eerr = dns.Exchange(req, addr.String()) require.NoError(t, eerr) - // TODO (d.kolyshev): Investigate - // require.Len(t, reply.Answer, 2) + require.Len(t, reply.Answer, 2) - // assert.Equal(t, "test.com.", reply.Answer[0].(*dns.CNAME).Target) - // assert.True(t, net.IP{1, 2, 3, 4}.Equal(reply.Answer[1].(*dns.A).A)) - assert.True(t, net.IP{1, 2, 3, 4}.Equal(reply.Answer[0].(*dns.A).A)) + assert.Equal(t, "test.com.", reply.Answer[0].(*dns.CNAME).Target) + assert.Equal(t, dns.TypeA, reply.Answer[1].Header().Rrtype) + assert.True(t, net.IP{1, 2, 3, 4}.Equal(reply.Answer[1].(*dns.A).A)) req = createTestMessageWithType("my.alias.example.org.", dns.TypeA) reply, eerr = dns.Exchange(req, addr.String()) @@ -963,11 +962,10 @@ func TestRewrite(t *testing.T) { assert.Equal(t, "my.alias.example.org.", reply.Question[0].Name) - // TODO (d.kolyshev): Investigate - //require.Len(t, reply.Answer, 2) - // - //assert.Equal(t, "example.org.", reply.Answer[0].(*dns.CNAME).Target) - //assert.Equal(t, dns.TypeA, reply.Answer[1].Header().Rrtype) + require.Len(t, reply.Answer, 2) + + assert.Equal(t, "example.org.", reply.Answer[0].(*dns.CNAME).Target) + assert.Equal(t, dns.TypeA, reply.Answer[1].Header().Rrtype) } for _, protect := range []bool{true, false} { diff --git a/internal/filtering/filtering.go b/internal/filtering/filtering.go index e552a16e..a8db8a87 100644 --- a/internal/filtering/filtering.go +++ b/internal/filtering/filtering.go @@ -577,6 +577,8 @@ func setRewriteResult(res *Result, host string, dnsr []*rules.DNSRewrite, qtype res.IPList = append(res.IPList, ip) log.Debug("rewrite: a/aaaa for %s is %s", host, ip) + } else if dnsRewrite.NewCNAME != "" { + res.CanonName = dnsRewrite.NewCNAME } } } diff --git a/internal/filtering/rewrite/storage.go b/internal/filtering/rewrite/storage.go index 4681ab4d..5083102d 100644 --- a/internal/filtering/rewrite/storage.go +++ b/internal/filtering/rewrite/storage.go @@ -87,25 +87,27 @@ func (s *DefaultStorage) MatchRequest(dReq *urlfilter.DNSRequest) (rws []*rules. // TODO(a.garipov): Check cnames for cycles on initialisation. cnames := stringutil.NewSet() host := dReq.Hostname + var lastCNAMERule *rules.NetworkRule for len(rrules) > 0 && rrules[0].DNSRewrite != nil && rrules[0].DNSRewrite.NewCNAME != "" { - rule := rrules[0] - rwAns := rule.DNSRewrite.NewCNAME + lastCNAMERule = rrules[0] + lastDNSRewrite := lastCNAMERule.DNSRewrite + rwAns := lastDNSRewrite.NewCNAME log.Debug("rewrite: cname for %s is %s", host, rwAns) if dReq.Hostname == rwAns { - // A request for the hostname itself is an exception rule. + // A request for the hostname itself is an exception lastCNAMERule. // TODO(d.kolyshev): Check rewrite of a pattern onto itself. return nil } - if host == rwAns && isWildcard(rule.RuleText) { + if host == rwAns && isWildcard(lastCNAMERule.RuleText) { // An "*.example.com → sub.example.com" rewrite matching in a loop. // // See https://github.com/AdguardTeam/AdGuardHome/issues/4016. - return []*rules.DNSRewrite{rule.DNSRewrite} + return []*rules.DNSRewrite{lastDNSRewrite} } if cnames.Has(rwAns) { @@ -129,14 +131,19 @@ func (s *DefaultStorage) MatchRequest(dReq *urlfilter.DNSRequest) (rws []*rules. host = rwAns } - return s.collectDNSRewrites(rrules, dReq.DNSType) + return s.collectDNSRewrites(rrules, lastCNAMERule, dReq.DNSType) } // collectDNSRewrites filters DNSRewrite by question type. func (s *DefaultStorage) collectDNSRewrites( rewrites []*rules.NetworkRule, + cnameRule *rules.NetworkRule, qtyp uint16, ) (rws []*rules.DNSRewrite) { + if cnameRule != nil { + rewrites = append([]*rules.NetworkRule{cnameRule}, rewrites...) + } + for _, rewrite := range rewrites { dnsRewrite := rewrite.DNSRewrite if matchesQType(dnsRewrite, qtyp) { @@ -224,16 +231,16 @@ func (s *DefaultStorage) resetRules() (err error) { // matchesQType returns true if dnsrewrite matches the question type qt. func matchesQType(dnsrr *rules.DNSRewrite, qt uint16) (ok bool) { - // Add CNAMEs, since they match for all types requests. - if dnsrr.RRType == dns.TypeCNAME || dnsrr.NewCNAME != "" { - return true - } - // Reject types other than A and AAAA. if qt != dns.TypeA && qt != dns.TypeAAAA { return false } + // Add CNAMEs, since they match for all types requests. + if dnsrr.RRType == dns.TypeCNAME || dnsrr.NewCNAME != "" { + return true + } + return dnsrr.RRType == qt } diff --git a/internal/filtering/rewrite/storage_test.go b/internal/filtering/rewrite/storage_test.go index 4db06a4e..55dc551c 100644 --- a/internal/filtering/rewrite/storage_test.go +++ b/internal/filtering/rewrite/storage_test.go @@ -123,6 +123,11 @@ func TestDefaultStorage_MatchRequest(t *testing.T) { name: "rewritten_a", host: "www.host.com", wantDNSRewrites: []*rules.DNSRewrite{{ + Value: nil, + NewCNAME: "host.com", + RCode: dns.RcodeSuccess, + RRType: dns.TypeNone, + }, { Value: net.IP{1, 2, 3, 4}.To16(), NewCNAME: "", RCode: dns.RcodeSuccess, @@ -138,6 +143,11 @@ func TestDefaultStorage_MatchRequest(t *testing.T) { name: "rewritten_aaaa", host: "www.host.com", wantDNSRewrites: []*rules.DNSRewrite{{ + Value: nil, + NewCNAME: "host.com", + RCode: dns.RcodeSuccess, + RRType: dns.TypeNone, + }, { Value: net.ParseIP("1:2:3::4"), NewCNAME: "", RCode: dns.RcodeSuccess, @@ -169,6 +179,11 @@ func TestDefaultStorage_MatchRequest(t *testing.T) { name: "wildcard_cname_interaction", host: "www.host2.com", wantDNSRewrites: []*rules.DNSRewrite{{ + Value: nil, + NewCNAME: "host.com", + RCode: dns.RcodeSuccess, + RRType: dns.TypeNone, + }, { Value: net.IP{1, 2, 3, 4}.To16(), NewCNAME: "", RCode: dns.RcodeSuccess, @@ -184,6 +199,11 @@ func TestDefaultStorage_MatchRequest(t *testing.T) { name: "two_cnames", host: "b.host.com", wantDNSRewrites: []*rules.DNSRewrite{{ + Value: nil, + NewCNAME: "somehost.com", + RCode: dns.RcodeSuccess, + RRType: dns.TypeNone, + }, { Value: net.IP{0, 0, 0, 0}.To16(), NewCNAME: "", RCode: dns.RcodeSuccess, @@ -194,6 +214,11 @@ func TestDefaultStorage_MatchRequest(t *testing.T) { name: "two_cnames_and_wildcard", host: "b.host3.com", wantDNSRewrites: []*rules.DNSRewrite{{ + Value: nil, + NewCNAME: "x.host.com", + RCode: dns.RcodeSuccess, + RRType: dns.TypeNone, + }, { Value: net.IP{1, 2, 3, 5}.To16(), NewCNAME: "", RCode: dns.RcodeSuccess,