Pull request: AG-31778-fix-safesearch-https

Squashed commit of the following:

commit 85ea3d985e83209e3b49119959aedd330df24d23
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Apr 18 15:19:38 2024 +0200

    all: imp docs

commit b0695daddbcf191454c5e829ca4d19def8ddacbf
Merge: a79f98f2f 48c6242a7
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 17 11:06:49 2024 +0200

    Merge remote-tracking branch 'origin/master' into AG-31778-fix-safesearch-https

    # Conflicts:
    #	CHANGELOG.md

commit a79f98f2f215a4a79ca4d186c0da33db936429dc
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 17 11:05:34 2024 +0200

    dnsforward: imp code

commit b901a1169cc78313298d70cce770cd1523ccbf9f
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Apr 16 11:03:52 2024 +0200

    dnsforward: imp code

commit fb6e66971b1b984147ec400ceaff856e7b5710c7
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Apr 16 10:08:51 2024 +0200

    all: safesearch rewrites

commit 88add21831fff7e04539f5dd299832883a6f3995
Merge: b78ad8f74 201ac73cf
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Apr 16 09:43:20 2024 +0200

    Merge remote-tracking branch 'origin/master' into AG-31778-fix-safesearch-https

    # Conflicts:
    #	CHANGELOG.md

commit b78ad8f748c7fa52533e0541cae16bd51c201370
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Apr 12 13:34:39 2024 +0200

    all: safesearch rewrites

commit fb3efbb053242c537ca872542006917b8e8ac1ff
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Apr 11 13:15:37 2024 +0200

    safesearch: imp code

commit 1193c704f4d30be4a2cc66e84a31c9a6020ab269
Merge: 14e823d7c ff7c715c5
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Apr 11 13:13:44 2024 +0200

    Merge remote-tracking branch 'origin/master' into AG-31778-fix-safesearch-https

    # Conflicts:
    #	CHANGELOG.md

commit 14e823d7cc13c275c2ed04704883a94b95e29963
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Apr 11 13:11:43 2024 +0200

    all: safesearch https

commit cd403a2897ae56a9059a78f24b104af5805d84ab
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Apr 11 12:09:27 2024 +0200

    Revert "all: safesearch https"

    This reverts commit 1c9564b9b4db70f85b2f827cc06b65d2b67b08b1.

commit 1c9564b9b4db70f85b2f827cc06b65d2b67b08b1
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 10 12:41:47 2024 +0200

    all: safesearch https

commit 5f42688fbab566973acc8dc414a992819492a9ac
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 10 09:22:30 2024 +0200

    filtering: imp code

commit eb9bd9f47cd71cafe8eee4698a8a0d5d25dea3d3
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 10 09:19:22 2024 +0200

    all: changelog

commit 0c77c705a942fe83d3809a7efbc8a6baf5886762
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Apr 10 08:55:22 2024 +0200

    safesearch: imp tests

commit 492a93fbb5ff54678e22a15577f509b2327c2ebe
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Apr 9 14:45:16 2024 +0200

    all: changelog

commit a665e7246d11503c47d48ccc714e6862f764e930
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Apr 9 14:41:24 2024 +0200

    safesearch: https req
This commit is contained in:
Dimitry Kolyshev
2024-04-22 10:48:26 +03:00
parent 48c6242a7b
commit 762ef4a6db
14 changed files with 111 additions and 276 deletions

View File

@@ -2,7 +2,6 @@ package dnsforward
import (
"cmp"
"context"
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
@@ -491,19 +490,10 @@ func TestServerRace(t *testing.T) {
}
func TestSafeSearch(t *testing.T) {
resolver := &aghtest.Resolver{
OnLookupIP: func(_ context.Context, _, host string) (ips []net.IP, err error) {
ip4, ip6 := aghtest.HostToIPs(host)
return []net.IP{ip4.AsSlice(), ip6.AsSlice()}, nil
},
}
safeSearchConf := filtering.SafeSearchConfig{
Enabled: true,
Google: true,
Yandex: true,
CustomResolver: resolver,
Enabled: true,
Google: true,
Yandex: true,
}
filterConf := &filtering.Config{
@@ -540,7 +530,6 @@ func TestSafeSearch(t *testing.T) {
client := &dns.Client{}
yandexIP := netip.AddrFrom4([4]byte{213, 180, 193, 56})
googleIP, _ := aghtest.HostToIPs("forcesafesearch.google.com")
testCases := []struct {
host string
@@ -564,19 +553,19 @@ func TestSafeSearch(t *testing.T) {
wantCNAME: "",
}, {
host: "www.google.com.",
want: googleIP,
want: netip.Addr{},
wantCNAME: "forcesafesearch.google.com.",
}, {
host: "www.google.com.af.",
want: googleIP,
want: netip.Addr{},
wantCNAME: "forcesafesearch.google.com.",
}, {
host: "www.google.be.",
want: googleIP,
want: netip.Addr{},
wantCNAME: "forcesafesearch.google.com.",
}, {
host: "www.google.by.",
want: googleIP,
want: netip.Addr{},
wantCNAME: "forcesafesearch.google.com.",
}}
@@ -593,12 +582,15 @@ func TestSafeSearch(t *testing.T) {
cname := testutil.RequireTypeAssert[*dns.CNAME](t, reply.Answer[0])
assert.Equal(t, tc.wantCNAME, cname.Target)
a := testutil.RequireTypeAssert[*dns.A](t, reply.Answer[1])
assert.NotEmpty(t, a.A)
} else {
require.Len(t, reply.Answer, 1)
}
a := testutil.RequireTypeAssert[*dns.A](t, reply.Answer[len(reply.Answer)-1])
assert.Equal(t, net.IP(tc.want.AsSlice()), a.A)
a := testutil.RequireTypeAssert[*dns.A](t, reply.Answer[0])
assert.Equal(t, net.IP(tc.want.AsSlice()), a.A)
}
})
}
}

