mirror of
https://github.com/coredns/coredns.git
synced 2026-08-20 23:08:28 -04:00
* plugin/cache: do not cache SOA-less NODATA responses An upstream may return NOERROR with a non-empty answer that still does not resolve the question and without an SOA record to bound a negative TTL: a CNAME chain that does not terminate in a record of the queried type at the chain's terminal name (an incomplete recursion result from a forwarder). Because the answer section is non-empty, response.Typify classifies it as NoError (positive), so the cache plugin stores it keyed on <qname,qtype> and replays the non-answer to clients until the TTL expires. Per RFC 2308 section 5, negative responses without an SOA record SHOULD NOT be cached. Following RFC 1034 section 3.6.2 and RFC 2308 sections 1 and 2.2, the effective owner name is the target at the end of the CNAME chain, and the response is NODATA unless it carries the queried type at that terminal name; this holds for every query type, not just A/AAAA. Skip caching such a response (mirroring the existing NameError && !hasSOA guard) and let the next query be resolved upstream again. An empty answer section is deliberately left cacheable: it is indistinguishable from a legitimate NOERROR positive response that carries its data outside the answer section (for example the whoami plugin). Refs coredns#6958, coredns#5077, coredns#4987. Signed-off-by: Nitin Nizhawan <nitin.nizhawan@gmail.com> * plugin/cache: fail closed on malformed CNAME chains in isNODATA canonicalName now returns a validity flag and rejects chains that are not a single unambiguous path to a terminal name: an owner with more than one distinct CNAME target (RFC 2181 section 10.1) and a revisited owner / CNAME loop (RFC 1034 section 3.6.2). isNODATA treats an invalid chain as a non-answer, so a SOA-less response with such a chain is not cached. This makes the classification order-independent (previously the first CNAME per owner won, so a two-target owner was cacheable or not depending on wire order) and closes the loop-with-co-located-record case. Duplicate CNAME records naming the same target are still tolerated. Adds regression tests for the two-distinct-targets case in both orders, the CNAME loop with a co-located A, and the tolerated duplicate-identical-CNAME case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d59b4564-a9df-425f-858e-aadee0f35581 Signed-off-by: Nitin Nizhawan <nitin.nizhawan@gmail.com> * plugin/cache: split canonicalName into self-documenting helpers Extract the per-owner CNAME lookup into uniqueCNAMETarget and loop detection into a small case-insensitive nameSet type, leaving canonicalName as a short driver. Signature and algorithm are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d59b4564-a9df-425f-858e-aadee0f35581 Signed-off-by: Nitin Nizhawan <nitin.nizhawan@gmail.com> --------- Signed-off-by: Nitin Nizhawan <nitin.nizhawan@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d59b4564-a9df-425f-858e-aadee0f35581
16 KiB
16 KiB