mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
all: prevent data race when accessing zerolog.Logger
This commit is contained in:
committed by
Cuong Manh Le
parent
59dc74ffbb
commit
19bc44a7f3
203
cmd/ctrld/cli.go
203
cmd/ctrld/cli.go
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
10
config.go
10
config.go
@@ -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) {
|
||||
|
||||
@@ -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
2
doh.go
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
10
log.go
@@ -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{}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user