diff --git a/dns/client.go b/dns/client.go index 2982d11cf..ed4e8207b 100644 --- a/dns/client.go +++ b/dns/client.go @@ -240,8 +240,10 @@ func (c *Client) Exchange(ctx context.Context, transport adapter.DNSTransport, m if responseChecker != nil { var rejected bool // TODO: add accept_any rule and support to check response instead of addresses - if response.Rcode != dns.RcodeSuccess || len(response.Answer) == 0 { + if response.Rcode != dns.RcodeSuccess && response.Rcode != dns.RcodeNameError { rejected = true + } else if len(response.Answer) == 0 { + rejected = !responseChecker(nil) } else { rejected = !responseChecker(MessageToAddresses(response)) } diff --git a/dns/router.go b/dns/router.go index 5d028059a..7380c4cc4 100644 --- a/dns/router.go +++ b/dns/router.go @@ -273,13 +273,7 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte return action.Response(message), nil } } - var responseCheck func(responseAddrs []netip.Addr) bool - if rule != nil && rule.WithAddressLimit() { - responseCheck = func(responseAddrs []netip.Addr) bool { - metadata.DestinationAddresses = responseAddrs - return rule.MatchAddressLimit(metadata) - } - } + responseCheck := addressLimitResponseCheck(rule, metadata) if dnsOptions.Strategy == C.DomainStrategyAsIS { dnsOptions.Strategy = r.defaultDomainStrategy } @@ -395,13 +389,7 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ goto response } } - var responseCheck func(responseAddrs []netip.Addr) bool - if rule != nil && rule.WithAddressLimit() { - responseCheck = func(responseAddrs []netip.Addr) bool { - metadata.DestinationAddresses = responseAddrs - return rule.MatchAddressLimit(metadata) - } - } + responseCheck := addressLimitResponseCheck(rule, metadata) if dnsOptions.Strategy == C.DomainStrategyAsIS { dnsOptions.Strategy = r.defaultDomainStrategy } @@ -429,6 +417,18 @@ func isAddressQuery(message *mDNS.Msg) bool { return false } +func addressLimitResponseCheck(rule adapter.DNSRule, metadata *adapter.InboundContext) func(responseAddrs []netip.Addr) bool { + if rule == nil || !rule.WithAddressLimit() { + return nil + } + responseMetadata := *metadata + return func(responseAddrs []netip.Addr) bool { + checkMetadata := responseMetadata + checkMetadata.DestinationAddresses = responseAddrs + return rule.MatchAddressLimit(&checkMetadata) + } +} + func (r *Router) ClearCache() { r.client.ClearCache() if r.platformInterface != nil {