From a5b9d1d74c60202fb50000a0f822b9fc41178f05 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 20 Mar 2020 14:41:13 +0300 Subject: [PATCH] Merge: + DNS: blocked hosts: support wildcards; use urlfilter for processing of the blocked hosts Close #1469 Squashed commit of the following: commit b07f408550a526726c8e38886ce0fcc1f4c3d93d Merge: 56aa0dfc c5a39b94 Author: Simon Zolin Date: Fri Mar 20 14:32:21 2020 +0300 Merge remote-tracking branch 'origin/master' into 1469-wildcards commit 56aa0dfcca8265fed35e9b92f85dc54de947cc11 Author: Simon Zolin Date: Thu Mar 19 12:02:17 2020 +0300 update text commit 468bcd9ea6e57eedd96bbb4b8414d86a60abcdc3 Author: Simon Zolin Date: Thu Mar 19 11:51:01 2020 +0300 * access: use urlfilter for blocked hosts processing commit 1b157d39dfb32dd74d527274e5466b1642cd6916 Author: Simon Zolin Date: Wed Mar 18 13:13:06 2020 +0300 minor commit 34811eb08ab690104d29710b0e1bc9fb003a4cd4 Author: Ildar Kamalov Date: Fri Mar 13 19:05:12 2020 +0300 * client: change field description commit fe0acec1bbd0b810f00481412efcc9776022b694 Author: Simon Zolin Date: Fri Mar 13 16:51:17 2020 +0300 + DNS: blocked hosts: support wildcards --- AGHTechDoc.md | 2 +- client/src/__locales/en.json | 2 +- dnsforward/access.go | 35 +++++++++++++++++++++++++---------- dnsforward/dnsforward_test.go | 17 ++++++++++++++++- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index b1303621..a91e25c1 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -946,7 +946,7 @@ Response: { allowed_clients: ["127.0.0.1", ...] disallowed_clients: ["127.0.0.1", ...] - blocked_hosts: ["host.com", ...] + blocked_hosts: ["host.com", ...] // host name or a wildcard } diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index a4f2293e..f0bfb04f 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -357,7 +357,7 @@ "access_disallowed_title": "Disallowed clients", "access_disallowed_desc": "A list of CIDR or IP addresses. If configured, AdGuard Home will drop requests from these IP addresses.", "access_blocked_title": "Blocked domains", - "access_blocked_desc": "Don't confuse this with filters. AdGuard Home will drop DNS queries with these domains in query's question.", + "access_blocked_desc": "Don't confuse this with filters. AdGuard Home will drop DNS queries with these domains in query's question. Here you can specify the exact domain names, wildcards and urlfilter-rules, e.g. 'example.org', '*.example.org' or '||example.org^'.", "access_settings_saved": "Access settings successfully saved", "updates_checked": "Updates successfully checked", "updates_version_equal": "AdGuard Home is up-to-date", diff --git a/dnsforward/access.go b/dnsforward/access.go index 6868c6d7..6eed4337 100644 --- a/dnsforward/access.go +++ b/dnsforward/access.go @@ -2,11 +2,15 @@ package dnsforward import ( "encoding/json" + "fmt" "net" "net/http" + "strings" "sync" "github.com/AdguardTeam/golibs/log" + "github.com/AdguardTeam/urlfilter" + "github.com/AdguardTeam/urlfilter/filterlist" ) type accessCtx struct { @@ -18,7 +22,7 @@ type accessCtx struct { allowedClientsIPNet []net.IPNet // CIDRs of whitelist clients disallowedClientsIPNet []net.IPNet // CIDRs of clients that should be blocked - blockedHosts map[string]bool // hosts that should be blocked + blockedHostsEngine *urlfilter.DNSEngine // finds hosts that should be blocked } func (a *accessCtx) Init(allowedClients, disallowedClients, blockedHosts []string) error { @@ -32,15 +36,26 @@ func (a *accessCtx) Init(allowedClients, disallowedClients, blockedHosts []strin return err } - convertArrayToMap(&a.blockedHosts, blockedHosts) - return nil -} - -func convertArrayToMap(dst *map[string]bool, src []string) { - *dst = make(map[string]bool) - for _, s := range src { - (*dst)[s] = true + buf := strings.Builder{} + for _, s := range blockedHosts { + buf.WriteString(s) + buf.WriteString("\n") } + + listArray := []filterlist.RuleList{} + list := &filterlist.StringRuleList{ + ID: int(0), + RulesText: buf.String(), + IgnoreCosmetic: true, + } + listArray = append(listArray, list) + rulesStorage, err := filterlist.NewRuleStorage(listArray) + if err != nil { + return fmt.Errorf("filterlist.NewRuleStorage(): %s", err) + } + a.blockedHostsEngine = urlfilter.NewDNSEngine(rulesStorage) + + return nil } // Split array of IP or CIDR into 2 containers for fast search @@ -107,7 +122,7 @@ func (a *accessCtx) IsBlockedIP(ip string) bool { // IsBlockedDomain - return TRUE if this domain should be blocked func (a *accessCtx) IsBlockedDomain(host string) bool { a.lock.Lock() - _, ok := a.blockedHosts[host] + _, ok := a.blockedHostsEngine.Match(host, nil) a.lock.Unlock() return ok } diff --git a/dnsforward/dnsforward_test.go b/dnsforward/dnsforward_test.go index 49dcc6ae..60b606bf 100644 --- a/dnsforward/dnsforward_test.go +++ b/dnsforward/dnsforward_test.go @@ -796,11 +796,26 @@ func TestIsBlockedIPDisallowed(t *testing.T) { func TestIsBlockedIPBlockedDomain(t *testing.T) { a := &accessCtx{} - assert.True(t, a.Init(nil, nil, []string{"host1", "host2"}) == nil) + assert.True(t, a.Init(nil, nil, []string{"host1", + "host2", + "*.host.com", + "||host3.com^", + }) == nil) + // match by "host2.com" assert.True(t, a.IsBlockedDomain("host1")) assert.True(t, a.IsBlockedDomain("host2")) assert.True(t, !a.IsBlockedDomain("host3")) + + // match by wildcard "*.host.com" + assert.True(t, !a.IsBlockedDomain("host.com")) + assert.True(t, a.IsBlockedDomain("asdf.host.com")) + assert.True(t, a.IsBlockedDomain("qwer.asdf.host.com")) + assert.True(t, !a.IsBlockedDomain("asdf.zhost.com")) + + // match by wildcard "||host3.com^" + assert.True(t, a.IsBlockedDomain("host3.com")) + assert.True(t, a.IsBlockedDomain("asdf.host3.com")) } func TestValidateUpstream(t *testing.T) {