From 306c1983a2257f376a1c1e7c809264bb1d10af77 Mon Sep 17 00:00:00 2001 From: Stanislav Chzhen Date: Wed, 22 Mar 2023 13:42:20 +0300 Subject: [PATCH] Pull request 1758: 1472-edns-custom-ip-api Merge in DNS/adguard-home from 1472-edns-custom-ip-api to master Updates #1472 Squashed commit of the following: commit 7605ec5bd5467ddd28a650385193eb2332653bb6 Merge: 8b2ac227 194ead34 Author: Stanislav Chzhen Date: Wed Mar 22 13:39:25 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit 8b2ac22793a51d2555d32c1f5b5c118118807d1f Merge: d5ca8b6e c3edab43 Author: Stanislav Chzhen Date: Tue Mar 21 18:26:55 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit d5ca8b6e1d87480d4ee4afd346e6bf04907fca95 Author: Stanislav Chzhen Date: Tue Mar 21 18:26:24 2023 +0300 dnsforward: imp tests commit 1302586d22812c22755ea1c7e7fcd32330d707c5 Author: Vladislav Abdulmyanov Date: Tue Mar 21 16:47:56 2023 +0200 client: change validation for custom edns ip commit 44e4dc6d1e47de6597ed9ee328db9639e38b4868 Author: Vladislav Abdulmyanov Date: Tue Mar 21 16:31:42 2023 +0200 client: implement edns custom ip commit 8a3e7ad8ebf16262818821340da23baa5f004bff Merge: 04ac1112 f736d85e Author: Stanislav Chzhen Date: Tue Mar 21 15:04:40 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit 04ac1112dda2e778243555b2f54819e5ba586e05 Author: Stanislav Chzhen Date: Tue Mar 21 15:03:39 2023 +0300 dnsforward: imp tests commit b44f6d0ccb3ba7b7a5be07c9cf293dad9c83c794 Merge: 19c6851e 48431f8b Author: Stanislav Chzhen Date: Mon Mar 20 17:55:49 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit 19c6851e30f30b0572334822e8639e03760de986 Author: Stanislav Chzhen Date: Fri Mar 10 10:40:15 2023 +0300 all: fix chlog commit 6dcdcbd666ebf3a56a38251e8ead09c605068ce3 Merge: a7f1bf71 a2053526 Author: Stanislav Chzhen Date: Fri Mar 10 10:23:37 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit a7f1bf715e3557c710b700b9bd923868eb07715b Author: Stanislav Chzhen Date: Tue Mar 7 19:24:18 2023 +0300 home: fix default value commit 0311a9bb6571975963d747ef4ef427b59dca03bc Merge: 7e0bb3df 1011b8f9 Author: Stanislav Chzhen Date: Tue Mar 7 19:04:18 2023 +0300 Merge branch 'master' into 1472-edns-custom-ip-api commit 7e0bb3df78f10f4b4ae0fd49681d1aa0040521c5 Author: Stanislav Chzhen Date: Tue Mar 7 19:03:24 2023 +0300 all: fix chlog commit 202d7ccf4721ccf39726da01d237e07317bfaa58 Author: Stanislav Chzhen Date: Tue Mar 7 11:35:41 2023 +0300 dnsforward: fix typo commit fe95e003a0c3b316a44b5ec0b848a60ddd4c85cf Author: Stanislav Chzhen Date: Tue Mar 7 11:28:21 2023 +0300 all: fix docs commit 66835a9aa22b3015f9238c1d6f5aa9bd6067db8a Author: Stanislav Chzhen Date: Tue Mar 7 10:48:08 2023 +0300 dnsforward: add todo commit b58255e1e6660a8229bb9c40f2acddebb3dbdc66 Author: Stanislav Chzhen Date: Mon Mar 6 15:40:02 2023 +0300 all: upd chlog commit 9b2be7facba30c815144e08a7835353cad14c405 Author: Stanislav Chzhen Date: Fri Mar 3 11:22:19 2023 +0300 dnsforward: edns custom ip api --- CHANGELOG.md | 3 + client/src/__locales/en.json | 2 + .../components/Settings/Dns/Config/Form.js | 41 ++++- .../components/Settings/Dns/Config/index.js | 4 + internal/dnsforward/config.go | 15 +- internal/dnsforward/http.go | 164 ++++++++++++------ internal/dnsforward/http_test.go | 16 +- .../TestDNSForwardHTTP_handleGetConfig.json | 12 +- .../TestDNSForwardHTTP_handleSetConfig.json | 144 +++++++++++++-- internal/home/config.go | 2 +- openapi/CHANGELOG.md | 12 ++ openapi/openapi.yaml | 8 +- 12 files changed, 326 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b060ada..61f8706a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ NOTE: Add new changes BELOW THIS COMMENT. ### Added +- The ability to set custom IP for EDNS Client Subnet by using the DNS-server + configuration section on the DNS settings page in the UI ([#1472]). - The ability to manage safesearch for each service by using the new `safe_search` field ([#1163]). @@ -68,6 +70,7 @@ In this release, the schema version has changed from 17 to 19. ([#5584]). [#1163]: https://github.com/AdguardTeam/AdGuardHome/issues/1163 +[#1472]: https://github.com/AdguardTeam/AdGuardHome/issues/1472 [#5567]: https://github.com/AdguardTeam/AdGuardHome/issues/5567 [#5584]: https://github.com/AdguardTeam/AdGuardHome/issues/5584 diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index ee0345d7..5ccd771b 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -290,6 +290,8 @@ "rate_limit": "Rate limit", "edns_enable": "Enable EDNS client subnet", "edns_cs_desc": "Add the EDNS Client Subnet option (ECS) to upstream requests and log the values sent by the clients in the query log.", + "edns_use_custom_ip": "Use custom IP for EDNS", + "edns_use_custom_ip_desc": "Allow to use custom IP for EDNS", "rate_limit_desc": "The number of requests per second allowed per client. Setting it to 0 means no limit.", "blocking_ipv4_desc": "IP address to be returned for a blocked A request", "blocking_ipv6_desc": "IP address to be returned for a blocked AAAA request", diff --git a/client/src/components/Settings/Dns/Config/Form.js b/client/src/components/Settings/Dns/Config/Form.js index a2dd2bf9..52d94741 100644 --- a/client/src/components/Settings/Dns/Config/Form.js +++ b/client/src/components/Settings/Dns/Config/Form.js @@ -13,15 +13,11 @@ import { validateIpv4, validateIpv6, validateRequiredValue, + validateIp, } from '../../../../helpers/validators'; import { BLOCKING_MODES, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants'; const checkboxes = [ - { - name: 'edns_cs_enabled', - placeholder: 'edns_enable', - subtitle: 'edns_cs_desc', - }, { name: 'dnssec_enabled', placeholder: 'dnssec_enable', @@ -66,6 +62,8 @@ const Form = ({ const { t } = useTranslation(); const { blocking_mode, + edns_cs_enabled, + edns_cs_use_custom, } = useSelector((state) => state.form[FORM_NAME.BLOCKING_MODE].values ?? {}, shallowEqual); return
@@ -92,6 +90,39 @@ const Form = ({ /> +
+
+ +
+
+
+
+ +
+ + {edns_cs_use_custom && ()} + +
{checkboxes.map(({ name, placeholder, subtitle }) =>
{ blocking_ipv4, blocking_ipv6, edns_cs_enabled, + edns_cs_use_custom, + edns_cs_custom_ip, dnssec_enabled, disable_ipv6, processingSetConfig, @@ -39,6 +41,8 @@ const Config = () => { edns_cs_enabled, disable_ipv6, dnssec_enabled, + edns_cs_use_custom, + edns_cs_custom_ip, }} onSubmit={handleFormSubmit} processing={processingSetConfig} diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index f18e7513..008b2539 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -200,7 +200,7 @@ type FilteringConfig struct { // EDNSClientSubnet is the settings list for EDNS Client Subnet. type EDNSClientSubnet struct { // CustomIP for EDNS Client Subnet. - CustomIP string `yaml:"custom_ip"` + CustomIP netip.Addr `yaml:"custom_ip"` // Enabled defines if EDNS Client Subnet is enabled. Enabled bool `yaml:"enabled"` @@ -340,15 +340,8 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) { } if srvConf.EDNSClientSubnet.UseCustom { - // TODO(s.chzhen): Add wrapper around netip.Addr. - var ip net.IP - ip, err = netutil.ParseIP(srvConf.EDNSClientSubnet.CustomIP) - if err != nil { - return conf, fmt.Errorf("edns: %w", err) - } - // TODO(s.chzhen): Use netip.Addr instead of net.IP inside dnsproxy. - conf.EDNSAddr = ip + conf.EDNSAddr = net.IP(srvConf.EDNSClientSubnet.CustomIP.AsSlice()) } if srvConf.CacheSize != 0 { @@ -377,7 +370,7 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) { err = s.prepareTLS(&conf) if err != nil { - return conf, fmt.Errorf("validating tls: %w", err) + return proxy.Config{}, fmt.Errorf("validating tls: %w", err) } if c := srvConf.DNSCryptConfig; c.Enabled { @@ -388,7 +381,7 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) { } if conf.UpstreamConfig == nil || len(conf.UpstreamConfig.Upstreams) == 0 { - return conf, errors.Error("no default upstream servers configured") + return proxy.Config{}, errors.Error("no default upstream servers configured") } return conf, nil diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go index 0c8b6726..924a3675 100644 --- a/internal/dnsforward/http.go +++ b/internal/dnsforward/http.go @@ -23,26 +23,78 @@ import ( ) // jsonDNSConfig is the JSON representation of the DNS server configuration. +// +// TODO(s.chzhen): Split it into smaller pieces. Use aghalg.NullBool instead +// of *bool. type jsonDNSConfig struct { - Upstreams *[]string `json:"upstream_dns"` - UpstreamsFile *string `json:"upstream_dns_file"` - Bootstraps *[]string `json:"bootstrap_dns"` - ProtectionEnabled *bool `json:"protection_enabled"` - RateLimit *uint32 `json:"ratelimit"` - BlockingMode *BlockingMode `json:"blocking_mode"` - EDNSCSEnabled *bool `json:"edns_cs_enabled"` - DNSSECEnabled *bool `json:"dnssec_enabled"` - DisableIPv6 *bool `json:"disable_ipv6"` - UpstreamMode *string `json:"upstream_mode"` - CacheSize *uint32 `json:"cache_size"` - CacheMinTTL *uint32 `json:"cache_ttl_min"` - CacheMaxTTL *uint32 `json:"cache_ttl_max"` - CacheOptimistic *bool `json:"cache_optimistic"` - ResolveClients *bool `json:"resolve_clients"` - UsePrivateRDNS *bool `json:"use_private_ptr_resolvers"` - LocalPTRUpstreams *[]string `json:"local_ptr_upstreams"` - BlockingIPv4 net.IP `json:"blocking_ipv4"` - BlockingIPv6 net.IP `json:"blocking_ipv6"` + // Upstreams is the list of upstream DNS servers. + Upstreams *[]string `json:"upstream_dns"` + + // UpstreamsFile is the file containing upstream DNS servers. + UpstreamsFile *string `json:"upstream_dns_file"` + + // Bootstraps is the list of DNS servers resolving IP addresses of the + // upstream DoH/DoT resolvers. + Bootstraps *[]string `json:"bootstrap_dns"` + + // ProtectionEnabled defines if protection is enabled. + ProtectionEnabled *bool `json:"protection_enabled"` + + // RateLimit is the number of requests per second allowed per client. + RateLimit *uint32 `json:"ratelimit"` + + // BlockingMode defines the way blocked responses are constructed. + BlockingMode *BlockingMode `json:"blocking_mode"` + + // EDNSCSEnabled defines if EDNS Client Subnet is enabled. + EDNSCSEnabled *bool `json:"edns_cs_enabled"` + + // EDNSCSUseCustom defines if EDNSCSCustomIP should be used. + EDNSCSUseCustom *bool `json:"edns_cs_use_custom"` + + // DNSSECEnabled defines if DNSSEC is enabled. + DNSSECEnabled *bool `json:"dnssec_enabled"` + + // DisableIPv6 defines if IPv6 addresses should be dropped. + DisableIPv6 *bool `json:"disable_ipv6"` + + // UpstreamMode defines the way DNS requests are constructed. + UpstreamMode *string `json:"upstream_mode"` + + // CacheSize in bytes. + CacheSize *uint32 `json:"cache_size"` + + // CacheMinTTL is custom minimum TTL for cached DNS responses. + CacheMinTTL *uint32 `json:"cache_ttl_min"` + + // CacheMaxTTL is custom maximum TTL for cached DNS responses. + CacheMaxTTL *uint32 `json:"cache_ttl_max"` + + // CacheOptimistic defines if expired entries should be served. + CacheOptimistic *bool `json:"cache_optimistic"` + + // ResolveClients defines if clients IPs should be resolved into hostnames. + ResolveClients *bool `json:"resolve_clients"` + + // UsePrivateRDNS defines if privates DNS resolvers should be used. + UsePrivateRDNS *bool `json:"use_private_ptr_resolvers"` + + // LocalPTRUpstreams is the list of local private DNS resolvers. + LocalPTRUpstreams *[]string `json:"local_ptr_upstreams"` + + // BlockingIPv4 is custom IPv4 address for blocked A requests. + BlockingIPv4 net.IP `json:"blocking_ipv4"` + + // BlockingIPv6 is custom IPv6 address for blocked AAAA requests. + BlockingIPv6 net.IP `json:"blocking_ipv6"` + + // EDNSCSCustomIP is custom IP for EDNS Client Subnet. + EDNSCSCustomIP netip.Addr `json:"edns_cs_custom_ip"` + + // DefaultLocalPTRUpstreams is used to pass the addresses from + // systemResolvers to the front-end. It's not a pointer to the slice since + // there is no need to omit it while decoding from JSON. + DefaultLocalPTRUpstreams []string `json:"default_local_ptr_upstreams,omitempty"` } func (s *Server) getDNSConfig() (c *jsonDNSConfig) { @@ -57,7 +109,11 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) { blockingIPv4 := s.conf.BlockingIPv4 blockingIPv6 := s.conf.BlockingIPv6 ratelimit := s.conf.Ratelimit + + customIP := s.conf.EDNSClientSubnet.CustomIP enableEDNSClientSubnet := s.conf.EDNSClientSubnet.Enabled + useCustom := s.conf.EDNSClientSubnet.UseCustom + enableDNSSEC := s.conf.EnableDNSSEC aaaaDisabled := s.conf.AAAADisabled cacheSize := s.conf.CacheSize @@ -74,46 +130,40 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) { upstreamMode = "parallel" } - return &jsonDNSConfig{ - Upstreams: &upstreams, - UpstreamsFile: &upstreamFile, - Bootstraps: &bootstraps, - ProtectionEnabled: &protectionEnabled, - BlockingMode: &blockingMode, - BlockingIPv4: blockingIPv4, - BlockingIPv6: blockingIPv6, - RateLimit: &ratelimit, - EDNSCSEnabled: &enableEDNSClientSubnet, - DNSSECEnabled: &enableDNSSEC, - DisableIPv6: &aaaaDisabled, - CacheSize: &cacheSize, - CacheMinTTL: &cacheMinTTL, - CacheMaxTTL: &cacheMaxTTL, - CacheOptimistic: &cacheOptimistic, - UpstreamMode: &upstreamMode, - ResolveClients: &resolveClients, - UsePrivateRDNS: &usePrivateRDNS, - LocalPTRUpstreams: &localPTRUpstreams, - } -} - -func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) { defLocalPTRUps, err := s.filterOurDNSAddrs(s.sysResolvers.Get()) if err != nil { log.Debug("getting dns configuration: %s", err) } - resp := struct { - jsonDNSConfig - // DefautLocalPTRUpstreams is used to pass the addresses from - // systemResolvers to the front-end. It's not a pointer to the slice - // since there is no need to omit it while decoding from JSON. - DefautLocalPTRUpstreams []string `json:"default_local_ptr_upstreams,omitempty"` - }{ - jsonDNSConfig: *s.getDNSConfig(), - DefautLocalPTRUpstreams: defLocalPTRUps, + return &jsonDNSConfig{ + Upstreams: &upstreams, + UpstreamsFile: &upstreamFile, + Bootstraps: &bootstraps, + ProtectionEnabled: &protectionEnabled, + BlockingMode: &blockingMode, + BlockingIPv4: blockingIPv4, + BlockingIPv6: blockingIPv6, + RateLimit: &ratelimit, + EDNSCSCustomIP: customIP, + EDNSCSEnabled: &enableEDNSClientSubnet, + EDNSCSUseCustom: &useCustom, + DNSSECEnabled: &enableDNSSEC, + DisableIPv6: &aaaaDisabled, + CacheSize: &cacheSize, + CacheMinTTL: &cacheMinTTL, + CacheMaxTTL: &cacheMaxTTL, + CacheOptimistic: &cacheOptimistic, + UpstreamMode: &upstreamMode, + ResolveClients: &resolveClients, + UsePrivateRDNS: &usePrivateRDNS, + LocalPTRUpstreams: &localPTRUpstreams, + DefaultLocalPTRUpstreams: defLocalPTRUps, } +} +// handleGetConfig handles requests to the GET /control/dns_info endpoint. +func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) { + resp := s.getDNSConfig() _ = aghhttp.WriteJSONResponse(w, r, resp) } @@ -204,6 +254,7 @@ func (req *jsonDNSConfig) checkCacheTTL() bool { return min <= max } +// handleSetConfig handles requests to the POST /control/dns_config endpoint. func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) { req := &jsonDNSConfig{} err := json.NewDecoder(r.Body).Decode(req) @@ -231,8 +282,8 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) { } } -// setConfigRestartable sets the server parameters. shouldRestart is true if -// the server should be restarted to apply changes. +// setConfig sets the server parameters. shouldRestart is true if the server +// should be restarted to apply changes. func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) { s.serverLock.Lock() defer s.serverLock.Unlock() @@ -250,6 +301,10 @@ func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) { s.conf.FastestAddr = *dc.UpstreamMode == "fastest_addr" } + if dc.EDNSCSUseCustom != nil && *dc.EDNSCSUseCustom { + s.conf.EDNSClientSubnet.CustomIP = dc.EDNSCSCustomIP + } + setIfNotNil(&s.conf.ProtectionEnabled, dc.ProtectionEnabled) setIfNotNil(&s.conf.EnableDNSSEC, dc.DNSSECEnabled) setIfNotNil(&s.conf.AAAADisabled, dc.DisableIPv6) @@ -281,6 +336,7 @@ func (s *Server) setConfigRestartable(dc *jsonDNSConfig) (shouldRestart bool) { setIfNotNil(&s.conf.UpstreamDNSFileName, dc.UpstreamsFile), setIfNotNil(&s.conf.BootstrapDNS, dc.Bootstraps), setIfNotNil(&s.conf.EDNSClientSubnet.Enabled, dc.EDNSCSEnabled), + setIfNotNil(&s.conf.EDNSClientSubnet.UseCustom, dc.EDNSCSUseCustom), setIfNotNil(&s.conf.CacheSize, dc.CacheSize), setIfNotNil(&s.conf.CacheMinTTL, dc.CacheMinTTL), setIfNotNil(&s.conf.CacheMaxTTL, dc.CacheMaxTTL), diff --git a/internal/dnsforward/http_test.go b/internal/dnsforward/http_test.go index ef2228c1..144568d3 100644 --- a/internal/dnsforward/http_test.go +++ b/internal/dnsforward/http_test.go @@ -181,6 +181,12 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) { }, { name: "edns_cs_enabled", wantSet: "", + }, { + name: "edns_cs_use_custom", + wantSet: "", + }, { + name: "edns_cs_use_custom_bad_ip", + wantSet: "decoding request: ParseAddr(\"bad.ip\"): unexpected character (at \"bad.ip\")", }, { name: "dnssec_enabled", wantSet: "", @@ -222,16 +228,20 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) { Req json.RawMessage `json:"req"` Want json.RawMessage `json:"want"` } - loadTestData(t, t.Name()+jsonExt, &data) + + testData := t.Name() + jsonExt + loadTestData(t, testData, &data) for _, tc := range testCases { + // NOTE: Do not use require.Contains, because the size of the data + // prevents it from printing a meaningful error message. caseData, ok := data[tc.name] - require.True(t, ok) + require.Truef(t, ok, "%q does not contain test data for test case %s", testData, tc.name) t.Run(tc.name, func(t *testing.T) { t.Cleanup(func() { s.conf = defaultConf - s.conf.FilteringConfig.EDNSClientSubnet.Enabled = false + s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{} }) rBody := io.NopCloser(bytes.NewReader(caseData.Req)) diff --git a/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json index 3ac6f2f5..fe2c5666 100644 --- a/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json +++ b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json @@ -26,7 +26,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" }, "fastest_addr": { "upstream_dns": [ @@ -55,7 +57,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" }, "parallel": { "upstream_dns": [ @@ -84,6 +88,8 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } } diff --git a/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json index f55359a9..ca8c963a 100644 --- a/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json +++ b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json @@ -33,7 +33,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "bootstraps": { @@ -66,7 +68,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "blocking_mode_good": { @@ -100,7 +104,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "blocking_mode_bad": { @@ -134,7 +140,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "ratelimit": { @@ -168,7 +176,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "edns_cs_enabled": { @@ -202,7 +212,85 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" + } + }, + "edns_cs_use_custom": { + "req": { + "edns_cs_enabled": true, + "edns_cs_use_custom": true, + "edns_cs_custom_ip": "1.2.3.4" + }, + "want": { + "upstream_dns": [ + "8.8.8.8:53", + "8.8.4.4:53" + ], + "upstream_dns_file": "", + "bootstrap_dns": [ + "9.9.9.10", + "149.112.112.10", + "2620:fe::10", + "2620:fe::fe:10" + ], + "protection_enabled": true, + "ratelimit": 0, + "blocking_mode": "default", + "blocking_ipv4": "", + "blocking_ipv6": "", + "edns_cs_enabled": true, + "dnssec_enabled": false, + "disable_ipv6": false, + "upstream_mode": "", + "cache_size": 0, + "cache_ttl_min": 0, + "cache_ttl_max": 0, + "cache_optimistic": false, + "resolve_clients": false, + "use_private_ptr_resolvers": false, + "local_ptr_upstreams": [], + "edns_cs_use_custom": true, + "edns_cs_custom_ip": "1.2.3.4" + } + }, + "edns_cs_use_custom_bad_ip": { + "req": { + "edns_cs_enabled": true, + "edns_cs_use_custom": true, + "edns_cs_custom_ip": "bad.ip" + }, + "want": { + "upstream_dns": [ + "8.8.8.8:53", + "8.8.4.4:53" + ], + "upstream_dns_file": "", + "bootstrap_dns": [ + "9.9.9.10", + "149.112.112.10", + "2620:fe::10", + "2620:fe::fe:10" + ], + "protection_enabled": true, + "ratelimit": 0, + "blocking_mode": "default", + "blocking_ipv4": "", + "blocking_ipv6": "", + "edns_cs_enabled": false, + "dnssec_enabled": false, + "disable_ipv6": false, + "upstream_mode": "", + "cache_size": 0, + "cache_ttl_min": 0, + "cache_ttl_max": 0, + "cache_optimistic": false, + "resolve_clients": false, + "use_private_ptr_resolvers": false, + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "dnssec_enabled": { @@ -236,7 +324,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "cache_size": { @@ -270,7 +360,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "upstream_mode_parallel": { @@ -304,7 +396,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "upstream_mode_fastest_addr": { @@ -338,7 +432,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "upstream_dns_bad": { @@ -374,7 +470,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "bootstraps_bad": { @@ -410,7 +508,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "cache_bad_ttl": { @@ -445,7 +545,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "upstream_mode_bad": { @@ -479,7 +581,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "local_ptr_upstreams_good": { @@ -517,7 +621,9 @@ "use_private_ptr_resolvers": false, "local_ptr_upstreams": [ "123.123.123.123" - ] + ], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "local_ptr_upstreams_bad": { @@ -554,7 +660,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } }, "local_ptr_upstreams_null": { @@ -588,7 +696,9 @@ "cache_optimistic": false, "resolve_clients": false, "use_private_ptr_resolvers": false, - "local_ptr_upstreams": [] + "local_ptr_upstreams": [], + "edns_cs_use_custom": false, + "edns_cs_custom_ip": "" } } } diff --git a/internal/home/config.go b/internal/home/config.go index 6aad27b6..30dcb69d 100644 --- a/internal/home/config.go +++ b/internal/home/config.go @@ -286,7 +286,7 @@ var config = &configuration{ CacheSize: 4 * 1024 * 1024, EDNSClientSubnet: &dnsforward.EDNSClientSubnet{ - CustomIP: "", + CustomIP: netip.Addr{}, Enabled: false, UseCustom: false, }, diff --git a/openapi/CHANGELOG.md b/openapi/CHANGELOG.md index 20dde662..3b43140e 100644 --- a/openapi/CHANGELOG.md +++ b/openapi/CHANGELOG.md @@ -4,6 +4,18 @@ ## v0.108.0: API changes +## v0.107.27: API changes + +### The new optional fields `"edns_cs_use_custom"` and `"edns_cs_custom_ip"` in `DNSConfig` + +* The new optional fields `"edns_cs_use_custom"` and `"edns_cs_custom_ip"` in + `POST /control/dns_config` method makes AdGuard Home use or not use the + custom IP for EDNS Client Subnet. + +* The new optional fields `"edns_cs_use_custom"` and `"edns_cs_custom_ip"` in + `GET /control/dns_info` method are set if AdGuard Home uses custom IP for + EDNS Client Subnet. + ## v0.107.23: API changes diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 0bbac1e0..2ec4d858 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1254,7 +1254,7 @@ 'example': 'en' 'DNSConfig': 'type': 'object' - 'description': 'Query log configuration' + 'description': 'DNS server configuration' 'properties': 'bootstrap_dns': 'type': 'array' @@ -1280,8 +1280,6 @@ 'type': 'string' 'protection_enabled': 'type': 'boolean' - 'dhcp_available': - 'type': 'boolean' 'ratelimit': 'type': 'integer' 'blocking_mode': @@ -1298,6 +1296,10 @@ 'type': 'string' 'edns_cs_enabled': 'type': 'boolean' + 'edns_cs_use_custom': + 'type': 'boolean' + 'edns_cs_custom_ip': + 'type': 'string' 'disable_ipv6': 'type': 'boolean' 'dnssec_enabled':