Files
go-dns/docs/bind-tsig-configuration.md
T

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

  1. Check syntax:

    named-checkconf
    
  2. Reload BIND (adjust command for your installation):

    rndc reload
    
  3. 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
    
  4. Verify AXFR with TSIG:

    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):

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.

  • Guide — how callers use AXFR, UPDATE, and TSIG
  • API — exported symbols
  • Project specification — library scope, TSIG model, AXFR-only transfers