A DNS UPDATE multiplexer that fans out TSIG-signed RFC 2136 dynamic DNS updates from a single sender (kea-dhcp-ddns) to multiple PowerDNS targets, re-signing each outbound update with the target's own TSIG key.
Written in Rust with hickory-proto, tokio, and serde/toml.
You have kea-dhcp-ddns handing out DHCP leases and updating DNS records via RFC 2136, but your DNS infrastructure spans multiple PowerDNS nodes (e.g. different zones, different data centers, or just redundancy). Kea can send updates to only one target. You need them delivered to all of them, each with its own TSIG signature.
The native PowerDNS answer would be a database backend with active-active replication — but that means maintaining yet another MySQL/MariaDB cluster. This project is an alternative: a small, safe, zero-database middlebox.
kea-dhcp-ddns ──(TSIG-signed UPDATE)──► ddns-mux
│
├─(per-target TSIG)──► pdns-1
├─(per-target TSIG)──► pdns-2
└─(per-target TSIG)──► pdns-3
- ddns-mux listens for DNS UPDATE messages over both UDP and TCP.
- Each inbound message is verified against the configured TSIG key.
- The update is fanned out concurrently to all configured targets.
- Each target receives its own TSIG-signed copy of the update.
- A confirmation strategy determines the aggregate result returned to kea:
all(default): every target must succeedany: at least one target must succeed
- A TSIG-signed response is sent back to the original sender.
Forwarding uses UDP first, falling back to TCP if the response is truncated. A 5-second timeout applies to each target.
See config.toml.example:
listen_tcp = "127.0.0.1:5353"
listen_udp = "127.0.0.1:5353"
require_confirmation = "all"
[incoming_tsig]
algorithm = "hmac-sha256"
key = "base64-encoded-secret=="
name = "kea-ddns-key."
[[targets]]
address = "192.168.1.1:53"
[targets.tsig]
algorithm = "hmac-sha256"
key = "base64-encoded-secret-for-pdns1=="
name = "ddns-mux-pdns1."
[[targets]]
address = "192.168.1.2:53"
[targets.tsig]
algorithm = "hmac-sha256"
key = "base64-encoded-secret-for-pdns2=="
name = "ddns-mux-pdns2."Supported algorithms: hmac-sha256, hmac-sha384, hmac-sha512.
cargo build --release
./target/release/ddns-mux /path/to/config.tomlLogging is handled by tracing. Set the level via RUST_LOG (e.g. RUST_LOG=info).
This project was built with the assistance of AI coding agents:
- Claude Code (Anthropic)
- Codex (OpenAI)
- Gemini CLI (Google)
- OpenCode with Qwen 3.6 27B
This GitHub repository is a read-only mirror of my internal workspace. Issues and Pull Requests are currently disabled. If you have feedback or patches, feel free to reach out to me directly. If the project becomes popular, I will reconsider this.