plugin/rewrite: Add EDNS0 Unset Action (#7380)

* plugin/rewrite: EDNS0 unset action

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>

* plugin/rewrite: EDNS0 unset tests

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>

* plugin/rewrite: EDNS0 unset documentation

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>

* gofmt whitespace fixes

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>

* plugin/rewrite: improve edns0 test coverage

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>

---------

Signed-off-by: Dennis Simmons <215134900+dennis-ix@users.noreply.github.com>
This commit is contained in:
Dennis Simmons
2025-06-20 00:49:37 +03:00
committed by GitHub
parent 9c51e1741c
commit b2a2a5f648
3 changed files with 178 additions and 2 deletions

View File

@@ -80,10 +80,25 @@ func setupEdns0Opt(r *dns.Msg) *dns.OPT {
return o
}
func unsetEdns0Option(opt *dns.OPT, code uint16) {
var newOpts []dns.EDNS0
for _, o := range opt.Option {
if o.Option() != code {
newOpts = append(newOpts, o)
}
}
opt.Option = newOpts
}
// Rewrite will alter the request EDNS0 NSID option
func (rule *edns0NsidRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) {
o := setupEdns0Opt(state.Req)
if rule.action == Unset {
unsetEdns0Option(o, dns.EDNS0NSID)
return nil, RewriteDone
}
var resp ResponseRules
for _, s := range o.Option {
@@ -118,6 +133,11 @@ func (rule *edns0NsidRule) Mode() string { return rule.mode }
func (rule *edns0LocalRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) {
o := setupEdns0Opt(state.Req)
if rule.action == Unset {
unsetEdns0Option(o, rule.code)
return nil, RewriteDone
}
var resp ResponseRules
for _, s := range o.Option {
@@ -162,6 +182,8 @@ func newEdns0Rule(mode string, args ...string) (Rule, error) {
case Append:
case Replace:
case Set:
case Unset:
return newEdns0UnsetRule(mode, action, ruleType, args...)
default:
return nil, fmt.Errorf("invalid action: %q", action)
}
@@ -198,6 +220,28 @@ func newEdns0Rule(mode string, args ...string) (Rule, error) {
}
}
func newEdns0UnsetRule(mode string, action string, ruleType string, args ...string) (Rule, error) {
switch ruleType {
case "local":
if len(args) != 3 {
return nil, fmt.Errorf("local unset action requires exactly two arguments")
}
return newEdns0LocalRule(mode, action, args[2], "", false)
case "nsid":
if len(args) != 2 {
return nil, fmt.Errorf("nsid unset action requires exactly one argument")
}
return &edns0NsidRule{mode, action, false}, nil
case "subnet":
if len(args) != 2 {
return nil, fmt.Errorf("subnet unset action requires exactly one argument")
}
return &edns0SubnetRule{mode, 0, 0, action, false}, nil
default:
return nil, fmt.Errorf("invalid rule type %q", ruleType)
}
}
func newEdns0LocalRule(mode, action, code, data string, revert bool) (*edns0LocalRule, error) {
c, err := strconv.ParseUint(code, 0, 16)
if err != nil {
@@ -393,6 +437,11 @@ func (rule *edns0SubnetRule) fillEcsData(state request.Request, ecs *dns.EDNS0_S
func (rule *edns0SubnetRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) {
o := setupEdns0Opt(state.Req)
if rule.action == Unset {
unsetEdns0Option(o, dns.EDNS0SUBNET)
return nil, RewriteDone
}
var resp ResponseRules
for _, s := range o.Option {
@@ -433,6 +482,7 @@ const (
Replace = "replace"
Set = "set"
Append = "append"
Unset = "unset"
)
// Supported local EDNS0 variables