From 7e194a0a7d483932eb3f416b8f26131ade588acc Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sun, 12 Jul 2020 17:43:25 +0100 Subject: [PATCH] Apply floor of 60s to TTL of DNSKEY and DS records in cache. Short TTLs and specifically zero TTLs can mess up DNSSEC validation. --- src/cache.c | 21 +++++++++++++++++---- src/config.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cache.c b/src/cache.c index 30c9c41..2f2c519 100644 --- a/src/cache.c +++ b/src/cache.c @@ -472,16 +472,29 @@ void cache_start_insert(void) struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class, time_t now, unsigned long ttl, unsigned int flags) { - /* Don't log DNSSEC records here, done elsewhere */ - if (flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV)) +#ifdef HAVE_DNSSEC + if (flags & (F_DNSKEY | F_DS)) { + /* The DNSSEC validation process works by getting needed records into the + cache, then retrying the validation until they are all in place. + This can be messed up by very short TTLs, and _really_ messed up by + zero TTLs, so we force the TTL to be at least long enough to do a validation. + Ideally, we should use some kind of reference counting so that records are + locked until the validation that asked for them is complete, but this + is much easier, and just as effective. */ + if (ttl < DNSSEC_MIN_TTL) + ttl = DNSSEC_MIN_TTL; + } + else +#endif + { + /* Don't log DNSSEC records here, done elsewhere */ log_query(flags | F_UPSTREAM, name, addr, NULL); - /* Don't mess with TTL for DNSSEC records. */ if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl) ttl = daemon->max_cache_ttl; if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl) ttl = daemon->min_cache_ttl; - } + } return really_insert(name, addr, class, now, ttl, flags); } diff --git a/src/config.h b/src/config.h index 7d08f7d..f3a9fe7 100644 --- a/src/config.h +++ b/src/config.h @@ -40,6 +40,7 @@ #define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */ #define SMALLDNAME 50 /* most domain names are smaller than this */ #define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */ +#define DNSSEC_MIN_TTL 60 /* DNSKEY and DS records in cache last at least this long */ #define HOSTSFILE "/etc/hosts" #define ETHERSFILE "/etc/ethers" #define DEFLEASE 3600 /* default lease time, 1 hour */