Merge: + dns rewrites: support wildcard override
Close #922
Squashed commit of the following:
commit 8ab742d84916a02043989fcfa5fc258e84046205
Merge: 2abde92f e398117d
Author: Simon Zolin <s.zolin@adguard.com>
Date: Thu Jan 16 12:47:44 2020 +0300
Merge remote-tracking branch 'origin/master' into 922-rewrites
commit 2abde92fe2d1bdb153787b4ecac60f9744c7fd1a
Author: Simon Zolin <s.zolin@adguard.com>
Date: Thu Jan 16 12:34:41 2020 +0300
minor
commit 3c20579cde85967786830d2d1b87cd987fc2ae12
Author: Simon Zolin <s.zolin@adguard.com>
Date: Fri Jan 10 19:06:53 2020 +0300
don't change the order of rewrite entry list (apply priority at runtime)
commit 4f658f98011a7e31852c0ce379f2a02738f5614f
Author: Simon Zolin <s.zolin@adguard.com>
Date: Tue Dec 31 15:21:50 2019 +0300
minor
commit 9e56b4f3abefe3ff1d19bc61375f31dc55242e52
Author: Simon Zolin <s.zolin@adguard.com>
Date: Tue Dec 31 15:14:14 2019 +0300
* remove unused code
commit 4178f025a388eb768914306efa91ffead87e5a0c
Author: Simon Zolin <s.zolin@adguard.com>
Date: Tue Dec 31 15:13:57 2019 +0300
+ dns rewrites: support wildcard override
This commit is contained in:
@@ -4,11 +4,123 @@ package dnsfilter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// RewriteEntry is a rewrite array element
|
||||
type RewriteEntry struct {
|
||||
Domain string `yaml:"domain"`
|
||||
Answer string `yaml:"answer"` // IP address or canonical name
|
||||
Type uint16 `yaml:"-"` // DNS record type: CNAME, A or AAAA
|
||||
IP net.IP `yaml:"-"` // Parsed IP address (if Type is A or AAAA)
|
||||
}
|
||||
|
||||
func (r *RewriteEntry) equals(b RewriteEntry) bool {
|
||||
return r.Domain == b.Domain && r.Answer == b.Answer
|
||||
}
|
||||
|
||||
func isWildcard(host string) bool {
|
||||
return len(host) >= 2 &&
|
||||
host[0] == '*' && host[1] == '.'
|
||||
}
|
||||
|
||||
// Return TRUE of host name matches a wildcard pattern
|
||||
func matchDomainWildcard(host, wildcard string) bool {
|
||||
return isWildcard(wildcard) &&
|
||||
strings.HasSuffix(host, wildcard[1:])
|
||||
}
|
||||
|
||||
type rewritesArray []RewriteEntry
|
||||
|
||||
func (a rewritesArray) Len() int { return len(a) }
|
||||
|
||||
func (a rewritesArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
// Priority: CNAME, A/AAAA; exact, wildcard.
|
||||
func (a rewritesArray) Less(i, j int) bool {
|
||||
if a[i].Type == dns.TypeCNAME && a[j].Type != dns.TypeCNAME {
|
||||
return false
|
||||
} else if a[i].Type != dns.TypeCNAME && a[j].Type == dns.TypeCNAME {
|
||||
return true
|
||||
}
|
||||
|
||||
if isWildcard(a[i].Domain) && !isWildcard(a[j].Domain) {
|
||||
return false
|
||||
} else if !isWildcard(a[i].Domain) && isWildcard(a[j].Domain) {
|
||||
return true
|
||||
}
|
||||
|
||||
return i < j
|
||||
}
|
||||
|
||||
// Prepare entry for use
|
||||
func (r *RewriteEntry) prepare() {
|
||||
ip := net.ParseIP(r.Answer)
|
||||
if ip == nil {
|
||||
r.Type = dns.TypeCNAME
|
||||
return
|
||||
}
|
||||
|
||||
r.IP = ip
|
||||
r.Type = dns.TypeAAAA
|
||||
|
||||
ip4 := ip.To4()
|
||||
if ip4 != nil {
|
||||
r.IP = ip4
|
||||
r.Type = dns.TypeA
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dnsfilter) prepareRewrites() {
|
||||
for i := range d.Rewrites {
|
||||
d.Rewrites[i].prepare()
|
||||
}
|
||||
}
|
||||
|
||||
// Get the list of matched rewrite entries.
|
||||
// Priority: CNAME, A/AAAA; exact, wildcard.
|
||||
// If matched exactly, don't return wildcard entries.
|
||||
func findRewrites(a []RewriteEntry, host string) []RewriteEntry {
|
||||
rr := rewritesArray{}
|
||||
for _, r := range a {
|
||||
if r.Domain != host {
|
||||
if !matchDomainWildcard(host, r.Domain) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
rr = append(rr, r)
|
||||
}
|
||||
|
||||
if len(rr) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sort.Sort(rr)
|
||||
|
||||
isWC := isWildcard(rr[0].Domain)
|
||||
if !isWC {
|
||||
for i, r := range rr {
|
||||
if isWildcard(r.Domain) {
|
||||
rr = rr[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return rr
|
||||
}
|
||||
|
||||
func rewriteArrayDup(a []RewriteEntry) []RewriteEntry {
|
||||
a2 := make([]RewriteEntry, len(a))
|
||||
copy(a2, a)
|
||||
return a2
|
||||
}
|
||||
|
||||
type rewriteEntryJSON struct {
|
||||
Domain string `json:"domain"`
|
||||
Answer string `json:"answer"`
|
||||
@@ -49,6 +161,7 @@ func (d *Dnsfilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
|
||||
Domain: jsent.Domain,
|
||||
Answer: jsent.Answer,
|
||||
}
|
||||
ent.prepare()
|
||||
d.confLock.Lock()
|
||||
d.Config.Rewrites = append(d.Config.Rewrites, ent)
|
||||
d.confLock.Unlock()
|
||||
@@ -74,7 +187,7 @@ func (d *Dnsfilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request)
|
||||
arr := []RewriteEntry{}
|
||||
d.confLock.Lock()
|
||||
for _, ent := range d.Config.Rewrites {
|
||||
if ent == entDel {
|
||||
if ent.equals(entDel) {
|
||||
log.Debug("Rewrites: removed element: %s -> %s", ent.Domain, ent.Answer)
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user