Pull request 2431: next-fix-ups-logger

Merge in DNS/adguard-home from next-fix-ups-logger to master

Squashed commit of the following:

commit 94a0c3508cb16e1b4e7f7793b1ee6a8da0c24de7
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jun 27 18:11:12 2025 +0300

    next: typos

commit 6358dc11c90464b3464d39eb302e5265a3e61cdd
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jun 27 17:32:03 2025 +0300

    next: imp upstream; add more settings
This commit is contained in:
Ainar Garipov 2025-06-27 18:27:54 +03:00
parent e38d3a529a
commit 5e44582236
12 changed files with 208 additions and 77 deletions

View File

@ -3,28 +3,33 @@
# TODO(a.garipov): Move to the top level once the rewrite is over.
dns:
addresses:
- '0.0.0.0:53'
bootstrap_dns:
- '9.9.9.10'
- '149.112.112.10'
- '2620:fe::10'
- '2620:fe::fe:10'
upstream_dns:
- '8.8.8.8'
dns64_prefixes:
- '1234::/64'
upstream_timeout: 1s
bootstrap_prefer_ipv6: true
use_dns64: true
upstream_mode: parallel
addresses:
- '0.0.0.0:53'
bootstrap_dns:
- '9.9.9.10'
- '149.112.112.10'
- '2620:fe::10'
- '2620:fe::fe:10'
upstream_dns:
- '8.8.8.8'
dns64_prefixes:
- '1234::/64'
upstream_timeout: 1s
cache_size: 1048576
ratelimit: 100
bootstrap_prefer_ipv6: true
refuse_any: true
use_dns64: true
http:
pprof:
enabled: true
port: 6060
addresses:
- '0.0.0.0:3000'
secure_addresses: []
timeout: 5s
force_https: true
pprof:
port: 6060
enabled: true
addresses:
- '0.0.0.0:3000'
secure_addresses: []
timeout: 5s
force_https: true
log:
verbose: true
verbose: true
schema_version: 100

View File

