fix(rewrite): fix cname target rewrite for CNAME chains (#7853)

* fix(rewrite): fix cname target rewrite for CNAME chains

This fix corrects the cname target rewrite to handle CNAME chains:
- Preserves only the CNAME records before matching the rule
- Rewrites only the CNAME target that matches the rule
- Includes all records from the re-resolved upstream response

Signed-off-by: hide <hide@hide.net.eu.org>

* docs(rewrite): document how answer records are handled in CNAME target rewrite

Signed-off-by: hide <hide@hide.net.eu.org>

* fix(rewrite): simplify slice append per staticcheck S1011

Signed-off-by: hide <hide@hide.net.eu.org>

* docs(rewrite): add extra line between code and paragraph

Signed-off-by: hide <hide@hide.net.eu.org>

---------

Signed-off-by: hide <hide@hide.net.eu.org>
Co-authored-by: hide <hide@hide.net.eu.org>
This commit is contained in:
hide
2026-02-22 06:10:35 +09:00
committed by GitHub
parent 191a783e46
commit 78524a7921
3 changed files with 38 additions and 13 deletions

View File

@@ -91,21 +91,21 @@ func (r *cnameTargetRuleWithReqState) RewriteResponse(res *dns.Msg, rr dns.RR) {
}
var newAnswer []dns.RR
// iterate over first upstram response
// iterate over first upstream response
// add the cname record to the new answer
for _, rr := range res.Answer {
if cname, ok := rr.(*dns.CNAME); ok {
// change the target name in the response
cname.Target = toTarget
newAnswer = append(newAnswer, rr)
}
}
// iterate over upstream response received
for _, rr := range upRes.Answer {
if rr.Header().Name == toTarget {
// preserve CNAME records until the rewrite target
newAnswer = append(newAnswer, rr)
if cname.Target == fromTarget {
// change the target name in the response
cname.Target = toTarget
break
}
}
}
// add the upstream response to the new answer
newAnswer = append(newAnswer, upRes.Answer...)
res.Answer = newAnswer
// if not propagated, the truncated response might get cached,
// and it will be impossible to resolve the full response