Skip to content

Commit

Permalink
feat: add MIDDLEWARE_LOCALDNS_RESOLVERS
Browse files Browse the repository at this point in the history
  • Loading branch information
qdm12 committed Nov 26, 2023
1 parent 131e42c commit 95ae9e8
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 29 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ ENV \
MIDDLEWARE_LOG_DIRECTORY=/var/log/dns/ \
MIDDLEWARE_LOG_REQUESTS=on \
MIDDLEWARE_LOG_RESPONSES=off \
MIDDLEWARE_LOCALDNS_RESOLVERS= \
CACHE_TYPE=lru \
CACHE_LRU_MAX_ENTRIES=10000 \
BLOCK_MALICIOUS=on \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ If you're running Kubernetes, there is a separate article on [how to set up K8s]
| `METRICS_TYPE` | `noop` | `noop` or `prometheus` |
| `METRICS_PROMETHEUS_ADDRESS` | `:9090` | HTTP Prometheus server listening address |
| `METRICS_PROMETHEUS_SUBSYSTEM` | `dns` | Prometheus metrics prefix/subsystem |
| `MIDDLEWARE_LOCALDNS_RESOLVERS` | | Comma separated list of local DNS resolvers to use for local names DNS requests |
| `CHECK_DNS` | `on` | `on` or `off`. Check resolving github.com using `127.0.0.1:53` at start |
| `UPDATE_PERIOD` | `24h` | Period to update block lists and restart Unbound. Set to `0` to disable. |
Expand Down
60 changes: 60 additions & 0 deletions internal/config/localdns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package config

import (
"errors"
"fmt"
"net/netip"

"github.com/qdm12/gosettings/reader"
"github.com/qdm12/gotree"
)

type LocalDNS struct {
Resolvers []netip.AddrPort
}

var (
ErrLocalResolverAddressNotValid = errors.New("local resolver address is not valid")
ErrLocalResolverPortIsZero = errors.New("local resolver port is zero")
)

func (l *LocalDNS) validate() (err error) {
for _, resolver := range l.Resolvers {
switch {
case !resolver.IsValid():
return fmt.Errorf("%w: %s",
ErrLocalResolverAddressNotValid, resolver)
case resolver.Port() == 0:
return fmt.Errorf("%w: %s",
ErrLocalResolverPortIsZero, resolver)
}
}

return nil
}

func (l *LocalDNS) String() string {
return l.ToLinesNode().String()
}

func (l *LocalDNS) ToLinesNode() (node *gotree.Node) {
if len(l.Resolvers) == 0 {
return gotree.New("Local DNS middleware: disabled")
}

node = gotree.New("Local DNS middleware:")
resolversNode := gotree.New("Local resolvers:")
for _, resolver := range l.Resolvers {
resolversNode.Appendf("%s", resolver)
}
node.AppendNode(resolversNode)
return node
}

