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 <s.zolin@adguard.com>
Date:   Fri Mar 20 14:32:21 2020 +0300

    Merge remote-tracking branch 'origin/master' into 1469-wildcards

commit 56aa0dfcca8265fed35e9b92f85dc54de947cc11
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Thu Mar 19 12:02:17 2020 +0300

    update text

commit 468bcd9ea6e57eedd96bbb4b8414d86a60abcdc3
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Thu Mar 19 11:51:01 2020 +0300

    * access: use urlfilter for blocked hosts processing

commit 1b157d39dfb32dd74d527274e5466b1642cd6916
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Wed Mar 18 13:13:06 2020 +0300

    minor

commit 34811eb08ab690104d29710b0e1bc9fb003a4cd4
Author: Ildar Kamalov <i.kamalov@adguard.com>
Date:   Fri Mar 13 19:05:12 2020 +0300

    * client: change field description

commit fe0acec1bbd0b810f00481412efcc9776022b694
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Mar 13 16:51:17 2020 +0300

    + DNS: blocked hosts: support wildcards
This commit is contained in:
Simon Zolin 2020-03-20 14:41:13 +03:00
parent c5a39b942f
commit a5b9d1d74c
4 changed files with 43 additions and 13 deletions

View File

@ -946,7 +946,7 @@ Response:
{ {
allowed_clients: ["127.0.0.1", ...] allowed_clients: ["127.0.0.1", ...]
disallowed_clients: ["127.0.0.1", ...] disallowed_clients: ["127.0.0.1", ...]
blocked_hosts: ["host.com", ...] blocked_hosts: ["host.com", ...] // host name or a wildcard
} }

View File

@ -357,7 +357,7 @@
"access_disallowed_title": "Disallowed clients", "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_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_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", "access_settings_saved": "Access settings successfully saved",
"updates_checked": "Updates successfully checked", "updates_checked": "Updates successfully checked",
"updates_version_equal": "AdGuard Home is up-to-date", "updates_version_equal": "AdGuard Home is up-to-date",

View File

@ -2,11 +2,15 @@ package dnsforward
import ( import (
"encoding/json" "encoding/json"
"fmt"
"net" "net"
"net/http" "net/http"
"strings"
"sync" "sync"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/urlfilter"
"github.com/AdguardTeam/urlfilter/filterlist"
) )
type accessCtx struct { type accessCtx struct {
@ -18,7 +22,7 @@ type accessCtx struct {
allowedClientsIPNet []net.IPNet // CIDRs of whitelist clients allowedClientsIPNet []net.IPNet // CIDRs of whitelist clients
disallowedClientsIPNet []net.IPNet // CIDRs of clients that should be blocked 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 { func (a *accessCtx) Init(allowedClients, disallowedClients, blockedHosts []string) error {
@ -32,15 +36,26 @@ func (a *accessCtx) Init(allowedClients, disallowedClients, blockedHosts []strin
return err return err
} }
convertArrayToMap(&a.blockedHosts, blockedHosts) buf := strings.Builder{}
return nil for _, s := range blockedHosts {
} buf.WriteString(s)
buf.WriteString("\n")
func convertArrayToMap(dst *map[string]bool, src []string) {
*dst = make(map[string]bool)
for _, s := range src {
(*dst)[s] = true
} }
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 // 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 // IsBlockedDomain - return TRUE if this domain should be blocked
func (a *accessCtx) IsBlockedDomain(host string) bool { func (a *accessCtx) IsBlockedDomain(host string) bool {
a.lock.Lock() a.lock.Lock()
_, ok := a.blockedHosts[host] _, ok := a.blockedHostsEngine.Match(host, nil)
a.lock.Unlock() a.lock.Unlock()
return ok return ok
} }

View File

@ -796,11 +796,26 @@ func TestIsBlockedIPDisallowed(t *testing.T) {
func TestIsBlockedIPBlockedDomain(t *testing.T) { func TestIsBlockedIPBlockedDomain(t *testing.T) {
a := &accessCtx{} 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("host1"))
assert.True(t, a.IsBlockedDomain("host2")) assert.True(t, a.IsBlockedDomain("host2"))
assert.True(t, !a.IsBlockedDomain("host3")) 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) { func TestValidateUpstream(t *testing.T) {