Pull request 2703: AGDNS-4222-imp-domain-name-validation

Squashed commit of the following:

commit 35e16b8de54046a0ca5cfcc4157afbb9f09f62c6
Merge: 710580701 ae4bfe947
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Tue Jul 14 15:04:07 2026 +0300

    Merge branch 'master' into AGDNS-4222-imp-domain-name-validation

commit 7105807012
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Mon Jul 13 13:04:41 2026 +0300

    all: upd chlog; filtering: imp tests; add docs;

commit 636bbda8a4
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Mon Jul 13 12:51:26 2026 +0300

    filtering: add test case; all: upd chlog;

commit 4b3bd46352
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Mon Jul 13 12:04:57 2026 +0300

    filtering: rm outdated docs;

commit c6c19ae3d4
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Mon Jul 13 11:58:14 2026 +0300

    filtering: imp answer field validation;
This commit is contained in:
Maksim Kazantsev 2026-07-14 12:19:53 +00:00
parent ae4bfe947c
commit a8a958a77b
4 changed files with 29 additions and 4 deletions

View file

@ -68,6 +68,8 @@ See also the [v0.107.78 GitHub milestone][ms-v0.107.78].
- The parsing of the `ech` parameter in DNS rewrite rules for the HTTPS record type ([#8276]).
- Validation of the `answer` field in DNS rewrite rules in case it is represented as CNAME.
- Blocked services check on the Custom filtering rules page does not work properly without specifying of a client.
[#7955]: https://github.com/AdguardTeam/AdGuardHome/issues/7955

View file

@ -74,8 +74,6 @@ func (d *DNSFilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
err = rw.normalize(ctx, l)
if err != nil {
// Shouldn't happen currently, since normalize only returns a non-nil
// error when a rewrite is nil, but be change-proof.
aghhttp.ErrorAndLog(ctx, l, r, w, http.StatusBadRequest, "normalizing: %s", err)
return
@ -173,8 +171,6 @@ func (d *DNSFilter) handleRewriteUpdate(w http.ResponseWriter, r *http.Request)
err = rwAdd.normalize(ctx, l)
if err != nil {
// Shouldn't happen currently, since normalize only returns a non-nil
// error when a rewrite is nil, but be change-proof.
aghhttp.ErrorAndLog(ctx, l, r, w, http.StatusBadRequest, "normalizing: %s", err)
return

View file

@ -50,6 +50,7 @@ const (
decodeUpdateErrorMsg = decodeMsg + " filtering.rewriteUpdateJSON\n"
)
// TODO(m.kazantsev): Improve maintainability.
func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
t.Parallel()
@ -66,6 +67,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
updAnswer = "upd.rewrite"
invDomain = "inv.local"
invAnswer = "inv.rewrite"
invalidDomain = "invalid_domain"
)
testRewrites := []*rewriteJSON{
@ -148,6 +150,21 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
wantStatus: http.StatusBadRequest,
wantBody: decodeErrorMsg,
wantList: testRewrites,
}, {
name: "add_error_invalid_cname",
url: addURL,
method: http.MethodPost,
reqData: rewriteJSON{
Domain: addDomain,
Answer: "invalid_domain",
Enabled: aghalg.NBTrue,
},
wantConfMod: false,
wantStatus: http.StatusBadRequest,
wantBody: `normalizing: invalid CNAME target "invalid_domain": bad domain name ` +
`"invalid_domain": bad top-level domain name label "invalid_domain": bad top-level ` +
`domain name label rune '_'` + "\n",
wantList: testRewrites,
}, {
name: "delete",
url: deleteURL,

View file

@ -10,6 +10,7 @@ import (
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/netutil"
"github.com/miekg/dns"
)
@ -93,6 +94,15 @@ func (rw *LegacyRewrite) normalize(ctx context.Context, l *slog.Logger) (err err
ip, err := netip.ParseAddr(rw.Answer)
if err != nil {
l.DebugContext(ctx, "normalizing legacy rewrite", slogutil.KeyError, err)
// Not an IP address, treat as CNAME target, but validate as a domain
// name first.
err = netutil.ValidateDomainName(rw.Answer)
if err != nil {
// Use capital letters, as the error message is shown to the user.
return fmt.Errorf("invalid CNAME target %q: %w", rw.Answer, err)
}
rw.Type = dns.TypeCNAME
return nil