Pull request 2021: upd golibs
Merge in DNS/adguard-home from upd-golibs to master
Squashed commit of the following:
commit 266b002c5450329761dee21d918c80d08e5d8ab9
Merge: 99eb7745d e305bd8e4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Thu Oct 5 14:21:51 2023 +0300
Merge branch 'master' into upd-golibs
commit 99eb7745d0bee190399f9b16cb7151f34a591b54
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Thu Oct 5 14:14:28 2023 +0300
home: imp alignment
commit 556cde56720ce449aec17b500825681fc8c084bf
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Thu Oct 5 13:35:35 2023 +0300
dnsforward: imp naming, docs
commit 1ee99655a3318263db1edbcb9e4eeb33bfe441c8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Thu Oct 5 13:28:39 2023 +0300
home: make ports uint16
commit b228032ea1f5902ab9bac7b5d55d84aaf6354616
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Wed Oct 4 18:56:59 2023 +0300
all: rm system resolvers
commit 4b5becbed5890db80612e53861f000aaf4c869ff
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date: Wed Oct 4 17:30:16 2023 +0300
all: upd golibs
This commit is contained in:
@@ -436,18 +436,18 @@ func (conf *ServerConfig) collectDNSAddrs() (
|
||||
// defaultPlainDNSPort is the default port for plain DNS.
|
||||
const defaultPlainDNSPort uint16 = 53
|
||||
|
||||
// upstreamMatcher is a function that matches address of an upstream.
|
||||
type upstreamMatcher func(addr netip.AddrPort) (ok bool)
|
||||
// addrPortMatcher is a function that matches an IP address with port.
|
||||
type addrPortMatcher func(addr netip.AddrPort) (ok bool)
|
||||
|
||||
// filterOut filters out all the upstreams that match um. It returns all the
|
||||
// closing errors joined.
|
||||
func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) {
|
||||
func (m addrPortMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) {
|
||||
var errs []error
|
||||
delFunc := func(u upstream.Upstream) (ok bool) {
|
||||
// TODO(e.burkov): We should probably consider the protocol of u to
|
||||
// only filter out the listening addresses of the same protocol.
|
||||
addr, parseErr := aghnet.ParseAddrPort(u.Address(), defaultPlainDNSPort)
|
||||
if parseErr != nil || !um(addr) {
|
||||
if parseErr != nil || !m(addr) {
|
||||
// Don't filter out the upstream if it either cannot be parsed, or
|
||||
// does not match um.
|
||||
return false
|
||||
@@ -469,23 +469,21 @@ func (um upstreamMatcher) filterOut(upsConf *proxy.UpstreamConfig) (err error) {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// filterOurAddrs filters out all the upstreams that pointing to the local
|
||||
// listening addresses to avoid recursive queries. upsConf may appear empty
|
||||
// after the filtering. All the filtered upstreams are closed and these
|
||||
// closings errors are joined.
|
||||
func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err error) {
|
||||
// ourAddrsMatcher returns a matcher that matches all the configured listening
|
||||
// addresses.
|
||||
func (conf *ServerConfig) ourAddrsMatcher() (m addrPortMatcher, err error) {
|
||||
addrs, unspecPorts := conf.collectDNSAddrs()
|
||||
if len(addrs) == 0 {
|
||||
log.Debug("dnsforward: no listen addresses")
|
||||
|
||||
return nil
|
||||
// Match no addresses.
|
||||
return func(_ netip.AddrPort) (ok bool) { return false }, nil
|
||||
}
|
||||
|
||||
var matcher upstreamMatcher
|
||||
if len(unspecPorts) == 0 {
|
||||
log.Debug("dnsforward: filtering out addresses %s", addrs)
|
||||
|
||||
matcher = func(a netip.AddrPort) (ok bool) {
|
||||
m = func(a netip.AddrPort) (ok bool) {
|
||||
_, ok = addrs[a]
|
||||
|
||||
return ok
|
||||
@@ -495,12 +493,12 @@ func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err err
|
||||
ifaceAddrs, err = aghnet.CollectAllIfacesAddrs()
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debug("dnsforward: filtering out addresses %s on ports %d", ifaceAddrs, unspecPorts)
|
||||
|
||||
matcher = func(a netip.AddrPort) (ok bool) {
|
||||
m = func(a netip.AddrPort) (ok bool) {
|
||||
if _, ok = unspecPorts[a.Port()]; ok {
|
||||
return slices.Contains(ifaceAddrs, a.Addr())
|
||||
}
|
||||
@@ -509,7 +507,7 @@ func (conf *ServerConfig) filterOurAddrs(upsConf *proxy.UpstreamConfig) (err err
|
||||
}
|
||||
}
|
||||
|
||||
return matcher.filterOut(upsConf)
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// prepareTLS - prepares TLS configuration for the DNS proxy
|
||||
|
||||
@@ -25,8 +25,10 @@ import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/netutil/sysresolv"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// DefaultTimeout is the default upstream timeout
|
||||
@@ -72,6 +74,11 @@ type DHCP interface {
|
||||
Enabled() (ok bool)
|
||||
}
|
||||
|
||||
type SystemResolvers interface {
|
||||
// Addrs returns the list of system resolvers' addresses.
|
||||
Addrs() (addrs []netip.AddrPort)
|
||||
}
|
||||
|
||||
// Server is the main way to start a DNS server.
|
||||
//
|
||||
// Example:
|
||||
@@ -126,7 +133,7 @@ type Server struct {
|
||||
|
||||
// sysResolvers used to fetch system resolvers to use by default for private
|
||||
// PTR resolving.
|
||||
sysResolvers aghnet.SystemResolvers
|
||||
sysResolvers SystemResolvers
|
||||
|
||||
// recDetector is a cache for recursive requests. It is used to detect
|
||||
// and prevent recursive requests only for private upstreams.
|
||||
@@ -225,9 +232,7 @@ func NewServer(p DNSCreateParams) (s *Server, err error) {
|
||||
anonymizer: p.Anonymizer,
|
||||
}
|
||||
|
||||
// TODO(e.burkov): Enable the refresher after the actual implementation
|
||||
// passes the public testing.
|
||||
s.sysResolvers, err = aghnet.NewSystemResolvers(nil)
|
||||
s.sysResolvers, err = sysresolv.NewSystemResolvers(nil, defaultPlainDNSPort)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("initializing system resolvers: %w", err)
|
||||
}
|
||||
@@ -442,19 +447,30 @@ const defaultLocalTimeout = 1 * time.Second
|
||||
// setupLocalResolvers initializes the resolvers for local addresses. For
|
||||
// internal use only.
|
||||
func (s *Server) setupLocalResolvers() (err error) {
|
||||
matcher, err := s.conf.ourAddrsMatcher()
|
||||
if err != nil {
|
||||
// Don't wrap the error because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
bootstraps := s.conf.BootstrapDNS
|
||||
resolvers := s.conf.LocalPTRResolvers
|
||||
filterConfig := false
|
||||
|
||||
if len(resolvers) == 0 {
|
||||
resolvers = s.sysResolvers.Get()
|
||||
bootstraps = nil
|
||||
sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher)
|
||||
resolvers = make([]string, 0, len(sysResolvers))
|
||||
for _, r := range sysResolvers {
|
||||
resolvers = append(resolvers, r.String())
|
||||
}
|
||||
} else {
|
||||
resolvers = stringutil.FilterOut(resolvers, IsCommentOrEmpty)
|
||||
filterConfig = true
|
||||
}
|
||||
|
||||
log.Debug("dnsforward: upstreams to resolve ptr for local addresses: %v", resolvers)
|
||||
|
||||
uc, err := s.prepareLocalUpstreamConfig(resolvers, nil, &upstream.Options{
|
||||
uc, err := s.prepareUpstreamConfig(resolvers, nil, &upstream.Options{
|
||||
Bootstrap: bootstraps,
|
||||
Timeout: defaultLocalTimeout,
|
||||
// TODO(e.burkov): Should we verify server's certificates?
|
||||
@@ -464,6 +480,12 @@ func (s *Server) setupLocalResolvers() (err error) {
|
||||
return fmt.Errorf("preparing private upstreams: %w", err)
|
||||
}
|
||||
|
||||
if filterConfig {
|
||||
if err = matcher.filterOut(uc); err != nil {
|
||||
return fmt.Errorf("filtering private upstreams: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
s.localResolvers = &proxy.Proxy{
|
||||
Config: proxy.Config{
|
||||
UpstreamConfig: uc,
|
||||
|
||||
@@ -179,17 +179,16 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) {
|
||||
// defaultLocalPTRUpstreams returns the list of default local PTR resolvers
|
||||
// filtered of AdGuard Home's own DNS server addresses. It may appear empty.
|
||||
func (s *Server) defaultLocalPTRUpstreams() (ups []string, err error) {
|
||||
s.serverLock.RLock()
|
||||
defer s.serverLock.RUnlock()
|
||||
|
||||
uc, err := s.prepareLocalUpstreamConfig(s.sysResolvers.Get(), nil, nil)
|
||||
matcher, err := s.conf.ourAddrsMatcher()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting system upstream config: %w", err)
|
||||
// Don't wrap the error because it's informative enough as is.
|
||||
return nil, err
|
||||
}
|
||||
defer func() { err = errors.Join(err, uc.Close()) }()
|
||||
|
||||
for _, u := range uc.Upstreams {
|
||||
ups = append(ups, u.Address())
|
||||
sysResolvers := slices.DeleteFunc(s.sysResolvers.Addrs(), matcher)
|
||||
ups = make([]string, 0, len(sysResolvers))
|
||||
for _, r := range sysResolvers {
|
||||
ups = append(ups, r.String())
|
||||
}
|
||||
|
||||
return ups, nil
|
||||
@@ -228,7 +227,7 @@ func (req *jsonDNSConfig) checkBootstrap() (err error) {
|
||||
return errors.Error("empty")
|
||||
}
|
||||
|
||||
if _, err = upstream.NewResolver(b, nil); err != nil {
|
||||
if _, err = upstream.NewUpstreamResolver(b, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,17 +28,12 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// fakeSystemResolvers is a mock aghnet.SystemResolvers implementation for
|
||||
// tests.
|
||||
type fakeSystemResolvers struct {
|
||||
// SystemResolvers is embedded here simply to make *fakeSystemResolvers
|
||||
// an aghnet.SystemResolvers without actually implementing all methods.
|
||||
aghnet.SystemResolvers
|
||||
}
|
||||
// emptySysResolvers is an empty [SystemResolvers] implementation that always
|
||||
// returns nil.
|
||||
type emptySysResolvers struct{}
|
||||
|
||||
// Get implements the aghnet.SystemResolvers interface for *fakeSystemResolvers.
|
||||
// It always returns nil.
|
||||
func (fsr *fakeSystemResolvers) Get() (rs []string) {
|
||||
// Addrs implements the aghnet.SystemResolvers interface for emptySysResolvers.
|
||||
func (emptySysResolvers) Addrs() (addrs []netip.AddrPort) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -79,7 +74,7 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
||||
ConfigModified: func() {},
|
||||
}
|
||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||
s.sysResolvers = &fakeSystemResolvers{}
|
||||
s.sysResolvers = &emptySysResolvers{}
|
||||
|
||||
require.NoError(t, s.Start())
|
||||
testutil.CleanupAndRequireSuccess(t, s.Stop)
|
||||
@@ -156,7 +151,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||
ConfigModified: func() {},
|
||||
}
|
||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||
s.sysResolvers = &fakeSystemResolvers{}
|
||||
s.sysResolvers = &emptySysResolvers{}
|
||||
|
||||
defaultConf := s.conf
|
||||
|
||||
@@ -485,7 +480,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) {
|
||||
hostsListener := newLocalUpstreamListener(t, 0, goodHandler)
|
||||
hostsUps := (&url.URL{
|
||||
Scheme: "tcp",
|
||||
Host: netutil.JoinHostPort(upstreamHost, int(hostsListener.Port())),
|
||||
Host: netutil.JoinHostPort(upstreamHost, hostsListener.Port()),
|
||||
}).String()
|
||||
|
||||
hc, err := aghnet.NewHostsContainer(
|
||||
|
||||
@@ -103,27 +103,6 @@ func (s *Server) prepareUpstreamConfig(
|
||||
return uc, nil
|
||||
}
|
||||
|
||||
// prepareLocalUpstreamConfig returns the upstream configuration for private
|
||||
// upstreams based on upstreams and configuration of s. It also filters out
|
||||
// the own listening addresses from the upstreams, so it may appear empty.
|
||||
func (s *Server) prepareLocalUpstreamConfig(
|
||||
upstreams []string,
|
||||
defaultUpstreams []string,
|
||||
opts *upstream.Options,
|
||||
) (uc *proxy.UpstreamConfig, err error) {
|
||||
uc, err = s.prepareUpstreamConfig(upstreams, defaultUpstreams, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("preparing private upstreams: %w", err)
|
||||
}
|
||||
|
||||
err = s.conf.filterOurAddrs(uc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("filtering private upstreams: %w", err)
|
||||
}
|
||||
|
||||
return uc, nil
|
||||
}
|
||||
|
||||
// replaceUpstreamsWithHosts replaces unique upstreams with their resolved
|
||||
// versions based on the system hosts file.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user