// Package rfc2136 implements a CoreDNS plugin that accepts dynamic DNS // updates per RFC 2136 (UPDATE opcode), authenticated via TSIG. The // primary use case is self-hosted ACME DNS-01 cert automation: an ACME // client (e.g. Caddy via caddy-dns/rfc2136) injects _acme-challenge TXT // records into a delegated sub-zone that this plugin serves. // // Scope: // - Handles UPDATE messages (OPCODE=5) for configured zones. // - Verifies TSIG signatures (HMAC-SHA256 today; algorithm-pluggable). // - Stores records in memory; optional periodic snapshot to disk. // - Serves queries (SOA, NS, A, AAAA, TXT) for the configured zone // from the in-memory store plus a synthetic SOA/NS apex. // // Non-goals: // - General-purpose authoritative DNS (use `auto`/`file` for that). // - DNSSEC signing (add later via the `dnssec` plugin in front). // // Phase 1 status: skeleton only. ServeDNS passes through to the next // plugin; setup parses the Corefile but does not yet do anything with // the parsed configuration. See plan at // ~/.claude/plans/dood-does-coredns-offer-enumerated-piglet.md package rfc2136 import ( "context" "github.com/coredns/coredns/plugin" "github.com/miekg/dns" ) // RFC2136 is the plugin handler. One instance per Corefile server block. type RFC2136 struct { // Next is the downstream plugin in the chain. Next plugin.Handler // Zones is the set of canonical (dot-terminated, lowercase) zone // names this instance is authoritative for. Queries outside these // zones pass through to Next. Zones []string // Phase 2 will add: // - tsigKeys map[string]tsigKey // - store *recordStore // - ttl uint32 } // Name implements plugin.Handler. func (p *RFC2136) Name() string { return "rfc2136" } // ServeDNS implements plugin.Handler. Phase 1 is a pass-through so the // plugin can register, parse config, and live in the chain without // changing behavior. Phase 2 wires the UPDATE handler and zone serving. func (p *RFC2136) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { return plugin.NextOrFailure(p.Name(), p.Next, ctx, w, r) }