all: prevent data race when accessing zerolog.Logger

This commit is contained in:
Cuong Manh Le
2023-07-26 16:48:17 +00:00
committed by Cuong Manh Le
parent 59dc74ffbb
commit 19bc44a7f3
24 changed files with 242 additions and 222 deletions

View File

@@ -147,7 +147,7 @@ func initCLI() {
}
if daemon && runtime.GOOS == "windows" {
mainLog.Fatal().Msg("Cannot run in daemon mode. Please install a Windows service.")
mainLog.Load().Fatal().Msg("Cannot run in daemon mode. Please install a Windows service.")
}
if !daemon {
@@ -156,10 +156,10 @@ func initCLI() {
go func() {
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Fatal().Err(err).Msg("failed create new service")
mainLog.Load().Fatal().Err(err).Msg("failed create new service")
}
if err := s.Run(); err != nil {
mainLog.Error().Err(err).Msg("failed to start service")
mainLog.Load().Error().Err(err).Msg("failed to start service")
}
}()
}
@@ -170,7 +170,7 @@ func initCLI() {
readBase64Config(configBase64)
processNoConfigFlags(noConfigStart)
if err := v.Unmarshal(&cfg); err != nil {
mainLog.Fatal().Msgf("failed to unmarshal config: %v", err)
mainLog.Load().Fatal().Msgf("failed to unmarshal config: %v", err)
}
processLogAndCacheFlags()
@@ -179,18 +179,18 @@ func initCLI() {
// so it's able to log information in processCDFlags.
initLogging()
mainLog.Info().Msgf("starting ctrld %s", curVersion())
mainLog.Info().Msgf("os: %s", osVersion())
mainLog.Load().Info().Msgf("starting ctrld %s", curVersion())
mainLog.Load().Info().Msgf("os: %s", osVersion())
// Wait for network up.
if !ctrldnet.Up() {
mainLog.Fatal().Msg("network is not up yet")
mainLog.Load().Fatal().Msg("network is not up yet")
}
p.router = router.New(&cfg, cdUID != "")
cs, err := newControlServer(filepath.Join(homedir, ctrldControlUnixSock))
if err != nil {
mainLog.Warn().Err(err).Msg("could not create control server")
mainLog.Load().Warn().Err(err).Msg("could not create control server")
}
p.cs = cs
@@ -198,7 +198,7 @@ func initCLI() {
// time for validating server certificate. Some routers need NTP synchronization
// to set the current time, so this check must happen before processCDFlags.
if err := p.router.PreRun(); err != nil {
mainLog.Fatal().Err(err).Msg("failed to perform router pre-run check")
mainLog.Load().Fatal().Err(err).Msg("failed to perform router pre-run check")
}
oldLogPath := cfg.Service.LogPath
@@ -213,19 +213,20 @@ func initCLI() {
}
if err := writeConfigFile(); err != nil {
mainLog.Fatal().Err(err).Msg("failed to write config file")
mainLog.Load().Fatal().Err(err).Msg("failed to write config file")
} else {
mainLog.Info().Msg("writing config file to: " + defaultConfigFile)
mainLog.Load().Info().Msg("writing config file to: " + defaultConfigFile)
}
if newLogPath := cfg.Service.LogPath; newLogPath != "" && oldLogPath != newLogPath {
// After processCDFlags, log config may change, so reset mainLog and re-init logging.
mainLog = zerolog.New(io.Discard)
l := zerolog.New(io.Discard)
mainLog.Store(&l)
// Copy logs written so far to new log file if possible.
if buf, err := os.ReadFile(oldLogPath); err == nil {
if err := os.WriteFile(newLogPath, buf, os.FileMode(0o600)); err != nil {
mainLog.Warn().Err(err).Msg("could not copy old log file")
mainLog.Load().Warn().Err(err).Msg("could not copy old log file")
}
}
initLoggingWithBackup(false)
@@ -237,22 +238,22 @@ func initCLI() {
if daemon {
exe, err := os.Executable()
if err != nil {
mainLog.Error().Err(err).Msg("failed to find the binary")
mainLog.Load().Error().Err(err).Msg("failed to find the binary")
os.Exit(1)
}
curDir, err := os.Getwd()
if err != nil {
mainLog.Error().Err(err).Msg("failed to get current working directory")
mainLog.Load().Error().Err(err).Msg("failed to get current working directory")
os.Exit(1)
}
// If running as daemon, re-run the command in background, with daemon off.
cmd := exec.Command(exe, append(os.Args[1:], "-d=false")...)
cmd.Dir = curDir
if err := cmd.Start(); err != nil {
mainLog.Error().Err(err).Msg("failed to start process as daemon")
mainLog.Load().Error().Err(err).Msg("failed to start process as daemon")
os.Exit(1)
}
mainLog.Info().Int("pid", cmd.Process.Pid).Msg("DNS proxy started")
mainLog.Load().Info().Int("pid", cmd.Process.Pid).Msg("DNS proxy started")
os.Exit(0)
}
@@ -260,7 +261,7 @@ func initCLI() {
for _, lc := range p.cfg.Listener {
if shouldAllocateLoopbackIP(lc.IP) {
if err := allocateIP(lc.IP); err != nil {
mainLog.Error().Err(err).Msgf("could not allocate IP: %s", lc.IP)
mainLog.Load().Error().Err(err).Msgf("could not allocate IP: %s", lc.IP)
}
}
}
@@ -269,7 +270,7 @@ func initCLI() {
for _, lc := range p.cfg.Listener {
if shouldAllocateLoopbackIP(lc.IP) {
if err := deAllocateIP(lc.IP); err != nil {
mainLog.Error().Err(err).Msgf("could not de-allocate IP: %s", lc.IP)
mainLog.Load().Error().Err(err).Msgf("could not de-allocate IP: %s", lc.IP)
}
}
}
@@ -279,15 +280,15 @@ func initCLI() {
rootCertPool = cp
}
p.onStarted = append(p.onStarted, func() {
mainLog.Debug().Msg("router setup")
mainLog.Load().Debug().Msg("router setup")
if err := p.router.Setup(); err != nil {
mainLog.Error().Err(err).Msg("could not configure router")
mainLog.Load().Error().Err(err).Msg("could not configure router")
}
})
p.onStopped = append(p.onStopped, func() {
mainLog.Debug().Msg("router cleanup")
mainLog.Load().Debug().Msg("router cleanup")
if err := p.router.Cleanup(); err != nil {
mainLog.Error().Err(err).Msg("could not cleanup router")
mainLog.Load().Error().Err(err).Msg("could not cleanup router")
}
p.resetDNS()
})
@@ -342,7 +343,7 @@ func initCLI() {
cfg: &cfg,
}
if err := p.router.ConfigureService(sc); err != nil {
mainLog.Fatal().Err(err).Msg("failed to configure service on router")
mainLog.Load().Fatal().Err(err).Msg("failed to configure service on router")
}
// No config path, generating config in HOME directory.
@@ -386,7 +387,7 @@ func initCLI() {
tryReadingConfig(writeDefaultConfig)
if err := v.Unmarshal(&cfg); err != nil {
mainLog.Fatal().Msgf("failed to unmarshal config: %v", err)
mainLog.Load().Fatal().Msgf("failed to unmarshal config: %v", err)
}
initLogging()
@@ -400,12 +401,12 @@ func initCLI() {
s, err := newService(p, sc)
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
return
}
if router.Name() != "" {
mainLog.Debug().Msg("cleaning up router before installing")
mainLog.Load().Debug().Msg("cleaning up router before installing")
_ = p.router.Cleanup()
}
@@ -417,12 +418,12 @@ func initCLI() {
}
if doTasks(tasks) {
if err := p.router.Install(sc); err != nil {
mainLog.Warn().Err(err).Msg("post installation failed, please check system/service log for details error")
mainLog.Load().Warn().Err(err).Msg("post installation failed, please check system/service log for details error")
return
}
status, err := s.Status()
if err != nil {
mainLog.Warn().Err(err).Msg("could not get service status")
mainLog.Load().Warn().Err(err).Msg("could not get service status")
return
}
@@ -430,15 +431,15 @@ func initCLI() {
status = selfCheckStatus(status, domain)
switch status {
case service.StatusRunning:
mainLog.Notice().Msg("Service started")
mainLog.Load().Notice().Msg("Service started")
default:
marker := bytes.Repeat([]byte("="), 32)
mainLog.Error().Msg("ctrld service may not have started due to an error or misconfiguration, service log:")
_, _ = mainLog.Write(marker)
mainLog.Load().Error().Msg("ctrld service may not have started due to an error or misconfiguration, service log:")
_, _ = mainLog.Load().Write(marker)
for msg := range runCmdLogCh {
_, _ = mainLog.Write([]byte(msg))
_, _ = mainLog.Load().Write([]byte(msg))
}
_, _ = mainLog.Write(marker)
_, _ = mainLog.Load().Write(marker)
uninstall(p, s)
os.Exit(1)
}
@@ -473,7 +474,7 @@ func initCLI() {
Run: func(cmd *cobra.Command, _ []string) {
exe, err := os.Executable()
if err != nil {
mainLog.Fatal().Msgf("could not find executable path: %v", err)
mainLog.Load().Fatal().Msgf("could not find executable path: %v", err)
os.Exit(1)
}
flags := make([]string, 0)
@@ -487,7 +488,7 @@ func initCLI() {
command.Stderr = os.Stderr
command.Stdin = os.Stdin
if err := command.Run(); err != nil {
mainLog.Fatal().Msg(err.Error())
mainLog.Load().Fatal().Msg(err.Error())
}
},
}
@@ -509,14 +510,14 @@ func initCLI() {
p := &prog{router: router.New(&cfg, cdUID != "")}
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
return
}
initLogging()
if doTasks([]task{{s.Stop, true}}) {
p.router.Cleanup()
p.resetDNS()
mainLog.Notice().Msg("Service stopped")
mainLog.Load().Notice().Msg("Service stopped")
}
},
}
@@ -533,12 +534,12 @@ func initCLI() {
Run: func(cmd *cobra.Command, args []string) {
s, err := newService(&prog{}, svcConfig)
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
return
}
initLogging()
if doTasks([]task{{s.Restart, true}}) {
mainLog.Notice().Msg("Service restarted")
mainLog.Load().Notice().Msg("Service restarted")
}
},
}
@@ -553,23 +554,23 @@ func initCLI() {
Run: func(cmd *cobra.Command, args []string) {
s, err := newService(&prog{}, svcConfig)
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
return
}
status, err := s.Status()
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
os.Exit(1)
}
switch status {
case service.StatusUnknown:
mainLog.Notice().Msg("Unknown status")
mainLog.Load().Notice().Msg("Unknown status")
os.Exit(2)
case service.StatusRunning:
mainLog.Notice().Msg("Service is running")
mainLog.Load().Notice().Msg("Service is running")
os.Exit(0)
case service.StatusStopped:
mainLog.Notice().Msg("Service is stopped")
mainLog.Load().Notice().Msg("Service is stopped")
os.Exit(1)
}
},
@@ -599,7 +600,7 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
p := &prog{router: router.New(&cfg, cdUID != "")}
s, err := newService(p, svcConfig)
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
return
}
if iface == "" {
@@ -639,7 +640,7 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
println()
})
if err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
}
},
}
@@ -767,18 +768,18 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
Run: func(cmd *cobra.Command, args []string) {
dir, err := userHomeDir()
if err != nil {
mainLog.Fatal().Err(err).Msg("failed to find ctrld home dir")
mainLog.Load().Fatal().Err(err).Msg("failed to find ctrld home dir")
}
cc := newControlClient(filepath.Join(dir, ctrldControlUnixSock))
resp, err := cc.post(listClientsPath, nil)
if err != nil {
mainLog.Fatal().Err(err).Msg("failed to get clients list")
mainLog.Load().Fatal().Err(err).Msg("failed to get clients list")
}
defer resp.Body.Close()
var clients []*clientinfo.Client
if err := json.NewDecoder(resp.Body).Decode(&clients); err != nil {
mainLog.Fatal().Err(err).Msg("failed to decode clients list result")
mainLog.Load().Fatal().Err(err).Msg("failed to decode clients list result")
}
map2Slice := func(m map[string]struct{}) []string {
s := make([]string, 0, len(m))
@@ -847,7 +848,7 @@ func readConfigFile(writeDefaultConfig bool) bool {
// If err == nil, there's a config supplied via `--config`, no default config written.
err := v.ReadInConfig()
if err == nil {
mainLog.Info().Msg("loading config file from: " + v.ConfigFileUsed())
mainLog.Load().Info().Msg("loading config file from: " + v.ConfigFileUsed())
defaultConfigFile = v.ConfigFileUsed()
return true
}
@@ -859,16 +860,16 @@ func readConfigFile(writeDefaultConfig bool) bool {
// If error is viper.ConfigFileNotFoundError, write default config.
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
if err := v.Unmarshal(&cfg); err != nil {
mainLog.Fatal().Msgf("failed to unmarshal default config: %v", err)
mainLog.Load().Fatal().Msgf("failed to unmarshal default config: %v", err)
}
if err := writeConfigFile(); err != nil {
mainLog.Fatal().Msgf("failed to write default config file: %v", err)
mainLog.Load().Fatal().Msgf("failed to write default config file: %v", err)
} else {
fp, err := filepath.Abs(defaultConfigFile)
if err != nil {
mainLog.Fatal().Msgf("failed to get default config file path: %v", err)
mainLog.Load().Fatal().Msgf("failed to get default config file path: %v", err)
}
mainLog.Info().Msg("writing default config file to: " + fp)
mainLog.Load().Info().Msg("writing default config file to: " + fp)
}
defaultConfigWritten = true
return false
@@ -879,13 +880,13 @@ func readConfigFile(writeDefaultConfig bool) bool {
var i any
if err, ok := toml.NewDecoder(f).Decode(&i).(*toml.DecodeError); ok {
row, col := err.Position()
mainLog.Fatal().Msgf("failed to decode config file at line: %d, column: %d, error: %v", row, col, err)
mainLog.Load().Fatal().Msgf("failed to decode config file at line: %d, column: %d, error: %v", row, col, err)
}
}
}
// Otherwise, report fatal error and exit.
mainLog.Fatal().Msgf("failed to decode config file: %v", err)
mainLog.Load().Fatal().Msgf("failed to decode config file: %v", err)
return false
}
@@ -895,7 +896,7 @@ func readBase64Config(configBase64 string) {
}
configStr, err := base64.StdEncoding.DecodeString(configBase64)
if err != nil {
mainLog.Fatal().Msgf("invalid base64 config: %v", err)
mainLog.Load().Fatal().Msgf("invalid base64 config: %v", err)
}
// readBase64Config is called when:
@@ -907,7 +908,7 @@ func readBase64Config(configBase64 string) {
v = viper.NewWithOptions(viper.KeyDelimiter("::"))
v.SetConfigType("toml")
if err := v.ReadConfig(bytes.NewReader(configStr)); err != nil {
mainLog.Fatal().Msgf("failed to read base64 config: %v", err)
mainLog.Load().Fatal().Msgf("failed to read base64 config: %v", err)
}
}
@@ -916,7 +917,7 @@ func processNoConfigFlags(noConfigStart bool) {
return
}
if listenAddress == "" || primaryUpstream == "" {
mainLog.Fatal().Msg(`"listen" and "primary_upstream" flags must be set in no config mode`)
mainLog.Load().Fatal().Msg(`"listen" and "primary_upstream" flags must be set in no config mode`)
}
processListenFlag()
@@ -952,7 +953,7 @@ func processNoConfigFlags(noConfigStart bool) {
}
func processCDFlags() {
logger := mainLog.With().Str("mode", "cd").Logger()
logger := mainLog.Load().With().Str("mode", "cd").Logger()
logger.Info().Msgf("fetching Controld D configuration from API: %s", cdUID)
resolverConfig, err := controld.FetchResolverConfig(cdUID, rootCmd.Version, cdDev)
if uer, ok := err.(*controld.UtilityErrorResponse); ok && uer.ErrorField.Code == controld.InvalidConfigCode {
@@ -993,7 +994,7 @@ func processCDFlags() {
logger.Info().Msg("using defined custom config of Control-D resolver")
readBase64Config(resolverConfig.Ctrld.CustomConfig)
if err := v.Unmarshal(&cfg); err != nil {
mainLog.Fatal().Msgf("failed to unmarshal config: %v", err)
mainLog.Load().Fatal().Msgf("failed to unmarshal config: %v", err)
}
} else {
cfg.Network = make(map[string]*ctrld.NetworkConfig)
@@ -1034,11 +1035,11 @@ func processListenFlag() {
}
host, portStr, err := net.SplitHostPort(listenAddress)
if err != nil {
mainLog.Fatal().Msgf("invalid listener address: %v", err)
mainLog.Load().Fatal().Msgf("invalid listener address: %v", err)
}
port, err := strconv.Atoi(portStr)
if err != nil {
mainLog.Fatal().Msgf("invalid port number: %v", err)
mainLog.Load().Fatal().Msgf("invalid port number: %v", err)
}
lc := &ctrld.ListenerConfig{
IP: host,
@@ -1094,7 +1095,7 @@ func defaultIfaceName() string {
if oi := osinfo.New(); strings.Contains(oi.String(), "Microsoft") {
return "lo"
}
mainLog.Fatal().Err(err).Msg("failed to get default route interface")
mainLog.Load().Fatal().Err(err).Msg("failed to get default route interface")
}
return dri
}
@@ -1106,7 +1107,7 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
}
dir, err := userHomeDir()
if err != nil {
mainLog.Error().Err(err).Msg("failed to check ctrld listener status: could not get home directory")
mainLog.Load().Error().Err(err).Msg("failed to check ctrld listener status: could not get home directory")
return service.StatusUnknown
}
@@ -1115,7 +1116,7 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
ctx := context.Background()
maxAttempts := 20
mainLog.Debug().Msg("waiting for ctrld listener to be ready")
mainLog.Load().Debug().Msg("waiting for ctrld listener to be ready")
cc := newControlClient(filepath.Join(dir, ctrldControlUnixSock))
// The socket control server may not start yet, so attempt to ping
@@ -1129,17 +1130,17 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
}
resp, err := cc.post(startedPath, nil)
if err != nil {
mainLog.Error().Err(err).Msg("failed to connect to control server")
mainLog.Load().Error().Err(err).Msg("failed to connect to control server")
return service.StatusUnknown
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
mainLog.Error().Msg("ctrld listener is not ready")
mainLog.Load().Error().Msg("ctrld listener is not ready")
return service.StatusUnknown
}
mainLog.Debug().Msg("ctrld listener is ready")
mainLog.Debug().Msg("performing self-check")
mainLog.Load().Debug().Msg("ctrld listener is ready")
mainLog.Load().Debug().Msg("performing self-check")
bo = backoff.NewBackoff("self-check", logf, 10*time.Second)
bo.LogLongerThan = 500 * time.Millisecond
c := new(dns.Client)
@@ -1149,14 +1150,14 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
)
if err := v.ReadInConfig(); err != nil {
mainLog.Fatal().Err(err).Msg("failed to read new config")
mainLog.Load().Fatal().Err(err).Msg("failed to read new config")
}
if err := v.Unmarshal(&cfg); err != nil {
mainLog.Fatal().Err(err).Msg("failed to update new config")
mainLog.Load().Fatal().Err(err).Msg("failed to update new config")
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
mainLog.Error().Err(err).Msg("could not watch config change")
mainLog.Load().Error().Err(err).Msg("could not watch config change")
return service.StatusUnknown
}
defer watcher.Close()
@@ -1165,7 +1166,7 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
mu.Lock()
defer mu.Unlock()
if err := v.UnmarshalKey("listener", &lcChanged); err != nil {
mainLog.Error().Msgf("failed to unmarshal listener config: %v", err)
mainLog.Load().Error().Msgf("failed to unmarshal listener config: %v", err)
return
}
})
@@ -1187,27 +1188,27 @@ func selfCheckStatus(status service.Status, domain string) service.Status {
m.RecursionDesired = true
r, _, err := c.ExchangeContext(ctx, m, net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port)))
if r != nil && r.Rcode == dns.RcodeSuccess && len(r.Answer) > 0 {
mainLog.Debug().Msgf("self-check against %q succeeded", domain)
mainLog.Load().Debug().Msgf("self-check against %q succeeded", domain)
return status
}
lastAnswer = r
lastErr = err
bo.BackOff(ctx, fmt.Errorf("ExchangeContext: %w", err))
}
mainLog.Debug().Msgf("self-check against %q failed", domain)
mainLog.Load().Debug().Msgf("self-check against %q failed", domain)
lc := cfg.FirstListener()
addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
marker := strings.Repeat("=", 32)
mainLog.Debug().Msg(marker)
mainLog.Debug().Msgf("listener address : %s", addr)
mainLog.Debug().Msgf("last error : %v", lastErr)
mainLog.Load().Debug().Msg(marker)
mainLog.Load().Debug().Msgf("listener address : %s", addr)
mainLog.Load().Debug().Msgf("last error : %v", lastErr)
if lastAnswer != nil {
mainLog.Debug().Msgf("last answer from ctrld :")
mainLog.Debug().Msg(marker)
mainLog.Load().Debug().Msgf("last answer from ctrld :")
mainLog.Load().Debug().Msg(marker)
for _, s := range strings.Split(lastAnswer.String(), "\n") {
mainLog.Debug().Msgf("%s", s)
mainLog.Load().Debug().Msgf("%s", s)
}
mainLog.Debug().Msg(marker)
mainLog.Load().Debug().Msg(marker)
}
return service.StatusUnknown
}
@@ -1260,7 +1261,7 @@ func readConfig(writeDefaultConfig bool) {
dir, err := userHomeDir()
if err != nil {
mainLog.Fatal().Msgf("failed to get user home dir: %v", err)
mainLog.Load().Fatal().Msgf("failed to get user home dir: %v", err)
}
for _, config := range configs {
ctrld.SetConfigNameWithPath(v, config.name, dir)
@@ -1279,20 +1280,20 @@ func uninstall(p *prog, s service.Service) {
initLogging()
if doTasks(tasks) {
if err := p.router.ConfigureService(svcConfig); err != nil {
mainLog.Fatal().Err(err).Msg("could not configure service")
mainLog.Load().Fatal().Err(err).Msg("could not configure service")
}
if err := p.router.Uninstall(svcConfig); err != nil {
mainLog.Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error")
mainLog.Load().Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error")
return
}
p.resetDNS()
if router.Name() != "" {
mainLog.Debug().Msg("Router cleanup")
mainLog.Load().Debug().Msg("Router cleanup")
}
// Stop already did router.Cleanup and report any error if happens,
// ignoring error here to prevent false positive.
_ = p.router.Cleanup()
mainLog.Notice().Msg("Service uninstalled")
mainLog.Load().Notice().Msg("Service uninstalled")
return
}
}
@@ -1305,7 +1306,7 @@ func validateConfig(cfg *ctrld.Config) {
var ve validator.ValidationErrors
if errors.As(err, &ve) {
for _, fe := range ve {
mainLog.Error().Msgf("invalid config: %s: %s", fe.Namespace(), fieldErrorMsg(fe))
mainLog.Load().Error().Msgf("invalid config: %s: %s", fe.Namespace(), fieldErrorMsg(fe))
}
}
os.Exit(1)
@@ -1472,14 +1473,14 @@ func updateListenerConfig() {
maxAttempts := 10
for {
if attempts == maxAttempts {
logMsg(mainLog.Fatal(), n, "could not find available listen ip and port")
logMsg(mainLog.Load().Fatal(), n, "could not find available listen ip and port")
}
addr := net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port))
if listenOk(addr) {
break
}
if !check.IP && !check.Port {
logMsg(mainLog.Fatal(), n, "failed to listen on: %s", addr)
logMsg(mainLog.Load().Fatal(), n, "failed to listen on: %s", addr)
}
if tryAllPort53 {
tryAllPort53 = false
@@ -1490,7 +1491,7 @@ func updateListenerConfig() {
listener.Port = 53
}
if check.IP {
logMsg(mainLog.Warn(), n, "could not listen on address: %s, trying: %s", addr, net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
logMsg(mainLog.Load().Warn(), n, "could not listen on address: %s, trying: %s", addr, net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
}
continue
}
@@ -1503,7 +1504,7 @@ func updateListenerConfig() {
listener.Port = 53
}
if check.IP {
logMsg(mainLog.Warn(), n, "could not listen on address: %s, trying localhost: %s", addr, net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
logMsg(mainLog.Load().Warn(), n, "could not listen on address: %s, trying localhost: %s", addr, net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
}
continue
}
@@ -1515,7 +1516,7 @@ func updateListenerConfig() {
if check.Port {
listener.Port = 5354
}
logMsg(mainLog.Warn(), n, "could not listen on address: %s, trying current ip with port 5354", addr)
logMsg(mainLog.Load().Warn(), n, "could not listen on address: %s, trying current ip with port 5354", addr)
continue
}
if tryPort5354 {
@@ -1526,7 +1527,7 @@ func updateListenerConfig() {
if check.Port {
listener.Port = 5354
}
logMsg(mainLog.Warn(), n, "could not listen on address: %s, trying 0.0.0.0:5354", addr)
logMsg(mainLog.Load().Warn(), n, "could not listen on address: %s, trying 0.0.0.0:5354", addr)
continue
}
if check.IP && !isZeroIP { // for "0.0.0.0" or "::", we only need to try new port.
@@ -1540,9 +1541,9 @@ func updateListenerConfig() {
listener.Port = oldPort
}
if listener.IP == oldIP && listener.Port == oldPort {
logMsg(mainLog.Fatal(), n, "could not listener on: %s", net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
logMsg(mainLog.Load().Fatal(), n, "could not listener on: %s", net.JoinHostPort(listener.IP, strconv.Itoa(listener.Port)))
}
logMsg(mainLog.Warn(), n, "could not listen on address: %s, pick a random ip+port", addr)
logMsg(mainLog.Load().Warn(), n, "could not listen on address: %s, pick a random ip+port", addr)
attempts++
}
}
@@ -1555,7 +1556,7 @@ func updateListenerConfig() {
// ip address, other than "127.0.0.1", so trying to listen on default route interface
// address instead.
if ip := net.ParseIP(listener.IP); ip != nil && ip.IsLoopback() && ip.String() != "127.0.0.1" {
logMsg(mainLog.Warn(), n, "using loopback interface do not work with systemd-resolved")
logMsg(mainLog.Load().Warn(), n, "using loopback interface do not work with systemd-resolved")
found := false
if netIface, _ := net.InterfaceByName(defaultIfaceName()); netIface != nil {
addrs, _ := netIface.Addrs()
@@ -1565,14 +1566,14 @@ func updateListenerConfig() {
if listenOk(addr) {
found = true
listener.IP = netIP.IP.String()
logMsg(mainLog.Warn(), n, "use %s as listener address", listener.IP)
logMsg(mainLog.Load().Warn(), n, "use %s as listener address", listener.IP)
break
}
}
}
}
if !found {
logMsg(mainLog.Fatal(), n, "could not use %q as DNS nameserver with systemd resolved", listener.IP)
logMsg(mainLog.Load().Fatal(), n, "could not use %q as DNS nameserver with systemd resolved", listener.IP)
}
}
}

View File

@@ -44,7 +44,7 @@ func (p *prog) serveDNS(listenerNum string) error {
listenerConfig := p.cfg.Listener[listenerNum]
// make sure ip is allocated
if allocErr := p.allocateIP(listenerConfig.IP); allocErr != nil {
mainLog.Error().Err(allocErr).Str("ip", listenerConfig.IP).Msg("serveUDP: failed to allocate listen ip")
mainLog.Load().Error().Err(allocErr).Str("ip", listenerConfig.IP).Msg("serveUDP: failed to allocate listen ip")
return allocErr
}
var failoverRcodes []int
@@ -64,7 +64,7 @@ func (p *prog) serveDNS(listenerNum string) error {
fmtSrcToDest := fmtRemoteToLocal(listenerNum, 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 %s", fmtSrcToDest, dns.TypeToString[q.Qtype], domain)
ctrld.Log(ctx, mainLog.Load().Debug(), "%s received query: %s %s", fmtSrcToDest, dns.TypeToString[q.Qtype], domain)
upstreams, matched := p.upstreamFor(ctx, listenerNum, listenerConfig, remoteAddr, domain)
var answer *dns.Msg
if !matched && listenerConfig.Restricted {
@@ -73,10 +73,10 @@ func (p *prog) serveDNS(listenerNum string) error {
} else {
answer = p.proxy(ctx, upstreams, failoverRcodes, m, ci)
rtt := time.Since(t)
ctrld.Log(ctx, mainLog.Debug(), "received response of %d bytes in %s", answer.Len(), rtt)
ctrld.Log(ctx, mainLog.Load().Debug(), "received response of %d bytes in %s", answer.Len(), rtt)
}
if err := w.WriteMsg(answer); err != nil {
ctrld.Log(ctx, mainLog.Error().Err(err), "serveUDP: failed to send DNS response to client")
ctrld.Log(ctx, mainLog.Load().Error().Err(err), "serveUDP: failed to send DNS response to client")
}
})
@@ -93,7 +93,7 @@ func (p *prog) serveDNS(listenerNum string) error {
case err := <-errCh:
// Local ipv6 listener should not terminate ctrld.
// It's a workaround for a quirk on Windows.
mainLog.Warn().Err(err).Msg("local ipv6 listener failed")
mainLog.Load().Warn().Err(err).Msg("local ipv6 listener failed")
}
return nil
})
@@ -113,7 +113,7 @@ func (p *prog) serveDNS(listenerNum string) error {
case err := <-errCh:
// RFC1918 listener should not terminate ctrld.
// It's a workaround for a quirk on system with systemd-resolved.
mainLog.Warn().Err(err).Msgf("could not listen on %s: %s", proto, listenAddr)
mainLog.Load().Warn().Err(err).Msgf("could not listen on %s: %s", proto, listenAddr)
}
}()
}
@@ -157,13 +157,13 @@ func (p *prog) upstreamFor(ctx context.Context, defaultUpstreamNum string, lc *c
defer func() {
if !matched && lc.Restricted {
ctrld.Log(ctx, mainLog.Info(), "query refused, %s does not match any network policy", addr.String())
ctrld.Log(ctx, mainLog.Load().Info(), "query refused, %s does not match any network policy", addr.String())
return
}
if matched {
ctrld.Log(ctx, mainLog.Info(), "%s, %s, %s -> %v", matchedPolicy, matchedNetwork, matchedRule, upstreams)
ctrld.Log(ctx, mainLog.Load().Info(), "%s, %s, %s -> %v", matchedPolicy, matchedNetwork, matchedRule, upstreams)
} else {
ctrld.Log(ctx, mainLog.Info(), "no explicit policy matched, using default routing -> %v", upstreams)
ctrld.Log(ctx, mainLog.Load().Info(), "no explicit policy matched, using default routing -> %v", upstreams)
}
}()
@@ -246,7 +246,7 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
answer.SetRcode(msg, answer.Rcode)
now := time.Now()
if cachedValue.Expire.After(now) {
ctrld.Log(ctx, mainLog.Debug(), "hit cached response")
ctrld.Log(ctx, mainLog.Load().Debug(), "hit cached response")
setCachedAnswerTTL(answer, now, cachedValue.Expire)
return answer
}
@@ -254,10 +254,10 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
}
}
resolve1 := func(n int, upstreamConfig *ctrld.UpstreamConfig, msg *dns.Msg) (*dns.Msg, error) {
ctrld.Log(ctx, mainLog.Debug(), "sending query to %s: %s", upstreams[n], upstreamConfig.Name)
ctrld.Log(ctx, mainLog.Load().Debug(), "sending query to %s: %s", upstreams[n], upstreamConfig.Name)
dnsResolver, err := ctrld.NewResolver(upstreamConfig)
if err != nil {
ctrld.Log(ctx, mainLog.Error().Err(err), "failed to create resolver")
ctrld.Log(ctx, mainLog.Load().Error().Err(err), "failed to create resolver")
return nil, err
}
resolveCtx, cancel := context.WithCancel(ctx)
@@ -271,12 +271,12 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
}
resolve := func(n int, upstreamConfig *ctrld.UpstreamConfig, msg *dns.Msg) *dns.Msg {
if upstreamConfig.UpstreamSendClientInfo() && ci != nil {
ctrld.Log(ctx, mainLog.Debug(), "including client info with the request")
ctrld.Log(ctx, mainLog.Load().Debug(), "including client info with the request")
ctx = context.WithValue(ctx, ctrld.ClientInfoCtxKey{}, ci)
}
answer, err := resolve1(n, upstreamConfig, msg)
if err != nil {
ctrld.Log(ctx, mainLog.Error().Err(err), "failed to resolve query")
ctrld.Log(ctx, mainLog.Load().Error().Err(err), "failed to resolve query")
return nil
}
return answer
@@ -288,7 +288,7 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
answer := resolve(n, upstreamConfig, msg)
if answer == nil {
if serveStaleCache && staleAnswer != nil {
ctrld.Log(ctx, mainLog.Debug(), "serving stale cached response")
ctrld.Log(ctx, mainLog.Load().Debug(), "serving stale cached response")
now := time.Now()
setCachedAnswerTTL(staleAnswer, now, now.Add(staleTTL))
return staleAnswer
@@ -296,7 +296,7 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
continue
}
if answer.Rcode != dns.RcodeSuccess && len(upstreamConfigs) > 1 && containRcode(failoverRcodes, answer.Rcode) {
ctrld.Log(ctx, mainLog.Debug(), "failover rcode matched, process to next upstream")
ctrld.Log(ctx, mainLog.Load().Debug(), "failover rcode matched, process to next upstream")
continue
}
@@ -312,11 +312,11 @@ func (p *prog) proxy(ctx context.Context, upstreams []string, failoverRcodes []i
}
setCachedAnswerTTL(answer, now, expired)
p.cache.Add(dnscache.NewKey(msg, upstreams[n]), dnscache.NewValue(answer, expired))
ctrld.Log(ctx, mainLog.Debug(), "add cached response")
ctrld.Log(ctx, mainLog.Load().Debug(), "add cached response")
}
return answer
}
ctrld.Log(ctx, mainLog.Error(), "all upstreams failed")
ctrld.Log(ctx, mainLog.Load().Error(), "all upstreams failed")
answer := new(dns.Msg)
answer.SetRcode(msg, dns.RcodeServerFailure)
return answer
@@ -490,7 +490,7 @@ func runDNSServer(addr, network string, handler dns.Handler) (*dns.Server, <-cha
defer close(errCh)
if err := s.ListenAndServe(); err != nil {
waitLock.Unlock()
mainLog.Error().Err(err).Msgf("could not listen and serve on: %s", s.Addr)
mainLog.Load().Error().Err(err).Msgf("could not listen and serve on: %s", s.Addr)
errCh <- err
}
}()

View File

@@ -4,6 +4,7 @@ import (
"io"
"os"
"path/filepath"
"sync/atomic"
"time"
"github.com/kardianos/service"
@@ -31,15 +32,20 @@ var (
iface string
ifaceStartStop string
mainLog = zerolog.New(io.Discard)
mainLog atomic.Pointer[zerolog.Logger]
consoleWriter zerolog.ConsoleWriter
)
func init() {
l := zerolog.New(io.Discard)
mainLog.Store(&l)
}
func main() {
ctrld.InitConfig(v, "ctrld")
initCLI()
if err := rootCmd.Execute(); err != nil {
mainLog.Error().Msg(err.Error())
mainLog.Load().Error().Msg(err.Error())
os.Exit(1)
}
}
@@ -63,7 +69,8 @@ func initConsoleLogging() {
w.TimeFormat = time.StampMilli
})
multi := zerolog.MultiLevelWriter(consoleWriter)
mainLog = mainLog.Output(multi).With().Timestamp().Logger()
l := mainLog.Load().Output(multi).With().Timestamp().Logger()
mainLog.Store(&l)
switch {
case silent:
zerolog.SetGlobalLevel(zerolog.NoLevel)
@@ -92,7 +99,7 @@ func initLoggingWithBackup(doBackup bool) {
if logFilePath := normalizeLogFilePath(cfg.Service.LogPath); logFilePath != "" {
// Create parent directory if necessary.
if err := os.MkdirAll(filepath.Dir(logFilePath), 0750); err != nil {
mainLog.Error().Msgf("failed to create log path: %v", err)
mainLog.Load().Error().Msgf("failed to create log path: %v", err)
os.Exit(1)
}
@@ -101,7 +108,7 @@ func initLoggingWithBackup(doBackup bool) {
if doBackup {
// Backup old log file with .1 suffix.
if err := os.Rename(logFilePath, logFilePath+".1"); err != nil && !os.IsNotExist(err) {
mainLog.Error().Msgf("could not backup old log file: %v", err)
mainLog.Load().Error().Msgf("could not backup old log file: %v", err)
} else {
// Backup was created, set flags for truncating old log file.
flags = os.O_CREATE | os.O_RDWR
@@ -109,16 +116,17 @@ func initLoggingWithBackup(doBackup bool) {
}
logFile, err := os.OpenFile(logFilePath, flags, os.FileMode(0o600))
if err != nil {
mainLog.Error().Msgf("failed to create log file: %v", err)
mainLog.Load().Error().Msgf("failed to create log file: %v", err)
os.Exit(1)
}
writers = append(writers, logFile)
}
writers = append(writers, consoleWriter)
multi := zerolog.MultiLevelWriter(writers...)
mainLog = mainLog.Output(multi).With().Timestamp().Logger()
l := mainLog.Load().Output(multi).With().Timestamp().Logger()
mainLog.Store(&l)
// TODO: find a better way.
ctrld.ProxyLog = mainLog
ctrld.ProxyLogger.Store(&l)
zerolog.SetGlobalLevel(zerolog.NoticeLevel)
logLevel := cfg.Service.LogLevel
@@ -136,7 +144,7 @@ func initLoggingWithBackup(doBackup bool) {
}
level, err := zerolog.ParseLevel(logLevel)
if err != nil {
mainLog.Warn().Err(err).Msg("could not set log level")
mainLog.Load().Warn().Err(err).Msg("could not set log level")
return
}
zerolog.SetGlobalLevel(level)

View File

@@ -11,6 +11,7 @@ import (
var logOutput strings.Builder
func TestMain(m *testing.M) {
mainLog = zerolog.New(&logOutput)
l := zerolog.New(&logOutput)
mainLog.Store(&l)
os.Exit(m.Run())
}

View File

@@ -17,7 +17,7 @@ func patchNetIfaceName(iface *net.Interface) error {
if name := networkServiceName(iface.Name, bytes.NewReader(b)); name != "" {
iface.Name = name
mainLog.Debug().Str("network_service", name).Msg("found network service name for interface")
mainLog.Load().Debug().Str("network_service", name).Msg("found network service name for interface")
}
return nil
}

View File

@@ -10,7 +10,7 @@ func (p *prog) watchLinkState() {
done := make(chan struct{})
defer close(done)
if err := netlink.LinkSubscribe(ch, done); err != nil {
mainLog.Warn().Err(err).Msg("could not subscribe link")
mainLog.Load().Warn().Err(err).Msg("could not subscribe link")
return
}
for lu := range ch {
@@ -18,7 +18,7 @@ func (p *prog) watchLinkState() {
continue
}
if lu.Change&unix.IFF_UP != 0 {
mainLog.Debug().Msgf("link state changed, re-bootstrapping")
mainLog.Load().Debug().Msgf("link state changed, re-bootstrapping")
for _, uc := range p.cfg.Upstream {
uc.ReBootstrap()
}

View File

@@ -24,37 +24,37 @@ var networkManagerCtrldConfFile = filepath.Join(nmConfDir, nmCtrldConfFilename)
func setupNetworkManager() error {
if content, _ := os.ReadFile(nmCtrldConfContent); string(content) == nmCtrldConfContent {
mainLog.Debug().Msg("NetworkManager already setup, nothing to do")
mainLog.Load().Debug().Msg("NetworkManager already setup, nothing to do")
return nil
}
err := os.WriteFile(networkManagerCtrldConfFile, []byte(nmCtrldConfContent), os.FileMode(0644))
if os.IsNotExist(err) {
mainLog.Debug().Msg("NetworkManager is not available")
mainLog.Load().Debug().Msg("NetworkManager is not available")
return nil
}
if err != nil {
mainLog.Debug().Err(err).Msg("could not write NetworkManager ctrld config file")
mainLog.Load().Debug().Err(err).Msg("could not write NetworkManager ctrld config file")
return err
}
reloadNetworkManager()
mainLog.Debug().Msg("setup NetworkManager done")
mainLog.Load().Debug().Msg("setup NetworkManager done")
return nil
}
func restoreNetworkManager() error {
err := os.Remove(networkManagerCtrldConfFile)
if os.IsNotExist(err) {
mainLog.Debug().Msg("NetworkManager is not available")
mainLog.Load().Debug().Msg("NetworkManager is not available")
return nil
}
if err != nil {
mainLog.Debug().Err(err).Msg("could not remove NetworkManager ctrld config file")
mainLog.Load().Debug().Err(err).Msg("could not remove NetworkManager ctrld config file")
return err
}
reloadNetworkManager()
mainLog.Debug().Msg("restore NetworkManager done")
mainLog.Load().Debug().Msg("restore NetworkManager done")
return nil
}
@@ -63,14 +63,14 @@ func reloadNetworkManager() {
defer cancel()
conn, err := dbus.NewSystemConnectionContext(ctx)
if err != nil {
mainLog.Error().Err(err).Msg("could not create new system connection")
mainLog.Load().Error().Err(err).Msg("could not create new system connection")
return
}
defer conn.Close()
waitCh := make(chan string)
if _, err := conn.ReloadUnitContext(ctx, nmSystemdUnitName, "ignore-dependencies", waitCh); err != nil {
mainLog.Debug().Err(err).Msg("could not reload NetworkManager")
mainLog.Load().Debug().Err(err).Msg("could not reload NetworkManager")
}
<-waitCh
}

View File

@@ -12,7 +12,7 @@ import (
func allocateIP(ip string) error {
cmd := exec.Command("ifconfig", "lo0", "alias", ip, "up")
if err := cmd.Run(); err != nil {
mainLog.Error().Err(err).Msg("allocateIP failed")
mainLog.Load().Error().Err(err).Msg("allocateIP failed")
return err
}
return nil
@@ -21,7 +21,7 @@ func allocateIP(ip string) error {
func deAllocateIP(ip string) error {
cmd := exec.Command("ifconfig", "lo0", "-alias", ip)
if err := cmd.Run(); err != nil {
mainLog.Error().Err(err).Msg("deAllocateIP failed")
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
return err
}
return nil
@@ -36,7 +36,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
args = append(args, nameservers...)
if err := exec.Command(cmd, args...).Run(); err != nil {
mainLog.Error().Err(err).Msgf("setDNS failed, ips = %q", nameservers)
mainLog.Load().Error().Err(err).Msgf("setDNS failed, ips = %q", nameservers)
return err
}
return nil
@@ -48,7 +48,7 @@ func resetDNS(iface *net.Interface) error {
args := []string{"-setdnsservers", iface.Name, "empty"}
if err := exec.Command(cmd, args...).Run(); err != nil {
mainLog.Error().Err(err).Msgf("resetDNS failed")
mainLog.Load().Error().Err(err).Msgf("resetDNS failed")
return err
}
return nil

View File

@@ -14,7 +14,7 @@ import (
func allocateIP(ip string) error {
cmd := exec.Command("ifconfig", "lo0", ip, "alias")
if err := cmd.Run(); err != nil {
mainLog.Error().Err(err).Msg("allocateIP failed")
mainLog.Load().Error().Err(err).Msg("allocateIP failed")
return err
}
return nil
@@ -23,7 +23,7 @@ func allocateIP(ip string) error {
func deAllocateIP(ip string) error {
cmd := exec.Command("ifconfig", "lo0", ip, "-alias")
if err := cmd.Run(); err != nil {
mainLog.Error().Err(err).Msg("deAllocateIP failed")
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
return err
}
return nil
@@ -33,7 +33,7 @@ func deAllocateIP(ip string) error {
func setDNS(iface *net.Interface, nameservers []string) error {
r, err := dns.NewOSConfigurator(logf, iface.Name)
if err != nil {
mainLog.Error().Err(err).Msg("failed to create DNS OS configurator")
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
return err
}
@@ -43,7 +43,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
}
if err := r.SetDNS(dns.OSConfig{Nameservers: ns}); err != nil {
mainLog.Error().Err(err).Msg("failed to set DNS")
mainLog.Load().Error().Err(err).Msg("failed to set DNS")
return err
}
return nil
@@ -52,12 +52,12 @@ func setDNS(iface *net.Interface, nameservers []string) error {
func resetDNS(iface *net.Interface) error {
r, err := dns.NewOSConfigurator(logf, iface.Name)
if err != nil {
mainLog.Error().Err(err).Msg("failed to create DNS OS configurator")
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
return err
}
if err := r.Close(); err != nil {
mainLog.Error().Err(err).Msg("failed to rollback DNS setting")
mainLog.Load().Error().Err(err).Msg("failed to rollback DNS setting")
return err
}
return nil

View File

@@ -29,7 +29,7 @@ import (
func allocateIP(ip string) error {
cmd := exec.Command("ip", "a", "add", ip+"/24", "dev", "lo")
if out, err := cmd.CombinedOutput(); err != nil {
mainLog.Error().Err(err).Msgf("allocateIP failed: %s", string(out))
mainLog.Load().Error().Err(err).Msgf("allocateIP failed: %s", string(out))
return err
}
return nil
@@ -38,7 +38,7 @@ func allocateIP(ip string) error {
func deAllocateIP(ip string) error {
cmd := exec.Command("ip", "a", "del", ip+"/24", "dev", "lo")
if err := cmd.Run(); err != nil {
mainLog.Error().Err(err).Msg("deAllocateIP failed")
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
return err
}
return nil
@@ -50,7 +50,7 @@ const maxSetDNSAttempts = 5
func setDNS(iface *net.Interface, nameservers []string) error {
r, err := dns.NewOSConfigurator(logf, iface.Name)
if err != nil {
mainLog.Error().Err(err).Msg("failed to create DNS OS configurator")
mainLog.Load().Error().Err(err).Msg("failed to create DNS OS configurator")
return err
}
@@ -69,7 +69,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
if err := r.SetDNS(osConfig); err != nil {
if strings.Contains(err.Error(), "Rejected send message") &&
strings.Contains(err.Error(), "org.freedesktop.network1.Manager") {
mainLog.Warn().Msg("Interfaces are managed by systemd-networkd, switch to systemd-resolve for setting DNS")
mainLog.Load().Warn().Msg("Interfaces are managed by systemd-networkd, switch to systemd-resolve for setting DNS")
trySystemdResolve = true
break
}
@@ -100,7 +100,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
time.Sleep(time.Second)
}
}
mainLog.Debug().Msg("DNS was not set for some reason")
mainLog.Load().Debug().Msg("DNS was not set for some reason")
return nil
}
@@ -116,7 +116,7 @@ func resetDNS(iface *net.Interface) (err error) {
if r, oerr := dns.NewOSConfigurator(logf, iface.Name); oerr == nil {
_ = r.SetDNS(dns.OSConfig{})
if err := r.Close(); err != nil {
mainLog.Error().Err(err).Msg("failed to rollback DNS setting")
mainLog.Load().Error().Err(err).Msg("failed to rollback DNS setting")
return
}
err = nil
@@ -148,13 +148,13 @@ func resetDNS(iface *net.Interface) (err error) {
c := client6.NewClient()
conversation, err := c.Exchange(iface.Name)
if err != nil && !errAddrInUse(err) {
mainLog.Debug().Err(err).Msg("could not exchange DHCPv6")
mainLog.Load().Debug().Err(err).Msg("could not exchange DHCPv6")
}
for _, packet := range conversation {
if packet.Type() == dhcpv6.MessageTypeReply {
msg, err := packet.GetInnerMessage()
if err != nil {
mainLog.Debug().Err(err).Msg("could not get inner DHCPv6 message")
mainLog.Load().Debug().Err(err).Msg("could not get inner DHCPv6 message")
return nil
}
nameservers := msg.Options.DNS()

View File

@@ -30,12 +30,12 @@ func setDNS(iface *net.Interface, nameservers []string) error {
func resetDNS(iface *net.Interface) error {
if ctrldnet.SupportsIPv6ListenLocal() {
if output, err := netsh("interface", "ipv6", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp"); err != nil {
mainLog.Warn().Err(err).Msgf("failed to reset ipv6 DNS: %s", string(output))
mainLog.Load().Warn().Err(err).Msgf("failed to reset ipv6 DNS: %s", string(output))
}
}
output, err := netsh("interface", "ipv4", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp")
if err != nil {
mainLog.Error().Err(err).Msgf("failed to reset ipv4 DNS: %s", string(output))
mainLog.Load().Error().Err(err).Msgf("failed to reset ipv4 DNS: %s", string(output))
return err
}
return nil
@@ -49,7 +49,7 @@ func setPrimaryDNS(iface *net.Interface, dns string) error {
idx := strconv.Itoa(iface.Index)
output, err := netsh("interface", ipVer, "set", "dnsserver", idx, "static", dns)
if err != nil {
mainLog.Error().Err(err).Msgf("failed to set primary DNS: %s", string(output))
mainLog.Load().Error().Err(err).Msgf("failed to set primary DNS: %s", string(output))
return err
}
if ipVer == "ipv4" && ctrldnet.SupportsIPv6ListenLocal() {
@@ -67,7 +67,7 @@ func addSecondaryDNS(iface *net.Interface, dns string) error {
}
output, err := netsh("interface", ipVer, "add", "dns", strconv.Itoa(iface.Index), dns, "index=2")
if err != nil {
mainLog.Warn().Err(err).Msgf("failed to add secondary DNS: %s", string(output))
mainLog.Load().Warn().Err(err).Msgf("failed to add secondary DNS: %s", string(output))
}
return nil
}
@@ -79,12 +79,12 @@ func netsh(args ...string) ([]byte, error) {
func currentDNS(iface *net.Interface) []string {
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
if err != nil {
mainLog.Error().Err(err).Msg("failed to get interface LUID")
mainLog.Load().Error().Err(err).Msg("failed to get interface LUID")
return nil
}
nameservers, err := luid.DNS()
if err != nil {
mainLog.Error().Err(err).Msg("failed to get interface DNS")
mainLog.Load().Error().Err(err).Msg("failed to get interface DNS")
return nil
}
ns := make([]string, 0, len(nameservers))

View File

@@ -26,7 +26,7 @@ const (
)
var logf = func(format string, args ...any) {
mainLog.Debug().Msgf(format, args...)
mainLog.Load().Debug().Msgf(format, args...)
}
var svcConfig = &service.Config{
@@ -72,7 +72,7 @@ func (p *prog) run() {
if p.cfg.Service.CacheEnable {
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
if err != nil {
mainLog.Error().Err(err).Msg("failed to create cacher, caching is disabled")
mainLog.Load().Error().Err(err).Msg("failed to create cacher, caching is disabled")
} else {
p.cache = cacher
}
@@ -93,7 +93,7 @@ func (p *prog) run() {
for _, cidr := range nc.Cidrs {
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
mainLog.Error().Err(err).Str("network", nc.Name).Str("cidr", cidr).Msg("invalid cidr")
mainLog.Load().Error().Err(err).Str("network", nc.Name).Str("cidr", cidr).Msg("invalid cidr")
continue
}
nc.IPNets = append(nc.IPNets, ipNet)
@@ -104,9 +104,9 @@ func (p *prog) run() {
uc.Init()
if uc.BootstrapIP == "" {
uc.SetupBootstrapIP()
mainLog.Info().Msgf("bootstrap IPs for upstream.%s: %q", n, uc.BootstrapIPs())
mainLog.Load().Info().Msgf("bootstrap IPs for upstream.%s: %q", n, uc.BootstrapIPs())
} else {
mainLog.Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("using bootstrap IP for upstream.%s", n)
mainLog.Load().Info().Str("bootstrap_ip", uc.BootstrapIP).Msgf("using bootstrap IP for upstream.%s", n)
}
uc.SetCertPool(rootCertPool)
go uc.Ping()
@@ -114,7 +114,7 @@ func (p *prog) run() {
p.ciTable = clientinfo.NewTable(&cfg, defaultRouteIP())
if leaseFile := p.cfg.Service.DHCPLeaseFile; leaseFile != "" {
mainLog.Debug().Msgf("watching custom lease file: %s", leaseFile)
mainLog.Load().Debug().Msgf("watching custom lease file: %s", leaseFile)
format := ctrld.LeaseFileFormat(p.cfg.Service.DHCPLeaseFileFormat)
p.ciTable.AddLeaseFile(leaseFile, format)
}
@@ -132,12 +132,12 @@ func (p *prog) run() {
listenerConfig := p.cfg.Listener[listenerNum]
upstreamConfig := p.cfg.Upstream[listenerNum]
if upstreamConfig == nil {
mainLog.Warn().Msgf("no default upstream for: [listener.%s]", listenerNum)
mainLog.Load().Warn().Msgf("no default upstream for: [listener.%s]", listenerNum)
}
addr := net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port))
mainLog.Info().Msgf("starting DNS server on listener.%s: %s", listenerNum, addr)
mainLog.Load().Info().Msgf("starting DNS server on listener.%s: %s", listenerNum, addr)
if err := p.serveDNS(listenerNum); err != nil {
mainLog.Fatal().Err(err).Msgf("unable to start dns proxy on listener.%s", listenerNum)
mainLog.Load().Fatal().Err(err).Msgf("unable to start dns proxy on listener.%s", listenerNum)
}
}(listenerNum)
}
@@ -159,17 +159,17 @@ func (p *prog) run() {
if p.cs != nil {
p.registerControlServerHandler()
if err := p.cs.start(); err != nil {
mainLog.Warn().Err(err).Msg("could not start control server")
mainLog.Load().Warn().Err(err).Msg("could not start control server")
}
}
wg.Wait()
}
func (p *prog) Stop(s service.Service) error {
mainLog.Info().Msg("Service stopped")
mainLog.Load().Info().Msg("Service stopped")
close(p.stopCh)
if err := p.deAllocateIP(); err != nil {
mainLog.Error().Err(err).Msg("de-allocate ip failed")
mainLog.Load().Error().Err(err).Msg("de-allocate ip failed")
return err
}
return nil
@@ -212,7 +212,7 @@ func (p *prog) setDNS() {
if lc == nil {
return
}
logger := mainLog.With().Str("iface", iface).Logger()
logger := mainLog.Load().With().Str("iface", iface).Logger()
netIface, err := netInterface(iface)
if err != nil {
logger.Error().Err(err).Msg("could not get interface")
@@ -257,7 +257,7 @@ func (p *prog) resetDNS() {
if iface == "auto" {
iface = defaultIfaceName()
}
logger := mainLog.With().Str("iface", iface).Logger()
logger := mainLog.Load().With().Str("iface", iface).Logger()
netIface, err := netInterface(iface)
if err != nil {
logger.Error().Err(err).Msg("could not get interface")
@@ -291,19 +291,19 @@ func randomPort() int {
func runLogServer(sockPath string) net.Conn {
addr, err := net.ResolveUnixAddr("unix", sockPath)
if err != nil {
mainLog.Warn().Err(err).Msg("invalid log sock path")
mainLog.Load().Warn().Err(err).Msg("invalid log sock path")
return nil
}
ln, err := net.ListenUnix("unix", addr)
if err != nil {
mainLog.Warn().Err(err).Msg("could not listen log socket")
mainLog.Load().Warn().Err(err).Msg("could not listen log socket")
return nil
}
defer ln.Close()
server, err := ln.Accept()
if err != nil {
mainLog.Warn().Err(err).Msg("could not accept connection")
mainLog.Load().Warn().Err(err).Msg("could not accept connection")
return nil
}
return server

View File

@@ -105,7 +105,7 @@ func doTasks(tasks []task) bool {
for _, task := range tasks {
if err := task.f(); err != nil {
if task.abortOnError {
mainLog.Error().Msg(errors.Join(prevErr, err).Error())
mainLog.Load().Error().Msg(errors.Join(prevErr, err).Error())
return false
}
prevErr = err
@@ -117,11 +117,11 @@ func doTasks(tasks []task) bool {
func checkHasElevatedPrivilege() {
ok, err := hasElevatedPrivilege()
if err != nil {
mainLog.Error().Msgf("could not detect user privilege: %v", err)
mainLog.Load().Error().Msgf("could not detect user privilege: %v", err)
return
}
if !ok {
mainLog.Error().Msg("Please relaunch process with admin/root privilege.")
mainLog.Load().Error().Msg("Please relaunch process with admin/root privilege.")
os.Exit(1)
}
}

View File

@@ -330,7 +330,7 @@ func (uc *UpstreamConfig) setupBootstrapIP(withBootstrapDNS bool) {
if len(uc.bootstrapIPs) > 0 {
break
}
ProxyLog.Warn().Msg("could not resolve bootstrap IPs, retrying...")
ProxyLogger.Load().Warn().Msg("could not resolve bootstrap IPs, retrying...")
b.BackOff(context.Background(), errors.New("no bootstrap IPs"))
}
for _, ip := range uc.bootstrapIPs {
@@ -340,7 +340,7 @@ func (uc *UpstreamConfig) setupBootstrapIP(withBootstrapDNS bool) {
uc.bootstrapIPs4 = append(uc.bootstrapIPs4, ip)
}
}
ProxyLog.Debug().Msgf("bootstrap IPs: %v", uc.bootstrapIPs)
ProxyLogger.Load().Debug().Msgf("bootstrap IPs: %v", uc.bootstrapIPs)
}
// ReBootstrap re-setup the bootstrap IP and the transport.
@@ -351,7 +351,7 @@ func (uc *UpstreamConfig) ReBootstrap() {
return
}
_, _, _ = uc.g.Do("ReBootstrap", func() (any, error) {
ProxyLog.Debug().Msg("re-bootstrapping upstream ip")
ProxyLogger.Load().Debug().Msg("re-bootstrapping upstream ip")
uc.rebootstrap.Store(true)
return true, nil
})
@@ -405,7 +405,7 @@ func (uc *UpstreamConfig) newDOHTransport(addrs []string) *http.Transport {
if uc.BootstrapIP != "" {
dialer := net.Dialer{Timeout: dialerTimeout, KeepAlive: dialerTimeout}
addr := net.JoinHostPort(uc.BootstrapIP, port)
Log(ctx, ProxyLog.Debug(), "sending doh request to: %s", addr)
Log(ctx, ProxyLogger.Load().Debug(), "sending doh request to: %s", addr)
return dialer.DialContext(ctx, network, addr)
}
pd := &ctrldnet.ParallelDialer{}
@@ -419,7 +419,7 @@ func (uc *UpstreamConfig) newDOHTransport(addrs []string) *http.Transport {
if err != nil {
return nil, err
}
Log(ctx, ProxyLog.Debug(), "sending doh request to: %s", conn.RemoteAddr())
Log(ctx, ProxyLogger.Load().Debug(), "sending doh request to: %s", conn.RemoteAddr())
return conn, nil
}
runtime.SetFinalizer(transport, func(transport *http.Transport) {

View File

@@ -48,7 +48,7 @@ func (uc *UpstreamConfig) newDOH3Transport(addrs []string) http.RoundTripper {
// if we have a bootstrap ip set, use it to avoid DNS lookup
if uc.BootstrapIP != "" {
addr = net.JoinHostPort(uc.BootstrapIP, port)
ProxyLog.Debug().Msgf("sending doh3 request to: %s", addr)
ProxyLogger.Load().Debug().Msgf("sending doh3 request to: %s", addr)
udpConn, err := net.ListenUDP("udp", nil)
if err != nil {
return nil, err
@@ -68,7 +68,7 @@ func (uc *UpstreamConfig) newDOH3Transport(addrs []string) http.RoundTripper {
if err != nil {
return nil, err
}
ProxyLog.Debug().Msgf("sending doh3 request to: %s", conn.RemoteAddr())
ProxyLogger.Load().Debug().Msgf("sending doh3 request to: %s", conn.RemoteAddr())
return conn, err
}
return rt

2
doh.go
View File

@@ -110,5 +110,5 @@ func addHeader(ctx context.Context, req *http.Request, sendClientInfo bool) {
}
}
}
Log(ctx, ProxyLog.Debug().Interface("header", req.Header), "sending request header")
Log(ctx, ProxyLogger.Load().Debug().Interface("header", req.Header), "sending request header")
}

View File

@@ -105,7 +105,7 @@ func (t *Table) Init() {
if t.discoverDHCP() || t.discoverARP() {
t.merlin = &merlinDiscover{}
if err := t.merlin.refresh(); err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not init Merlin discover")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not init Merlin discover")
} else {
t.hostnameResolvers = append(t.hostnameResolvers, t.merlin)
t.refreshers = append(t.refreshers, t.merlin)
@@ -113,9 +113,9 @@ func (t *Table) Init() {
}
if t.discoverDHCP() {
t.dhcp = &dhcp{selfIP: t.selfIP}
ctrld.ProxyLog.Debug().Msg("start dhcp discovery")
ctrld.ProxyLogger.Load().Debug().Msg("start dhcp discovery")
if err := t.dhcp.init(); err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not init DHCP discover")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not init DHCP discover")
} else {
t.ipResolvers = append(t.ipResolvers, t.dhcp)
t.macResolvers = append(t.macResolvers, t.dhcp)
@@ -125,9 +125,9 @@ func (t *Table) Init() {
}
if t.discoverARP() {
t.arp = &arpDiscover{}
ctrld.ProxyLog.Debug().Msg("start arp discovery")
ctrld.ProxyLogger.Load().Debug().Msg("start arp discovery")
if err := t.arp.refresh(); err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not init ARP discover")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not init ARP discover")
} else {
t.ipResolvers = append(t.ipResolvers, t.arp)
t.macResolvers = append(t.macResolvers, t.arp)
@@ -136,9 +136,9 @@ func (t *Table) Init() {
}
if t.discoverPTR() {
t.ptr = &ptrDiscover{resolver: ctrld.NewPrivateResolver()}
ctrld.ProxyLog.Debug().Msg("start ptr discovery")
ctrld.ProxyLogger.Load().Debug().Msg("start ptr discovery")
if err := t.ptr.refresh(); err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not init PTR discover")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not init PTR discover")
} else {
t.hostnameResolvers = append(t.hostnameResolvers, t.ptr)
t.refreshers = append(t.refreshers, t.ptr)
@@ -146,9 +146,9 @@ func (t *Table) Init() {
}
if t.discoverMDNS() {
t.mdns = &mdns{}
ctrld.ProxyLog.Debug().Msg("start mdns discovery")
ctrld.ProxyLogger.Load().Debug().Msg("start mdns discovery")
if err := t.mdns.init(t.quitCh); err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not init mDNS discover")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not init mDNS discover")
} else {
t.hostnameResolvers = append(t.hostnameResolvers, t.mdns)
}

View File

@@ -56,14 +56,14 @@ func (d *dhcp) watchChanges() {
if event.Has(fsnotify.Write) {
format := clientInfoFiles[event.Name]
if err := d.readLeaseFile(event.Name, format); err != nil && !os.IsNotExist(err) {
ctrld.ProxyLog.Err(err).Str("file", event.Name).Msg("leases file changed but failed to update client info")
ctrld.ProxyLogger.Load().Err(err).Str("file", event.Name).Msg("leases file changed but failed to update client info")
}
}
case err, ok := <-d.watcher.Errors:
if !ok {
return
}
ctrld.ProxyLog.Err(err).Msg("could not watch client info file")
ctrld.ProxyLogger.Load().Err(err).Msg("could not watch client info file")
}
}
@@ -167,7 +167,7 @@ func (d *dhcp) dnsmasqReadClientInfoReader(reader io.Reader) error {
}
ip := normalizeIP(string(fields[2]))
if net.ParseIP(ip) == nil {
ctrld.ProxyLog.Warn().Msgf("invalid ip address entry: %q", ip)
ctrld.ProxyLogger.Load().Warn().Msgf("invalid ip address entry: %q", ip)
ip = ""
}
@@ -219,7 +219,7 @@ func (d *dhcp) iscDHCPReadClientInfoReader(reader io.Reader) error {
case "lease":
ip = normalizeIP(strings.ToLower(fields[1]))
if net.ParseIP(ip) == nil {
ctrld.ProxyLog.Warn().Msgf("invalid ip address entry: %q", ip)
ctrld.ProxyLogger.Load().Warn().Msgf("invalid ip address entry: %q", ip)
ip = ""
}
case "hardware":
@@ -242,7 +242,7 @@ func (d *dhcp) iscDHCPReadClientInfoReader(reader io.Reader) error {
func (d *dhcp) addSelf() {
hostname, err := os.Hostname()
if err != nil {
ctrld.ProxyLog.Err(err).Msg("could not get hostname")
ctrld.ProxyLogger.Load().Err(err).Msg("could not get hostname")
return
}
hostname = normalizeHostname(hostname)

View File

@@ -83,11 +83,11 @@ func (m *mdns) probeLoop(conns []*net.UDPConn, remoteAddr net.Addr, quitCh chan
for {
err := m.probe(conns, remoteAddr)
if isErrNetUnreachableOrInvalid(err) {
ctrld.ProxyLog.Warn().Msgf("stop probing %q: network unreachable or invalid", remoteAddr)
ctrld.ProxyLogger.Load().Warn().Msgf("stop probing %q: network unreachable or invalid", remoteAddr)
break
}
if err != nil {
ctrld.ProxyLog.Warn().Err(err).Msg("error while probing mdns")
ctrld.ProxyLogger.Load().Warn().Err(err).Msg("error while probing mdns")
bo.BackOff(context.Background(), errors.New("mdns probe backoff"))
}
select {
@@ -113,7 +113,7 @@ func (m *mdns) readLoop(conn *net.UDPConn) {
if err, ok := err.(*net.OpError); ok && (err.Timeout() || err.Temporary()) {
continue
}
ctrld.ProxyLog.Debug().Err(err).Msg("mdns readLoop error")
ctrld.ProxyLogger.Load().Debug().Err(err).Msg("mdns readLoop error")
return
}
@@ -133,11 +133,11 @@ func (m *mdns) readLoop(conn *net.UDPConn) {
if ip != "" && name != "" {
name = normalizeHostname(name)
if val, loaded := m.name.LoadOrStore(ip, name); !loaded {
ctrld.ProxyLog.Debug().Msgf("found hostname: %q, ip: %q via mdns", name, ip)
ctrld.ProxyLogger.Load().Debug().Msgf("found hostname: %q, ip: %q via mdns", name, ip)
} else {
old := val.(string)
if old != name {
ctrld.ProxyLog.Debug().Msgf("update hostname: %q, ip: %q, old: %q via mdns", name, ip, old)
ctrld.ProxyLogger.Load().Debug().Msgf("update hostname: %q, ip: %q, old: %q via mdns", name, ip, old)
m.name.Store(ip, name)
}
}

View File

@@ -25,7 +25,7 @@ func (m *merlinDiscover) refresh() error {
if err != nil {
return err
}
ctrld.ProxyLog.Debug().Msg("reading Merlin custom client list")
ctrld.ProxyLogger.Load().Debug().Msg("reading Merlin custom client list")
m.parseMerlinCustomClientList(out)
return nil
}

View File

@@ -46,13 +46,13 @@ func (p *ptrDiscover) lookupHostname(ip string) string {
msg := new(dns.Msg)
addr, err := dns.ReverseAddr(ip)
if err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("invalid ip address")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("invalid ip address")
return ""
}
msg.SetQuestion(addr, dns.TypePTR)
ans, err := p.resolver.Resolve(ctx, msg)
if err != nil {
ctrld.ProxyLog.Error().Err(err).Msg("could not lookup IP")
ctrld.ProxyLogger.Load().Error().Err(err).Msg("could not lookup IP")
return ""
}
for _, rr := range ans.Answer {

View File

@@ -80,10 +80,10 @@ func FetchResolverConfig(uid, version string, cdDev bool) (*ResolverConfig, erro
}
ips := ctrld.LookupIP(apiDomain)
if len(ips) == 0 {
ctrld.ProxyLog.Warn().Msgf("No IPs found for %s, connecting to %s", apiDomain, addr)
ctrld.ProxyLogger.Load().Warn().Msgf("No IPs found for %s, connecting to %s", apiDomain, addr)
return ctrldnet.Dialer.DialContext(ctx, network, addr)
}
ctrld.ProxyLog.Debug().Msgf("API IPs: %v", ips)
ctrld.ProxyLogger.Load().Debug().Msgf("API IPs: %v", ips)
_, port, _ := net.SplitHostPort(addr)
addrs := make([]string, len(ips))
for i := range ips {

10
log.go
View File

@@ -4,14 +4,24 @@ import (
"context"
"fmt"
"io"
"sync/atomic"
"github.com/rs/zerolog"
)
func init() {
l := zerolog.New(io.Discard)
ProxyLogger.Store(&l)
}
// ProxyLog emits the log record for proxy operations.
// The caller should set it only once.
// DEPRECATED: use ProxyLogger instead.
var ProxyLog = zerolog.New(io.Discard)
// ProxyLogger emits the log record for proxy operations.
var ProxyLogger atomic.Pointer[zerolog.Logger]
// ReqIdCtxKey is the context.Context key for a request id.
type ReqIdCtxKey struct{}

View File

@@ -156,7 +156,7 @@ func lookupIP(domain string, timeout int, withBootstrapDNS bool) (ips []string)
if withBootstrapDNS {
resolver.nameservers = append([]string{net.JoinHostPort(bootstrapDNS, "53")}, resolver.nameservers...)
}
ProxyLog.Debug().Msgf("resolving %q using bootstrap DNS %q", domain, resolver.nameservers)
ProxyLogger.Load().Debug().Msgf("resolving %q using bootstrap DNS %q", domain, resolver.nameservers)
timeoutMs := 2000
if timeout > 0 && timeout < timeoutMs {
timeoutMs = timeout
@@ -199,15 +199,15 @@ func lookupIP(domain string, timeout int, withBootstrapDNS bool) (ips []string)
r, err := resolver.Resolve(ctx, m)
if err != nil {
ProxyLog.Error().Err(err).Msgf("could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
ProxyLogger.Load().Error().Err(err).Msgf("could not lookup %q record for domain %q", dns.TypeToString[dnsType], domain)
return
}
if r.Rcode != dns.RcodeSuccess {
ProxyLog.Error().Msgf("could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
ProxyLogger.Load().Error().Msgf("could not resolve domain %q, return code: %s", domain, dns.RcodeToString[r.Rcode])
return
}
if len(r.Answer) == 0 {
ProxyLog.Error().Msg("no answer from OS resolver")
ProxyLogger.Load().Error().Msg("no answer from OS resolver")
return
}
target := targetDomain(r.Answer)