cmd/cli: add config to control DNS watchdog

This commit is contained in:
Cuong Manh Le
2024-07-26 17:17:44 +07:00
committed by Cuong Manh Le
parent 18a19a3aa2
commit ec684348ed
6 changed files with 129 additions and 24 deletions
+22 -2
View File
@@ -40,7 +40,7 @@ const (
upstreamPrefix = "upstream." upstreamPrefix = "upstream."
upstreamOS = upstreamPrefix + "os" upstreamOS = upstreamPrefix + "os"
upstreamPrivate = upstreamPrefix + "private" upstreamPrivate = upstreamPrefix + "private"
dnsWatchdogInterval = time.Minute dnsWatchdogDefaultInterval = 20 * time.Second
) )
// ControlSocketName returns name for control unix socket. // ControlSocketName returns name for control unix socket.
@@ -532,7 +532,27 @@ func (p *prog) setDNS() {
return setDnsIgnoreUnusableInterface(i, nameservers) return setDnsIgnoreUnusableInterface(i, nameservers)
}) })
} }
if p.dnsWatchdogEnabled() {
go p.dnsWatchdog(netIface, nameservers, allIfaces) go p.dnsWatchdog(netIface, nameservers, allIfaces)
}
}
// dnsWatchdogEnabled reports whether DNS watchdog is enabled.
func (p *prog) dnsWatchdogEnabled() bool {
if ptr := p.cfg.Service.DnsWatchdogEnabled; ptr != nil {
return *ptr
}
return true
}
// dnsWatchdogDuration returns the time duration between each DNS watchdog loop.
func (p *prog) dnsWatchdogDuration() time.Duration {
if ptr := p.cfg.Service.DnsWatchdogInvterval; ptr != nil {
if (*ptr).Seconds() > 0 {
return *ptr
}
}
return dnsWatchdogDefaultInterval
} }
// dnsWatchdog watches for DNS changes on Darwin and Windows then re-applying ctrld's settings. // dnsWatchdog watches for DNS changes on Darwin and Windows then re-applying ctrld's settings.
@@ -546,7 +566,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string, allIfaces
mainLog.Load().Debug().Msg("start DNS settings watchdog") mainLog.Load().Debug().Msg("start DNS settings watchdog")
ns := nameservers ns := nameservers
slices.Sort(ns) slices.Sort(ns)
ticker := time.NewTicker(dnsWatchdogInterval) ticker := time.NewTicker(p.dnsWatchdogDuration())
logger := mainLog.Load().With().Str("iface", iface.Name).Logger() logger := mainLog.Load().With().Str("iface", iface.Name).Logger()
for range ticker.C { for range ticker.C {
if dnsChanged(iface, ns) { if dnsChanged(iface, ns) {
+57
View File
@@ -0,0 +1,57 @@
package cli
import (
"testing"
"time"
"github.com/Control-D-Inc/ctrld"
"github.com/stretchr/testify/assert"
)
func Test_prog_dnsWatchdogEnabled(t *testing.T) {
p := &prog{cfg: &ctrld.Config{}}
// Default value is true.
assert.True(t, p.dnsWatchdogEnabled())
tests := []struct {
name string
enabled bool
}{
{"enabled", true},
{"disabled", false},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
p.cfg.Service.DnsWatchdogEnabled = &tc.enabled
assert.Equal(t, tc.enabled, p.dnsWatchdogEnabled())
})
}
}
func Test_prog_dnsWatchdogInterval(t *testing.T) {
p := &prog{cfg: &ctrld.Config{}}
// Default value is 20s.
assert.Equal(t, dnsWatchdogDefaultInterval, p.dnsWatchdogDuration())
tests := []struct {
name string
duration time.Duration
expected time.Duration
}{
{"valid", time.Minute, time.Minute},
{"zero", 0, dnsWatchdogDefaultInterval},
{"nagative", time.Duration(-1 * time.Minute), dnsWatchdogDefaultInterval},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
p.cfg.Service.DnsWatchdogInvterval = &tc.duration
assert.Equal(t, tc.expected, p.dnsWatchdogDuration())
})
}
}
+2
View File
@@ -207,6 +207,8 @@ type ServiceConfig struct {
ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"` ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"`
MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"` MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"`
MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"` MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"`
DnsWatchdogEnabled *bool `mapstructure:"dns_watchdog_enabled" toml:"dns_watchdog_enabled,omitempty"`
DnsWatchdogInvterval *time.Duration `mapstructure:"dns_watchdog_interval" toml:"dns_watchdog_interval,omitempty"`
Daemon bool `mapstructure:"-" toml:"-"` Daemon bool `mapstructure:"-" toml:"-"`
AllocateIP bool `mapstructure:"-" toml:"-"` AllocateIP bool `mapstructure:"-" toml:"-"`
} }
+3
View File
@@ -5,6 +5,7 @@ import (
"os" "os"
"strings" "strings"
"testing" "testing"
"time"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/spf13/viper" "github.com/spf13/viper"
@@ -22,6 +23,8 @@ func TestLoadConfig(t *testing.T) {
assert.Equal(t, "info", cfg.Service.LogLevel) assert.Equal(t, "info", cfg.Service.LogLevel)
assert.Equal(t, "/path/to/log.log", cfg.Service.LogPath) assert.Equal(t, "/path/to/log.log", cfg.Service.LogPath)
assert.Equal(t, false, *cfg.Service.DnsWatchdogEnabled)
assert.Equal(t, time.Duration(20*time.Second), *cfg.Service.DnsWatchdogInvterval)
assert.Len(t, cfg.Network, 2) assert.Len(t, cfg.Network, 2)
assert.Contains(t, cfg.Network, "0") assert.Contains(t, cfg.Network, "0")
+21
View File
@@ -252,6 +252,27 @@ Specifying the `ip` and `port` of the Prometheus metrics server. The Prometheus
- Required: no - Required: no
- Default: "" - Default: ""
### dns_watchdog_enabled
Checking DNS changes to network interfaces and reverting to ctrld's own settings.
The DNS watchdog process only runs on Windows and MacOS.
- Type: boolean
- Required: no
- Default: true
### dns_watchdog_interval
Time duration between each DNS watchdog iteration.
A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
If the time duration is non-positive, default value will be used.
- Type: time duration string
- Required: no
- Default: 20s
## Upstream ## Upstream
The `[upstream]` section specifies the DNS upstream servers that `ctrld` will forward DNS requests to. The `[upstream]` section specifies the DNS upstream servers that `ctrld` will forward DNS requests to.
+2
View File
@@ -27,6 +27,8 @@ var sampleConfigContent = `
[service] [service]
log_level = "info" log_level = "info"
log_path = "/path/to/log.log" log_path = "/path/to/log.log"
dns_watchdog_enabled = false
dns_watchdog_interval = "20s"
[network.0] [network.0]
name = "Home Wifi" name = "Home Wifi"