Open-Source Wikis

/

CoreDNS

/

Plugins

/

Forwarding and caching

coredns/coredns

Forwarding and caching

Active contributors: johnbelamaric, miekg, chrisohaver, Tantalor93, rdrozhdzh

Purpose

This group covers plugins that send queries elsewhere or short-circuit them locally. Together they make CoreDNS a recursive-style resolver in front of upstreams.

Plugins in this group

Plugin Source One-liner
forward plugin/forward/ Forward to upstream resolvers over UDP, TCP, or DoT
grpc plugin/grpc/ Forward to upstream over gRPC (pb/dns.proto)
cache plugin/cache/ LRU cache for positive and negative responses
dns64 plugin/dns64/ RFC 6147 IPv6 synthesis from IPv4 answers
loop plugin/loop/ Detect forwarding loops at startup

How they cooperate

graph LR
    Q[query] --> Cache[cache]
    Cache -->|miss| Forward[forward]
    Cache -->|hit| Reply[reply]
    Forward --> U1[upstream 1]
    Forward --> U2[upstream 2]
    U1 -->|response| Cache
    U2 -->|response| Cache
    Cache -->|stored| Reply

cache lives in front of forward (or any backend) and stores positive (success) and denial (denial) replies in two sharded caches. forward opens persistent connections to one or more upstreams, picks one according to a policy (random, round-robin, sequential), and writes the reply through the cache wrapper so future queries hit.

forward

The cornerstone forwarder.

  • Multiple upstreams (max 15) randomized on first use, with round-robin and sequential policies.
  • Persistent connection cache per upstream (default expire 10s); idle TCP/UDP/DoT connections live in plugin/pkg/proxy.
  • Inband health checking: when a query fails, up runs . IN NS against the upstream every 500 ms until it answers; queries continue with healthy peers in the meantime. max_fails (default 2) controls how many consecutive failures mark an upstream down.
  • DoT (tls://...) supported including per-endpoint server name (tls://9.9.9.9%dns.quad9.net).
  • Knobs: force_tcp, prefer_udp, expire, max_idle_conns, max_fails, max_concurrent, max_connect_attempts, next (rcode list to fall through), failover (rcodes to retry on next upstream), failfast_all_unhealthy_upstreams, health_check.
  • Dnstap integration: when the dnstap plugin is loaded, every upstream exchange is reported.
  • Metrics: latency histograms, request counters, connection cache size, upstream selection counters (plugin/forward/metrics.go).

Forward.ServeDNS walks the upstream list, retries up to defaultTimeout (5s) or max_connect_attempts, and falls through on next rcodes. The full lifecycle is in plugin/forward/forward.go.

grpc

Sibling of forward that speaks the gRPC service from pb/dns.proto. Same connection cache, same policies; useful for cluster-internal CoreDNS-to-CoreDNS forwarding where TLS+gRPC is preferred over DoT.

cache

A two-cache plugin: positive replies (success) and denials (denial) live in separate sharded LRUs. Sharding factor is 256 by default; default capacity is 9984 entries.

Key behavior:

  • TTLs are clamped between configurable min and max per cache. Defaults: success 5s..3600s, denial 5s..1800s.
  • The plugin wraps the downstream dns.ResponseWriter with its own ResponseWriter so it can call res.Copy() and store before forwarding to the client.
  • prefetch AMOUNT [DURATION] [PERCENTAGE%] refreshes popular entries before they expire by replaying the question through the chain with a synthetic TCP-style RemoteAddr. Prefetch responses go through newPrefetchResponseWriter which short-circuits the actual client write.
  • serve_stale [DURATION] [REFRESH_MODE] keeps expired entries usable while a refresh runs (RFC 8767). verify mode only writes the new entry when the refresh succeeds (verifyStaleResponseWriter).
  • keepttl preserves the original TTL of cached records when serving them.
  • servfail DURATION enables a brief negative cache for SERVFAIL replies to dampen storms.
  • DNSSEC-aware: DO/CD bits are part of the cache key (see key() in plugin/cache/cache.go).
  • Metrics: hits, misses, drops, size, evictions, prefetches, served stale (plugin/cache/metrics.go).

The cache lookup path is in plugin/cache/handler.go; the writer path that stores entries is in plugin/cache/cache.go.

dns64

RFC 6147 IPv6 synthesis. When a client asks for AAAA and gets NODATA, dns64 re-issues the question as A and synthesises AAAA records inside a configurable IPv6 prefix (64:ff9b::/96 by default). The plugin uses plugin/pkg/upstream to look up the A record through the rest of the chain.

loop

Sends a probe at startup to detect short forwarding loops (a CoreDNS that forwards to itself). Logs and aborts startup if a loop is found. No runtime cost after startup.

Cross-plugin notes

  • cache should always come before forward so cached replies don't pay the forwarding cost.
  • forward and grpc both report through dnstap if the dnstap plugin is loaded.
  • Connection caching in plugin/pkg/proxy is shared between forward and grpc.
  • forward honours metadata set by upstream plugins; metadata.SetValueFunc("forward/upstream", ...) lets downstream consumers know which upstream answered.
  • dns64 cooperates with cache only when the synthesized answer's TTL is non-zero.

Key source files

File Purpose
plugin/forward/forward.go, setup.go, policy.go, dnstap.go, metrics.go The forwarder
plugin/grpc/grpc.go, setup.go gRPC forwarder
plugin/cache/cache.go, handler.go, setup.go, item.go, metrics.go Caching layer
plugin/cache/freq/ Frequency tracker for prefetch
plugin/dns64/dns64.go IPv6 synthesis
plugin/loop/loop.go Loop probe
plugin/pkg/proxy/ Shared upstream connection cache
plugin/pkg/up/ Periodic probes for forward health
  • Backends — where the forwarded query might originate before forwarding.
  • Observabilitydnstap, prometheus, log, errors for tracking forwards and cache.
  • Transports — DoT, DoQ, gRPC server side.
  • Shared packagespkg/proxy, pkg/up, pkg/cache.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Forwarding and caching – CoreDNS wiki | Factory