chore(settings): refactor settings processing (#756)

- Better settings tree structure logged using `qdm12/gotree`
- Read settings from environment variables, then files, then secret files
- Settings methods to default them, merge them and override them
- `DNS_PLAINTEXT_ADDRESS` default changed to `127.0.0.1` to use DoT. Warning added if set to something else.
- `HTTPPROXY_LISTENING_ADDRESS` instead of `HTTPPROXY_PORT` (with retro-compatibility)
This commit is contained in:
Quentin McGaw
2022-01-06 06:40:23 -05:00
committed by GitHub
parent 46738b2934
commit 7d824a5179
275 changed files with 7167 additions and 6328 deletions

View File

@@ -8,7 +8,7 @@ import (
"github.com/qdm12/dns/pkg/blacklist"
"github.com/qdm12/dns/pkg/unbound"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
"github.com/qdm12/gluetun/internal/dns/state"
"github.com/qdm12/gluetun/internal/loopstate"
@@ -46,8 +46,8 @@ type Loop struct {
const defaultBackoffTime = 10 * time.Second
func NewLoop(conf unbound.Configurator, settings configuration.DNS, client *http.Client,
logger Logger) *Loop {
func NewLoop(conf unbound.Configurator, settings settings.DNS,
client *http.Client, logger Logger) *Loop {
start := make(chan struct{})
running := make(chan models.LoopStatus)
stop := make(chan struct{})

View File

@@ -1,35 +1,45 @@
package dns
import "github.com/qdm12/dns/pkg/nameserver"
import (
"net"
"github.com/qdm12/dns/pkg/nameserver"
)
func (l *Loop) useUnencryptedDNS(fallback bool) {
settings := l.GetSettings()
// Try with user provided plaintext ip address
targetIP := settings.PlaintextAddress
if targetIP != nil {
// if it's not 127.0.0.1 (default for DoT)
targetIP := settings.ServerAddress
if targetIP != nil && !targetIP.Equal(net.IPv4(127, 0, 0, 1)) { //nolint:gomnd
if fallback {
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String())
} else {
l.logger.Info("using plaintext DNS at address " + targetIP.String())
}
nameserver.UseDNSInternally(targetIP)
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP, settings.KeepNameserver)
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP, *settings.KeepNameserver)
if err != nil {
l.logger.Error(err.Error())
}
return
}
provider := settings.Unbound.Providers[0]
targetIP = provider.DoT().IPv4[0]
// Use first plaintext DNS IPv4 address
targetIP, err := settings.DoT.Unbound.GetFirstPlaintextIPv4()
if err != nil {
// Unbound should always have a default provider
panic(err)
}
if fallback {
l.logger.Info("falling back on plaintext DNS at address " + targetIP.String())
} else {
l.logger.Info("using plaintext DNS at address " + targetIP.String())
}
nameserver.UseDNSInternally(targetIP)
err := nameserver.UseDNSSystemWide(l.resolvConf, targetIP, settings.KeepNameserver)
err = nameserver.UseDNSSystemWide(l.resolvConf, targetIP, *settings.KeepNameserver)
if err != nil {
l.logger.Error(err.Error())
}

View File

@@ -31,7 +31,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
unboundCancel := func() { waitError <- nil }
closeStreams := func() {}
for l.GetSettings().Enabled {
for *l.GetSettings().DoT.Enabled {
var err error
unboundCancel, waitError, closeStreams, err = l.setupUnbound(ctx)
if err == nil {
@@ -54,7 +54,7 @@ func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
l.logAndWait(ctx, err)
}
if !l.GetSettings().Enabled {
if !*l.GetSettings().DoT.Enabled {
const fallback = false
l.useUnencryptedDNS(fallback)
}

View File

@@ -3,7 +3,7 @@ package dns
import (
"context"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
)
type SettingsGetSetter interface {
@@ -12,17 +12,17 @@ type SettingsGetSetter interface {
}
type SettingsGetter interface {
GetSettings() (settings configuration.DNS)
GetSettings() (settings settings.DNS)
}
func (l *Loop) GetSettings() (settings configuration.DNS) { return l.state.GetSettings() }
func (l *Loop) GetSettings() (settings settings.DNS) { return l.state.GetSettings() }
type SettingsSetter interface {
SetSettings(ctx context.Context, settings configuration.DNS) (
SetSettings(ctx context.Context, settings settings.DNS) (
outcome string)
}
func (l *Loop) SetSettings(ctx context.Context, settings configuration.DNS) (
func (l *Loop) SetSettings(ctx context.Context, settings settings.DNS) (
outcome string) {
return l.state.SetSettings(ctx, settings)
}

View File

@@ -26,7 +26,8 @@ func (l *Loop) setupUnbound(ctx context.Context) (
settings := l.GetSettings()
unboundCtx, cancel := context.WithCancel(context.Background())
stdoutLines, stderrLines, waitError, err := l.conf.Start(unboundCtx, settings.Unbound.VerbosityDetailsLevel)
stdoutLines, stderrLines, waitError, err := l.conf.Start(unboundCtx,
*settings.DoT.Unbound.VerbosityDetailsLevel)
if err != nil {
cancel()
return nil, nil, nil, err
@@ -42,9 +43,9 @@ func (l *Loop) setupUnbound(ctx context.Context) (
}
// use Unbound
nameserver.UseDNSInternally(net.IP{127, 0, 0, 1})
err = nameserver.UseDNSSystemWide(l.resolvConf, net.IP{127, 0, 0, 1},
settings.KeepNameserver)
nameserver.UseDNSInternally(settings.ServerAddress)
err = nameserver.UseDNSSystemWide(l.resolvConf, settings.ServerAddress,
*settings.KeepNameserver)
if err != nil {
l.logger.Error(err.Error())
}

View File

@@ -4,23 +4,23 @@ import (
"context"
"reflect"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
)
type SettingsGetSetter interface {
GetSettings() (settings configuration.DNS)
GetSettings() (settings settings.DNS)
SetSettings(ctx context.Context,
settings configuration.DNS) (outcome string)
settings settings.DNS) (outcome string)
}
func (s *State) GetSettings() (settings configuration.DNS) {
func (s *State) GetSettings() (settings settings.DNS) {
s.settingsMu.RLock()
defer s.settingsMu.RUnlock()
return s.settings
}
func (s *State) SetSettings(ctx context.Context, settings configuration.DNS) (
func (s *State) SetSettings(ctx context.Context, settings settings.DNS) (
outcome string) {
s.settingsMu.Lock()
@@ -31,8 +31,8 @@ func (s *State) SetSettings(ctx context.Context, settings configuration.DNS) (
}
// Check for only update period change
tempSettings := s.settings
tempSettings.UpdatePeriod = settings.UpdatePeriod
tempSettings := s.settings.Copy()
*tempSettings.DoT.UpdatePeriod = *settings.DoT.UpdatePeriod
onlyUpdatePeriodChanged := reflect.DeepEqual(tempSettings, settings)
s.settings = settings
@@ -45,7 +45,7 @@ func (s *State) SetSettings(ctx context.Context, settings configuration.DNS) (
// Restart
_, _ = s.statusApplier.ApplyStatus(ctx, constants.Stopped)
if settings.Enabled {
if *settings.DoT.Enabled {
outcome, _ = s.statusApplier.ApplyStatus(ctx, constants.Running)
}
return outcome

View File

@@ -3,7 +3,7 @@ package state
import (
"sync"
"github.com/qdm12/gluetun/internal/configuration"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/loopstate"
)
@@ -14,7 +14,7 @@ type Manager interface {
}
func New(statusApplier loopstate.Applier,
settings configuration.DNS,
settings settings.DNS,
updateTicker chan<- struct{}) *State {
return &State{
statusApplier: statusApplier,
@@ -26,7 +26,7 @@ func New(statusApplier loopstate.Applier,
type State struct {
statusApplier loopstate.Applier
settings configuration.DNS
settings settings.DNS
settingsMu sync.RWMutex
updateTicker chan<- struct{}

View File

@@ -18,8 +18,8 @@ func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) {
timer.Stop()
timerIsStopped := true
settings := l.GetSettings()
if settings.UpdatePeriod > 0 {
timer.Reset(settings.UpdatePeriod)
if period := *settings.DoT.UpdatePeriod; period > 0 {
timer.Reset(period)
timerIsStopped = false
}
lastTick := time.Unix(0, 0)
@@ -47,14 +47,14 @@ func (l *Loop) RunRestartTicker(ctx context.Context, done chan<- struct{}) {
_, _ = l.statusManager.ApplyStatus(ctx, constants.Running)
settings := l.GetSettings()
timer.Reset(settings.UpdatePeriod)
timer.Reset(*settings.DoT.UpdatePeriod)
case <-l.updateTicker:
if !timer.Stop() {
<-timer.C
}
timerIsStopped = true
settings := l.GetSettings()
newUpdatePeriod := settings.UpdatePeriod
newUpdatePeriod := *settings.DoT.UpdatePeriod
if newUpdatePeriod == 0 {
continue
}

View File

@@ -9,17 +9,27 @@ func (l *Loop) updateFiles(ctx context.Context) (err error) {
}
settings := l.GetSettings()
unboundSettings, err := settings.DoT.Unbound.ToUnboundFormat()
if err != nil {
return err
}
l.logger.Info("downloading hostnames and IP block lists")
blockedHostnames, blockedIPs, blockedIPPrefixes, errs := l.blockBuilder.All(
ctx, settings.BlacklistBuild)
blacklistSettings, err := settings.DoT.Blacklist.ToBlacklistFormat()
if err != nil {
return err
}
blockedHostnames, blockedIPs, blockedIPPrefixes, errs :=
l.blockBuilder.All(ctx, blacklistSettings)
for _, err := range errs {
l.logger.Warn(err.Error())
}
// TODO change to BlockHostnames() when migrating to qdm12/dns v2
settings.Unbound.Blacklist.FqdnHostnames = blockedHostnames
settings.Unbound.Blacklist.IPs = blockedIPs
settings.Unbound.Blacklist.IPPrefixes = blockedIPPrefixes
unboundSettings.Blacklist.FqdnHostnames = blockedHostnames
unboundSettings.Blacklist.IPs = blockedIPs
unboundSettings.Blacklist.IPPrefixes = blockedIPPrefixes
return l.conf.MakeUnboundConf(settings.Unbound)
return l.conf.MakeUnboundConf(unboundSettings)
}