mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-05-27 12:52:27 +02:00
all: eliminate usage of global ProxyLogger
So setting up logging for ctrld binary and ctrld packages could be done more easily, decouple the required setup for interactive vs daemon running. This is the first step toward replacing rs/zerolog libary with a different logging library.
This commit is contained in:
committed by
Cuong Manh Le
parent
47c04bf0f6
commit
0e66697247
+58
-77
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"runtime"
|
||||
@@ -15,7 +14,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/sync/singleflight"
|
||||
"tailscale.com/net/netmon"
|
||||
"tailscale.com/net/tsaddr"
|
||||
@@ -50,10 +48,6 @@ var controldPublicDnsWithPort = net.JoinHostPort(controldPublicDns, "53")
|
||||
var localResolver Resolver
|
||||
|
||||
func init() {
|
||||
// Initializing ProxyLogger here, so other places don't have to do nil check.
|
||||
l := zerolog.New(io.Discard)
|
||||
ProxyLogger.Store(&l)
|
||||
|
||||
localResolver = newLocalResolver()
|
||||
}
|
||||
|
||||
@@ -81,8 +75,8 @@ func LanQueryCtx(ctx context.Context) context.Context {
|
||||
}
|
||||
|
||||
// defaultNameservers is like nameservers with each element formed "ip:53".
|
||||
func defaultNameservers() []string {
|
||||
ns := nameservers()
|
||||
func defaultNameservers(ctx context.Context) []string {
|
||||
ns := nameservers(ctx)
|
||||
nss := make([]string, len(ns))
|
||||
for i := range ns {
|
||||
nss[i] = net.JoinHostPort(ns[i], "53")
|
||||
@@ -91,42 +85,36 @@ func defaultNameservers() []string {
|
||||
}
|
||||
|
||||
// availableNameservers returns list of current available DNS servers of the system.
|
||||
func availableNameservers() []string {
|
||||
func availableNameservers(ctx context.Context) []string {
|
||||
var nss []string
|
||||
// Ignore local addresses to prevent loop.
|
||||
regularIPs, loopbackIPs, _ := netmon.LocalAddresses()
|
||||
machineIPsMap := make(map[string]struct{}, len(regularIPs))
|
||||
|
||||
//load the logger
|
||||
logger := *ProxyLogger.Load()
|
||||
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Got local addresses - regular IPs: %v, loopback IPs: %v", regularIPs, loopbackIPs)
|
||||
// Load the logger.
|
||||
logger := LoggerFromCtx(ctx)
|
||||
logger.Debug().Msgf("Got local addresses - regular IPs: %v, loopback IPs: %v", regularIPs, loopbackIPs)
|
||||
|
||||
for _, v := range slices.Concat(regularIPs, loopbackIPs) {
|
||||
ipStr := v.String()
|
||||
machineIPsMap[ipStr] = struct{}{}
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Added local IP to OS resolverexclusion map: %s", ipStr)
|
||||
logger.Debug().Msgf("Added local IP to OS resolverexclusion map: %s", ipStr)
|
||||
}
|
||||
|
||||
systemNameservers := nameservers()
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Got system nameservers: %v", systemNameservers)
|
||||
systemNameservers := nameservers(ctx)
|
||||
logger.Debug().Msgf("Got system nameservers: %v", systemNameservers)
|
||||
|
||||
for _, ns := range systemNameservers {
|
||||
if _, ok := machineIPsMap[ns]; ok {
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Skipping local nameserver: %s", ns)
|
||||
logger.Debug().Msgf("Skipping local nameserver: %s", ns)
|
||||
continue
|
||||
}
|
||||
nss = append(nss, ns)
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Added non-local nameserver: %s", ns)
|
||||
logger.Debug().Msgf("Added non-local nameserver: %s", ns)
|
||||
}
|
||||
|
||||
Log(context.Background(), logger.Debug(),
|
||||
"Final available nameservers: %v", nss)
|
||||
logger.Debug().Msgf("Final available nameservers: %v", nss)
|
||||
|
||||
return nss
|
||||
}
|
||||
|
||||
@@ -135,8 +123,8 @@ func availableNameservers() []string {
|
||||
//
|
||||
// It's the caller's responsibility to ensure the system DNS is in a clean state before
|
||||
// calling this function.
|
||||
func InitializeOsResolver(guardAgainstNoNameservers bool) []string {
|
||||
nameservers := availableNameservers()
|
||||
func InitializeOsResolver(ctx context.Context, guardAgainstNoNameservers bool) []string {
|
||||
nameservers := availableNameservers(ctx)
|
||||
// if no nameservers, return empty slice so we dont remove all nameservers
|
||||
if len(nameservers) == 0 && guardAgainstNoNameservers {
|
||||
return []string{}
|
||||
@@ -188,7 +176,7 @@ type Resolver interface {
|
||||
var errUnknownResolver = errors.New("unknown resolver")
|
||||
|
||||
// NewResolver creates a Resolver based on the given upstream config.
|
||||
func NewResolver(uc *UpstreamConfig) (Resolver, error) {
|
||||
func NewResolver(ctx context.Context, uc *UpstreamConfig) (Resolver, error) {
|
||||
typ := uc.Type
|
||||
switch typ {
|
||||
case ResolverTypeDOH, ResolverTypeDOH3:
|
||||
@@ -200,15 +188,16 @@ func NewResolver(uc *UpstreamConfig) (Resolver, error) {
|
||||
case ResolverTypeOS:
|
||||
resolverMutex.Lock()
|
||||
if or == nil {
|
||||
ProxyLogger.Load().Debug().Msgf("Initialize new OS resolver")
|
||||
or = newResolverWithNameserver(defaultNameservers())
|
||||
logger := LoggerFromCtx(ctx)
|
||||
logger.Debug().Msgf("Initialize new OS resolver")
|
||||
or = newResolverWithNameserver(defaultNameservers(ctx))
|
||||
}
|
||||
resolverMutex.Unlock()
|
||||
return or, nil
|
||||
case ResolverTypeLegacy:
|
||||
return &legacyResolver{uc: uc}, nil
|
||||
case ResolverTypePrivate:
|
||||
return NewPrivateResolver(), nil
|
||||
return NewPrivateResolver(ctx), nil
|
||||
case ResolverTypeLocal:
|
||||
return localResolver, nil
|
||||
}
|
||||
@@ -235,14 +224,16 @@ type publicResponse struct {
|
||||
}
|
||||
|
||||
// SetDefaultLocalIPv4 updates the stored local IPv4.
|
||||
func SetDefaultLocalIPv4(ip net.IP) {
|
||||
Log(context.Background(), ProxyLogger.Load().Debug(), "SetDefaultLocalIPv4: %s", ip)
|
||||
func SetDefaultLocalIPv4(ctx context.Context, ip net.IP) {
|
||||
logger := LoggerFromCtx(ctx)
|
||||
logger.Debug().Msgf("SetDefaultLocalIPv4: %s", ip)
|
||||
defaultLocalIPv4.Store(ip)
|
||||
}
|
||||
|
||||
// SetDefaultLocalIPv6 updates the stored local IPv6.
|
||||
func SetDefaultLocalIPv6(ip net.IP) {
|
||||
Log(context.Background(), ProxyLogger.Load().Debug(), "SetDefaultLocalIPv6: %s", ip)
|
||||
func SetDefaultLocalIPv6(ctx context.Context, ip net.IP) {
|
||||
logger := LoggerFromCtx(ctx)
|
||||
logger.Debug().Msgf("SetDefaultLocalIPv6: %s", ip)
|
||||
defaultLocalIPv6.Store(ip)
|
||||
}
|
||||
|
||||
@@ -300,10 +291,11 @@ func (o *osResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
// Unique key for the singleflight group.
|
||||
key := fmt.Sprintf("%s:%d:", domain, qtype)
|
||||
|
||||
logger := LoggerFromCtx(ctx)
|
||||
// Checking the cache first.
|
||||
if val, ok := o.cache.Load(key); ok {
|
||||
if val, ok := val.(*dns.Msg); ok {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "hit hot cached result: %s - %s", domain, dns.TypeToString[qtype])
|
||||
Log(ctx, logger.Debug(), "hit hot cached result: %s - %s", domain, dns.TypeToString[qtype])
|
||||
res := val.Copy()
|
||||
SetCacheReply(res, msg, val.Rcode)
|
||||
return res, nil
|
||||
@@ -338,7 +330,7 @@ func (o *osResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
res := sharedMsg.Copy()
|
||||
SetCacheReply(res, msg, sharedMsg.Rcode)
|
||||
if shared {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "shared result: %s - %s", domain, dns.TypeToString[qtype])
|
||||
Log(ctx, logger.Debug(), "shared result: %s - %s", domain, dns.TypeToString[qtype])
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -368,7 +360,8 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
if msg != nil && len(msg.Question) > 0 {
|
||||
question = msg.Question[0].Name
|
||||
}
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "os resolver query for %s with nameservers: %v public: %v", question, nss, publicServers)
|
||||
logger := LoggerFromCtx(ctx)
|
||||
Log(ctx, logger.Debug(), "os resolver query for %s with nameservers: %v public: %v", question, nss, publicServers)
|
||||
|
||||
// New check: If no resolvers are available, return an error.
|
||||
if numServers == 0 {
|
||||
@@ -417,7 +410,7 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
// If splitting fails, fallback to the original server string
|
||||
host = server
|
||||
}
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "got answer from nameserver: %s", host)
|
||||
Log(ctx, logger.Debug(), "got answer from nameserver: %s", host)
|
||||
}
|
||||
|
||||
// try local nameservers
|
||||
@@ -444,7 +437,7 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
switch {
|
||||
case res.lan:
|
||||
// Always prefer LAN responses immediately
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "using LAN answer from: %s", res.server)
|
||||
Log(ctx, logger.Debug(), "using LAN answer from: %s", res.server)
|
||||
cancel()
|
||||
logAnswer(res.server)
|
||||
return res.answer, nil
|
||||
@@ -454,7 +447,7 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
// if there are no LAN nameservers, we should not wait
|
||||
// just use the first response
|
||||
if len(nss) == 0 {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "using public answer from: %s", res.server)
|
||||
Log(ctx, logger.Debug(), "using public answer from: %s", res.server)
|
||||
cancel()
|
||||
logAnswer(res.server)
|
||||
return res.answer, nil
|
||||
@@ -465,12 +458,12 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
})
|
||||
}
|
||||
case res.answer != nil:
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "got non-success answer from: %s with code: %d",
|
||||
Log(ctx, logger.Debug(), "got non-success answer from: %s with code: %d",
|
||||
res.server, res.answer.Rcode)
|
||||
// When there are no LAN nameservers, we should not wait
|
||||
// for other nameservers to respond.
|
||||
if len(nss) == 0 {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "no lan nameservers using public non success answer")
|
||||
Log(ctx, logger.Debug(), "no lan nameservers using public non success answer")
|
||||
cancel()
|
||||
logAnswer(res.server)
|
||||
return res.answer, nil
|
||||
@@ -483,17 +476,17 @@ func (o *osResolver) resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error
|
||||
|
||||
if len(publicResponses) > 0 {
|
||||
resp := publicResponses[0]
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "using public answer from: %s", resp.server)
|
||||
Log(ctx, logger.Debug(), "using public answer from: %s", resp.server)
|
||||
logAnswer(resp.server)
|
||||
return resp.answer, nil
|
||||
}
|
||||
if controldSuccessAnswer != nil {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "using ControlD answer from: %s", controldPublicDnsWithPort)
|
||||
Log(ctx, logger.Debug(), "using ControlD answer from: %s", controldPublicDnsWithPort)
|
||||
logAnswer(controldPublicDnsWithPort)
|
||||
return controldSuccessAnswer, nil
|
||||
}
|
||||
if nonSuccessAnswer != nil {
|
||||
Log(ctx, ProxyLogger.Load().Debug(), "using non-success answer from: %s", nonSuccessServer)
|
||||
Log(ctx, logger.Debug(), "using non-success answer from: %s", nonSuccessServer)
|
||||
logAnswer(nonSuccessServer)
|
||||
return nonSuccessAnswer, nil
|
||||
}
|
||||
@@ -515,7 +508,7 @@ func (r *legacyResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, e
|
||||
if msg != nil && len(msg.Question) > 0 {
|
||||
dnsTyp = msg.Question[0].Qtype
|
||||
}
|
||||
_, udpNet := r.uc.netForDNSType(dnsTyp)
|
||||
_, udpNet := r.uc.netForDNSType(ctx, dnsTyp)
|
||||
dnsClient := &dns.Client{
|
||||
Net: udpNet,
|
||||
Dialer: dialer,
|
||||
@@ -541,39 +534,43 @@ func (d dummyResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, err
|
||||
|
||||
// LookupIP looks up domain using current system nameservers settings.
|
||||
// It returns a slice of that host's IPv4 and IPv6 addresses.
|
||||
func LookupIP(domain string) []string {
|
||||
nss := initDefaultOsResolver()
|
||||
return lookupIP(domain, -1, nss)
|
||||
func LookupIP(ctx context.Context, domain string) []string {
|
||||
nss := initDefaultOsResolver(ctx)
|
||||
return lookupIP(ctx, domain, -1, nss)
|
||||
}
|
||||
|
||||
// initDefaultOsResolver initializes the default OS resolver with system's default nameservers if it hasn't been initialized yet.
|
||||
// It returns the combined list of LAN and public nameservers currently held by the resolver.
|
||||
func initDefaultOsResolver() []string {
|
||||
func initDefaultOsResolver(ctx context.Context) []string {
|
||||
logger := LoggerFromCtx(ctx)
|
||||
resolverMutex.Lock()
|
||||
defer resolverMutex.Unlock()
|
||||
if or == nil {
|
||||
ProxyLogger.Load().Debug().Msgf("Initialize new OS resolver with default nameservers")
|
||||
or = newResolverWithNameserver(defaultNameservers())
|
||||
logger.Debug().Msgf("Initialize new OS resolver with default nameservers")
|
||||
or = newResolverWithNameserver(defaultNameservers(ctx))
|
||||
}
|
||||
nss := *or.lanServers.Load()
|
||||
nss = append(nss, *or.publicServers.Load()...)
|
||||
return nss
|
||||
|
||||
}
|
||||
|
||||
// lookupIP looks up domain with given timeout and bootstrapDNS.
|
||||
// If the timeout is negative, default timeout 2000 ms will be used.
|
||||
// It returns nil if bootstrapDNS is nil or empty.
|
||||
func lookupIP(domain string, timeout int, bootstrapDNS []string) (ips []string) {
|
||||
func lookupIP(ctx context.Context, domain string, timeout int, bootstrapDNS []string) (ips []string) {
|
||||
if net.ParseIP(domain) != nil {
|
||||
return []string{domain}
|
||||
}
|
||||
logger := LoggerFromCtx(ctx)
|
||||
if bootstrapDNS == nil {
|
||||
ProxyLogger.Load().Debug().Msgf("empty bootstrap DNS")
|
||||
logger.Debug().Msgf("empty bootstrap DNS")
|
||||
return nil
|
||||
}
|
||||
|
||||
resolver := newResolverWithNameserver(bootstrapDNS)
|
||||
ProxyLogger.Load().Debug().Msgf("resolving %q using bootstrap DNS %q", domain, bootstrapDNS)
|
||||
logger.Debug().Msgf("resolving %q using bootstrap DNS %q", domain, bootstrapDNS)
|
||||
|
||||
timeoutMs := 2000
|
||||
if timeout > 0 && timeout < timeoutMs {
|
||||
timeoutMs = timeout
|
||||
@@ -616,15 +613,15 @@ func lookupIP(domain string, timeout int, bootstrapDNS []string) (ips []string)
|
||||
|
||||
r, err := resolver.Resolve(ctx, m)
|
||||
if err != nil {
|
||||
ProxyLogger.Load().Error().Err(err).Msgf("could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
|
||||
logger.Error().Err(err).Msgf("could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
|
||||
return
|
||||
}
|
||||
if r.Rcode != dns.RcodeSuccess {
|
||||
ProxyLogger.Load().Error().Msgf("could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
|
||||
logger.Error().Msgf("could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
|
||||
return
|
||||
}
|
||||
if len(r.Answer) == 0 {
|
||||
ProxyLogger.Load().Error().Msg("no answer from OS resolver")
|
||||
logger.Error().Msg("no answer from OS resolver")
|
||||
return
|
||||
}
|
||||
target := targetDomain(r.Answer)
|
||||
@@ -641,22 +638,6 @@ func lookupIP(domain string, timeout int, bootstrapDNS []string) (ips []string)
|
||||
return ips
|
||||
}
|
||||
|
||||
// NewBootstrapResolver returns an OS resolver, which use following nameservers:
|
||||
//
|
||||
// - Gateway IP address (depends on OS).
|
||||
// - Input servers.
|
||||
func NewBootstrapResolver(servers ...string) Resolver {
|
||||
logger := *ProxyLogger.Load()
|
||||
|
||||
Log(context.Background(), logger.Debug(), "NewBootstrapResolver called with servers: %v", servers)
|
||||
nss := defaultNameservers()
|
||||
nss = append([]string{controldPublicDnsWithPort}, nss...)
|
||||
for _, ns := range servers {
|
||||
nss = append([]string{net.JoinHostPort(ns, "53")}, nss...)
|
||||
}
|
||||
return NewResolverWithNameserver(nss)
|
||||
}
|
||||
|
||||
// NewPrivateResolver returns an OS resolver, which includes only private DNS servers,
|
||||
// excluding:
|
||||
//
|
||||
@@ -664,8 +645,8 @@ func NewBootstrapResolver(servers ...string) Resolver {
|
||||
// - Nameservers which is local RFC1918 addresses.
|
||||
//
|
||||
// This is useful for doing PTR lookup in LAN network.
|
||||
func NewPrivateResolver() Resolver {
|
||||
nss := initDefaultOsResolver()
|
||||
func NewPrivateResolver(ctx context.Context) Resolver {
|
||||
nss := initDefaultOsResolver(ctx)
|
||||
resolveConfNss := currentNameserversFromResolvconf()
|
||||
localRfc1918Addrs := Rfc1918Addresses()
|
||||
n := 0
|
||||
|
||||
Reference in New Issue
Block a user