From 7d10628a5fe3fd2745be4763cdc58c9f7dc76f5b Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 9 Apr 2018 13:02:42 +0200 Subject: [PATCH] New syntax for blocking/whitelisting rules: exact matching Example: =example.com Matches `example.com` but not `api.example.com` --- dnscrypt-proxy/example-blacklist.txt | 1 + dnscrypt-proxy/example-dnscrypt-proxy.toml | 1 + dnscrypt-proxy/example-whitelist.txt | 1 + dnscrypt-proxy/pattern_matcher.go | 17 +++++++++++++++++ 4 files changed, 20 insertions(+) diff --git a/dnscrypt-proxy/example-blacklist.txt b/dnscrypt-proxy/example-blacklist.txt index 7f3d2158..91b4a3e0 100644 --- a/dnscrypt-proxy/example-blacklist.txt +++ b/dnscrypt-proxy/example-blacklist.txt @@ -10,6 +10,7 @@ ## ads.* | matches anything with an "ads." prefix ## *.example.com | matches example.com and all names within that zone such as www.example.com ## example.com | identical to the above +## =example.com | block example.com but not *.example.com ## *sex* | matches any name containing that substring ## ads[0-9]* | matches "ads" followed by one or more digits ## ads*.example* | *, ? and [] can be used anywhere, but prefixes/suffixes are faster diff --git a/dnscrypt-proxy/example-dnscrypt-proxy.toml b/dnscrypt-proxy/example-dnscrypt-proxy.toml index 73ebd3aa..075d1850 100644 --- a/dnscrypt-proxy/example-dnscrypt-proxy.toml +++ b/dnscrypt-proxy/example-dnscrypt-proxy.toml @@ -297,6 +297,7 @@ cache_neg_ttl = 60 ## Blacklists are made of one pattern per line. Example of valid patterns: ## ## example.com +## =example.com ## *sex* ## ads.* ## ads*.example.* diff --git a/dnscrypt-proxy/example-whitelist.txt b/dnscrypt-proxy/example-whitelist.txt index c5accd10..c1cbdd13 100644 --- a/dnscrypt-proxy/example-whitelist.txt +++ b/dnscrypt-proxy/example-whitelist.txt @@ -10,6 +10,7 @@ ## ads.* | matches anything with an "ads." prefix ## *.example.com | matches example.com and all names within that zone such as www.example.com ## example.com | identical to the above +## =example.com | whitelists example.com but not *.example.com ## *sex* | matches any name containing that substring ## ads[0-9]* | matches "ads" followed by one or more digits ## ads*.example* | *, ? and [] can be used anywhere, but prefixes/suffixes are faster diff --git a/dnscrypt-proxy/pattern_matcher.go b/dnscrypt-proxy/pattern_matcher.go index fef7ff81..17f1606b 100644 --- a/dnscrypt-proxy/pattern_matcher.go +++ b/dnscrypt-proxy/pattern_matcher.go @@ -18,6 +18,7 @@ const ( PatternTypeSuffix PatternTypeSubstring PatternTypePattern + PatternTypeExact ) type PatternMatcher struct { @@ -25,6 +26,7 @@ type PatternMatcher struct { blockedSuffixes *critbitgo.Trie blockedSubstrings []string blockedPatterns []string + blockedExact map[string]interface{} indirectVals map[string]interface{} } @@ -32,6 +34,7 @@ func NewPatternPatcher() *PatternMatcher { patternMatcher := PatternMatcher{ blockedPrefixes: critbitgo.NewTrie(), blockedSuffixes: critbitgo.NewTrie(), + blockedExact: make(map[string]interface{}), indirectVals: make(map[string]interface{}), } return &patternMatcher @@ -51,6 +54,7 @@ func isGlobCandidate(str string) bool { func (patternMatcher *PatternMatcher) Add(pattern string, val interface{}, position int) (PatternType, error) { leadingStar := strings.HasPrefix(pattern, "*") trailingStar := strings.HasSuffix(pattern, "*") + exact := strings.HasPrefix(pattern, "=") patternType := PatternTypeNone if isGlobCandidate(pattern) { patternType = PatternTypePattern @@ -70,6 +74,12 @@ func (patternMatcher *PatternMatcher) Add(pattern string, val interface{}, posit return patternType, fmt.Errorf("Syntax error in block rules at pattern %d", position) } pattern = pattern[:len(pattern)-1] + } else if exact { + patternType = PatternTypeExact + if len(pattern) < 2 { + return patternType, fmt.Errorf("Syntax error in block rules at pattern %d", position) + } + pattern = pattern[1:] } else { patternType = PatternTypeSuffix if leadingStar { @@ -97,6 +107,8 @@ func (patternMatcher *PatternMatcher) Add(pattern string, val interface{}, posit patternMatcher.blockedPrefixes.Insert([]byte(pattern), val) case PatternTypeSuffix: patternMatcher.blockedSuffixes.Insert([]byte(StringReverse(pattern)), val) + case PatternTypeExact: + patternMatcher.blockedExact[pattern] = val default: dlog.Fatal("Unexpected block type") } @@ -140,5 +152,10 @@ func (patternMatcher *PatternMatcher) Eval(qName string) (reject bool, reason st return true, pattern, patternMatcher.indirectVals[pattern] } } + + if xval := patternMatcher.blockedExact[qName]; xval != nil { + return true, qName, xval + } + return false, "", nil }