replyFromUpstream tries to resolve the request via configured upstream servers. It returns true if the response actually came from an upstream.
(d *DNSContext)
| 581 | // replyFromUpstream tries to resolve the request via configured upstream |
| 582 | // servers. It returns true if the response actually came from an upstream. |
| 583 | func (p *Proxy) replyFromUpstream(d *DNSContext) (ok bool, err error) { |
| 584 | req := d.Req |
| 585 | |
| 586 | upstreams, isPrivate := p.selectUpstreams(d) |
| 587 | if len(upstreams) == 0 { |
| 588 | d.Res = p.messages.NewMsgNXDOMAIN(req) |
| 589 | |
| 590 | return false, fmt.Errorf("selecting upstream: %w", upstream.ErrNoUpstreams) |
| 591 | } |
| 592 | |
| 593 | if isPrivate { |
| 594 | p.recDetector.add(d.Req) |
| 595 | } |
| 596 | |
| 597 | src := "upstream" |
| 598 | wrapped := upstreamsWithStats(upstreams) |
| 599 | |
| 600 | // Perform the DNS request. |
| 601 | resp, u, err := p.exchangeUpstreams(req, wrapped) |
| 602 | if dns64Ups := p.performDNS64(req, resp, wrapped); dns64Ups != nil { |
| 603 | u = dns64Ups |
| 604 | } else if p.isBogusNXDomain(resp) { |
| 605 | p.logger.Debug("response contains bogus-nxdomain ip") |
| 606 | resp = p.messages.NewMsgNXDOMAIN(req) |
| 607 | } |
| 608 | |
| 609 | var wrappedFallbacks []upstream.Upstream |
| 610 | if err != nil && !isPrivate && p.Fallbacks != nil { |
| 611 | p.logger.Debug("using fallback", slogutil.KeyError, err) |
| 612 | |
| 613 | src = "fallback" |
| 614 | |
| 615 | // upstreams mustn't appear empty since they have been validated when |
| 616 | // creating proxy. |
| 617 | upstreams = p.Fallbacks.getUpstreamsForDomain(req.Question[0].Name) |
| 618 | |
| 619 | wrappedFallbacks = upstreamsWithStats(upstreams) |
| 620 | resp, u, err = upstream.ExchangeParallel(wrappedFallbacks, req) |
| 621 | } |
| 622 | |
| 623 | if err != nil { |
| 624 | p.logger.Debug("resolving err", "src", src, slogutil.KeyError, err) |
| 625 | } |
| 626 | |
| 627 | if resp != nil { |
| 628 | p.logger.Debug("resolved", "upstream", u.Address(), "src", src) |
| 629 | } |
| 630 | |
| 631 | unwrapped, stats := collectQueryStats(p.UpstreamMode, u, wrapped, wrappedFallbacks) |
| 632 | d.queryStatistics = stats |
| 633 | |
| 634 | ctx := context.TODO() |
| 635 | p.handleExchangeResult(ctx, d, req, resp, unwrapped) |
| 636 | |
| 637 | return resp != nil, err |
| 638 | } |
| 639 | |
| 640 | // handleExchangeResult handles the result after the upstream exchange. It sets |
no test coverage detected