View File

@@ -31,6 +31,7 @@ func (s *Server) filterDNSRequest(dctx *dnsContext) (res *filtering.Result, err
req := pctx.Req
q := req.Question[0]
host := strings.TrimSuffix(q.Name, ".")
resVal, err := s.dnsFilter.CheckHost(host, q.Qtype, dctx.setts)
if err != nil {
return nil, fmt.Errorf("checking host %q: %w", host, err)
@@ -39,22 +40,15 @@ func (s *Server) filterDNSRequest(dctx *dnsContext) (res *filtering.Result, err
// TODO(a.garipov): Make CheckHost return a pointer.
res = &resVal
switch {
case res.IsFiltered:
log.Debug(
"dnsforward: host %q is filtered, reason: %q; rule: %q",
host,
res.Reason,
res.Rules[0].Text,
)
pctx.Res = s.genDNSFilterMessage(pctx, res)
case res.Reason.In(filtering.Rewritten, filtering.RewrittenRule) &&
res.CanonName != "" &&
len(res.IPList) == 0:
case isRewrittenCNAME(res):
// Resolve the new canonical name, not the original host name. The
// original question is readded in processFilteringAfterResponse.
dctx.origQuestion = q
req.Question[0].Name = dns.Fqdn(res.CanonName)
case res.Reason == filtering.Rewritten:
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):
pctx.Res = s.getCNAMEWithIPs(req, res.IPList, res.CanonName)
case res.Reason.In(filtering.RewrittenRule, filtering.RewrittenAutoHosts):
if err = s.filterDNSRewrite(req, res, pctx); err != nil {
@@ -65,6 +59,17 @@ func (s *Server) filterDNSRequest(dctx *dnsContext) (res *filtering.Result, err
return res, err
}
// 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.
func (s *Server) checkHostRules(

View File

@@ -52,7 +52,7 @@ func (s *Server) genDNSFilterMessage(
) (resp *dns.Msg) {
req := dctx.Req
qt := req.Question[0].Qtype
if qt != dns.TypeA && qt != dns.TypeAAAA {
if qt != dns.TypeA && qt != dns.TypeAAAA && qt != dns.TypeHTTPS {
m, _, _ := s.dnsFilter.BlockingMode()
if m == filtering.BlockingModeNullIP {
return s.replyCompressed(req)

View File

@@ -598,7 +598,8 @@ func (s *Server) processFilteringAfterResponse(dctx *dnsContext) (rc resultCode)
return resultCodeSuccess
case
filtering.Rewritten,
filtering.RewrittenRule:
filtering.RewrittenRule,
filtering.FilteredSafeSearch:
if dctx.origQuestion.Name == "" {
// origQuestion is set in case we get only CNAME without IP from
@@ -608,11 +609,10 @@ func (s *Server) processFilteringAfterResponse(dctx *dnsContext) (rc resultCode)
pctx := dctx.proxyCtx
pctx.Req.Question[0], pctx.Res.Question[0] = dctx.origQuestion, dctx.origQuestion
if len(pctx.Res.Answer) > 0 {
rr := s.genAnswerCNAME(pctx.Req, res.CanonName)
answer := append([]dns.RR{rr}, pctx.Res.Answer...)
pctx.Res.Answer = answer
}
rr := s.genAnswerCNAME(pctx.Req, res.CanonName)
answer := append([]dns.RR{rr}, pctx.Res.Answer...)
pctx.Res.Answer = answer
return resultCodeSuccess
default: