Resolve is the default resolving method used by the DNS proxy to query upstream servers. It expects dctx is filled with the client's request.
(ctx context.Context, dctx *DNSContext)
| 687 | // Resolve is the default resolving method used by the DNS proxy to query |
| 688 | // upstream servers. It expects dctx is filled with the client's request. |
| 689 | func (p *Proxy) Resolve(ctx context.Context, dctx *DNSContext) (err error) { |
| 690 | if p.EnableEDNSClientSubnet { |
| 691 | dctx.processECS(p.EDNSAddr, p.logger) |
| 692 | } |
| 693 | |
| 694 | dctx.calcFlagsAndSize() |
| 695 | |
| 696 | cacheWorks := p.cacheWorks(dctx) |
| 697 | if cacheWorks { |
| 698 | // Request for DNSSEC from the upstream to cache the |
| 699 | // DNSSEC resource records as well. In case of disabled DNSSEC, |
| 700 | // requesting and therefore caching of DNSSEC resource records depends |
| 701 | // on the DO bit of the initiating query. |
| 702 | // |
| 703 | // See https://datatracker.ietf.org/doc/html/rfc4035#section-4.5 and |
| 704 | // https://datatracker.ietf.org/doc/html/rfc3225#section-3. |
| 705 | p.addDO(dctx.Req) |
| 706 | |
| 707 | // Only add pending requests if the cache is enabled, since this is a |
| 708 | // mitigation against cache poisoning. |
| 709 | // |
| 710 | // TODO(e.burkov): Consider tracking all requests. |
| 711 | var loaded bool |
| 712 | loaded, err = p.pendingRequests.queue(ctx, dctx) |
| 713 | if loaded { |
| 714 | return err |
| 715 | } |
| 716 | defer func() { p.pendingRequests.done(ctx, dctx, err) }() |
| 717 | |
| 718 | if p.replyFromCache(dctx) { |
| 719 | // Complete the response from cache. |
| 720 | filterMsg(dctx.Res, dctx.Res, dctx.adBit, dctx.doBit, 0) |
| 721 | dctx.scrub() |
| 722 | |
| 723 | return nil |
| 724 | } |
| 725 | } |
| 726 | |
| 727 | var ok bool |
| 728 | ok, err = p.replyFromUpstream(dctx) |
| 729 | |
| 730 | // Don't cache the responses having CD flag, just like Dnsmasq does. It |
| 731 | // prevents the cache from being poisoned with unvalidated answers which may |
| 732 | // differ from validated ones. |
| 733 | // |
| 734 | // See https://github.com/imp/dnsmasq/blob/770bce967cfc9967273d0acfb3ea018fb7b17522/src/forward.c#L1169-L1172. |
| 735 | if cacheWorks && ok && !dctx.Res.CheckingDisabled { |
| 736 | // Cache the response with DNSSEC RRs. |
| 737 | p.cacheResp(dctx) |
| 738 | } |
| 739 | |
| 740 | // It is possible that the response is nil if the upstream hasn't been |
| 741 | // chosen. |
| 742 | if dctx.Res != nil { |
| 743 | filterMsg(dctx.Res, dctx.Res, dctx.adBit, dctx.doBit, 0) |
| 744 | } |
| 745 | |
| 746 | // Complete the response. |