Send DNS NOTIFY to secondaries after every UPDATE
Per RFC 1996, a master that mutates a zone SHOULD notify its
secondaries so they can immediately AXFR rather than wait for their
next SOA-refresh poll. Without this, propagation lag from UPDATE to
public DNS is bounded by the secondary's refresh interval (300s for
us) — which is borderline for ACME validation timing.
New Corefile directive:
notify <host[:port]> [<host[:port]>...]
Targets accept bare hostnames (port 53 default), host:port, or
[ipv6]:port. The same list applies to every zone in the rfc2136
block.
Implementation: fire-and-forget UDP per target, each in its own
goroutine, capped by a 2s timeout. The UPDATE response to the client
is never held pending NOTIFY acks (RFC 1996 §4 explicitly decouples
them). Failures log at DEBUG only — a briefly-unreachable secondary
is normal and would otherwise spam logs.
Retires the external scripts/notify-secondaries.py workflow for any
deployment that wires the directive: secondaries now hear about
changes within seconds of the UPDATE landing, no cron or manual
invocation needed.
New tests:
- TestSendNotify_DeliversToTarget — packet arrives, opcode + zone correct
- TestSendNotify_NoTargets_NoCrash — empty list short-circuits
- TestSendNotify_BadTarget_LogsButDoesNotBlock — fire-and-forget timing
- TestNotifyOne_AppendsDefaultPort — host vs host:port normalization
This commit is contained in:
parent
89993ca207
commit
7367401734
6 changed files with 241 additions and 0 deletions
29
README.md
29
README.md
|
|
@ -51,6 +51,7 @@ rfc2136 <zone> [<zone>...] {
|
|||
git-author <name> <email> # optional
|
||||
rate-limit <burst> <period-seconds> # default 100 / 60s
|
||||
rate-limit off # disable rate-limit
|
||||
notify <host[:port]> [<host[:port]>...] # NOTIFY secondaries on every UPDATE
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -149,6 +150,34 @@ UPDATE traffic is token-bucket capped per TSIG key. Default 100
|
|||
UPDATEs per 60 seconds. ACME storms are well within this; anything
|
||||
beyond is suspicious. Tune via `rate-limit <burst> <period>`.
|
||||
|
||||
### NOTIFY to secondaries (optional)
|
||||
|
||||
After every successful UPDATE, the plugin can fire DNS NOTIFY (RFC
|
||||
1996) to a list of secondary servers. This collapses propagation lag
|
||||
from "up to the secondary's SOA refresh interval" (often 300s) to
|
||||
"a few seconds" — secondaries that receive NOTIFY do an immediate SOA
|
||||
poll and AXFR if changed.
|
||||
|
||||
Configure with the `notify` directive:
|
||||
|
||||
```
|
||||
rfc2136 example.com {
|
||||
zones-dir /zones
|
||||
tsig-key ...
|
||||
notify ns2.example.com ns3.example.com 216.218.130.2
|
||||
}
|
||||
```
|
||||
|
||||
Semantics:
|
||||
- Targets may be `host`, `host:port`, or `[ipv6]:port`. Default port is 53.
|
||||
- Fire-and-forget: each target gets its own goroutine with a 2s timeout.
|
||||
The UPDATE response to the client is **not** held pending NOTIFY acks
|
||||
(RFC 1996 §4 decouples them).
|
||||
- Failures log at DEBUG only — a briefly-unreachable secondary is
|
||||
normal and would otherwise spam.
|
||||
- Missed NOTIFY = no harm; secondary catches up on its own refresh.
|
||||
- The same target list applies to every zone in the block.
|
||||
|
||||
## Building
|
||||
|
||||
This plugin is consumed by a custom CoreDNS build via `plugin.cfg`:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue