5.0 KiB
BIND TSIG configuration for go-dns
This guide describes how to configure BIND 9 so a TSIG shared secret can perform:
- Dynamic updates (RFC 2136) — the same operations as
nsupdate - Full zone transfer (AXFR) — read the entire zone over TCP
The go-dns library (godns) signs requests with TSIG; BIND verifies the signature and applies ACLs for that key. Key generation is not part of go-dns — operators create keys with BIND tooling or copy secrets from existing secret management.
Prerequisites
- BIND 9.x authoritative server for the target zone
- Shell access to edit
named.conf(or included snippets) and reload the server - A TSIG key name, algorithm, and Base64 secret (see Define the TSIG key)
Define the TSIG key
Generate a key on the server (or any host with BIND utilities):
tsig-keygen -a hmac-sha256 go-dns-key
Or:
rndc tsig-keygen -a hmac-sha256 go-dns-key
Output is a key { ... }; block suitable for named.conf. Example:
key "go-dns-key" {
algorithm hmac-sha256;
secret "q4f6j2+8vK9mN3pR7sT1uW5xY0zA2bC4dE6fG8hI0jK=";
};
Place the key in named.conf or in an included file (e.g. /etc/bind/keys.conf) referenced with:
include "/etc/bind/keys.conf";
Important: Treat the secret like a password. Do not commit it to version control. go-dns callers pass the same key name, algorithm, and secret at runtime.
Configure the zone
Reference the key in the zone block for the origin you want to update and transfer. Both ACLs are required for go-dns clients that perform updates and AXFR with the same key:
zone "example.com" {
type master;
file "/var/lib/bind/db.example.com";
allow-update { key "go-dns-key"; };
allow-transfer { key "go-dns-key"; };
};
| Directive | Purpose |
|---|---|
allow-update |
Permits RFC 2136 UPDATE messages signed with this TSIG key |
allow-transfer |
Permits AXFR (full zone transfer) to clients signing with this TSIG key |
If you only need updates or only transfers, grant the corresponding directive alone. go-dns supports separate keys per client instance when policy requires different read and write credentials.
Optional: stricter update policy
Broad allow-update { key "..."; }; grants update access to the entire zone. For finer control, use update-policy instead of or in addition to allow-update:
zone "example.com" {
type master;
file "/var/lib/bind/db.example.com";
allow-transfer { key "go-dns-key"; };
update-policy {
grant go-dns-key subdomain example.com. A AAAA TXT;
};
};
Policy syntax and grant types are documented in the BIND 9 Administrator Reference Manual. Choose allow-update or update-policy according to your security model; do not leave zones open to unauthenticated updates.
Reload and validate configuration
-
Check syntax:
named-checkconf -
Reload BIND (adjust command for your installation):
rndc reload -
Verify dynamic update (replace host, zone, and key values):
nsupdate -y hmac-sha256:go-dns-key:BASE64SECRET <<EOF server ns.example.com zone example.com update add test.example.com 300 IN A 192.0.2.10 send EOF -
Verify AXFR with TSIG:
dig @ns.example.com example.com AXFR -y hmac-sha256:go-dns-key:BASE64SECRET +tcpA successful transfer lists all zone records and terminates with the zone's SOA RR.
Security notes
- Restrict scope — Grant the key only on zones that automation must manage. Avoid
allow-update { key ...; };on parent zones unless intentional. - Do not expose AXFR publicly — Zone transfers reveal full zone contents. Restrict
allow-transferto trusted networks or TSIG keys; never useallow-transfer { any; };on the Internet. - Separate read and write keys — Use one TSIG key with
allow-transferonly and another withallow-updateonly when policy requires split privileges. go-dns clients configure one key per session. - Rotate secrets — When rotating a TSIG secret, update BIND and all go-dns callers together; mismatched secrets produce
BADSIGerrors. - Algorithm choice — Prefer hmac-sha256 (or stronger) over legacy hmac-md5 for new keys.
Complete minimal example
The following fragment is a self-contained illustration (adjust paths and zone data file):
key "go-dns-key" {
algorithm hmac-sha256;
secret "q4f6j2+8vK9mN3pR7sT1uW5xY0zA2bC4dE6fG8hI0jK=";
};
zone "example.com" {
type master;
file "/var/lib/bind/db.example.com";
allow-update { key "go-dns-key"; };
allow-transfer { key "go-dns-key"; };
};
Ensure db.example.com exists with a valid SOA and NS records before loading the zone.
Related documentation
- Guide — how callers use AXFR, UPDATE, and TSIG
- API — exported symbols
- Project specification — library scope, TSIG model, AXFR-only transfers