diff --git a/plugin/rewrite/README.md b/plugin/rewrite/README.md index 895ef6325..826c3ec1f 100644 --- a/plugin/rewrite/README.md +++ b/plugin/rewrite/README.md @@ -51,6 +51,7 @@ will behave as follows: * `continue` will continue applying the next rule in the rule list. * `stop` will consider the current rule the last rule and will not continue. The default behaviour is `stop` + * When multiple rules are matched, the request rewrite follows the line order in the configuration, while the response rewrite(`answer` option) is executed in reverse order. ## Examples diff --git a/plugin/rewrite/reverter.go b/plugin/rewrite/reverter.go index 853d96d9d..4aa6f8a5e 100644 --- a/plugin/rewrite/reverter.go +++ b/plugin/rewrite/reverter.go @@ -90,8 +90,9 @@ func (r *ResponseReverter) WriteMsg(res1 *dns.Msg) error { } func (r *ResponseReverter) rewriteResourceRecord(res *dns.Msg, rr dns.RR) { - for _, rule := range r.ResponseRules { - rule.RewriteResponse(res, rr) + // The reverting rules need to be done in reversed order. + for i := len(r.ResponseRules) - 1; i >= 0; i-- { + r.ResponseRules[i].RewriteResponse(res, rr) } } diff --git a/plugin/rewrite/reverter_test.go b/plugin/rewrite/reverter_test.go index 9156728b2..b4a782455 100644 --- a/plugin/rewrite/reverter_test.go +++ b/plugin/rewrite/reverter_test.go @@ -126,6 +126,24 @@ func TestValueResponseReverter(t *testing.T) { rules = append(rules, r) doValueReverterTests("suffix", rules, t) + + // multiple rules + rules = []Rule{} + r, err = newNameRule("continue", "suffix", `.domain.uk`, ".domain.us", "answer", "auto") + if err != nil { + t.Errorf("cannot parse rule: %s", err) + return + } + rules = append(rules, r) + + r, err = newNameRule("stop", "suffix", `.domain.us`, ".cluster.local", "answer", "auto") + if err != nil { + t.Errorf("cannot parse rule: %s", err) + return + } + rules = append(rules, r) + + doValueReverterTests("suffix_multiple", rules, t) } func doValueReverterTests(name string, rules []Rule, t *testing.T) {