From acf9a0fa19928e605ac8ac3314890c9fef73e16b Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Thu, 17 Sep 2020 16:28:43 +0200 Subject: cache: default to DNSSEC (#4085) * cache: default to DNSSEC This change does away with the DNS/DNSSEC distinction the cache currently makes. Cache will always make coredns perform a DNSSEC query and store that result. If a client just needs plain DNS, the DNSSEC records are stripped from the response. It should also be more memory efficient, because we store a reply once and not one DNS and another for DNSSEC. Fixes: #3836 Signed-off-by: Miek Gieben * Change OPT RR when one is present in the msg. Signed-off-by: Miek Gieben * Fix comment for isDNSSEC Signed-off-by: Miek Gieben * Update plugin/cache/handler.go Co-authored-by: Chris O'Haver * Update plugin/cache/item.go Co-authored-by: Chris O'Haver * Code review; fix comment for isDNSSEC Signed-off-by: Miek Gieben * Update doc and set AD to false Set Authenticated Data to false when DNSSEC was not wanted. Also update the readme with the new behavior. Signed-off-by: Miek Gieben * Update plugin/cache/handler.go Co-authored-by: Chris O'Haver Co-authored-by: Chris O'Haver --- plugin/cache/cache.go | 60 ++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'plugin/cache/cache.go') diff --git a/plugin/cache/cache.go b/plugin/cache/cache.go index 9988d9c70..32185de19 100644 --- a/plugin/cache/cache.go +++ b/plugin/cache/cache.go @@ -65,31 +65,21 @@ func New() *Cache { // key returns key under which we store the item, -1 will be returned if we don't store the message. // Currently we do not cache Truncated, errors zone transfers or dynamic update messages. // qname holds the already lowercased qname. -func key(qname string, m *dns.Msg, t response.Type, do bool) (bool, uint64) { +func key(qname string, m *dns.Msg, t response.Type) (bool, uint64) { // We don't store truncated responses. if m.Truncated { return false, 0 } - // Nor errors or Meta or Update + // Nor errors or Meta or Update. if t == response.OtherError || t == response.Meta || t == response.Update { return false, 0 } - return true, hash(qname, m.Question[0].Qtype, do) + return true, hash(qname, m.Question[0].Qtype) } -var one = []byte("1") -var zero = []byte("0") - -func hash(qname string, qtype uint16, do bool) uint64 { +func hash(qname string, qtype uint16) uint64 { h := fnv.New64() - - if do { - h.Write(one) - } else { - h.Write(zero) - } - h.Write([]byte{byte(qtype >> 8)}) h.Write([]byte{byte(qtype)}) h.Write([]byte(qname)) @@ -152,14 +142,10 @@ func (w *ResponseWriter) RemoteAddr() net.Addr { // WriteMsg implements the dns.ResponseWriter interface. func (w *ResponseWriter) WriteMsg(res *dns.Msg) error { - do := false - mt, opt := response.Typify(res, w.now().UTC()) - if opt != nil { - do = opt.Do() - } + mt, _ := response.Typify(res, w.now().UTC()) // key returns empty string for anything we don't want to cache. - hasKey, key := key(w.state.Name(), res, mt, do) + hasKey, key := key(w.state.Name(), res, mt) msgTTL := dnsutil.MinimalTTL(res, mt) var duration time.Duration @@ -187,18 +173,38 @@ func (w *ResponseWriter) WriteMsg(res *dns.Msg) error { return nil } + do := w.state.Do() + // Apply capped TTL to this reply to avoid jarring TTL experience 1799 -> 8 (e.g.) + // We also may need to filter out DNSSEC records, see toMsg() for similar code. ttl := uint32(duration.Seconds()) - for i := range res.Answer { - res.Answer[i].Header().Ttl = ttl + j := 0 + for _, r := range res.Answer { + if !do && isDNSSEC(r) { + continue + } + res.Answer[j].Header().Ttl = ttl + j++ } - for i := range res.Ns { - res.Ns[i].Header().Ttl = ttl + res.Answer = res.Answer[:j] + j = 0 + for _, r := range res.Ns { + if !do && isDNSSEC(r) { + continue + } + res.Ns[j].Header().Ttl = ttl + j++ } - for i := range res.Extra { - if res.Extra[i].Header().Rrtype != dns.TypeOPT { - res.Extra[i].Header().Ttl = ttl + res.Ns = res.Ns[:j] + j = 0 + for _, r := range res.Extra { + if !do && isDNSSEC(r) { + continue + } + if res.Extra[j].Header().Rrtype != dns.TypeOPT { + res.Extra[j].Header().Ttl = ttl } + j++ } return w.ResponseWriter.WriteMsg(res) } -- cgit v1.2.3