mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
Use separate context when querying upstream ips
While at it, also include query type in log, and only honor upstream timeout when it greater than zero.
This commit is contained in:
@@ -32,12 +32,13 @@ func (p *prog) serveUDP(listenerNum string) error {
|
|||||||
failoverRcodes = listenerConfig.Policy.FailoverRcodeNumbers
|
failoverRcodes = listenerConfig.Policy.FailoverRcodeNumbers
|
||||||
}
|
}
|
||||||
handler := dns.HandlerFunc(func(w dns.ResponseWriter, m *dns.Msg) {
|
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()
|
reqId := requestID()
|
||||||
fmtSrcToDest := fmtRemoteToLocal(listenerNum, w.RemoteAddr().String(), w.LocalAddr().String())
|
fmtSrcToDest := fmtRemoteToLocal(listenerNum, w.RemoteAddr().String(), w.LocalAddr().String())
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
ctx := context.WithValue(context.Background(), ctrld.ReqIdCtxKey{}, reqId)
|
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)
|
upstreams, matched := p.upstreamFor(ctx, listenerNum, listenerConfig, w.RemoteAddr(), domain)
|
||||||
var answer *dns.Msg
|
var answer *dns.Msg
|
||||||
if !matched && listenerConfig.Restricted {
|
if !matched && listenerConfig.Restricted {
|
||||||
|
|||||||
@@ -155,9 +155,6 @@ func (uc *UpstreamConfig) Init() {
|
|||||||
// SetupBootstrapIP manually find all available IPs of the upstream.
|
// SetupBootstrapIP manually find all available IPs of the upstream.
|
||||||
// The first usable IP will be used as bootstrap IP of the upstream.
|
// The first usable IP will be used as bootstrap IP of the upstream.
|
||||||
func (uc *UpstreamConfig) SetupBootstrapIP() {
|
func (uc *UpstreamConfig) SetupBootstrapIP() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(uc.Timeout)*time.Millisecond)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
c := new(dns.Client)
|
c := new(dns.Client)
|
||||||
bootstrapIP := func(record dns.RR) string {
|
bootstrapIP := func(record dns.RR) string {
|
||||||
switch ar := record.(type) {
|
switch ar := record.(type) {
|
||||||
@@ -169,24 +166,25 @@ func (uc *UpstreamConfig) SetupBootstrapIP() {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(ctx, ProxyLog.Debug(), "Resolving %q using bootstrap DNS %q", uc.Domain, bootstrapDNS)
|
ProxyLog.Debug().Msgf("Resolving %q using bootstrap DNS %q", uc.Domain, bootstrapDNS)
|
||||||
// Find all A, AAAA records of the upstream.
|
do := func(dnsType uint16) {
|
||||||
for _, dnsType := range []uint16{dns.TypeAAAA, dns.TypeA} {
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(uc.Timeout)*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion(uc.Domain+".", dnsType)
|
m.SetQuestion(uc.Domain+".", dnsType)
|
||||||
m.RecursionDesired = true
|
m.RecursionDesired = true
|
||||||
r, _, err := c.ExchangeContext(ctx, m, net.JoinHostPort(bootstrapDNS, "53"))
|
r, _, err := c.ExchangeContext(ctx, m, net.JoinHostPort(bootstrapDNS, "53"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ProxyLog.Error().Err(err).Str("type", dns.TypeToString[dnsType]).Msgf("could not resolve domain %s for upstream", uc.Domain)
|
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 {
|
if r.Rcode != dns.RcodeSuccess {
|
||||||
ProxyLog.Error().Msgf("could not resolve domain return code: %d, upstream", r.Rcode)
|
ProxyLog.Error().Msgf("could not resolve domain return code: %d, upstream", r.Rcode)
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
if len(r.Answer) == 0 {
|
if len(r.Answer) == 0 {
|
||||||
ProxyLog.Error().Msg("no answer from bootstrap DNS server")
|
ProxyLog.Error().Msg("no answer from bootstrap DNS server")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
for _, a := range r.Answer {
|
for _, a := range r.Answer {
|
||||||
ip := bootstrapIP(a)
|
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)
|
ProxyLog.Debug().Msgf("Bootstrap IPs: %v", uc.bootstrapIPs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReBootstrap re-setup the bootstrap IP and the transport.
|
// ReBootstrap re-setup the bootstrap IP and the transport.
|
||||||
func (uc *UpstreamConfig) ReBootstrap() {
|
func (uc *UpstreamConfig) ReBootstrap() {
|
||||||
|
switch uc.Type {
|
||||||
|
case ResolverTypeDOH, ResolverTypeDOH3:
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
_, _, _ = uc.g.Do("rebootstrap", func() (any, error) {
|
_, _, _ = uc.g.Do("rebootstrap", func() (any, error) {
|
||||||
ProxyLog.Debug().Msg("re-bootstrapping upstream ip")
|
ProxyLog.Debug().Msg("re-bootstrapping upstream ip")
|
||||||
n := uint32(len(uc.bootstrapIPs))
|
n := uint32(len(uc.bootstrapIPs))
|
||||||
|
|
||||||
timeoutMs := 1000
|
timeoutMs := 1000
|
||||||
if uc.Timeout < timeoutMs {
|
if uc.Timeout > 0 && uc.Timeout < timeoutMs {
|
||||||
timeoutMs = uc.Timeout
|
timeoutMs = uc.Timeout
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMs)*time.Millisecond)
|
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
|
uc.transport.IdleConnTimeout = 5 * time.Second
|
||||||
|
|
||||||
dialerTimeoutMs := 2000
|
dialerTimeoutMs := 2000
|
||||||
if uc.Timeout < dialerTimeoutMs {
|
if uc.Timeout > 0 && uc.Timeout < dialerTimeoutMs {
|
||||||
dialerTimeoutMs = uc.Timeout
|
dialerTimeoutMs = uc.Timeout
|
||||||
}
|
}
|
||||||
dialerTimeout := time.Duration(dialerTimeoutMs) * time.Millisecond
|
dialerTimeout := time.Duration(dialerTimeoutMs) * time.Millisecond
|
||||||
|
|||||||
Reference in New Issue
Block a user