From 8685584bf52450f255099617eb641ab636e97ff5 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Wed, 11 Dec 2019 19:02:46 +0300 Subject: [PATCH] + DNS Rewrites: support wildcard domain name --- AGHTechDoc.md | 2 ++ dnsfilter/dnsfilter.go | 15 +++++++++-- dnsfilter/dnsfilter_test.go | 54 +++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index ea2ed95a..4ed2c4e3 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -916,6 +916,8 @@ Response: ... ] +`domain` can be an exact host name (`www.host.com`) or a wildcard (`*.host.com`). + ### API: Add a rewrite entry diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index 3843f1dc..ae91164f 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -334,6 +334,13 @@ func (d *Dnsfilter) CheckHost(host string, qtype uint16, setts *RequestFiltering return Result{}, nil } +// Return TRUE of host name matches a wildcard pattern +func matchDomainWildcard(host, wildcard string) bool { + return len(wildcard) >= 2 && + wildcard[0] == '*' && wildcard[1] == '.' && + strings.HasSuffix(host, wildcard[1:]) +} + // Process rewrites table // . Find CNAME for a domain name // . if found, set domain name to canonical name @@ -347,7 +354,9 @@ func (d *Dnsfilter) processRewrites(host string, qtype uint16) Result { for _, r := range d.Rewrites { if r.Domain != host { - continue + if !matchDomainWildcard(host, r.Domain) { + continue + } } ip := net.ParseIP(r.Answer) @@ -362,7 +371,9 @@ func (d *Dnsfilter) processRewrites(host string, qtype uint16) Result { for _, r := range d.Rewrites { if r.Domain != host { - continue + if !matchDomainWildcard(host, r.Domain) { + continue + } } ip := net.ParseIP(r.Answer) diff --git a/dnsfilter/dnsfilter_test.go b/dnsfilter/dnsfilter_test.go index 96d7a256..02176539 100644 --- a/dnsfilter/dnsfilter_test.go +++ b/dnsfilter/dnsfilter_test.go @@ -474,6 +474,60 @@ func TestClientSettings(t *testing.T) { assert.True(t, r.IsFiltered && r.Reason == FilteredBlockedService) } +func TestRewrites(t *testing.T) { + d := Dnsfilter{} + // CNAME, A, AAAA + d.Rewrites = []RewriteEntry{ + RewriteEntry{"somecname", "somehost.com"}, + RewriteEntry{"somehost.com", "0.0.0.0"}, + + RewriteEntry{"host.com", "1.2.3.4"}, + RewriteEntry{"host.com", "1.2.3.5"}, + RewriteEntry{"host.com", "1:2:3::4"}, + RewriteEntry{"www.host.com", "host.com"}, + } + r := d.processRewrites("host2.com", dns.TypeA) + assert.Equal(t, NotFilteredNotFound, r.Reason) + + r = d.processRewrites("www.host.com", dns.TypeA) + assert.Equal(t, ReasonRewrite, r.Reason) + assert.Equal(t, "host.com", r.CanonName) + assert.True(t, len(r.IPList) == 2) + assert.True(t, r.IPList[0].Equal(net.ParseIP("1.2.3.4"))) + assert.True(t, r.IPList[1].Equal(net.ParseIP("1.2.3.5"))) + + r = d.processRewrites("www.host.com", dns.TypeAAAA) + assert.Equal(t, ReasonRewrite, r.Reason) + assert.True(t, len(r.IPList) == 1) + assert.True(t, r.IPList[0].Equal(net.ParseIP("1:2:3::4"))) + + // wildcard + d.Rewrites = []RewriteEntry{ + RewriteEntry{"*.host.com", "1.2.3.5"}, + RewriteEntry{"host.com", "1.2.3.4"}, + } + r = d.processRewrites("host.com", dns.TypeA) + assert.Equal(t, ReasonRewrite, r.Reason) + assert.True(t, r.IPList[0].Equal(net.ParseIP("1.2.3.4"))) + + r = d.processRewrites("www.host.com", dns.TypeA) + assert.Equal(t, ReasonRewrite, r.Reason) + assert.True(t, r.IPList[0].Equal(net.ParseIP("1.2.3.5"))) + + r = d.processRewrites("www.host2.com", dns.TypeA) + assert.Equal(t, NotFilteredNotFound, r.Reason) + + // wildcard + CNAME + d.Rewrites = []RewriteEntry{ + RewriteEntry{"*.host.com", "host.com"}, + RewriteEntry{"host.com", "1.2.3.4"}, + } + r = d.processRewrites("www.host.com", dns.TypeA) + assert.Equal(t, ReasonRewrite, r.Reason) + assert.Equal(t, "host.com", r.CanonName) + assert.True(t, r.IPList[0].Equal(net.ParseIP("1.2.3.4"))) +} + // BENCHMARKS func BenchmarkSafeBrowsing(b *testing.B) {