Files
gluetun/internal/dns/run.go
T
Quentin McGaw 4ea2337668 feat(dns): re-introduce DNS_SERVER option
- force to set `DNS_UPSTREAM_RESOLVER_TYPE=plain` to avoid any confusion/security hole
- force to set `DNS_UPSTREAM_PLAIN_ADDRESSES` to addresses only with port 53
2026-05-05 21:15:28 +00:00

113 lines
2.5 KiB
Go

package dns
import (
"context"
"github.com/qdm12/dns/v2/pkg/nameserver"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants"
)
func (l *Loop) Run(ctx context.Context, done chan<- struct{}) {
defer close(done)
var err error
l.localResolvers, err = nameserver.GetPrivateDNSServers()
if err != nil {
l.logger.Error("getting private DNS servers: " + err.Error())
return
}
select {
case <-l.start:
case <-ctx.Done():
return
}
for ctx.Err() == nil {
// Upper scope variables for the DNS forwarder server only
// Their values are to be used if DOT=off
var runError <-chan error
var settings settings.DNS
for {
settings = l.GetSettings()
var err error
if *settings.ServerEnabled { //nolint:nestif
runError, err = l.setupServer(ctx, settings)
if err == nil {
l.logger.Infof("ready and using DNS server with %s upstream resolvers", settings.UpstreamType)
err = l.updateFiles(ctx, settings)
if err != nil {
l.logger.Warn("downloading block lists failed, skipping: " + err.Error())
}
break
}
} else {
err = l.usePlainServers(settings.UpstreamPlainAddresses)
if err == nil {
l.logger.Infof("ready and using plain DNS resolvers: %v", settings.UpstreamPlainAddresses)
break
}
}
l.signalOrSetStatus(constants.Crashed)
if ctx.Err() != nil {
return
}
l.logAndWait(ctx, err)
}
l.backoffTime = defaultBackoffTime
l.signalOrSetStatus(constants.Running)
l.userTrigger = false
report, err := leakCheck(ctx, l.client)
if err != nil {
l.logger.Warnf("running leak check: %s", err)
} else {
l.logger.Infof("leak check report: %s", report)
}
exitLoop := l.runWait(ctx, runError)
if exitLoop {
return
}
}
}
func (l *Loop) runWait(ctx context.Context, runError <-chan error) (exitLoop bool) {
for {
select {
case <-ctx.Done():
l.stopServerIfAny()
// TODO revert OS and Go nameserver when exiting
return true
case <-l.stop:
l.userTrigger = true
l.logger.Info("stopping")
l.stopServerIfAny()
l.stopped <- struct{}{}
case <-l.start:
l.userTrigger = true
l.logger.Info("starting")
return false
case err := <-runError: // unexpected error
l.statusManager.SetStatus(constants.Crashed)
l.logAndWait(ctx, err)
return false
}
}
}
func (l *Loop) stopServerIfAny() {
if l.server == nil {
return
}
stopErr := l.server.Stop()
if stopErr != nil {
l.logger.Error("stopping server: " + stopErr.Error())
}
}