Skip to content

Commit 05f86f0

Browse files
committed
Pull request: AGDNS-3870-imp-dnssec
Merge in GO/dnsproxy from AGDNS-3870-imp-dnssec to master Squashed commit of the following: commit feaf325 Merge: 34d56aa 97cddca Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Apr 23 08:24:07 2026 +0700 Merge remote-tracking branch 'origin/master' commit 34d56aa Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Apr 16 09:16:46 2026 +0700 all: imp yaml conf commit 7e88ee1 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Apr 15 10:24:32 2026 +0700 cmd: imp code commit e9286ab Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Apr 14 14:07:27 2026 +0700 proxy: use dnssec commit 3171cb4 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Apr 13 13:12:35 2026 +0700 all: add dnssec conf
1 parent 97cddca commit 05f86f0

12 files changed

Lines changed: 62 additions & 5 deletions

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Usage of ./dnsproxy:
6363
Cache size (in bytes). Default: 64k.
6464
--config-path=path
6565
YAML configuration file. Minimal working configuration in config.yaml.dist. Options passed through command line will override the ones from this file.
66+
--dnssec
67+
Defines whether the proxy should set the DO bits in the upstream requests. Default: true.
6668
--doh-insecure-enabled
6769
If specified, the DoH server will skip TLS certificate verification.
6870
--doh-routes

config.yaml.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
---
77
bootstrap:
88
- "8.8.8.8:53"
9+
# DNSSEC validation is enabled by default, if you want to disable it set it to
10+
# false.
11+
dnssec: true
912
listen-addrs:
1013
- "0.0.0.0"
1114
listen-ports:

internal/cmd/args.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const (
6969
usePrivateRDNSIdx
7070
dohRoutesIdx
7171
dohInsecureEnabledIdx
72+
dnssecEnabledIdx
7273
)
7374

7475
// commandLineOption contains information about a command-line option: its long
@@ -419,6 +420,12 @@ var commandLineOptions = []*commandLineOption{
419420
short: "",
420421
valueType: "",
421422
},
423+
dnssecEnabledIdx: {
424+
description: "Defines whether the proxy should set the DO bits in the upstream requests.",
425+
long: "dnssec",
426+
short: "",
427+
valueType: "",
428+
},
422429
}
423430

424431
// parseCmdLineOptions parses the command-line options. conf must not be nil.
@@ -480,6 +487,7 @@ func parseCmdLineOptions(conf *configuration) (err error) {
480487
usePrivateRDNSIdx: &conf.UsePrivateRDNS,
481488
dohRoutesIdx: &conf.DoHRoutes,
482489
dohInsecureEnabledIdx: &conf.DoHInsecureEnabled,
490+
dnssecEnabledIdx: &conf.DNSSECEnabled,
483491
} {
484492
addOption(flags, fieldPtr, commandLineOptions[i])
485493
}

internal/cmd/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ type configuration struct {
194194
// RefuseAny makes the server to refuse requests of type ANY.
195195
RefuseAny bool `yaml:"refuse-any"`
196196

197+
// DNSSECEnabled defines whether the proxy should set the DO bits in the
198+
// upstream requests.
199+
DNSSECEnabled bool `yaml:"dnssec"`
200+
197201
// EnableEDNSSubnet uses EDNS Client Subnet extension.
198202
EnableEDNSSubnet bool `yaml:"edns"`
199203

@@ -223,6 +227,7 @@ func parseConfig() (conf *configuration, exitCode int, err error) {
223227
OptimisticMaxAge: timeutil.Duration(proxy.DefaultOptimisticMaxAge),
224228
RatelimitSubnetLenIPv4: 24,
225229
RatelimitSubnetLenIPv6: 56,
230+
DNSSECEnabled: true,
226231
HostsFileEnabled: true,
227232
PendingRequestsEnabled: true,
228233
}

internal/cmd/proxy.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ func createProxyConfig(
9898
netip.MustParsePrefix("0.0.0.0/0"),
9999
netip.MustParsePrefix("::0/0"),
100100
},
101+
DNSSECEnabled: conf.DNSSECEnabled,
101102
EnableEDNSClientSubnet: conf.EnableEDNSSubnet,
102103
UDPBufferSize: conf.UDPBufferSize,
103104
MaxGoroutines: conf.MaxGoRoutines,

proxy/cache_internal_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func TestServeCached(t *testing.T) {
5757
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(localhostAnyPort)},
5858
UpstreamConfig: newTestUpstreamConfig(t, defaultTimeout, testDefaultUpstreamAddr),
5959
TrustedProxies: defaultTrustedProxies,
60+
DNSSECEnabled: true,
6061
CacheEnabled: true,
6162
})
6263

@@ -374,6 +375,7 @@ func TestCacheExpirationWithTTLOverride(t *testing.T) {
374375
},
375376
TrustedProxies: defaultTrustedProxies,
376377
CacheEnabled: true,
378+
DNSSECEnabled: true,
377379
CacheMinTTL: 20,
378380
CacheMaxTTL: 40,
379381
})

