diff --git a/internal/next/AdGuardHome.example.yaml b/internal/next/AdGuardHome.example.yaml index 1bdd8313..dd75a302 100644 --- a/internal/next/AdGuardHome.example.yaml +++ b/internal/next/AdGuardHome.example.yaml @@ -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 diff --git a/internal/next/configmgr/config.go b/internal/next/configmgr/config.go index 0a828f13..e4fdc00e 100644 --- a/internal/next/configmgr/config.go +++ b/internal/next/configmgr/config.go @@ -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 diff --git a/internal/next/configmgr/configmgr.go b/internal/next/configmgr/configmgr.go index 0e271355..bd8e73c4 100644 --- a/internal/next/configmgr/configmgr.go +++ b/internal/next/configmgr/configmgr.go @@ -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 } diff --git a/internal/next/dnssvc/config.go b/internal/next/dnssvc/config.go index e4e882be..f70f4057 100644 --- a/internal/next/dnssvc/config.go +++ b/internal/next/dnssvc/config.go @@ -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 } diff --git a/internal/next/dnssvc/dnssvc.go b/internal/next/dnssvc/dnssvc.go index 9e3b5b35..10cce3e9 100644 --- a/internal/next/dnssvc/dnssvc.go +++ b/internal/next/dnssvc/dnssvc.go @@ -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 diff --git a/internal/next/dnssvc/dnssvc_test.go b/internal/next/dnssvc/dnssvc_test.go index c8a438eb..be81fc51 100644 --- a/internal/next/dnssvc/dnssvc_test.go +++ b/internal/next/dnssvc/dnssvc_test.go @@ -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) diff --git a/internal/next/websvc/dns.go b/internal/next/websvc/dns.go index cf185e2c..d6a79a49 100644 --- a/internal/next/websvc/dns.go +++ b/internal/next/websvc/dns.go @@ -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, }) } diff --git a/internal/next/websvc/dns_test.go b/internal/next/websvc/dns_test.go index 1965b3e6..960bf024 100644 --- a/internal/next/websvc/dns_test.go +++ b/internal/next/websvc/dns_test.go @@ -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, } diff --git a/internal/next/websvc/settings.go b/internal/next/websvc/settings.go index 44364ca3..f89d935a 100644 --- a/internal/next/websvc/settings.go +++ b/internal/next/websvc/settings.go @@ -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{ diff --git a/internal/next/websvc/settings_test.go b/internal/next/websvc/settings_test.go index b2003556..754cf796 100644 --- a/internal/next/websvc/settings_test.go +++ b/internal/next/websvc/settings_test.go @@ -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) diff --git a/internal/next/websvc/websvc.go b/internal/next/websvc/websvc.go index 3f709cd1..bf1a2578 100644 --- a/internal/next/websvc/websvc.go +++ b/internal/next/websvc/websvc.go @@ -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 ( diff --git a/openapi/next.yaml b/openapi/next.yaml index adab6d4d..c9fdee12 100644 --- a/openapi/next.yaml +++ b/openapi/next.yaml @@ -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':