From eff7637f86493c23af15cfa1f7744a6b38e2c8e2 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Sat, 4 Jul 2026 14:27:03 +0200 Subject: [PATCH] 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 --- .cursor/rules/project-specification.mdc | 2 +- .gitignore | 2 + README.md | 1 + docs/bind-tsig-configuration.md | 149 ++++++++++++++++++ .../00001-setup-project/impl-decisions.md | 41 +++++ docs/project-specification.md | 6 +- 6 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 docs/bind-tsig-configuration.md create mode 100644 docs/changes/00001-setup-project/impl-decisions.md diff --git a/.cursor/rules/project-specification.mdc b/.cursor/rules/project-specification.mdc index c18888f..8a38314 100644 --- a/.cursor/rules/project-specification.mdc +++ b/.cursor/rules/project-specification.mdc @@ -23,7 +23,7 @@ Follow `docs/project-specification.md` for design and implementation. - Domain names: **ASCII only** in v1 - UPDATE: **automatic TCP fallback** on UDP truncation - Integration tests: **BIND testcontainer** (`go test -tags=integration ./...`) -- **`docs/bind-tsig-configuration.md`** — BIND `allow-update` / `allow-transfer` guide (implementation phase) +- **`docs/bind-tsig-configuration.md`** — BIND `allow-update` / `allow-transfer` guide - Typed **zone data structures** (`Record`, `Zone`, etc.) for transfer/update results - Project `.cursor` overrides workspace rules for this module diff --git a/.gitignore b/.gitignore index 196ba28..193baf4 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ coverage.html # Local config (secrets) testconfig/local.toml +.env +.env.* diff --git a/README.md b/README.md index df04862..5c58fb1 100644 --- a/README.md +++ b/README.md @@ -21,5 +21,6 @@ Module path: `gitea.neitzel.de/konrad/go-dns` — import as **`godns`**. ## Documentation - [Project specification](docs/project-specification.md) +- [BIND TSIG configuration](docs/bind-tsig-configuration.md) - [Product backlog](docs/backlog.md) - [Change efforts](docs/changes/) diff --git a/docs/bind-tsig-configuration.md b/docs/bind-tsig-configuration.md new file mode 100644 index 0000000..da7fba5 --- /dev/null +++ b/docs/bind-tsig-configuration.md @@ -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 <