mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-12-18 21:11:50 +03:00
c0a33ce708
Squashed commit of the following: commit 463811748fa5a1f52e084c782e94f268b00b3abc Merge: 3de62244e130560b10
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Jul 10 15:06:01 2024 +0300 Merge remote-tracking branch 'origin/master' into upd-dnsproxy commit 3de62244ee10fce9fb97c73c2955479883ce34eb Merge: e2de50bf9e269260fb
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Jul 10 09:13:40 2024 +0300 Merge remote-tracking branch 'origin/master' into upd-dnsproxy commit e2de50bf9cf4eddaa0d87c20c8c1605bf4630fce Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Jul 10 09:11:25 2024 +0300 home: todos commit58fe497eec
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Jul 9 13:29:19 2024 +0300 home: imp code commit4db7cdc0c4
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Jul 9 11:31:12 2024 +0300 all: imp code commit7e8d3b50e7
Merge:559c3b79d
9a6dd0dc5
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Jul 8 10:56:14 2024 +0300 Merge remote-tracking branch 'origin/master' into upd-dnsproxy commit559c3b79d7
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Jul 8 10:54:03 2024 +0300 dnsforward: imp code commitba4a7e1c70
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Jul 8 10:49:46 2024 +0300 aghos: imp code commitcdf9ccd371
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Jul 5 16:19:27 2024 +0300 all: partial revert slog logger usage commitf16cddbb8c
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Jul 5 13:01:37 2024 +0300 all: upd dnsproxy commit5932c8d102
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Jul 5 11:49:37 2024 +0300 dnsforward: slog logger commit3d7f734ac9
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Jul 5 11:05:14 2024 +0300 all: slog logger commit9a74d5d98b
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Jul 4 12:16:21 2024 +0300 all: upd dnsproxy commit537bdacec8
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Jul 4 12:10:30 2024 +0300 all: upd dnsproxy commit38e10dee48
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Jul 4 10:37:50 2024 +0300 dnsforward: upstream mode
171 lines
5.1 KiB
Go
171 lines
5.1 KiB
Go
package dnsforward
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"time"
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
|
"github.com/AdguardTeam/golibs/log"
|
|
"github.com/AdguardTeam/golibs/netutil"
|
|
"github.com/AdguardTeam/golibs/stringutil"
|
|
)
|
|
|
|
// newBootstrap returns a bootstrap resolver based on the configuration of s.
|
|
// boots are the upstream resolvers that should be closed after use. r is the
|
|
// actual bootstrap resolver, which may include the system hosts.
|
|
//
|
|
// TODO(e.burkov): This function currently returns a resolver and a slice of
|
|
// the upstream resolvers, which are essentially the same. boots are returned
|
|
// for being able to close them afterwards, but it introduces an implicit
|
|
// contract that r could only be used before that. Anyway, this code should
|
|
// improve when the [proxy.UpstreamConfig] will become an [upstream.Resolver]
|
|
// and be used here.
|
|
func newBootstrap(
|
|
addrs []string,
|
|
etcHosts upstream.Resolver,
|
|
opts *upstream.Options,
|
|
) (r upstream.Resolver, boots []*upstream.UpstreamResolver, err error) {
|
|
if len(addrs) == 0 {
|
|
addrs = defaultBootstrap
|
|
}
|
|
|
|
boots, err = aghnet.ParseBootstraps(addrs, opts)
|
|
if err != nil {
|
|
// Don't wrap the error, since it's informative enough as is.
|
|
return nil, nil, err
|
|
}
|
|
|
|
var parallel upstream.ParallelResolver
|
|
for _, b := range boots {
|
|
parallel = append(parallel, upstream.NewCachingResolver(b))
|
|
}
|
|
|
|
if etcHosts != nil {
|
|
r = upstream.ConsequentResolver{etcHosts, parallel}
|
|
} else {
|
|
r = parallel
|
|
}
|
|
|
|
return r, boots, nil
|
|
}
|
|
|
|
// newUpstreamConfig returns the upstream configuration based on upstreams. If
|
|
// upstreams slice specifies no default upstreams, defaultUpstreams are used to
|
|
// create upstreams with no domain specifications. opts are used when creating
|
|
// upstream configuration.
|
|
func newUpstreamConfig(
|
|
upstreams []string,
|
|
defaultUpstreams []string,
|
|
opts *upstream.Options,
|
|
) (uc *proxy.UpstreamConfig, err error) {
|
|
uc, err = proxy.ParseUpstreamsConfig(upstreams, opts)
|
|
if err != nil {
|
|
return uc, fmt.Errorf("parsing upstreams: %w", err)
|
|
}
|
|
|
|
if len(uc.Upstreams) == 0 && len(defaultUpstreams) > 0 {
|
|
log.Info("dnsforward: warning: no default upstreams specified, using %v", defaultUpstreams)
|
|
|
|
var defaultUpstreamConfig *proxy.UpstreamConfig
|
|
defaultUpstreamConfig, err = proxy.ParseUpstreamsConfig(defaultUpstreams, opts)
|
|
if err != nil {
|
|
return uc, fmt.Errorf("parsing default upstreams: %w", err)
|
|
}
|
|
|
|
uc.Upstreams = defaultUpstreamConfig.Upstreams
|
|
}
|
|
|
|
return uc, nil
|
|
}
|
|
|
|
// newPrivateConfig creates an upstream configuration for resolving PTR records
|
|
// for local addresses. The configuration is built either from the provided
|
|
// addresses or from the system resolvers. unwanted filters the resulting
|
|
// upstream configuration.
|
|
func newPrivateConfig(
|
|
addrs []string,
|
|
unwanted addrPortSet,
|
|
sysResolvers SystemResolvers,
|
|
privateNets netutil.SubnetSet,
|
|
opts *upstream.Options,
|
|
) (uc *proxy.UpstreamConfig, err error) {
|
|
confNeedsFiltering := len(addrs) > 0
|
|
if confNeedsFiltering {
|
|
addrs = stringutil.FilterOut(addrs, IsCommentOrEmpty)
|
|
} else {
|
|
sysResolvers := slices.DeleteFunc(slices.Clone(sysResolvers.Addrs()), unwanted.Has)
|
|
addrs = make([]string, 0, len(sysResolvers))
|
|
for _, r := range sysResolvers {
|
|
addrs = append(addrs, r.String())
|
|
}
|
|
}
|
|
|
|
log.Debug("dnsforward: private-use upstreams: %v", addrs)
|
|
|
|
uc, err = proxy.ParseUpstreamsConfig(addrs, opts)
|
|
if err != nil {
|
|
return uc, fmt.Errorf("preparing private upstreams: %w", err)
|
|
}
|
|
|
|
if confNeedsFiltering {
|
|
err = filterOutAddrs(uc, unwanted)
|
|
if err != nil {
|
|
return uc, fmt.Errorf("filtering private upstreams: %w", err)
|
|
}
|
|
}
|
|
|
|
// Prevalidate the config to catch the exact error before creating proxy.
|
|
// See TODO on [PrivateRDNSError].
|
|
err = proxy.ValidatePrivateConfig(uc, privateNets)
|
|
if err != nil {
|
|
return uc, &PrivateRDNSError{err: err}
|
|
}
|
|
|
|
return uc, nil
|
|
}
|
|
|
|
// UpstreamHTTPVersions returns the HTTP versions for upstream configuration
|
|
// depending on configuration.
|
|
func UpstreamHTTPVersions(http3 bool) (v []upstream.HTTPVersion) {
|
|
if !http3 {
|
|
return upstream.DefaultHTTPVersions
|
|
}
|
|
|
|
return []upstream.HTTPVersion{
|
|
upstream.HTTPVersion3,
|
|
upstream.HTTPVersion2,
|
|
upstream.HTTPVersion11,
|
|
}
|
|
}
|
|
|
|
// setProxyUpstreamMode sets the upstream mode and related settings in conf
|
|
// based on provided parameters.
|
|
func setProxyUpstreamMode(
|
|
conf *proxy.Config,
|
|
upstreamMode UpstreamMode,
|
|
fastestTimeout time.Duration,
|
|
) (err error) {
|
|
switch upstreamMode {
|
|
case UpstreamModeParallel:
|
|
conf.UpstreamMode = proxy.UpstreamModeParallel
|
|
case UpstreamModeFastestAddr:
|
|
conf.UpstreamMode = proxy.UpstreamModeFastestAddr
|
|
conf.FastestPingTimeout = fastestTimeout
|
|
case UpstreamModeLoadBalance:
|
|
conf.UpstreamMode = proxy.UpstreamModeLoadBalance
|
|
default:
|
|
return fmt.Errorf("unexpected value %q", upstreamMode)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsCommentOrEmpty returns true if s starts with a "#" character or is empty.
|
|
// This function is useful for filtering out non-upstream lines from upstream
|
|
// configs.
|
|
func IsCommentOrEmpty(s string) (ok bool) {
|
|
return len(s) == 0 || s[0] == '#'
|
|
}
|