proxy/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ type Config struct {
178178
// RefuseAny makes proxy refuse the requests of type ANY.
179179
RefuseAny bool
180180

181+
// DNSSECEnabled specifies if the proxy should set the DO bits in the
182+
// upstream requests.
183+
DNSSECEnabled bool
184+
181185
// Enable EDNS Client Subnet option DNS requests to the upstream server will
182186
// contain an OPT record with Client Subnet option. If the original request
183187
// already has this option set, we pass it through as is. Otherwise, we set

proxy/pending_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func TestPendingRequests(t *testing.T) {
117117
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(localhostAnyPort)},
118118
CacheSizeBytes: testCacheSize,
119119
CacheEnabled: true,
120+
DNSSECEnabled: true,
120121
EnableEDNSClientSubnet: true,
121122
})
122123
require.NoError(t, err)

proxy/proxy.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,8 +668,14 @@ func (p *Proxy) handleExchangeResult(
668668
}
669669
}
670670

671-
// addDO adds EDNS0 RR if needed and sets DO bit of msg to true.
672-
func addDO(msg *dns.Msg) {
671+
// addDO adds EDNS0 RR if needed and sets DO bit of msg to true. msg must not
672+
// be nil.
673+
func (p *Proxy) addDO(msg *dns.Msg) {
674+
if !p.DNSSECEnabled {
675+
// Do nothing if DNSSEC is disabled in the proxy.
676+
return
677+
}
678+
673679
if o := msg.IsEdns0(); o != nil {
674680
if !o.Do() {
675681
o.SetDo()
@@ -715,7 +721,7 @@ func (p *Proxy) Resolve(ctx context.Context, dctx *DNSContext) (err error) {
715721

716722
// On cache miss request for DNSSEC from the upstream to cache it
717723
// afterwards.
718-
addDO(dctx.Req)
724+
p.addDO(dctx.Req)
719725
}
720726

721727
var ok bool
@@ -794,6 +800,12 @@ func (p *Proxy) cacheWorks(dctx *DNSContext) (ok bool) {
794800
// Don't cache the requests intended for local upstream servers, those
795801
// should be fast enough as is.
796802
reason = "requested address is private"
803+
case !p.DNSSECEnabled && !dctx.doBit:
804+
// Don't cache the responses without DNSSEC RRs if DNSSEC is disabled
805+
// and DO bit is not set, since those responses may differ from the ones
806+
// with DNSSEC RRs and thus may be not the desired result for user. In
807+
// case DNSSEC is enabled in the proxy, the DO bit will be enforced.
808+
reason = "dnssec disabled"
797809
case dctx.Req.CheckingDisabled:
798810
// Also don't lookup the cache for responses with DNSSEC checking
799811
// disabled since only validated responses are cached and those may be

proxy/proxy_internal_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ func TestProxy_Resolve_dnssecCache(t *testing.T) {
504504
UpstreamConfig: &UpstreamConfig{Upstreams: []upstream.Upstream{u}},
505505
TrustedProxies: defaultTrustedProxies,
506506
CacheEnabled: true,
507+
DNSSECEnabled: true,
507508
CacheSizeBytes: defaultCacheSize,
508509
})
509510

@@ -978,6 +979,7 @@ func TestExchangeCustomUpstreamConfigCache(t *testing.T) {
978979
UpstreamConfig: newTestUpstreamConfig(t, defaultTimeout, testDefaultUpstreamAddr),
979980
TrustedProxies: defaultTrustedProxies,
980981
CacheEnabled: true,
982+
DNSSECEnabled: true,
981983
})
982984

983985
servicetest.RequireRun(t, prx, testTimeout)
@@ -1107,6 +1109,7 @@ func TestECSProxy(t *testing.T) {
11071109
Upstreams: []upstream.Upstream{u},
11081110
},
11091111
TrustedProxies: defaultTrustedProxies,
1112+
DNSSECEnabled: true,
11101113
EnableEDNSClientSubnet: true,
11111114
CacheEnabled: true,
11121115
})
@@ -1216,6 +1219,7 @@ func TestECSProxyCacheMinMaxTTL(t *testing.T) {
12161219
TCPListenAddr: []*net.TCPAddr{net.TCPAddrFromAddrPort(localhostAnyPort)},
12171220
UpstreamConfig: &UpstreamConfig{Upstreams: []upstream.Upstream{u}},
12181221
TrustedProxies: defaultTrustedProxies,
1222+
DNSSECEnabled: true,
12191223
EnableEDNSClientSubnet: true,
12201224
CacheEnabled: true,
12211225
CacheMinTTL: 20,
@@ -1309,6 +1313,7 @@ func TestProxy_Resolve_withOptimisticResolver(t *testing.T) {
13091313
CacheOptimistic: true,
13101314
CacheOptimisticAnswerTTL: testOptimisticTTL,
13111315
CacheOptimisticMaxAge: testOptimisticMaxAge,
1316+
DNSSECEnabled: true,
13121317
},
13131318
logger: testLogger,
13141319
pendingRequests: newDefaultPendingRequests(),

0 commit comments

Comments
 (0)