From a50a8abb45e3db7b9085ab2dd9cd3ff0102141af Mon Sep 17 00:00:00 2001 From: Ainar Garipov <a.garipov@adguard.com> Date: Mon, 13 Feb 2023 19:07:10 +0300 Subject: [PATCH] Pull request 1734: 5479-ad-do-fix Updates #5479. Squashed commit of the following: commit 348d0b94412aee510f291228b76c41a1b2f31d3e Merge: a0cf6f35 ff04b2a7 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Feb 13 18:42:47 2023 +0300 Merge branch 'master' into 5479-ad-do-fix commit a0cf6f3565c22b049c1e98d24c19854d911fd6e0 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Feb 13 18:02:54 2023 +0300 dnsforward: imp names, docs commit dfc0be504b3844ba65c2f21ff604edfc6d9040cd Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Feb 13 14:34:49 2023 +0300 dnsforward: fix ad flag for do reqs --- CHANGELOG.md | 4 +++ internal/dnsforward/dns.go | 54 +++++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a23d483..c29314a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,8 @@ In this release, the schema version has changed from 14 to 16. ### Fixed +- Setting the AD (Authenticated Data) flag on responses that have the DO (DNSSEC + OK) flag set but not the AD flag ([#5479]). - Client names resolved via reverse DNS not being updated ([#4939]). - The icon for League Of Legends on the Blocked services page ([#5433]). @@ -91,10 +93,12 @@ In this release, the schema version has changed from 14 to 16. - Go 1.18 support, as it has reached end of life. + [#1717]: https://github.com/AdguardTeam/AdGuardHome/issues/1717 [#4299]: https://github.com/AdguardTeam/AdGuardHome/issues/4299 [#4939]: https://github.com/AdguardTeam/AdGuardHome/issues/4939 [#5433]: https://github.com/AdguardTeam/AdGuardHome/issues/5433 +[#5479]: https://github.com/AdguardTeam/AdGuardHome/issues/5479 <!-- NOTE: Add new changes ABOVE THIS COMMENT. diff --git a/internal/dnsforward/dns.go b/internal/dnsforward/dns.go index c132cd96..8d924f3b 100644 --- a/internal/dnsforward/dns.go +++ b/internal/dnsforward/dns.go @@ -651,13 +651,7 @@ func (s *Server) processUpstream(dctx *dnsContext) (rc resultCode) { s.setCustomUpstream(pctx, dctx.clientID) - origReqAD := false - if s.conf.EnableDNSSEC { - origReqAD = req.AuthenticatedData - if !req.AuthenticatedData { - req.AuthenticatedData = true - } - } + reqWantsDNSSEC := s.setReqAD(req) // Process the request further since it wasn't filtered. prx := s.proxy() @@ -688,12 +682,52 @@ func (s *Server) processUpstream(dctx *dnsContext) (rc resultCode) { dctx.responseFromUpstream = true dctx.responseAD = pctx.Res.AuthenticatedData - if s.conf.EnableDNSSEC && !origReqAD { + s.setRespAD(pctx, reqWantsDNSSEC) + + return resultCodeSuccess +} + +// setReqAD changes the request based on the server settings. wantsDNSSEC is +// false if the response should be cleared of the AD bit. +// +// TODO(a.garipov, e.burkov): This should probably be done in module dnsproxy. +func (s *Server) setReqAD(req *dns.Msg) (wantsDNSSEC bool) { + if !s.conf.EnableDNSSEC { + return false + } + + origReqAD := req.AuthenticatedData + req.AuthenticatedData = true + + // Per [RFC 6840] says, validating resolvers should only set the AD bit when + // the response has the AD bit set and the request contained either a set DO + // bit or a set AD bit. So, if neither of these is true, clear the AD bits + // in [Server.setRespAD]. + // + // [RFC 6840]: https://datatracker.ietf.org/doc/html/rfc6840#section-5.8 + return origReqAD || hasDO(req) +} + +// hasDO returns true if msg has EDNS(0) options and the DNSSEC OK flag is set +// in there. +// +// TODO(a.garipov): Move to golibs/dnsmsg when it's there. +func hasDO(msg *dns.Msg) (do bool) { + o := msg.IsEdns0() + if o == nil { + return false + } + + return o.Do() +} + +// setRespAD changes the request and response based on the server settings and +// the original request data. +func (s *Server) setRespAD(pctx *proxy.DNSContext, reqWantsDNSSEC bool) { + if s.conf.EnableDNSSEC && !reqWantsDNSSEC { pctx.Req.AuthenticatedData = false pctx.Res.AuthenticatedData = false } - - return resultCodeSuccess } // isDHCPClientHostQ returns true if q is from a request for a DHCP client