Sets up the package layout for a CoreDNS plugin that will accept RFC 2136 dynamic updates with TSIG authentication, primarily targeting self-hosted ACME DNS-01 cert automation. What this commit gives us: - go.mod against coredns/caddy v1.1.4, coredns/coredns v1.14.3, miekg/dns v1.1.72 - plugin.go: RFC2136 struct + Handler interface (ServeDNS is pass-through) - setup.go: init() registration + Corefile parser (skeleton — recognizes tsig-key, ttl, persist directives but doesn't yet wire them) - README.md, .gitignore go build ./... clean. No tests yet — those come with Phase 1.2 alongside the actual UPDATE handler and in-memory store. Plan: ~/.claude/plans/dood-does-coredns-offer-enumerated-piglet.md
56 lines
2.1 KiB
Go
56 lines
2.1 KiB
Go
// 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)
|
|
}
|