Documentation → TSIG Setup

TSIG Setup

TSIG (Transaction Signature) authenticates DNS messages between your primary nameserver and BoronDNS. Without it, any host that can reach your primary on port 53 can pull your zones.

How TSIG works

Both sides share a secret key. Each DNS message is HMAC-signed using that key and a timestamp. The receiver verifies the signature before processing the message. A replay attack is defeated because the timestamp must be within a 300-second window of the receiver's clock.

Generating a key

# 32 bytes → base64, suitable for hmac-sha256
openssl rand -base64 32
# dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j...

Use the same command on the primary side so both ends share the same secret.

Configuring BoronDNS

Store the secret in a file (preferred — keeps secrets out of the config file):

echo "dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j..." | \
  sudo tee /etc/borondns-secondary/keys/my-primary-key.key
sudo chmod 640 /etc/borondns-secondary/keys/my-primary-key.key
sudo chown borondns:borondns /etc/borondns-secondary/keys/my-primary-key.key

Add the key to config.toml:

[tsig."my-primary-key"]
algorithm   = "hmac-sha256"
secret_file = "/etc/borondns-secondary/keys/my-primary-key.key"

Then reference it in your zone block:

[[zones]]
name           = "example.com."
primaries      = [{ address = "10.0.0.1", port = 53 }]
notify_sources = ["10.0.0.1"]
tsig_name      = "my-primary-key"

Configuring the primary

BIND 9

In named.conf:

key "my-primary-key" {
    algorithm hmac-sha256;
    secret "dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j...";
};

server 10.0.0.2 {          // BoronDNS IP
    keys { my-primary-key; };
};

zone "example.com" {
    type master;
    allow-transfer { key my-primary-key; };
    also-notify { 10.0.0.2; };
};

Knot DNS

key:
  - id: my-primary-key
    algorithm: hmac-sha256
    secret: dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j...

acl:
  - id: borondns-xfr
    address: 10.0.0.2
    key: my-primary-key
    action: transfer

zone:
  - domain: example.com
    acl: borondns-xfr
    notify: 10.0.0.2

NSD

In nsd.conf:

key:
    name: "my-primary-key"
    algorithm: hmac-sha256
    secret: "dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j..."

zone:
    name: "example.com"
    zonefile: "example.com.zone"
    provide-xfr: 10.0.0.2 my-primary-key
    notify: 10.0.0.2 NOKEY

Multiple zones, one key

One key can cover multiple zones. Reference the same key name in each [[zones]]:

[tsig."shared-key"]
algorithm   = "hmac-sha256"
secret_file = "/etc/borondns-secondary/keys/shared-key.key"

[[zones]]
name           = "example.com."
primaries      = [{ address = "10.0.0.1", port = 53 }]
notify_sources = ["10.0.0.1"]
tsig_name      = "shared-key"

[[zones]]
name           = "example.net."
primaries      = [{ address = "10.0.0.1", port = 53 }]
notify_sources = ["10.0.0.1"]
tsig_name      = "shared-key"

Clock skew

TSIG verification rejects messages where the timestamp differs from the local clock by more than 300 seconds (5 minutes). If transfers fail with a signature error, check that both servers use NTP:

# Check time offset
chronyc tracking | grep "System time"

# Or with ntpq
ntpq -p

Rotating a key

  1. Generate a new secret and write it to a new key file.
  2. Add the new key to config.toml under a new name (e.g., my-primary-key-v2).
  3. Update the primary to accept both the old and new key.
  4. Update the [[zones]] blocks to reference the new key name.
  5. Restart BoronDNS (sudo systemctl restart borondns).
  6. Confirm zones are ACTIVE (/readyz), then remove the old key from the primary and from config.toml, and restart again.

Verifying TSIG with dig

# Test a zone transfer using the key
dig AXFR example.com \
    -y hmac-sha256:my-primary-key:dK3v5tP2mNqL8xR1hY9wZ0aB7cE4fG6j... \
    @10.0.0.1

If the primary accepts the key, you will see the full zone. A BADSIG error indicates the secret does not match.

Supported algorithms

AlgorithmKey sizeNotes
hmac-sha25632 bytesRecommended
hmac-sha51264 bytesHighest security
hmac-sha38448 bytes
hmac-sha22428 bytes
hmac-sha120 bytesLegacy — avoid for new deployments
hmac-md516 bytesLegacy — compatibility only