Add rejected DNS response cache support

This commit is contained in:
世界
2024-02-14 20:42:58 +08:00
parent 3908270235
commit 3ba856cf75
12 changed files with 253 additions and 36 deletions

View File

@@ -139,7 +139,17 @@ func NewRouter(
DisableCache: dnsOptions.DNSClientOptions.DisableCache,
DisableExpire: dnsOptions.DNSClientOptions.DisableExpire,
IndependentCache: dnsOptions.DNSClientOptions.IndependentCache,
Logger: router.dnsLogger,
RDRC: func() dns.RDRCStore {
cacheFile := service.FromContext[adapter.CacheFile](ctx)
if cacheFile == nil {
return nil
}
if !cacheFile.StoreRDRC() {
return nil
}
return cacheFile
},
Logger: router.dnsLogger,
})
for i, ruleOptions := range options.Rules {
routeRule, err := NewRule(router, router.logger, ruleOptions, true)
@@ -617,6 +627,11 @@ func (r *Router) Start() error {
return E.Cause(err, "initialize rule[", i, "]")
}
}
monitor.Start("initialize DNS client")
r.dnsClient.Start()
monitor.Finish()
for i, rule := range r.dnsRules {
monitor.Start("initialize DNS rule[", i, "]")
err := rule.Start()

View File

@@ -139,7 +139,9 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
}
cancel()
if err != nil {
if errors.Is(err, dns.ErrResponseRejected) {
if errors.Is(err, dns.ErrResponseRejectedCached) {
r.dnsLogger.DebugContext(ctx, E.Cause(err, "response rejected for ", formatQuestion(message.Question[0].String())), " (cached)")
} else if errors.Is(err, dns.ErrResponseRejected) {
r.dnsLogger.DebugContext(ctx, E.Cause(err, "response rejected for ", formatQuestion(message.Question[0].String())))
} else if len(message.Question) > 0 {
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "exchange failed for ", formatQuestion(message.Question[0].String())))
@@ -166,6 +168,15 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
}
func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
var (
responseAddrs []netip.Addr
cached bool
err error
)
responseAddrs, cached = r.dnsClient.LookupCache(ctx, domain, strategy)
if cached {
return responseAddrs, nil
}
r.dnsLogger.DebugContext(ctx, "lookup domain ", domain)
ctx, metadata := adapter.AppendContext(ctx)
metadata.Domain = domain
@@ -174,8 +185,6 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
transportStrategy dns.DomainStrategy
rule adapter.DNSRule
ruleIndex int
resultAddrs []netip.Addr
err error
)
ruleIndex = -1
for {
@@ -193,22 +202,24 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
dnsCtx, cancel = context.WithTimeout(dnsCtx, C.DNSTimeout)
if rule != nil && rule.WithAddressLimit() {
addressLimit = true
resultAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, strategy, func(responseAddrs []netip.Addr) bool {
responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, strategy, func(responseAddrs []netip.Addr) bool {
metadata.DestinationAddresses = responseAddrs
return rule.MatchAddressLimit(metadata)
})
} else {
addressLimit = false
resultAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, strategy)
responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, strategy)
}
cancel()
if err != nil {
if errors.Is(err, dns.ErrResponseRejected) {
if errors.Is(err, dns.ErrResponseRejectedCached) {
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain, " (cached)")
} else if errors.Is(err, dns.ErrResponseRejected) {
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain)
} else {
r.dnsLogger.ErrorContext(ctx, E.Cause(err, "lookup failed for ", domain))
}
} else if len(resultAddrs) == 0 {
} else if len(responseAddrs) == 0 {
r.dnsLogger.ErrorContext(ctx, "lookup failed for ", domain, ": empty result")
err = dns.RCodeNameError
}
@@ -216,10 +227,10 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
break
}
}
if len(resultAddrs) > 0 {
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(resultAddrs), " "))
if len(responseAddrs) > 0 {
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(responseAddrs), " "))
}
return resultAddrs, err
return responseAddrs, err
}
func (r *Router) LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error) {