diff --git a/adapter/dns.go b/adapter/dns.go index 4e79d657..bf73f4e5 100644 --- a/adapter/dns.go +++ b/adapter/dns.go @@ -27,8 +27,6 @@ type DNSClient interface { Start() Exchange(ctx context.Context, transport DNSTransport, message *dns.Msg, options DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) (*dns.Msg, error) Lookup(ctx context.Context, transport DNSTransport, domain string, options DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) ([]netip.Addr, error) - LookupCache(domain string, strategy C.DomainStrategy) ([]netip.Addr, bool) - ExchangeCache(ctx context.Context, message *dns.Msg) (*dns.Msg, bool) ClearCache() } diff --git a/dns/client.go b/dns/client.go index 8db45d41..939ca48c 100644 --- a/dns/client.go +++ b/dns/client.go @@ -353,68 +353,6 @@ func (c *Client) ClearCache() { } } -func (c *Client) LookupCache(domain string, strategy C.DomainStrategy) ([]netip.Addr, bool) { - if c.disableCache || c.independentCache { - return nil, false - } - if dns.IsFqdn(domain) { - domain = domain[:len(domain)-1] - } - dnsName := dns.Fqdn(domain) - if strategy == C.DomainStrategyIPv4Only { - addresses, err := c.questionCache(dns.Question{ - Name: dnsName, - Qtype: dns.TypeA, - Qclass: dns.ClassINET, - }, nil) - if err != ErrNotCached { - return addresses, true - } - } else if strategy == C.DomainStrategyIPv6Only { - addresses, err := c.questionCache(dns.Question{ - Name: dnsName, - Qtype: dns.TypeAAAA, - Qclass: dns.ClassINET, - }, nil) - if err != ErrNotCached { - return addresses, true - } - } else { - response4, _ := c.loadResponse(dns.Question{ - Name: dnsName, - Qtype: dns.TypeA, - Qclass: dns.ClassINET, - }, nil) - if response4 == nil { - return nil, false - } - response6, _ := c.loadResponse(dns.Question{ - Name: dnsName, - Qtype: dns.TypeAAAA, - Qclass: dns.ClassINET, - }, nil) - if response6 == nil { - return nil, false - } - return sortAddresses(MessageToAddresses(response4), MessageToAddresses(response6), strategy), true - } - return nil, false -} - -func (c *Client) ExchangeCache(ctx context.Context, message *dns.Msg) (*dns.Msg, bool) { - if c.disableCache || c.independentCache || len(message.Question) != 1 { - return nil, false - } - question := message.Question[0] - response, ttl := c.loadResponse(question, nil) - if response == nil { - return nil, false - } - logCachedResponse(c.logger, ctx, response, ttl) - response.Id = message.Id - return response, true -} - func sortAddresses(response4 []netip.Addr, response6 []netip.Addr, strategy C.DomainStrategy) []netip.Addr { if strategy == C.DomainStrategyPreferIPv6 { return append(response6, response4...) diff --git a/dns/router.go b/dns/router.go index ae9e68c7..8de1f6a9 100644 --- a/dns/router.go +++ b/dns/router.go @@ -214,97 +214,95 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte } r.logger.DebugContext(ctx, "exchange ", FormatQuestion(message.Question[0].String())) var ( + response *mDNS.Msg transport adapter.DNSTransport err error ) - response, cached := r.client.ExchangeCache(ctx, message) - if !cached { - var metadata *adapter.InboundContext - ctx, metadata = adapter.ExtendContext(ctx) - metadata.Destination = M.Socksaddr{} - metadata.QueryType = message.Question[0].Qtype - switch metadata.QueryType { - case mDNS.TypeA: - metadata.IPVersion = 4 - case mDNS.TypeAAAA: - metadata.IPVersion = 6 - } - metadata.Domain = FqdnToDomain(message.Question[0].Name) - if options.Transport != nil { - transport = options.Transport - if legacyTransport, isLegacy := transport.(adapter.LegacyDNSTransport); isLegacy { - if options.Strategy == C.DomainStrategyAsIS { - options.Strategy = legacyTransport.LegacyStrategy() - } - if !options.ClientSubnet.IsValid() { - options.ClientSubnet = legacyTransport.LegacyClientSubnet() - } - } + var metadata *adapter.InboundContext + ctx, metadata = adapter.ExtendContext(ctx) + metadata.Destination = M.Socksaddr{} + metadata.QueryType = message.Question[0].Qtype + switch metadata.QueryType { + case mDNS.TypeA: + metadata.IPVersion = 4 + case mDNS.TypeAAAA: + metadata.IPVersion = 6 + } + metadata.Domain = FqdnToDomain(message.Question[0].Name) + if options.Transport != nil { + transport = options.Transport + if legacyTransport, isLegacy := transport.(adapter.LegacyDNSTransport); isLegacy { if options.Strategy == C.DomainStrategyAsIS { - options.Strategy = r.defaultDomainStrategy + options.Strategy = legacyTransport.LegacyStrategy() } - response, err = r.client.Exchange(ctx, transport, message, options, nil) - } else { - var ( - rule adapter.DNSRule - ruleIndex int - ) - ruleIndex = -1 - for { - dnsCtx := adapter.OverrideContext(ctx) - dnsOptions := options - transport, rule, ruleIndex = r.matchDNS(ctx, true, ruleIndex, isAddressQuery(message), &dnsOptions) - if rule != nil { - switch action := rule.Action().(type) { - case *R.RuleActionReject: - switch action.Method { - case C.RuleActionRejectMethodDefault: - return &mDNS.Msg{ - MsgHdr: mDNS.MsgHdr{ - Id: message.Id, - Rcode: mDNS.RcodeRefused, - Response: true, - }, - Question: []mDNS.Question{message.Question[0]}, - }, nil - case C.RuleActionRejectMethodDrop: - return nil, tun.ErrDrop - } - case *R.RuleActionPredefined: - 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) - } - } - if dnsOptions.Strategy == C.DomainStrategyAsIS { - dnsOptions.Strategy = r.defaultDomainStrategy - } - response, err = r.client.Exchange(dnsCtx, transport, message, dnsOptions, responseCheck) - var rejected bool - if err != nil { - if errors.Is(err, ErrResponseRejectedCached) { - rejected = true - r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String())), " (cached)") - } else if errors.Is(err, ErrResponseRejected) { - rejected = true - r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String()))) - } else if len(message.Question) > 0 { - r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", FormatQuestion(message.Question[0].String()))) - } else { - r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ")) - } - } - if responseCheck != nil && rejected { - continue - } - break + if !options.ClientSubnet.IsValid() { + options.ClientSubnet = legacyTransport.LegacyClientSubnet() } } + if options.Strategy == C.DomainStrategyAsIS { + options.Strategy = r.defaultDomainStrategy + } + response, err = r.client.Exchange(ctx, transport, message, options, nil) + } else { + var ( + rule adapter.DNSRule + ruleIndex int + ) + ruleIndex = -1 + for { + dnsCtx := adapter.OverrideContext(ctx) + dnsOptions := options + transport, rule, ruleIndex = r.matchDNS(ctx, true, ruleIndex, isAddressQuery(message), &dnsOptions) + if rule != nil { + switch action := rule.Action().(type) { + case *R.RuleActionReject: + switch action.Method { + case C.RuleActionRejectMethodDefault: + return &mDNS.Msg{ + MsgHdr: mDNS.MsgHdr{ + Id: message.Id, + Rcode: mDNS.RcodeRefused, + Response: true, + }, + Question: []mDNS.Question{message.Question[0]}, + }, nil + case C.RuleActionRejectMethodDrop: + return nil, tun.ErrDrop + } + case *R.RuleActionPredefined: + 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) + } + } + if dnsOptions.Strategy == C.DomainStrategyAsIS { + dnsOptions.Strategy = r.defaultDomainStrategy + } + response, err = r.client.Exchange(dnsCtx, transport, message, dnsOptions, responseCheck) + var rejected bool + if err != nil { + if errors.Is(err, ErrResponseRejectedCached) { + rejected = true + r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String())), " (cached)") + } else if errors.Is(err, ErrResponseRejected) { + rejected = true + r.logger.DebugContext(ctx, E.Cause(err, "response rejected for ", FormatQuestion(message.Question[0].String()))) + } else if len(message.Question) > 0 { + r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", FormatQuestion(message.Question[0].String()))) + } else { + r.logger.ErrorContext(ctx, E.Cause(err, "exchange failed for ")) + } + } + if responseCheck != nil && rejected { + continue + } + break + } } if err != nil { return nil, err @@ -327,7 +325,6 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg, options adapte func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQueryOptions) ([]netip.Addr, error) { var ( responseAddrs []netip.Addr - cached bool err error ) printResult := func() { @@ -347,13 +344,6 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ err = E.Cause(err, "lookup ", domain) } } - responseAddrs, cached = r.client.LookupCache(domain, options.Strategy) - if cached { - if len(responseAddrs) == 0 { - return nil, E.New("lookup ", domain, ": empty result (cached)") - } - return responseAddrs, nil - } r.logger.DebugContext(ctx, "lookup domain ", domain) ctx, metadata := adapter.ExtendContext(ctx) metadata.Destination = M.Socksaddr{}