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 <E.Burkov@AdGuard.COM>
Date:   Thu Apr 17 20:45:12 2025 +0300

    home: fix typo

commit b1cbf45dcc54c6d4dc7de86868c189114caf7cb1
Merge: c2c868b7d 3521e8ed9
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Apr 17 20:44:14 2025 +0300

    Merge branch 'master' into AG-38975-upd-proxy

commit c2c868b7d938eee6e4e4a19d43b2ed734155c7da
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Apr 17 20:19:23 2025 +0300

    all: upd to tag

commit 1680a9d79f34bd42f0b64712b2e7e968890e7c6e
Merge: df42dec3a 4d258972d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Apr 16 14:08:46 2025 +0300

    Merge branch 'master' into AG-38975-upd-proxy

commit df42dec3a302af0e6e301365a943763cd87d752d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Apr 16 13:43:29 2025 +0300

    all: add thanks

commit f212d6a9ee3d614bd6db776204c65298f0359a87
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Apr 14 17:57:33 2025 +0300

    dnsforward: use bool

commit 055072e29dee0673cf38b198476e252bdbade8d9
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Apr 11 18:35:38 2025 +0300

    stats: imp doc

commit 6554101a73564b7786cd77d250344ba141c0cbb5
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Apr 10 19:32:34 2025 +0300

    all: log changes

commit da8ecf17778be9481232222c8bb7682beea475c6
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Apr 10 19:07:04 2025 +0300

    all: upd proxy, add config
This commit is contained in:
Eugene Burkov
2025-04-17 21:03:21 +03:00
parent 3521e8ed9f
commit feb9c886d8
9 changed files with 47 additions and 23 deletions

View File

@@ -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/
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
-->
@@ -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

View File

@@ -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();
});

View File

@@ -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}`);

8
go.mod
View File

@@ -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

16
go.sum
View File

@@ -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=

View File

@@ -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 {

View File

@@ -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,

View File

@@ -275,6 +275,7 @@ func newServerConfig(
ServeHTTP3: dnsConf.ServeHTTP3,
UseHTTP3Upstreams: dnsConf.UseHTTP3Upstreams,
ServePlainDNS: dnsConf.ServePlainDNS,
PendingRequestsEnabled: dnsConf.PendingRequests.Enabled,
}
var initialAddresses []netip.Addr

View File

@@ -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.