From ef99a87de72053a18f0cd5e193b226dc2df0c540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Tue, 31 Mar 2026 16:53:57 +0800 Subject: [PATCH] dns: reject method `reply` is not supported for DNS rules Add config-time validation in NewDNSRule that rejects RejectMethodReply for both default and logical DNS rules, matching the existing TCP/UDP validation in route/route.go. --- route/rule/nested_action_test.go | 20 ++++++++++++++++++++ route/rule/rule_dns.go | 15 +++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/route/rule/nested_action_test.go b/route/rule/nested_action_test.go index b21828c04..77ff29c7b 100644 --- a/route/rule/nested_action_test.go +++ b/route/rule/nested_action_test.go @@ -135,3 +135,23 @@ func TestNewDNSRuleRejectsNestedRuleAction(t *testing.T) { }, true, false) require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage) } + +func TestNewDNSRuleRejectsReplyRejectMethod(t *testing.T) { + t.Parallel() + + _, err := NewDNSRule(context.Background(), log.NewNOPFactory().NewLogger("dns"), option.DNSRule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultDNSRule{ + RawDefaultDNSRule: option.RawDefaultDNSRule{ + Domain: []string{"example.com"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeReject, + RejectOptions: option.RejectActionOptions{ + Method: C.RuleActionRejectMethodReply, + }, + }, + }, + }, false, false) + require.ErrorContains(t, err, "reject method `reply` is not supported for DNS rules") +} diff --git a/route/rule/rule_dns.go b/route/rule/rule_dns.go index 764deabf9..7dcc4711a 100644 --- a/route/rule/rule_dns.go +++ b/route/rule/rule_dns.go @@ -24,6 +24,10 @@ func NewDNSRule(ctx context.Context, logger log.ContextLogger, options option.DN if !checkServer && options.DefaultOptions.Action == C.RuleActionTypeEvaluate { return nil, E.New(options.DefaultOptions.Action, " is only allowed on top-level DNS rules") } + err := validateDNSRuleAction(options.DefaultOptions.DNSRuleAction) + if err != nil { + return nil, err + } switch options.DefaultOptions.Action { case "", C.RuleActionTypeRoute, C.RuleActionTypeEvaluate: if options.DefaultOptions.RouteOptions.Server == "" && checkServer { @@ -38,6 +42,10 @@ func NewDNSRule(ctx context.Context, logger log.ContextLogger, options option.DN if !checkServer && options.LogicalOptions.Action == C.RuleActionTypeEvaluate { return nil, E.New(options.LogicalOptions.Action, " is only allowed on top-level DNS rules") } + err := validateDNSRuleAction(options.LogicalOptions.DNSRuleAction) + if err != nil { + return nil, err + } switch options.LogicalOptions.Action { case "", C.RuleActionTypeRoute, C.RuleActionTypeEvaluate: if options.LogicalOptions.RouteOptions.Server == "" && checkServer { @@ -50,6 +58,13 @@ func NewDNSRule(ctx context.Context, logger log.ContextLogger, options option.DN } } +func validateDNSRuleAction(action option.DNSRuleAction) error { + if action.Action == C.RuleActionTypeReject && action.RejectOptions.Method == C.RuleActionRejectMethodReply { + return E.New("reject method `reply` is not supported for DNS rules") + } + return nil +} + var _ adapter.DNSRule = (*DefaultDNSRule)(nil) type DefaultDNSRule struct {