func (l *LocalDNS) read(reader *reader.Reader) (err error) {
l.Resolvers, err = reader.CSVNetipAddrPorts("MIDDLEWARE_LOCALDNS_RESOLVERS")
if err != nil {
return err
}
return nil
}
8 changes: 8 additions & 0 deletions internal/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Settings struct {
Log Log
MiddlewareLog MiddlewareLog
Metrics Metrics
LocalDNS LocalDNS
CheckDNS *bool
UpdatePeriod *time.Duration
}
Expand Down Expand Up @@ -74,6 +75,7 @@ func (s *Settings) Validate() (err error) {
"log": s.Log.validate,
"middleware log": s.MiddlewareLog.validate,
"metrics": s.Metrics.validate,
"local DNS": s.LocalDNS.validate,
}
for name, validate := range nameToValidate {
err = validate()
Expand Down Expand Up @@ -115,6 +117,7 @@ func (s *Settings) ToLinesNode() (node *gotree.Node) {
node.AppendNode(s.Log.ToLinesNode())
node.AppendNode(s.MiddlewareLog.ToLinesNode())
node.AppendNode(s.Metrics.ToLinesNode())
node.AppendNode(s.LocalDNS.ToLinesNode())
node.Appendf("Check DNS: %s", gosettings.BoolToYesNo(s.CheckDNS))

if *s.UpdatePeriod == 0 {
Expand Down Expand Up @@ -164,6 +167,11 @@ func (s *Settings) Read(reader *reader.Reader, warner Warner) (err error) {

s.Metrics.read(reader)

err = s.LocalDNS.read(reader)
if err != nil {
return fmt.Errorf("local DNS settings: %w", err)
}

s.CheckDNS, err = reader.BoolPtr("CHECK_DNS")
if err != nil {
return err
Expand Down
80 changes: 51 additions & 29 deletions internal/setup/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/qdm12/dns/v2/pkg/metrics/prometheus"
cachemiddleware "github.com/qdm12/dns/v2/pkg/middlewares/cache"
filtermiddleware "github.com/qdm12/dns/v2/pkg/middlewares/filter"
"github.com/qdm12/dns/v2/pkg/middlewares/localdns"
)

type Service interface {
Expand All @@ -18,14 +19,61 @@ type Service interface {
func DNS(userSettings config.Settings, ipv6Support bool, //nolint:ireturn
cache Cache, filter Filter, logger Logger, promRegistry PrometheusRegistry) (
server Service, err error) {
var middlewares []Middleware
commonPrometheus := prometheus.Settings{
Prefix: *userSettings.Metrics.Prometheus.Subsystem,
Registry: promRegistry,
}

middlewares, err := setupMiddlewares(userSettings, cache,
filter, logger, commonPrometheus)
if err != nil {
return nil, fmt.Errorf("setting up middlewares: %w", err)
}

switch userSettings.Upstream {
case "dot":
dotMetrics, err := dotMetrics(userSettings.Metrics.Type, commonPrometheus)
if err != nil {
return nil, fmt.Errorf("DoT metrics: %w", err)
}

return dotServer(userSettings, ipv6Support, middlewares,
logger, dotMetrics)
case "doh":
dohMetrics, err := dohMetrics(userSettings.Metrics.Type, commonPrometheus)
if err != nil {
return nil, fmt.Errorf("DoH metrics: %w", err)
}

return dohServer(userSettings, ipv6Support, middlewares,
logger, dohMetrics)
default:
panic(fmt.Sprintf("unknown upstream: %s", userSettings.Upstream))
}
}

func setupMiddlewares(userSettings config.Settings, cache Cache,
filter Filter, logger Logger, commonPrometheus prometheus.Settings) (
middlewares []Middleware, err error) {
cacheMiddleware, err := cachemiddleware.New(cachemiddleware.Settings{Cache: cache})
if err != nil {
return nil, fmt.Errorf("creating cache middleware: %w", err)
}
middlewares = append(middlewares, cacheMiddleware)

if len(userSettings.LocalDNS.Resolvers) > 0 {
localDNSMiddleware, err := localdns.New(localdns.Settings{
Resolvers: userSettings.LocalDNS.Resolvers,
Logger: logger,
})
if err != nil {
return nil, fmt.Errorf("creating local DNS middleware: %w", err)
}
// Place after cache middleware, since we want to avoid caching for local
// hostnames that may change regularly.
middlewares = append(middlewares, localDNSMiddleware)
}

filterMiddleware, err := filtermiddleware.New(filtermiddleware.Settings{Filter: filter})
if err != nil {
return nil, fmt.Errorf("creating filter middleware: %w", err)
Expand All @@ -34,14 +82,7 @@ func DNS(userSettings config.Settings, ipv6Support bool, //nolint:ireturn
// to catch filtered responses found from the cache.
middlewares = append(middlewares, filterMiddleware)

commonPrometheus := prometheus.Settings{
Prefix: *userSettings.Metrics.Prometheus.Subsystem,
Registry: promRegistry,
}

metricsType := userSettings.Metrics.Type

metricsMiddleware, err := middlewareMetrics(metricsType,
metricsMiddleware, err := middlewareMetrics(userSettings.Metrics.Type,
commonPrometheus)
if err != nil {
return nil, fmt.Errorf("middleware metrics: %w", err)
Expand All @@ -58,24 +99,5 @@ func DNS(userSettings config.Settings, ipv6Support bool, //nolint:ireturn
}
middlewares = append(middlewares, logMiddleware)

switch userSettings.Upstream {
case "dot":
dotMetrics, err := dotMetrics(metricsType, commonPrometheus)
if err != nil {
return nil, fmt.Errorf("DoT metrics: %w", err)
}

return dotServer(userSettings, ipv6Support, middlewares,
logger, dotMetrics)
case "doh":
dohMetrics, err := dohMetrics(metricsType, commonPrometheus)
if err != nil {
return nil, fmt.Errorf("DoH metrics: %w", err)
}

return dohServer(userSettings, ipv6Support, middlewares,
logger, dohMetrics)
default:
panic(fmt.Sprintf("unknown upstream: %s", userSettings.Upstream))
}
return middlewares, nil
}

0 comments on commit 95ae9e8

Please sign in to comment.