Pull request 1964: AG-23599 use hostsfile

Merge in DNS/adguard-home from AG-23599-use-hostsfile to master

Squashed commit of the following:

commit 4766e67a9d5faa4bc89a2a935d187ce4829f7214
Merge: 38369360b 762e5be97
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Aug 22 16:33:54 2023 +0300

    Merge branch 'master' into AG-23599-use-hostsfile

commit 38369360b7d0e5c9ec373c5a06bac8792ca9cd69
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Aug 21 18:09:15 2023 +0300

    filtering: imp tests

commit 1c4d4a9f9639f048173e1c949f39f9ecb6ed0347
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Aug 21 14:00:10 2023 +0300

    filtering: imp cognit, cyclo

commit c50c33d7240c2812a715759fabf140e02184b729
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Aug 21 12:57:31 2023 +0300

    filtering: imp code

commit 92203b16719a717a2946c0401e166b1b38ddb7bc
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Aug 18 17:39:11 2023 +0300

    all: imp code, docs

commit 523e8cd50f9136feede657385b7274fa6ba64131
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Aug 17 15:14:02 2023 +0300

    all: fix ipv6

commit 6ce4537132615cbdc34a0b1f326fedd2b63c355d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Aug 17 14:17:27 2023 +0300

    all: rm urlfilter from hosts

commit d6666e851680c7e586325ea5970e0356ab919074
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Aug 16 15:09:52 2023 +0300

    WIP

commit 4a2732960558bef6636d3c428bad4c7c830016ca
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Aug 16 14:47:13 2023 +0300

    all: use hostsfile
This commit is contained in:
Eugene Burkov
2023-08-22 16:45:11 +03:00
parent 762e5be97a
commit 4b4036fa6a
14 changed files with 639 additions and 753 deletions

View File

@@ -7,6 +7,7 @@ import (
"io/fs"
"net"
"net/http"
"net/netip"
"os"
"path/filepath"
"runtime"
@@ -19,8 +20,10 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/hostsfile"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/mathutil"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/urlfilter"
"github.com/AdguardTeam/urlfilter/filterlist"
@@ -326,16 +329,6 @@ func (d *DNSFilter) WriteDiskConfig(c *Config) {
c.UserRules = slices.Clone(d.UserRules)
}
// cloneRewrites returns a deep copy of entries.
func cloneRewrites(entries []*LegacyRewrite) (clone []*LegacyRewrite) {
clone = make([]*LegacyRewrite, len(entries))
for i, rw := range entries {
clone[i] = rw.clone()
}
return clone
}
// setFilters sets new filters, synchronously or asynchronously. When filters
// are set asynchronously, the old filters continue working until the new
// filters are ready.
@@ -503,31 +496,50 @@ func (d *DNSFilter) matchSysHosts(
qtype uint16,
setts *Settings,
) (res Result, err error) {
// TODO(e.burkov): Where else is this checked?
if !setts.FilteringEnabled || d.EtcHosts == nil {
return res, nil
}
dnsres, _ := d.EtcHosts.MatchRequest(&urlfilter.DNSRequest{
Hostname: host,
SortedClientTags: setts.ClientTags,
// TODO(e.burkov): Wait for urlfilter update to pass netip.Addr.
ClientIP: setts.ClientIP.String(),
ClientName: setts.ClientName,
DNSType: qtype,
})
if dnsres == nil {
return res, nil
var recs []*hostsfile.Record
switch qtype {
case dns.TypeA, dns.TypeAAAA:
recs = d.EtcHosts.MatchName(host)
case dns.TypePTR:
var ip net.IP
ip, err = netutil.IPFromReversedAddr(host)
if err != nil {
log.Debug("filtering: failed to parse PTR record %q: %s", host, err)
return res, nil
}
addr, _ := netip.AddrFromSlice(ip)
recs = d.EtcHosts.MatchAddr(addr)
default:
log.Debug("filtering: unsupported query type %s", dns.Type(qtype))
}
dnsr := dnsres.DNSRewrites()
if len(dnsr) == 0 {
return res, nil
var vals []rules.RRValue
var resRules []*ResultRule
resRulesLen := 0
for _, rec := range recs {
vals, resRules = appendRewriteResultFromHost(vals, resRules, rec, qtype)
if len(resRules) > resRulesLen {
resRulesLen = len(resRules)
log.Debug("filtering: matched %s in %q", host, rec.Source)
}
}
res = d.processDNSRewrites(dnsr)
res.Reason = RewrittenAutoHosts
for _, r := range res.Rules {
r.Text = stringutil.Coalesce(d.EtcHosts.Translate(r.Text), r.Text)
if len(vals) > 0 {
res.DNSRewriteResult = &DNSRewriteResult{
Response: DNSRewriteResultResponse{
qtype: vals,
},
RCode: dns.RcodeSuccess,
}
res.Rules = resRules
res.Reason = RewrittenRule
}
return res, nil
@@ -594,25 +606,6 @@ func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Result) {
return res
}
// setRewriteResult sets the Reason or IPList of res if necessary. res must not
// be nil.
func setRewriteResult(res *Result, host string, rewrites []*LegacyRewrite, qtype uint16) {
for _, rw := range rewrites {
if rw.Type == qtype && (qtype == dns.TypeA || qtype == dns.TypeAAAA) {
if rw.IP == nil {
// "A"/"AAAA" exception: allow getting from upstream.
res.Reason = NotFilteredNotFound
return
}
res.IPList = append(res.IPList, rw.IP)
log.Debug("rewrite: a/aaaa for %s is %s", host, rw.IP)
}
}
}
// matchBlockedServicesRules checks the host against the blocked services rules
// in settings, if any. The err is always nil, it is only there to make this
// a valid hostChecker function.
@@ -895,26 +888,6 @@ func (d *DNSFilter) matchHost(
return res, nil
}
// processDNSResultRewrites returns an empty Result if there are no dnsrewrite
// rules in dnsres. Otherwise, it returns the processed Result.
func (d *DNSFilter) processDNSResultRewrites(
dnsres *urlfilter.DNSResult,
host string,
) (dnsRWRes Result) {
dnsr := dnsres.DNSRewrites()
if len(dnsr) == 0 {
return Result{}
}
res := d.processDNSRewrites(dnsr)
if res.Reason == RewrittenRule && res.CanonName == host {
// A rewrite of a host to itself. Go on and try matching other things.
return Result{}
}
return res
}
// makeResult returns a properly constructed Result.
func makeResult(matchedRules []rules.Rule, reason Reason) (res Result) {
resRules := make([]*ResultRule, len(matchedRules))
@@ -987,7 +960,6 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter, err error) {
if d.BlockedServices != nil {
err = d.BlockedServices.Validate()
if err != nil {
return nil, fmt.Errorf("filtering: %w", err)
}