Skip to content

Commit

Permalink
Pull request: AG-33516-upstream-modes
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit 7ba8eb7
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Jul 3 16:00:12 2024 +0300

    main: imp code

commit e2b8ec5
Merge: 4c7c08c 55efb45
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Jul 3 13:03:36 2024 +0300

    Merge remote-tracking branch 'origin/master' into AG-33516-upstream-modes

commit 4c7c08c
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Jul 3 11:14:13 2024 +0300

    all: imp docs

commit a239d74
Author: Dimitry Kolyshev <[email protected]>
Date:   Wed Jul 3 11:14:03 2024 +0300

    proxy: imp code

commit d8bd87d
Author: Dimitry Kolyshev <[email protected]>
Date:   Fri Jun 28 11:48:52 2024 +0300

    main: upstream mode

commit afd8043
Author: Dimitry Kolyshev <[email protected]>
Date:   Fri Jun 28 08:11:45 2024 +0300

    proxy: upstream mode

commit fca53d2
Author: Dimitry Kolyshev <[email protected]>
Date:   Thu Jun 27 10:15:58 2024 +0300

    proxy: upstream mode
  • Loading branch information
Mizzick committed Jul 3, 2024
1 parent 55efb45 commit 2847564
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 45 deletions.
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ Application Options:
--insecure Disable secure TLS certificate validation
--ipv6-disabled If specified, all AAAA requests will be replied with NoError RCode and empty answer
--http3 Enable HTTP/3 support
--all-servers If specified, parallel queries to all configured upstream servers are enabled
--fastest-addr Respond to A or AAAA requests only with the fastest IP address
--upstream-mode If specified, determines the upstream usage logic.
--cache-optimistic If specified, optimistic DNS cache is enabled
--cache If specified, DNS cache is enabled
--refuse-any If specified, refuse ANY requests
Expand Down Expand Up @@ -267,17 +266,19 @@ specified and enabled if DNS64 is enabled.
### Fastest addr + cache-min-ttl
This option would be useful to the users with problematic network connection.
In this mode, `dnsproxy` would detect the fastest IP address among all that were returned,
and it will return only it.
In this mode, `dnsproxy` would detect the fastest IP address among all that were
returned, and it will return only it.
Additionally, for those with problematic network connection, it makes sense to override `cache-min-ttl`.
In this case, `dnsproxy` will make sure that DNS responses are cached for at least the specified amount of time.
Additionally, for those with problematic network connection, it makes sense to
override `cache-min-ttl`. In this case, `dnsproxy` will make sure that DNS
responses are cached for at least the specified amount of time.
It makes sense to run it with multiple upstream servers only.
Run a DNS proxy with two upstreams, min-TTL set to 10 minutes, fastest address detection is enabled:
Run a DNS proxy with two upstreams, min-TTL set to 10 minutes, fastest address
detection is enabled:
```
./dnsproxy -u 8.8.8.8 -u 1.1.1.1 --cache --cache-min-ttl=600 --fastest-addr
./dnsproxy -u 8.8.8.8 -u 1.1.1.1 --cache --cache-min-ttl=600 --upstream-mode=fastest_addr
```
who run `dnsproxy` with multiple upstreams
Expand Down
27 changes: 12 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type Options struct {
// EDNSAddr is the custom EDNS Client Address to send.
EDNSAddr string `yaml:"edns-addr" long:"edns-addr" description:"Send EDNS Client Address"`

// UpstreamMode determines the logic through which upstreams will be used.
UpstreamMode string `yaml:"upstream-mode" long:"upstream-mode" description:"" optional:"yes" optional-value:"load_balance"`

// ListenAddrs is the list of server's listen addresses.
ListenAddrs []string `yaml:"listen-addrs" short:"l" long:"listen" description:"Listening addresses"`

Expand Down Expand Up @@ -174,15 +177,6 @@ type Options struct {
// It enables HTTP/3 support for both the DoH upstreams and the DoH server.
HTTP3 bool `yaml:"http3" long:"http3" description:"Enable HTTP/3 support" optional:"yes" optional-value:"false"`

// AllServers makes server to query all configured upstream servers in
// parallel.
AllServers bool `yaml:"all-servers" long:"all-servers" description:"If specified, parallel queries to all configured upstream servers are enabled" optional:"yes" optional-value:"true"`

// FastestAddress controls whether the server should respond to A or AAAA
// requests only with the fastest IP address detected by ICMP response time
// or TCP connection time.
FastestAddress bool `yaml:"fastest-addr" long:"fastest-addr" description:"Respond to A or AAAA requests only with the fastest IP address" optional:"yes" optional-value:"true"`

// CacheOptimistic, if set to true, enables the optimistic DNS cache. That
// means that cached results will be served even if their cache TTL has
// already expired.
Expand Down Expand Up @@ -555,14 +549,17 @@ func (opts *Options) initUpstreams(
config.Fallbacks = fallbacks
}

if opts.AllServers {
config.UpstreamMode = proxy.UModeParallel
} else if opts.FastestAddress {
config.UpstreamMode = proxy.UModeFastestAddr
} else {
config.UpstreamMode = proxy.UModeLoadBalance
if opts.UpstreamMode != "" {
err = config.UpstreamMode.UnmarshalText([]byte(opts.UpstreamMode))
if err != nil {
return fmt.Errorf("parsing upstream mode: %w", err)
}

return nil
}

config.UpstreamMode = proxy.UpstreamModeLoadBalance

return nil
}

Expand Down
22 changes: 5 additions & 17 deletions proxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ import (
"github.com/ameshkov/dnscrypt/v2"
)

// UpstreamModeType - upstream mode
type UpstreamModeType int

const (
// UModeLoadBalance - LoadBalance
UModeLoadBalance UpstreamModeType = iota
// UModeParallel - parallel queries to all configured upstream servers are enabled
UModeParallel
// UModeFastestAddr - use Fastest Address algorithm
UModeFastestAddr
)

// LogPrefix is a prefix for logging.
const LogPrefix = "dnsproxy"

Expand Down Expand Up @@ -117,6 +105,9 @@ type Config struct {
// not empty.
HTTPSServerName string

// UpstreamMode determines the logic through which upstreams will be used.
UpstreamMode UpstreamMode

// UDPListenAddr is the set of UDP addresses to listen for plain
// DNS-over-UDP requests.
UDPListenAddr []*net.UDPAddr
Expand Down Expand Up @@ -195,12 +186,9 @@ type Config struct {
// buffers can handle larger bursts of requests before packets get dropped.
UDPBufferSize int

// UpstreamMode determines the logic through which upstreams will be used.
UpstreamMode UpstreamModeType

// FastestPingTimeout is the timeout for waiting the first successful
// dialing when the UpstreamMode is set to UModeFastestAddr. Non-positive
// value will be replaced with the default one.
// dialing when the UpstreamMode is set to [UpstreamModeFastestAddr].
// Non-positive value will be replaced with the default one.
FastestPingTimeout time.Duration

// RefuseAny makes proxy refuse the requests of type ANY.
Expand Down
4 changes: 2 additions & 2 deletions proxy/exchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ func (p *Proxy) exchangeUpstreams(
ups []upstream.Upstream,
) (resp *dns.Msg, u upstream.Upstream, err error) {
switch p.UpstreamMode {
case UModeParallel:
case UpstreamModeParallel:
return upstream.ExchangeParallel(ups, req)
case UModeFastestAddr:
case UpstreamModeFastestAddr:
switch req.Question[0].Qtype {
case dns.TypeA, dns.TypeAAAA:
return p.fastestAddr.ExchangeFastest(req, ups)
Expand Down
5 changes: 2 additions & 3 deletions proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,8 @@ func New(c *Config) (p *Proxy, err error) {
p.requestsSema = syncutil.EmptySemaphore{}
}

if p.UpstreamMode == UModeFastestAddr {
p.logger.Info("fastest ip is enabled")

p.logger.Info("upstream mode is set", "mode", p.UpstreamMode)
if p.UpstreamMode == UpstreamModeFastestAddr {
p.fastestAddr = fastip.New(&fastip.Config{
Logger: p.Logger,
PingWaitTimeout: p.FastestPingTimeout,
Expand Down
59 changes: 59 additions & 0 deletions proxy/upstreammode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package proxy

import (
"encoding"
"fmt"
)

// UpstreamMode is an enumeration of upstream mode representations.
//
// TODO(d.kolyshev): Set uint8 as underlying type.
type UpstreamMode string

const (
// UpstreamModeLoadBalance is the default upstream mode. It balances the
// upstreams load.
UpstreamModeLoadBalance UpstreamMode = "load_balance"

// UpstreamModeParallel makes server to query all configured upstream
// servers in parallel.
UpstreamModeParallel UpstreamMode = "parallel"

// UpstreamModeFastestAddr controls whether the server should respond to A
// or AAAA requests only with the fastest IP address detected by ICMP
// response time or TCP connection time.
UpstreamModeFastestAddr UpstreamMode = "fastest_addr"
)

// type check
var _ encoding.TextUnmarshaler = (*UpstreamMode)(nil)

// UnmarshalText implements [encoding.TextUnmarshaler] interface for
// *UpstreamMode.
func (m *UpstreamMode) UnmarshalText(b []byte) (err error) {
switch um := UpstreamMode(b); um {
case
UpstreamModeLoadBalance,
UpstreamModeParallel,
UpstreamModeFastestAddr:
*m = um
default:
return fmt.Errorf(
"invalid upstream mode %q, supported: %q, %q, %q",
b,
UpstreamModeLoadBalance,
UpstreamModeParallel,
UpstreamModeFastestAddr,
)
}

return nil
}

// type check
var _ encoding.TextMarshaler = UpstreamMode("")

// MarshalText implements [encoding.TextMarshaler] interface for UpstreamMode.
func (m UpstreamMode) MarshalText() (text []byte, err error) {
return []byte(m), nil
}
17 changes: 17 additions & 0 deletions proxy/upstreammode_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package proxy_test

import (
"testing"

"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/testutil"
)

func TestUpstreamMode_encoding(t *testing.T) {
t.Parallel()

v := proxy.UpstreamModeLoadBalance

testutil.AssertMarshalText(t, "load_balance", &v)
testutil.AssertUnmarshalText(t, "load_balance", &v)
}

0 comments on commit 2847564

Please sign in to comment.