From feb9c886d891d6e99fbe3c5e214bdeeda10eb211 Mon Sep 17 00:00:00 2001 From: Eugene Burkov Date: Thu, 17 Apr 2025 21:03:21 +0300 Subject: [PATCH] Pull request 2389: AG-38975 Update proxy Merge in DNS/adguard-home from AG-38975-upd-proxy to master Squashed commit of the following: commit 94fc1fb9bb1c004fea17d52f586af263b6918694 Author: Eugene Burkov Date: Thu Apr 17 20:45:12 2025 +0300 home: fix typo commit b1cbf45dcc54c6d4dc7de86868c189114caf7cb1 Merge: c2c868b7d 3521e8ed9 Author: Eugene Burkov Date: Thu Apr 17 20:44:14 2025 +0300 Merge branch 'master' into AG-38975-upd-proxy commit c2c868b7d938eee6e4e4a19d43b2ed734155c7da Author: Eugene Burkov Date: Thu Apr 17 20:19:23 2025 +0300 all: upd to tag commit 1680a9d79f34bd42f0b64712b2e7e968890e7c6e Merge: df42dec3a 4d258972d Author: Eugene Burkov Date: Wed Apr 16 14:08:46 2025 +0300 Merge branch 'master' into AG-38975-upd-proxy commit df42dec3a302af0e6e301365a943763cd87d752d Author: Eugene Burkov Date: Wed Apr 16 13:43:29 2025 +0300 all: add thanks commit f212d6a9ee3d614bd6db776204c65298f0359a87 Author: Eugene Burkov Date: Mon Apr 14 17:57:33 2025 +0300 dnsforward: use bool commit 055072e29dee0673cf38b198476e252bdbade8d9 Author: Eugene Burkov Date: Fri Apr 11 18:35:38 2025 +0300 stats: imp doc commit 6554101a73564b7786cd77d250344ba141c0cbb5 Author: Eugene Burkov Date: Thu Apr 10 19:32:34 2025 +0300 all: log changes commit da8ecf17778be9481232222c8bb7682beea475c6 Author: Eugene Burkov Date: Thu Apr 10 19:07:04 2025 +0300 all: upd proxy, add config --- CHANGELOG.md | 11 ++++++++++- client/tests/e2e/control-panel.spec.ts | 6 ------ client/tests/e2e/filtering.spec.ts | 6 +++--- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- internal/dnsforward/config.go | 7 +++++++ internal/home/config.go | 13 +++++++++++++ internal/home/dns.go | 1 + internal/stats/unit.go | 2 +- 9 files changed, 47 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b7aa61..791e8874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,15 @@ See also the [v0.107.61 GitHub milestone][ms-v0.107.61]. NOTE: Add new changes BELOW THIS COMMENT. --> + +### Security + +- Any simultaneous requests that are considered duplicates will now only result in a single request to upstreams, reducing the chance of a cache poisoning attack succeeding. This is controlled by the new configuration object `pending_requests`, which has a single `enabled` property, set to `true` by default. + + **NOTE:** We thank [Xiang Li][mr-xiang-li] for reporting this security issue. It's strongly recommended to leave it enabled, otherwise AdGuard Home will be vulnerable to untrusted clients. + +[mr-xiang-li]: https://lixiang521.com/ + @@ -55,7 +64,7 @@ See also the [v0.107.60 GitHub milestone][ms-v0.107.60]. [#7729]: https://github.com/AdguardTeam/AdGuardHome/issues/7729 [#7734]: https://github.com/AdguardTeam/AdGuardHome/issues/7734 -[go-1.24.2]: https://groups.google.com/g/golang-announce/c/Y2uBTVKjBQk +[go-1.24.2]: https://groups.google.com/g/golang-announce/c/Y2uBTVKjBQk [ms-v0.107.60]: https://github.com/AdguardTeam/AdGuardHome/milestone/95?closed=1 ## [v0.107.59] - 2025-03-21 diff --git a/client/tests/e2e/control-panel.spec.ts b/client/tests/e2e/control-panel.spec.ts index f1eaebac..9a4cace1 100644 --- a/client/tests/e2e/control-panel.spec.ts +++ b/client/tests/e2e/control-panel.spec.ts @@ -14,26 +14,20 @@ test.describe('Control Panel', () => { }); test('should sign out successfully', async ({ page }) => { - await page.getByTestId('sign_out').click(); - await page.waitForURL((url) => url.href.endsWith('/login.html')); - await expect(page.getByTestId('sign_in')).toBeVisible(); }); test('should change theme to dark and then light', async ({ page }) => { - await page.getByTestId('theme_dark').click(); - await expect(page.locator('body[data-theme="dark"]')).toBeVisible(); await page.getByTestId('theme_light').click(); - await expect(page.locator('body:not([data-theme="dark"])')).toBeVisible(); }); diff --git a/client/tests/e2e/filtering.spec.ts b/client/tests/e2e/filtering.spec.ts index c043791f..49bec97a 100644 --- a/client/tests/e2e/filtering.spec.ts +++ b/client/tests/e2e/filtering.spec.ts @@ -18,12 +18,12 @@ test.describe('Filtering', () => { const runTerminalCommand = (command: string) => { try { console.info(`Executing command: ${command}`); - + const output = execSync(command, { encoding: 'utf-8', stdio: 'pipe' }).trim(); - + console.info('Command executed successfully.'); console.debug(`Command output:\n${output}`); - + return output; } catch (error: any) { console.error(`Command execution failed with error:\n${error.message}`); diff --git a/go.mod b/go.mod index cc41305c..750d0ff3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.24.2 require ( - github.com/AdguardTeam/dnsproxy v0.75.2 + github.com/AdguardTeam/dnsproxy v0.75.3 github.com/AdguardTeam/golibs v0.32.7 github.com/AdguardTeam/urlfilter v0.20.0 github.com/NYTimes/gziphandler v1.1.1 @@ -90,7 +90,7 @@ require ( go.opentelemetry.io/otel/trace v1.35.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/mock v0.5.1 // indirect - golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394 // indirect + golang.org/x/exp/typeparams v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/mod v0.24.0 // indirect golang.org/x/oauth2 v0.29.0 // indirect golang.org/x/sync v0.13.0 // indirect @@ -102,8 +102,8 @@ require ( golang.org/x/vuln v1.1.4 // indirect gonum.org/v1/gonum v0.16.0 // indirect google.golang.org/api v0.228.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250407143221-ac9807e6c755 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect google.golang.org/grpc v1.71.1 // indirect google.golang.org/protobuf v1.36.6 // indirect honnef.co/go/tools v0.6.1 // indirect diff --git a/go.sum b/go.sum index 0fabdae7..72aa1eb3 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4 cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/longrunning v0.6.6 h1:XJNDo5MUfMM05xK3ewpbSdmt7R2Zw+aQEMbdQR65Rbw= cloud.google.com/go/longrunning v0.6.6/go.mod h1:hyeGJUrPHcx0u2Uu1UFSoYZLn4lkMrccJig0t4FI7yw= -github.com/AdguardTeam/dnsproxy v0.75.2 h1:bciOkzQh/GG8vcZGdFn6+rS3pu+2Npt9tbA4bNA/rsc= -github.com/AdguardTeam/dnsproxy v0.75.2/go.mod h1:U/ouLftmXMIrkTAf8JepqbPuoQzsbXJo0Vxxn+LAdgA= +github.com/AdguardTeam/dnsproxy v0.75.3 h1:pxlMNO+cP1A3px40PY/old6SAE82pkdLPUA2P3KY8u0= +github.com/AdguardTeam/dnsproxy v0.75.3/go.mod h1:50OyTHao+uQzUJiXay08hgfvWQ3o2Q2WV99W8u8ypDE= github.com/AdguardTeam/golibs v0.32.7 h1:3dmGlAVgmvquCCwHsvEl58KKcRAK3z1UnjMnwSIeDH4= github.com/AdguardTeam/golibs v0.32.7/go.mod h1:bE8KV1zqTzgZjmjFyBJ9f9O5DEKO717r7e57j1HclJA= github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs= @@ -207,8 +207,8 @@ golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= -golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394 h1:VI4qDpTkfFaCXEPrbojidLgVQhj2x4nzTccG0hjaLlU= -golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ= +golang.org/x/exp/typeparams v0.0.0-20250408133849-7e4ce0ab07d0 h1:oMe07YcizemJ09rs2kRkFYAp0pt4e1lYLwPWiEGMpXE= +golang.org/x/exp/typeparams v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -270,10 +270,10 @@ gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs= google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4= -google.golang.org/genproto/googleapis/api v0.0.0-20250407143221-ac9807e6c755 h1:AMLTAunltONNuzWgVPZXrjLWtXpsG6A3yLLPEoJ/IjU= -google.golang.org/genproto/googleapis/api v0.0.0-20250407143221-ac9807e6c755/go.mod h1:2R6XrVC8Oc08GlNh8ujEpc7HkLiEZ16QeY7FxIs20ac= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 h1:TwXJCGVREgQ/cl18iY0Z4wJCTL/GmW+Um2oSwZiZPnc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a h1:OQ7sHVzkx6L57dQpzUS4ckfWJ51KDH74XHTDe23xWAs= +google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a/go.mod h1:2R6XrVC8Oc08GlNh8ujEpc7HkLiEZ16QeY7FxIs20ac= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a h1:GIqLhp/cYUkuGuiT+vJk8vhOP86L4+SP5j8yXgeVpvI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go index 9c3a85ec..3217d2fd 100644 --- a/internal/dnsforward/config.go +++ b/internal/dnsforward/config.go @@ -274,6 +274,10 @@ type ServerConfig struct { // ServePlainDNS defines if plain DNS is allowed for incoming requests. ServePlainDNS bool + + // PendingRequestsEnabled defines if duplicate requests should be forwarded + // to upstreams along with the original one. + PendingRequestsEnabled bool } // UpstreamMode is a enumeration of upstream mode representations. See @@ -317,6 +321,9 @@ func (s *Server) newProxyConfig() (conf *proxy.Config, err error) { UsePrivateRDNS: srvConf.UsePrivateRDNS, PrivateSubnets: s.privateNets, MessageConstructor: s, + PendingRequests: &proxy.PendingRequestsConfig{ + Enabled: srvConf.PendingRequestsEnabled, + }, } if srvConf.EDNSClientSubnet.UseCustom { diff --git a/internal/home/config.go b/internal/home/config.go index aa09746a..2ec549d3 100644 --- a/internal/home/config.go +++ b/internal/home/config.go @@ -263,6 +263,16 @@ type dnsConfig struct { // HostsFileEnabled defines whether to use information from the system hosts // file to resolve queries. HostsFileEnabled bool `yaml:"hostsfile_enabled"` + + // PendingRequests configures duplicate requests policy. + PendingRequests *pendingRequests `yaml:"pending_requests"` +} + +// pendingRequests is a block with pending requests configuration. +type pendingRequests struct { + // Enabled controls if duplicate requests should be sent to the upstreams + // along with the original one. + Enabled bool `yaml:"enabled"` } // tlsConfigSettings is the TLS configuration for DNS-over-TLS, DNS-over-QUIC, @@ -470,6 +480,9 @@ var config = &configuration{ UsePrivateRDNS: true, ServePlainDNS: true, HostsFileEnabled: true, + PendingRequests: &pendingRequests{ + Enabled: true, + }, }, TLS: tlsConfigSettings{ PortHTTPS: defaultPortHTTPS, diff --git a/internal/home/dns.go b/internal/home/dns.go index 1c68d948..cfcd74a4 100644 --- a/internal/home/dns.go +++ b/internal/home/dns.go @@ -275,6 +275,7 @@ func newServerConfig( ServeHTTP3: dnsConf.ServeHTTP3, UseHTTP3Upstreams: dnsConf.UseHTTP3Upstreams, ServePlainDNS: dnsConf.ServePlainDNS, + PendingRequestsEnabled: dnsConf.PendingRequests.Enabled, } var initialAddresses []netip.Addr diff --git a/internal/stats/unit.go b/internal/stats/unit.go index 5eef6f3c..a8d7a3d6 100644 --- a/internal/stats/unit.go +++ b/internal/stats/unit.go @@ -64,7 +64,7 @@ type Entry struct { Domain string // UpstreamStats contains the DNS query statistics for both the upstream and - // fallback DNS servers. + // fallback DNS servers. Don't modify items in the slice. UpstreamStats []*proxy.UpstreamStatistics // Result is the result of processing the request.