@ -3,6 +3,7 @@ package configmgr
import (
"net/netip"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/container"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/timeutil"
@ -51,13 +52,17 @@ func (c *config) Validate() (err error) {
// dnsConfig is the on-disk DNS configuration.
type dnsConfig struct {
Addresses []netip.AddrPort `yaml:"addresses"`
BootstrapDNS []string `yaml:"bootstrap_dns"`
UpstreamDNS []string `yaml:"upstream_dns"`
DNS64Prefixes []netip.Prefix `yaml:"dns64_prefixes"`
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
BootstrapPreferIPv6 bool `yaml:"bootstrap_prefer_ipv6"`
UseDNS64 bool `yaml:"use_dns64"`
UpstreamMode proxy.UpstreamMode `yaml:"upstream_mode"`
Addresses []netip.AddrPort `yaml:"addresses"`
BootstrapDNS []string `yaml:"bootstrap_dns"`
UpstreamDNS []string `yaml:"upstream_dns"`
DNS64Prefixes []netip.Prefix `yaml:"dns64_prefixes"`
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
Ratelimit int `yaml:"ratelimit"`
CacheSize int `yaml:"cache_size"`
BootstrapPreferIPv6 bool `yaml:"bootstrap_prefer_ipv6"`
RefuseAny bool `yaml:"refuse_any"`
UseDNS64 bool `yaml:"use_dns64"`
}
// type check

View File

@ -158,12 +158,17 @@ func (m *Manager) assemble(
) (err error) {
dnsConf := &dnssvc.Config{
Logger: m.baseLogger.With(slogutil.KeyPrefix, "dnssvc"),
UpstreamMode: conf.DNS.UpstreamMode,
Addresses: conf.DNS.Addresses,
BootstrapServers: conf.DNS.BootstrapDNS,
UpstreamServers: conf.DNS.UpstreamDNS,
DNS64Prefixes: conf.DNS.DNS64Prefixes,
UpstreamTimeout: time.Duration(conf.DNS.UpstreamTimeout),
CacheSize: conf.DNS.CacheSize,
Ratelimit: conf.DNS.Ratelimit,
BootstrapPreferIPv6: conf.DNS.BootstrapPreferIPv6,
CacheEnabled: conf.DNS.CacheSize > 0,
RefuseAny: conf.DNS.RefuseAny,
UseDNS64: conf.DNS.UseDNS64,
}
err = m.updateDNS(ctx, dnsConf)
@ -263,11 +268,15 @@ func (m *Manager) updateDNS(ctx context.Context, c *dnssvc.Config) (err error) {
// updateCurrentDNS updates the DNS configuration in the current config.
func (m *Manager) updateCurrentDNS(c *dnssvc.Config) {
m.current.DNS.Addresses = slices.Clone(c.Addresses)
m.current.DNS.UpstreamMode = c.UpstreamMode
m.current.DNS.BootstrapDNS = slices.Clone(c.BootstrapServers)
m.current.DNS.UpstreamDNS = slices.Clone(c.UpstreamServers)
m.current.DNS.DNS64Prefixes = slices.Clone(c.DNS64Prefixes)
m.current.DNS.UpstreamTimeout = timeutil.Duration(c.UpstreamTimeout)
m.current.DNS.Ratelimit = c.Ratelimit
m.current.DNS.CacheSize = c.CacheSize
m.current.DNS.BootstrapPreferIPv6 = c.BootstrapPreferIPv6
m.current.DNS.RefuseAny = c.RefuseAny
m.current.DNS.UseDNS64 = c.UseDNS64
}

View File

@ -4,16 +4,21 @@ import (
"log/slog"
"net/netip"
"time"
"github.com/AdguardTeam/dnsproxy/proxy"
)
// Config is the AdGuard Home DNS service configuration structure.
//
// TODO(a.garipov): Add timeout for incoming requests.
type Config struct {
// Logger is used for logging the operation of the web API service. It must
// not be nil.
// Logger is used for logging the operation of the DNS service. It must not
// be nil.
Logger *slog.Logger
// UpstreamMode defines how upstreams are used.
UpstreamMode proxy.UpstreamMode
// Addresses are the addresses on which to serve plain DNS queries.
Addresses []netip.AddrPort
@ -31,10 +36,25 @@ type Config struct {
// UpstreamTimeout is the timeout for upstream requests.
UpstreamTimeout time.Duration
// CacheSize is the maximum cache size in bytes.
//
// TODO(a.garipov): Use bytesize.Bytes everywhere.
CacheSize int
// Ratelimit is the maximum number of requests per second from a given IP or
// subnet. If it is zero, rate limiting is disabled.
Ratelimit int
// BootstrapPreferIPv6, if true, instructs the bootstrapper to prefer IPv6
// addresses to IPv4 ones when bootstrapping.
BootstrapPreferIPv6 bool
// CacheEnabled defines if the response cache should be used.
CacheEnabled bool
// RefuseAny, if true, refuses DNS queries with the type ANY.
RefuseAny bool
// UseDNS64, if true, enables DNS64 protection for incoming requests.
UseDNS64 bool
}

View File

@ -15,9 +15,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/next/agh"
// TODO(a.garipov): Add a “dnsproxy proxy” package to shield us from changes
// and replacement of module dnsproxy.
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
@ -29,16 +26,30 @@ import (
// TODO(a.garipov): Consider saving a [*proxy.Config] instance for those
// fields that are only used in [New] and [Service.Config].
type Service struct {
logger *slog.Logger
proxy *proxy.Proxy
// logger is used for logging the operation of the DNS service.
logger *slog.Logger
// proxy is the current DNS proxy.
proxy *proxy.Proxy
// proxyConf contains the fields that have been used to create proxy to
// return them in [Service.Config].
proxyConf *proxy.Config
// The fields below have been used to create proxy and are saved to return
// them in [Service.Config].
bootstraps []string
bootstrapResolvers []*upstream.UpstreamResolver
upstreams []string
dns64Prefixes []netip.Prefix
upsTimeout time.Duration
running atomic.Bool
upstreamTimeout time.Duration
bootstrapPreferIPv6 bool
useDNS64 bool
// The fields above have been used to create proxy and are saved to return
// them in [Service.Config].
// running is true when the service has started.
running atomic.Bool
}
// New returns a new properly initialized *Service. If c is nil, svc is a nil
@ -50,16 +61,24 @@ func New(c *Config) (svc *Service, err error) {
}
svc = &Service{
logger: c.Logger,
logger: c.Logger,
proxyConf: &proxy.Config{
UpstreamMode: c.UpstreamMode,
Ratelimit: c.Ratelimit,
DNS64Prefs: c.DNS64Prefixes,
CacheSizeBytes: c.CacheSize,
CacheEnabled: c.CacheEnabled,
RefuseAny: c.RefuseAny,
UseDNS64: c.UseDNS64,
},
bootstraps: c.BootstrapServers,
upstreams: c.UpstreamServers,
dns64Prefixes: c.DNS64Prefixes,
upsTimeout: c.UpstreamTimeout,
upstreamTimeout: c.UpstreamTimeout,
bootstrapPreferIPv6: c.BootstrapPreferIPv6,
useDNS64: c.UseDNS64,
}
upstreams, resolvers, err := addressesToUpstreams(
svc.logger,
c.UpstreamServers,
c.BootstrapServers,
c.UpstreamTimeout,
@ -70,15 +89,20 @@ func New(c *Config) (svc *Service, err error) {
}
svc.bootstrapResolvers = resolvers
svc.proxy, err = proxy.New(&proxy.Config{
Logger: svc.logger,
UDPListenAddr: udpAddrs(c.Addresses),
TCPListenAddr: tcpAddrs(c.Addresses),
Logger: svc.logger,
UpstreamConfig: &proxy.UpstreamConfig{
Upstreams: upstreams,
},
UseDNS64: c.UseDNS64,
DNS64Prefs: c.DNS64Prefixes,
UDPListenAddr: udpAddrs(c.Addresses),
TCPListenAddr: tcpAddrs(c.Addresses),
UpstreamMode: svc.proxyConf.UpstreamMode,
Ratelimit: svc.proxyConf.Ratelimit,
DNS64Prefs: svc.proxyConf.DNS64Prefs,
CacheEnabled: svc.proxyConf.CacheEnabled,
RefuseAny: svc.proxyConf.RefuseAny,
UseDNS64: svc.proxyConf.UseDNS64,
})
if err != nil {
return nil, fmt.Errorf("proxy: %w", err)
@ -89,19 +113,20 @@ func New(c *Config) (svc *Service, err error) {
// addressesToUpstreams is a wrapper around [upstream.AddressToUpstream]. It
// accepts a slice of addresses and other upstream parameters, and returns a
// slice of upstreams.
// slice of upstreams. logger must not be nil.
func addressesToUpstreams(
logger *slog.Logger,
upsStrs []string,
bootstraps []string,
timeout time.Duration,
preferIPv6 bool,
) (upstreams []upstream.Upstream, boots []*upstream.UpstreamResolver, err error) {
opts := &upstream.Options{
boots, err = aghnet.ParseBootstraps(bootstraps, &upstream.Options{
// TODO(d.kolyshev): Use consts.
Logger: logger.With("upstream_type", "bootstrap"),
Timeout: timeout,
PreferIPv6: preferIPv6,
}
boots, err = aghnet.ParseBootstraps(bootstraps, opts)
})
if err != nil {
// Don't wrap the error, since it's informative enough as is.
return nil, nil, err
@ -116,6 +141,7 @@ func addressesToUpstreams(
upstreams = make([]upstream.Upstream, len(upsStrs))
for i, upsStr := range upsStrs {
upstreams[i], err = upstream.AddressToUpstream(upsStr, &upstream.Options{
Logger: logger.With("upstream_type", "main"),
Bootstrap: bootstrap,
Timeout: timeout,
PreferIPv6: preferIPv6,
@ -220,13 +246,18 @@ func (svc *Service) Config() (c *Config) {
c = &Config{
Logger: svc.logger,
UpstreamMode: svc.proxyConf.UpstreamMode,
Addresses: addrs,
BootstrapServers: svc.bootstraps,
UpstreamServers: svc.upstreams,
DNS64Prefixes: svc.dns64Prefixes,
UpstreamTimeout: svc.upsTimeout,
DNS64Prefixes: svc.proxyConf.DNS64Prefs,
UpstreamTimeout: svc.upstreamTimeout,
CacheSize: svc.proxyConf.CacheSizeBytes,
Ratelimit: svc.proxyConf.Ratelimit,
BootstrapPreferIPv6: svc.bootstrapPreferIPv6,
UseDNS64: svc.useDNS64,
CacheEnabled: svc.proxyConf.CacheEnabled,
RefuseAny: svc.proxyConf.RefuseAny,
UseDNS64: svc.proxyConf.UseDNS64,
}
return c

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/AdguardTeam/AdGuardHome/internal/next/dnssvc"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/miekg/dns"
@ -56,14 +57,12 @@ func TestService(t *testing.T) {
_, _ = testutil.RequireReceive(t, upstreamStartedCh, testTimeout)
c := &dnssvc.Config{
Logger: slogutil.NewDiscardLogger(),
Addresses: []netip.AddrPort{netip.MustParseAddrPort(listenAddr)},
BootstrapServers: []string{upstreamSrv.PacketConn.LocalAddr().String()},
UpstreamServers: []string{upstreamAddr},
DNS64Prefixes: nil,
UpstreamTimeout: testTimeout,
BootstrapPreferIPv6: false,
UseDNS64: false,
Logger: slogutil.NewDiscardLogger(),
UpstreamMode: proxy.UpstreamModeParallel,
Addresses: []netip.AddrPort{netip.MustParseAddrPort(listenAddr)},
BootstrapServers: []string{upstreamSrv.PacketConn.LocalAddr().String()},
UpstreamServers: []string{upstreamAddr},
UpstreamTimeout: testTimeout,
}
svc, err := dnssvc.New(c)

View File

@ -8,6 +8,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/AdGuardHome/internal/next/jsonpatch"
"github.com/AdguardTeam/dnsproxy/proxy"
)
// ReqPatchSettingsDNS describes the request to the PATCH /api/v1/settings/dns
@ -15,6 +16,8 @@ import (
type ReqPatchSettingsDNS struct {
// TODO(a.garipov): Add more as we go.
UpstreamMode jsonpatch.NonRemovable[proxy.UpstreamMode] `json:"upstream_mode"`
Addresses jsonpatch.NonRemovable[[]netip.AddrPort] `json:"addresses"`
BootstrapServers jsonpatch.NonRemovable[[]string] `json:"bootstrap_servers"`
UpstreamServers jsonpatch.NonRemovable[[]string] `json:"upstream_servers"`
@ -22,7 +25,11 @@ type ReqPatchSettingsDNS struct {
UpstreamTimeout jsonpatch.NonRemovable[aghhttp.JSONDuration] `json:"upstream_timeout"`
CacheSize jsonpatch.NonRemovable[int] `json:"cache_size"`
Ratelimit jsonpatch.NonRemovable[int] `json:"ratelimit"`
BootstrapPreferIPv6 jsonpatch.NonRemovable[bool] `json:"bootstrap_prefer_ipv6"`
RefuseAny jsonpatch.NonRemovable[bool] `json:"refuse_any"`
UseDNS64 jsonpatch.NonRemovable[bool] `json:"use_dns64"`
}
@ -31,13 +38,23 @@ type ReqPatchSettingsDNS struct {
type HTTPAPIDNSSettings struct {
// TODO(a.garipov): Add more as we go.
Addresses []netip.AddrPort `json:"addresses"`
BootstrapServers []string `json:"bootstrap_servers"`
UpstreamServers []string `json:"upstream_servers"`
DNS64Prefixes []netip.Prefix `json:"dns64_prefixes"`
UpstreamTimeout aghhttp.JSONDuration `json:"upstream_timeout"`
BootstrapPreferIPv6 bool `json:"bootstrap_prefer_ipv6"`
UseDNS64 bool `json:"use_dns64"`
UpstreamMode proxy.UpstreamMode `json:"upstream_mode"`
Addresses []netip.AddrPort `json:"addresses"`
BootstrapServers []string `json:"bootstrap_servers"`
UpstreamServers []string `json:"upstream_servers"`
DNS64Prefixes []netip.Prefix `json:"dns64_prefixes"`
UpstreamTimeout aghhttp.JSONDuration `json:"upstream_timeout"`
Ratelimit int `json:"ratelimit"`
CacheSize int `json:"cache_size"`
BootstrapPreferIPv6 bool `json:"bootstrap_prefer_ipv6"`
RefuseAny bool `json:"refuse_any"`
UseDNS64 bool `json:"use_dns64"`
}
// handlePatchSettingsDNS is the handler for the PATCH /api/v1/settings/dns HTTP
@ -57,6 +74,8 @@ func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Reques
// TODO(a.garipov): Add more as we go.
req.UpstreamMode.Set(&newConf.UpstreamMode)
req.Addresses.Set(&newConf.Addresses)
req.BootstrapServers.Set(&newConf.BootstrapServers)
req.UpstreamServers.Set(&newConf.UpstreamServers)
@ -64,7 +83,14 @@ func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Reques
req.UpstreamTimeout.Set((*aghhttp.JSONDuration)(&newConf.UpstreamTimeout))
if req.CacheSize.IsSet {
newConf.CacheSize = req.CacheSize.Value
newConf.CacheEnabled = req.CacheSize.Value > 0
}
req.Ratelimit.Set(&newConf.Ratelimit)
req.BootstrapPreferIPv6.Set(&newConf.BootstrapPreferIPv6)
req.RefuseAny.Set(&newConf.RefuseAny)
req.UseDNS64.Set(&newConf.UseDNS64)
ctx := r.Context()
@ -84,12 +110,16 @@ func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Reques
}
aghhttp.WriteJSONResponseOK(w, r, &HTTPAPIDNSSettings{
UpstreamMode: newConf.UpstreamMode,
Addresses: newConf.Addresses,
BootstrapServers: newConf.BootstrapServers,
UpstreamServers: newConf.UpstreamServers,
DNS64Prefixes: newConf.DNS64Prefixes,
UpstreamTimeout: aghhttp.JSONDuration(newConf.UpstreamTimeout),
Ratelimit: newConf.Ratelimit,
BootstrapPreferIPv6: newConf.BootstrapPreferIPv6,
CacheSize: newConf.CacheSize,
RefuseAny: newConf.RefuseAny,
UseDNS64: newConf.UseDNS64,
})
}

View File

@ -15,6 +15,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/next/agh"
"github.com/AdguardTeam/AdGuardHome/internal/next/dnssvc"
"github.com/AdguardTeam/AdGuardHome/internal/next/websvc"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/netutil/urlutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -22,12 +23,16 @@ import (
func TestService_HandlePatchSettingsDNS(t *testing.T) {
wantDNS := &websvc.HTTPAPIDNSSettings{
UpstreamMode: proxy.UpstreamModeParallel,
Addresses: []netip.AddrPort{netip.MustParseAddrPort("127.0.1.1:53")},
BootstrapServers: []string{"1.0.0.1"},
UpstreamServers: []string{"1.1.1.1"},
DNS64Prefixes: []netip.Prefix{netip.MustParsePrefix("1234::/64")},
UpstreamTimeout: aghhttp.JSONDuration(2 * time.Second),
Ratelimit: 100,
CacheSize: 1048576,
BootstrapPreferIPv6: true,
RefuseAny: true,
UseDNS64: true,
}
@ -56,12 +61,16 @@ func TestService_HandlePatchSettingsDNS(t *testing.T) {
}
req := jobj{
"upstream_mode": wantDNS.UpstreamMode,
"addresses": wantDNS.Addresses,
"bootstrap_servers": wantDNS.BootstrapServers,
"upstream_servers": wantDNS.UpstreamServers,
"dns64_prefixes": wantDNS.DNS64Prefixes,
"upstream_timeout": wantDNS.UpstreamTimeout,
"cache_size": wantDNS.CacheSize,
"ratelimit": wantDNS.Ratelimit,
"bootstrap_prefer_ipv6": wantDNS.BootstrapPreferIPv6,
"refuse_any": wantDNS.RefuseAny,
"use_dns64": wantDNS.UseDNS64,
}

View File

@ -29,12 +29,16 @@ func (svc *Service) handleGetSettingsAll(w http.ResponseWriter, r *http.Request)
// TODO(a.garipov): Add all currently supported parameters.
aghhttp.WriteJSONResponseOK(w, r, &RespGetV1SettingsAll{
DNS: &HTTPAPIDNSSettings{
UpstreamMode: dnsConf.UpstreamMode,
Addresses: dnsConf.Addresses,
BootstrapServers: dnsConf.BootstrapServers,
UpstreamServers: dnsConf.UpstreamServers,
DNS64Prefixes: dnsConf.DNS64Prefixes,
UpstreamTimeout: aghhttp.JSONDuration(dnsConf.UpstreamTimeout),
Ratelimit: dnsConf.Ratelimit,
BootstrapPreferIPv6: dnsConf.BootstrapPreferIPv6,
CacheSize: dnsConf.CacheSize,
RefuseAny: dnsConf.RefuseAny,
UseDNS64: dnsConf.UseDNS64,
},
HTTP: &HTTPAPIHTTPSettings{

View File

@ -12,6 +12,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/next/agh"
"github.com/AdguardTeam/AdGuardHome/internal/next/dnssvc"
"github.com/AdguardTeam/AdGuardHome/internal/next/websvc"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/netutil/urlutil"
"github.com/stretchr/testify/assert"
@ -22,22 +23,32 @@ func TestService_HandleGetSettingsAll(t *testing.T) {
// TODO(a.garipov): Add all currently supported parameters.
wantDNS := &websvc.HTTPAPIDNSSettings{
UpstreamMode: proxy.UpstreamModeParallel,
Addresses: []netip.AddrPort{netip.MustParseAddrPort("127.0.0.1:53")},
BootstrapServers: []string{"94.140.14.140", "94.140.14.141"},
UpstreamServers: []string{"94.140.14.14", "1.1.1.1"},
UpstreamTimeout: aghhttp.JSONDuration(1 * time.Second),
Ratelimit: 100,
CacheSize: 1048576,
BootstrapPreferIPv6: true,
RefuseAny: true,
UseDNS64: true,
}
confMgr := newConfigManager()
confMgr.onDNS = func() (s agh.ServiceWithConfig[*dnssvc.Config]) {
c, err := dnssvc.New(&dnssvc.Config{
Logger: slogutil.NewDiscardLogger(),
UpstreamMode: proxy.UpstreamModeParallel,
Addresses: wantDNS.Addresses,
UpstreamServers: wantDNS.UpstreamServers,
BootstrapServers: wantDNS.BootstrapServers,
UpstreamTimeout: time.Duration(wantDNS.UpstreamTimeout),
CacheSize: 1048576,
Ratelimit: 100,
BootstrapPreferIPv6: true,
RefuseAny: true,
UseDNS64: true,
})
require.NoError(t, err)

View File

@ -3,7 +3,9 @@
// NOTE: Packages other than cmd must not import this package, as it imports
// most other packages.
//
// TODO(a.garipov): Add tests.
// TODO(a.garipov): Add tests.
//
// TODO(a.garipov): Split into subpackages for groups of handlers?
package websvc
import (

View File

@ -2284,7 +2284,8 @@
'dnssec': false
'edns_client_subnet': false
'ipv6': true
'rate_limit': 20
'ratelimit': 20
'refuse_any': true
'upstream_mode': 'load_balancing'
'upstream_servers':
- '1.1.1.1'
@ -2300,7 +2301,8 @@
- 'dnssec'
- 'edns_client_subnet'
- 'ipv6'
- 'rate_limit'
- 'ratelimit'
- 'refuse_any'
- 'upstream_mode'
- 'upstream_servers'
- 'upstream_timeout'
@ -2380,13 +2382,17 @@
If `true`, accept `AAAA` DNS queries. If `false`, respond to them
with an empty answer.
'type': 'boolean'
'rate_limit':
'ratelimit':
'description': >
The number of requests per second that a single client is allowed to
make. `0` means no limit.
'format': 'int64'
'minimum': 0
'type': 'integer'
'refuse_any':
'description': >
If `true`, reject `ANY` DNS queries.
'type': 'boolean'
'upstream_mode':
'$ref': '#/components/schemas/DnsUpstreamMode'
'upstream_servers':