aboutsummaryrefslogtreecommitdiff
path: root/plugin/cache/handler.go
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2020-09-17 16:28:43 +0200
committerGravatar GitHub <noreply@github.com> 2020-09-17 07:28:43 -0700
commitacf9a0fa19928e605ac8ac3314890c9fef73e16b (patch)
treea442ad2a7894d86b462eade46c44db4572016333 /plugin/cache/handler.go
parent22b68466262219284a47063e7f7bf9a833d21b61 (diff)
downloadcoredns-acf9a0fa19928e605ac8ac3314890c9fef73e16b.tar.gz
coredns-acf9a0fa19928e605ac8ac3314890c9fef73e16b.tar.zst
coredns-acf9a0fa19928e605ac8ac3314890c9fef73e16b.zip
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 <miek@miek.nl> * Change OPT RR when one is present in the msg. Signed-off-by: Miek Gieben <miek@miek.nl> * Fix comment for isDNSSEC Signed-off-by: Miek Gieben <miek@miek.nl> * Update plugin/cache/handler.go Co-authored-by: Chris O'Haver <cohaver@infoblox.com> * Update plugin/cache/item.go Co-authored-by: Chris O'Haver <cohaver@infoblox.com> * Code review; fix comment for isDNSSEC Signed-off-by: Miek Gieben <miek@miek.nl> * 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 <miek@miek.nl> * Update plugin/cache/handler.go Co-authored-by: Chris O'Haver <cohaver@infoblox.com> Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
Diffstat (limited to 'plugin/cache/handler.go')
-rw-r--r--plugin/cache/handler.go42
1 files changed, 37 insertions, 5 deletions
diff --git a/plugin/cache/handler.go b/plugin/cache/handler.go
index 20a058ed2..f079e6c51 100644
--- a/plugin/cache/handler.go
+++ b/plugin/cache/handler.go
@@ -15,6 +15,7 @@ import (
// ServeDNS implements the plugin.Handler interface.
func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := request.Request{W: w, Req: r}
+ do := state.Do()
zone := plugin.Zones(c.Zones).Matches(state.Name())
if zone == "" {
@@ -22,15 +23,24 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
}
now := c.now().UTC()
-
server := metrics.WithServer(ctx)
+ // On cache miss, if the request has the OPT record and the DO bit set we leave the message as-is. If there isn't a DO bit
+ // set we will modify the request to _add_ one. This means we will always do DNSSEC lookups on cache misses.
+ // When writing to cache, any DNSSEC RRs in the response are written to cache with the response.
+ // When sending a response to a non-DNSSEC client, we remove DNSSEC RRs from the response. We use a 2048 buffer size, which is
+ // less than 4096 (and older default) and more than 1024 which may be too small. We might need to tweaks this
+ // value to be smaller still to prevent UDP fragmentation?
+
ttl := 0
i := c.getIgnoreTTL(now, state, server)
if i != nil {
ttl = i.ttl(now)
}
if i == nil {
+ if !do {
+ setDo(r)
+ }
crr := &ResponseWriter{ResponseWriter: w, Cache: c, state: state, server: server}
return plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r)
}
@@ -40,11 +50,14 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
now = now.Add(time.Duration(ttl) * time.Second)
go func() {
r := r.Copy()
+ if !do {
+ setDo(r)
+ }
crr := &ResponseWriter{Cache: c, state: state, server: server, prefetch: true, remoteAddr: w.LocalAddr()}
plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r)
}()
}
- resp := i.toMsg(r, now)
+ resp := i.toMsg(r, now, do)
w.WriteMsg(resp)
if c.shouldPrefetch(i, now) {
@@ -80,7 +93,7 @@ func (c *Cache) shouldPrefetch(i *item, now time.Time) bool {
func (c *Cache) Name() string { return "cache" }
func (c *Cache) get(now time.Time, state request.Request, server string) (*item, bool) {
- k := hash(state.Name(), state.QType(), state.Do())
+ k := hash(state.Name(), state.QType())
if i, ok := c.ncache.Get(k); ok && i.(*item).ttl(now) > 0 {
cacheHits.WithLabelValues(server, Denial).Inc()
@@ -97,7 +110,7 @@ func (c *Cache) get(now time.Time, state request.Request, server string) (*item,
// getIgnoreTTL unconditionally returns an item if it exists in the cache.
func (c *Cache) getIgnoreTTL(now time.Time, state request.Request, server string) *item {
- k := hash(state.Name(), state.QType(), state.Do())
+ k := hash(state.Name(), state.QType())
if i, ok := c.ncache.Get(k); ok {
ttl := i.(*item).ttl(now)
@@ -118,7 +131,7 @@ func (c *Cache) getIgnoreTTL(now time.Time, state request.Request, server string
}
func (c *Cache) exists(state request.Request) *item {
- k := hash(state.Name(), state.QType(), state.Do())
+ k := hash(state.Name(), state.QType())
if i, ok := c.ncache.Get(k); ok {
return i.(*item)
}
@@ -127,3 +140,22 @@ func (c *Cache) exists(state request.Request) *item {
}
return nil
}
+
+// setDo sets the DO bit and UDP buffer size in the message m.
+func setDo(m *dns.Msg) {
+ o := m.IsEdns0()
+ if o != nil {
+ o.SetDo()
+ o.SetUDPSize(defaultUDPBufSize)
+ return
+ }
+
+ o = &dns.OPT{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeOPT}}
+ o.SetDo()
+ o.SetUDPSize(defaultUDPBufSize)
+ m.Extra = append(m.Extra, o)
+}
+
+// defaultUDPBufsize is the bufsize the cache plugin uses on outgoing requests that don't
+// have an OPT RR.
+const defaultUDPBufSize = 2048