AdGuardHome/internal/dnsforward/filter.go

209 lines
5.4 KiB
Go
Raw Permalink Normal View History

package dnsforward
import (
Pull request:* all: remove github.com/joomcode/errorx dependency Merge in DNS/adguard-home from 2240-removing-errorx-dependency to master Squashed commit of the following: commit 5bbe0567356f06e3b9ee5b3dc38d357b472cacb1 Merge: a6040850d 02d16a0b4 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 5 14:32:22 2020 +0300 Merge branch 'master' into 2240-removing-errorx-dependency commit a6040850da3cefb131208097477b0956e80063fb Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 5 14:23:36 2020 +0300 * dhcpd: convert some abbreviations to lowercase. commit d05bd51b994906b0ff52c5a8e779bd1f512f4bb7 Author: Eugene Burkov <e.burkov@adguard.com> Date: Thu Nov 5 12:47:20 2020 +0300 * agherr: last final fixes commit 164bca55035ff44e50b0abb33e129a0d24ffe87c Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Nov 3 19:11:10 2020 +0300 * all: final fixes again commit a0ac26f409c0b28a176cf2861d52c2f471b59484 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Nov 3 18:51:39 2020 +0300 * all: final fixes commit 6147b02d402b513323b07e85856b348884f3a088 Merge: 9fd3af1a3 62cc334f4 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 18:26:03 2020 +0300 Merge branch 'master' into 2240-removing-errorx-dependency commit 9fd3af1a39a3189b5c41315a8ad1568ae5cb4fc9 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 18:23:08 2020 +0300 * all: remove useless helper commit 7cd9aeae639762b28b25f354d69c5cf74f670211 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 17:19:26 2020 +0300 * agherr: improved code tidiness commit a74a49236e9aaace070646dac710de9201105262 Merge: dc9dedbf2 df34ee5c0 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 16:54:29 2020 +0300 Merge branch 'master' into 2240-removing-errorx-dependency commit dc9dedbf205756e3adaa3bc776d349bf3d8c69a5 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 16:40:08 2020 +0300 * agherr: improve and cover by tests commit fd6bfe9e282156cc60e006cb7cd46cce4d3a07a8 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 14:06:27 2020 +0300 * all: improve code quality commit ea00c2f8c5060e9611f9a80cfd0e4a039526d0c4 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 13:03:57 2020 +0300 * all: fix linter style warnings commit 8e75e1a681a7218c2b4c69adfa2b7e1e2966f9ac Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Nov 3 12:29:26 2020 +0300 * all: remove github.com/joomcode/errorx dependency Closes #2240.
2020-11-05 12:20:57 +00:00
"fmt"
2023-09-07 15:13:48 +01:00
"net"
2024-03-12 14:45:11 +00:00
"slices"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/golibs/log"
2023-09-11 15:51:50 +01:00
"github.com/AdguardTeam/urlfilter/rules"
"github.com/miekg/dns"
)
2023-07-26 11:18:44 +01:00
// clientRequestFilteringSettings looks up client filtering settings using the
// client's IP address and ID, if any, from dctx.
func (s *Server) clientRequestFilteringSettings(dctx *dnsContext) (setts *filtering.Settings) {
setts = s.dnsFilter.Settings()
2022-09-07 16:03:18 +01:00
setts.ProtectionEnabled = dctx.protectionEnabled
if s.conf.FilterHandler != nil {
s.conf.FilterHandler(dctx.proxyCtx.Addr.Addr(), dctx.clientID, setts)
}
Pull request: all: client id support Merge in DNS/adguard-home from 1383-client-id to master Updates #1383. Squashed commit of the following: commit ebe2678bfa9bf651a2cb1e64499b38edcf19a7ad Author: Ildar Kamalov <ik@adguard.com> Date: Wed Jan 27 17:51:59 2021 +0300 - client: check if IP is valid commit 0c330585a170ea149ee75e43dfa65211e057299c Author: Ildar Kamalov <ik@adguard.com> Date: Wed Jan 27 17:07:50 2021 +0300 - client: find clients by client_id commit 71c9593ee35d996846f061e114b7867c3aa3c978 Merge: 9104f161 3e9edd9e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Jan 27 16:09:45 2021 +0300 Merge branch 'master' into 1383-client-id commit 9104f1615d2d462606c52017df25a422df872cea Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Jan 27 13:28:50 2021 +0300 dnsforward: imp tests commit ed47f26e611ade625a2cc2c2f71a291b796bbf8f Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Jan 27 12:39:52 2021 +0300 dnsforward: fix address commit 98b222ba69a5d265f620c180c960d01c84a1fb3b Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 19:50:31 2021 +0300 home: imp code commit 4f3966548a2d8437d0b68207dd108dd1a6cb7d20 Merge: 199fdc05 c215b820 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 19:45:13 2021 +0300 Merge branch 'master' into 1383-client-id commit 199fdc056f8a8be5500584f3aaee32865188aedc Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 19:20:37 2021 +0300 all: imp tests, logging, etc commit 35ff14f4d534251aecb2ea60baba225f3eed8a3e Author: Ildar Kamalov <ik@adguard.com> Date: Tue Jan 26 18:55:19 2021 +0300 + client: remove block button from clients with client_id commit 32991a0b4c56583a02fb5e00bba95d96000bce20 Author: Ildar Kamalov <ik@adguard.com> Date: Tue Jan 26 18:54:25 2021 +0300 + client: add requests count for client_id commit 2d68df4d2eac4a296d7469923e601dad4575c1a1 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 15:49:50 2021 +0300 stats: handle client ids commit 4e14ab3590328f93a8cd6e9cbe1665baf74f220b Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 13:45:25 2021 +0300 openapi: fix example commit ca9cf3f744fe197cace2c28ddc5bc68f71dad1f3 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 13:37:10 2021 +0300 openapi: improve clients find api docs commit f79876e550c424558b704bc316a4cd04f25db011 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Tue Jan 26 13:18:52 2021 +0300 home: accept ids in clients find commit 5b72595122aa0bd64debadfd753ed8a0e0840629 Merge: 607e241f abf8f65f Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Jan 25 18:34:56 2021 +0300 Merge branch 'master' into 1383-client-id commit 607e241f1c339dd6397218f70b8301e3de6a1ee0 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Jan 25 18:30:39 2021 +0300 dnsforward: fix quic commit f046352fef93e46234c2bbe8ae316d21034260e5 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Jan 25 16:53:09 2021 +0300 all: remove wildcard requirement commit 3b679489bae82c54177372be453fe184d8f0bab6 Author: Andrey Meshkov <am@adguard.com> Date: Mon Jan 25 16:02:28 2021 +0300 workDir now supports symlinks commit 0647ab4f113de2223f6949df001f42ecab05c995 Author: Ildar Kamalov <ik@adguard.com> Date: Mon Jan 25 14:59:46 2021 +0300 - client: remove wildcard from domain validation commit b1aec04a4ecadc9d65648ed6d284188fecce01c3 Author: Ildar Kamalov <ik@adguard.com> Date: Mon Jan 25 14:55:39 2021 +0300 + client: add form to download mobileconfig ... and 12 more commits
2021-01-27 15:32:13 +00:00
2023-07-03 12:10:40 +01:00
return setts
}
2022-09-07 16:03:18 +01:00
// filterDNSRequest applies the dnsFilter and sets dctx.proxyCtx.Res if the
// request was filtered.
func (s *Server) filterDNSRequest(dctx *dnsContext) (res *filtering.Result, err error) {
pctx := dctx.proxyCtx
req := pctx.Req
q := req.Question[0]
host := strings.TrimSuffix(q.Name, ".")
2024-05-15 11:34:12 +01:00
2022-09-07 16:03:18 +01:00
resVal, err := s.dnsFilter.CheckHost(host, q.Qtype, dctx.setts)
if err != nil {
return nil, fmt.Errorf("checking host %q: %w", host, err)
}
// TODO(a.garipov): Make CheckHost return a pointer.
res = &resVal
switch {
2024-05-15 11:34:12 +01:00
case isRewrittenCNAME(res):
// Resolve the new canonical name, not the original host name. The
// original question is readded in processFilteringAfterResponse.
2022-09-07 16:03:18 +01:00
dctx.origQuestion = q
Pull request: 2704 local addresses vol.3 Merge in DNS/adguard-home from 2704-local-addresses-vol.3 to master Updates #2704. Updates #2829. Updates #2928. Squashed commit of the following: commit 8c42355c0093a3ac6951f79a5211e7891800f93a Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Apr 7 18:07:41 2021 +0300 dnsforward: rm errors pkg commit 7594a21a620239951039454dd5686a872e6f41a8 Merge: 830b0834 908452f8 Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Apr 7 18:00:03 2021 +0300 Merge branch 'master' into 2704-local-addresses-vol.3 commit 830b0834090510096061fed20b600195ab3773b8 Author: Eugene Burkov <e.burkov@adguard.com> Date: Wed Apr 7 17:47:51 2021 +0300 dnsforward: reduce local upstream timeout commit 493e81d9e8bacdc690f88af29a38d211b9733c7e Author: Ildar Kamalov <ik@adguard.com> Date: Tue Apr 6 19:11:00 2021 +0300 client: private_upstream test commit a0194ac28f15114578359b8c2460cd9af621e912 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Apr 6 18:36:23 2021 +0300 all: expand api, fix conflicts commit 0f4e06836fed958391aa597c8b02453564980ca3 Merge: 89cf93ad 8746005d Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Apr 6 18:35:04 2021 +0300 Merge branch 'master' into 2704-local-addresses-vol.3 commit 89cf93ad4f26c2bf4f1b18ecaa4d3a1e169f9b06 Author: Ildar Kamalov <ik@adguard.com> Date: Tue Apr 6 18:02:40 2021 +0300 client: add local ptr upstreams to upstream test commit e6dd869dddd4888474d625cbb005bad6390e4760 Author: Ildar Kamalov <ik@adguard.com> Date: Tue Apr 6 15:24:22 2021 +0300 client: add private DNS form commit b858057b9a957a416117f22b8bd0025f90e8c758 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Apr 6 13:05:28 2021 +0300 aghstrings: mk cloning correct commit 8009ba60a6a7d6ceb7b6483a29f4e68d533af243 Author: Eugene Burkov <e.burkov@adguard.com> Date: Tue Apr 6 12:37:46 2021 +0300 aghstrings: fix lil bug commit 0dd19f2e7cc7c0de21517c37abd8336a907e1c0d Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Apr 5 20:45:01 2021 +0300 all: log changes commit eb5558d96fffa6e7bca7e14d3740d26e47382e23 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Apr 5 20:18:53 2021 +0300 dnsforward: keep the style commit d6d5fcbde40a633129c0e04887b81cf0b1ce6875 Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Apr 5 20:02:52 2021 +0300 dnsforward: disable redundant filtering for local ptr commit 4f864c32027d10db9bcb4a264d2338df8c20afac Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Apr 5 17:53:17 2021 +0300 dnsforward: imp tests commit 7848e6f2341868f8ba0bb839956a0b7444cf02ca Author: Eugene Burkov <e.burkov@adguard.com> Date: Mon Apr 5 14:52:12 2021 +0300 all: imp code commit 19ac30653800eebf8aaee499f65560ae2d458a5a Author: Eugene Burkov <e.burkov@adguard.com> Date: Sun Apr 4 16:28:05 2021 +0300 all: mv more logic to aghstrings commit fac892ec5f0d2e30d6d64def0609267bbae4a202 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Apr 2 20:23:23 2021 +0300 dnsforward: use filepath commit 05a3aeef1181b914788d14c7519287d467ab301f Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Apr 2 20:17:54 2021 +0300 aghstrings: introduce the pkg commit f24e1b63d6e1bf266a4ed063f46f86d7abf65663 Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Apr 2 20:01:23 2021 +0300 all: imp code commit 0217a0ebb341f99a90c9b68013bebf6ff73d08ae Author: Eugene Burkov <e.burkov@adguard.com> Date: Fri Apr 2 18:04:13 2021 +0300 openapi: log changes ... and 3 more commits
2021-04-07 18:16:06 +01:00
req.Question[0].Name = dns.Fqdn(res.CanonName)
2024-05-15 11:34:12 +01:00
case res.IsFiltered:
log.Debug("dnsforward: host %q is filtered, reason: %q", host, res.Reason)
pctx.Res = s.genDNSFilterMessage(pctx, res)
case res.Reason.In(filtering.Rewritten, filtering.FilteredSafeSearch):
2024-01-30 15:43:51 +00:00
pctx.Res = s.getCNAMEWithIPs(req, res.IPList, res.CanonName)
2022-09-07 16:03:18 +01:00
case res.Reason.In(filtering.RewrittenRule, filtering.RewrittenAutoHosts):
if err = s.filterDNSRewrite(req, res, pctx); err != nil {
return nil, err
}
2022-09-07 16:03:18 +01:00
}
2022-09-07 16:03:18 +01:00
return res, err
}
2024-05-15 11:34:12 +01:00
// isRewrittenCNAME returns true if the request considered to be rewritten with
// CNAME and has no resolved IPs.
func isRewrittenCNAME(res *filtering.Result) (ok bool) {
return res.Reason.In(
filtering.Rewritten,
filtering.RewrittenRule,
filtering.FilteredSafeSearch) &&
res.CanonName != "" &&
len(res.IPList) == 0
}
// checkHostRules checks the host against filters. It is safe for concurrent
// use.
2023-09-11 15:51:50 +01:00
func (s *Server) checkHostRules(
host string,
rrtype rules.RRType,
setts *filtering.Settings,
) (r *filtering.Result, err error) {
s.serverLock.RLock()
defer s.serverLock.RUnlock()
2023-09-11 15:51:50 +01:00
res, err := s.dnsFilter.CheckHostRules(host, rrtype, setts)
if err != nil {
return nil, err
}
return &res, err
}
2023-09-11 15:51:50 +01:00
// filterDNSResponse checks each resource record of answer section of
// dctx.proxyCtx.Res. It sets dctx.result and dctx.origResp if at least one of
// canonical names, IP addresses, or HTTPS RR hints in it matches the filtering
// rules, as well as sets dctx.proxyCtx.Res to the filtered response.
func (s *Server) filterDNSResponse(dctx *dnsContext) (err error) {
setts := dctx.setts
2022-06-02 15:55:48 +01:00
if !setts.FilteringEnabled {
2023-09-11 15:51:50 +01:00
return nil
2022-06-02 15:55:48 +01:00
}
2023-09-11 15:51:50 +01:00
var res *filtering.Result
pctx := dctx.proxyCtx
for i, a := range pctx.Res.Answer {
host := ""
2023-09-11 15:51:50 +01:00
var rrtype rules.RRType
2022-06-02 15:55:48 +01:00
switch a := a.(type) {
case *dns.CNAME:
2022-06-02 15:55:48 +01:00
host = strings.TrimSuffix(a.Target, ".")
rrtype = dns.TypeCNAME
2023-09-07 15:13:48 +01:00
res, err = s.checkHostRules(host, rrtype, setts)
case *dns.A:
2022-06-02 15:55:48 +01:00
host = a.A.String()
rrtype = dns.TypeA
2023-09-07 15:13:48 +01:00
res, err = s.checkHostRules(host, rrtype, setts)
case *dns.AAAA:
2022-06-02 15:55:48 +01:00
host = a.AAAA.String()
rrtype = dns.TypeAAAA
2023-09-07 15:13:48 +01:00
res, err = s.checkHostRules(host, rrtype, setts)
case *dns.HTTPS:
res, err = s.filterHTTPSRecords(a, setts)
default:
continue
}
2023-09-07 15:13:48 +01:00
log.Debug("dnsforward: checked %s %s for %s", dns.Type(rrtype), host, a.Header().Name)
2022-06-02 15:55:48 +01:00
if err != nil {
2023-09-11 15:51:50 +01:00
return fmt.Errorf("filtering answer at index %d: %w", i, err)
} else if res != nil && res.IsFiltered {
dctx.result = res
dctx.origResp = pctx.Res
2022-09-07 16:03:18 +01:00
pctx.Res = s.genDNSFilterMessage(pctx, res)
2023-09-11 15:51:50 +01:00
2023-08-02 14:26:34 +01:00
log.Debug("dnsforward: matched %q by response: %q", pctx.Req.Question[0].Name, host)
2023-09-11 15:51:50 +01:00
break
}
}
2023-09-11 15:51:50 +01:00
return nil
}
2023-09-07 15:13:48 +01:00
// removeIPv6Hints deletes IPv6 hints from RR values.
func removeIPv6Hints(rr *dns.HTTPS) {
rr.Value = slices.DeleteFunc(rr.Value, func(kv dns.SVCBKeyValue) (del bool) {
_, ok := kv.(*dns.SVCBIPv6Hint)
return ok
})
}
// filterHTTPSRecords filters HTTPS answers information through all rule list
// filters of the server filters. Removes IPv6 hints if IPv6 resolving is
// disabled.
func (s *Server) filterHTTPSRecords(rr *dns.HTTPS, setts *filtering.Settings) (r *filtering.Result, err error) {
if s.conf.AAAADisabled {
removeIPv6Hints(rr)
}
for _, kv := range rr.Value {
var ips []net.IP
switch hint := kv.(type) {
case *dns.SVCBIPv4Hint:
ips = hint.Hint
case *dns.SVCBIPv6Hint:
ips = hint.Hint
default:
// Go on.
}
if len(ips) == 0 {
continue
}
r, err = s.filterSVCBHint(ips, setts)
if err != nil {
return nil, fmt.Errorf("filtering svcb hints: %w", err)
}
if r != nil {
return r, nil
}
}
return nil, nil
}
// filterSVCBHint filters SVCB hint information.
func (s *Server) filterSVCBHint(
hint []net.IP,
setts *filtering.Settings,
) (res *filtering.Result, err error) {
for _, h := range hint {
res, err = s.checkHostRules(h.String(), dns.TypeHTTPS, setts)
if err != nil {
return nil, fmt.Errorf("checking rules for %s: %w", h, err)
}
if res != nil && res.IsFiltered {
return res, nil
}
}
return nil, nil
}