docs: add BIND TSIG guide and align project documentation

Create bind-tsig-configuration.md for allow-update and allow-transfer
setup. Link from README and project spec; extend .gitignore for .env files.
Record implementation decisions for change C-00001-setup-project.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Konrad Neitzel
2026-07-04 14:27:03 +02:00
co-authored by Cursor
parent 47f17445d0
commit eff7637f86
6 changed files with 198 additions and 3 deletions
+149
View File
@@ -0,0 +1,149 @@
# 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))
## Define the TSIG key
Generate a key on the server (or any host with BIND utilities):
```bash
tsig-keygen -a hmac-sha256 go-dns-key
```
Or:
```bash
rndc tsig-keygen -a hmac-sha256 go-dns-key
```
Output is a `key { ... };` block suitable for `named.conf`. Example:
```bind
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:
```bind
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:
```bind
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`:
```bind
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
1. Check syntax:
```bash
named-checkconf
```
2. Reload BIND (adjust command for your installation):
```bash
rndc reload
```
3. Verify **dynamic update** (replace host, zone, and key values):
```bash
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
```
4. Verify **AXFR** with TSIG:
```bash
dig @ns.example.com example.com AXFR -y hmac-sha256:go-dns-key:BASE64SECRET +tcp
```
A 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-transfer` to trusted networks or TSIG keys; never use `allow-transfer { any; };` on the Internet.
- **Separate read and write keys** — Use one TSIG key with `allow-transfer` only and another with `allow-update` only 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 `BADSIG` errors.
- **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):
```bind
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
- [Project specification](project-specification.md) — library scope, TSIG model, AXFR-only transfers
- [Change 00001 spec](changes/00001-setup-project/spec.md) — full DNS operation catalog and BIND guide requirements
- [Product backlog](backlog.md) — future work (e.g. IXFR)