diff --git a/cmd/ctrld/dns_proxy.go b/cmd/ctrld/dns_proxy.go index bbe84f1..808cba2 100644 --- a/cmd/ctrld/dns_proxy.go +++ b/cmd/ctrld/dns_proxy.go @@ -32,12 +32,13 @@ func (p *prog) serveUDP(listenerNum string) error { failoverRcodes = listenerConfig.Policy.FailoverRcodeNumbers } handler := dns.HandlerFunc(func(w dns.ResponseWriter, m *dns.Msg) { - domain := canonicalName(m.Question[0].Name) + q := m.Question[0] + domain := canonicalName(q.Name) reqId := requestID() fmtSrcToDest := fmtRemoteToLocal(listenerNum, w.RemoteAddr().String(), w.LocalAddr().String()) t := time.Now() ctx := context.WithValue(context.Background(), ctrld.ReqIdCtxKey{}, reqId) - ctrld.Log(ctx, mainLog.Debug(), "%s received query: %s", fmtSrcToDest, domain) + ctrld.Log(ctx, mainLog.Debug(), "%s received query: %s %s", fmtSrcToDest, dns.TypeToString[q.Qtype], domain) upstreams, matched := p.upstreamFor(ctx, listenerNum, listenerConfig, w.RemoteAddr(), domain) var answer *dns.Msg if !matched && listenerConfig.Restricted { diff --git a/config.go b/config.go index dfafd91..2700efb 100644 --- a/config.go +++ b/config.go @@ -155,9 +155,6 @@ func (uc *UpstreamConfig) Init() { // SetupBootstrapIP manually find all available IPs of the upstream. // The first usable IP will be used as bootstrap IP of the upstream. func (uc *UpstreamConfig) SetupBootstrapIP() { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(uc.Timeout)*time.Millisecond) - defer cancel() - c := new(dns.Client) bootstrapIP := func(record dns.RR) string { switch ar := record.(type) { @@ -169,24 +166,25 @@ func (uc *UpstreamConfig) SetupBootstrapIP() { return "" } - Log(ctx, ProxyLog.Debug(), "Resolving %q using bootstrap DNS %q", uc.Domain, bootstrapDNS) - // Find all A, AAAA records of the upstream. - for _, dnsType := range []uint16{dns.TypeAAAA, dns.TypeA} { + ProxyLog.Debug().Msgf("Resolving %q using bootstrap DNS %q", uc.Domain, bootstrapDNS) + do := func(dnsType uint16) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(uc.Timeout)*time.Millisecond) + defer cancel() m := new(dns.Msg) m.SetQuestion(uc.Domain+".", dnsType) m.RecursionDesired = true r, _, err := c.ExchangeContext(ctx, m, net.JoinHostPort(bootstrapDNS, "53")) if err != nil { ProxyLog.Error().Err(err).Str("type", dns.TypeToString[dnsType]).Msgf("could not resolve domain %s for upstream", uc.Domain) - continue + return } if r.Rcode != dns.RcodeSuccess { ProxyLog.Error().Msgf("could not resolve domain return code: %d, upstream", r.Rcode) - continue + return } if len(r.Answer) == 0 { ProxyLog.Error().Msg("no answer from bootstrap DNS server") - continue + return } for _, a := range r.Answer { ip := bootstrapIP(a) @@ -210,17 +208,26 @@ func (uc *UpstreamConfig) SetupBootstrapIP() { } } } + // Find all A, AAAA records of the upstream. + for _, dnsType := range []uint16{dns.TypeAAAA, dns.TypeA} { + do(dnsType) + } ProxyLog.Debug().Msgf("Bootstrap IPs: %v", uc.bootstrapIPs) } // ReBootstrap re-setup the bootstrap IP and the transport. func (uc *UpstreamConfig) ReBootstrap() { + switch uc.Type { + case ResolverTypeDOH, ResolverTypeDOH3: + default: + return + } _, _, _ = uc.g.Do("rebootstrap", func() (any, error) { ProxyLog.Debug().Msg("re-bootstrapping upstream ip") n := uint32(len(uc.bootstrapIPs)) timeoutMs := 1000 - if uc.Timeout < timeoutMs { + if uc.Timeout > 0 && uc.Timeout < timeoutMs { timeoutMs = uc.Timeout } ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMs)*time.Millisecond) @@ -274,7 +281,7 @@ func (uc *UpstreamConfig) setupDOHTransportWithoutPingUpstream() { uc.transport.IdleConnTimeout = 5 * time.Second dialerTimeoutMs := 2000 - if uc.Timeout < dialerTimeoutMs { + if uc.Timeout > 0 && uc.Timeout < dialerTimeoutMs { dialerTimeoutMs = uc.Timeout } dialerTimeout := time.Duration(dialerTimeoutMs) * time.Millisecond