getnamingo-registry/docs/dns.md
2025-07-11 13:21:43 +03:00

19 KiB
Raw Permalink Blame History

Namingo Registry: DNS Setup Guide

This guide walks you through configuring the core DNS setup for your Namingo-powered registry. It includes creating a hidden master DNS server, which acts as the authoritative source for all zone data. Your TLD DNS servers (public-facing) will be configured to receive updates from this hidden master.

⚠️ This setup is [Required] for proper zone publication and delegation of domains under your TLDs.

1. Hidden Master DNS Server Setup

This section covers how to set up your hidden master — the central source Namingo updates with zone changes. Public-facing DNS servers (e.g., slaves or Anycast nodes) will pull zones from it and serve them to the world.

⚠️ Choose only one of the following DNS backends based on your environment and preferences. Do not install all of them.

1.1. BIND9 (with native DNSSEC, OpenDNSSEC, or Unsigned Zones)

BIND9 supports multiple DNSSEC modes: native signing with automatic key rollover, external signing using OpenDNSSEC, or serving unsigned zones. Choose the method that fits your operational needs.

1.1.1. Installation

apt install bind9 bind9-utils bind9-doc

1.1.2. Generate a TSIG key

Generate a TSIG key which will be used to authenticate DNS updates between the master and slave servers. Note: replace test with your TLD.

cd /etc/bind
tsig-keygen -a HMAC-SHA256 test.key

The output will be in the format that can be directly included in your BIND configuration files. It looks something like this:

key "test.key" {
    algorithm hmac-sha256;
    secret "base64-encoded-secret==";
};

Copy this output for use in the configuration files of both the master and slave DNS servers. (/etc/bind/named.conf.local)

⚠️ Choose one configuration from the following section that fits your setup. Do not combine them.

1.1.3a. Native DNSSEC Signed by BIND

Edit the named.conf.local file:

nano /etc/bind/named.conf.local

Add the following DNSSEC policy:

dnssec-policy "namingo-policy" {
    keys {
        ksk lifetime P1Y algorithm ed25519;
        zsk lifetime P2M algorithm ed25519;
    };
    nsec3param iterations 0 optout false salt-length 0;
    publish-safety 7d;
    max-zone-ttl 86400;
    dnskey-ttl 3600;
    zone-propagation-delay 3600;
    parent-propagation-delay 7200;
    parent-ds-ttl 86400;
};

Then, add the zone definition:

zone "test." {
    type master;
    file "/var/lib/bind/test.zone";
    dnssec-policy "namingo-policy";
    key-directory "/var/lib/bind";
    inline-signing yes;
    allow-transfer { key "test.key"; };
    also-notify { <slave-server-IP>; };
};

Replace <slave-server-IP> with the actual IP address of your slave server. Replace test with your TLD.

🔒 Security Tip: DNSSEC private keys must be properly secured.

Set correct ownership and permissions, then restart BIND9 to apply changes:

chown -R bind:bind /var/lib/bind
chmod -R go-rwx /var/lib/bind
systemctl restart bind9

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

⚠️ Important: In the Control Panel → TLD Management, click the Enable DNSSEC button. After the keys are created, the DS Record will appear on the same page and should be submitted to IANA or the parent registry.

1.1.3a.1. Optional: Configure BIND with PKCS#11 Support
apt install softhsm2 opensc libengine-pkcs11-openssl

If using SoftHSM, also initialize the token with:

softhsm2-util --init-token --slot 0 --label YourTokenLabel

Edit /etc/bind/named.conf.options and add the following:

options {
    // Existing options...
    dnssec-policy "hsm-policy";
};

dnssec-policy "hsm-policy" {
    keys {
        ksk lifetime P1Y algorithm ecdsap256sha256;
        zsk lifetime P2M algorithm ecdsap256sha256;
    };
    max-zone-ttl 86400;
    dnskey-ttl 3600;
    zone-propagation-delay 3600;
    parent-propagation-delay 7200;
    parent-ds-ttl 86400;
};

Then, add the zone definition:

zone "test." {
    type master;
    file "/var/lib/bind/test.zone";
    dnssec-policy "hsm-policy";
    inline-signing yes;
    allow-transfer { key "test.key"; };
    also-notify { <slave-server-IP>; };
};

Replace <slave-server-IP> with the actual IP address of your slave server. Replace test with your TLD.

Set the PKCS#11 provider in environment before running BIND:

export PKCS11_PROVIDER=/usr/lib/softhsm/libsofthsm2.so

Set correct permissions and restart BIND9 to apply changes:

chown -R bind:bind /var/lib/bind
systemctl restart bind9

BIND will automatically generate keys within the device when configured correctly:

rndc loadkeys your.tld
rndc signing -list your.tld

You can verify the keys with tools provided by your HSM vendor or via standard PKCS#11 utilities:

softhsm2-util --show-slots

or

pkcs11-tool --list-objects --login --token-label YourTokenLabel

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

⚠️ Important: In the Control Panel → TLD Management, click the Enable DNSSEC button. After the keys are created, the DS Record will appear on the same page and should be submitted to IANA or the parent registry.

1.1.3b. External DNSSEC Signed by OpenDNSSEC

Edit the named.conf.local file:

nano /etc/bind/named.conf.local

Add the following zone definition:

zone "test." {
    type master;
    file "/var/lib/bind/test.zone.signed";
    allow-transfer { key "test.key"; };
    also-notify { <slave-server-IP>; };
};

Replace <slave-server-IP> with the actual IP address of your slave server. Replace test with your TLD.

Install OpenDNSSEC:

apt install opendnssec opendnssec-enforcer-sqlite3 opendnssec-signer softhsm2
mkdir -p /var/lib/softhsm/tokens
chown -R opendnssec:opendnssec /var/lib/softhsm/tokens
softhsm2-util --init-token --slot 0 --label OpenDNSSEC --pin 1234 --so-pin 1234

Update files in /etc/opendnssec to match your registry policy. As minimum, please enable at least Signer Threads in /etc/opendnssec/conf.xml, but we recommend to fully review all the files. Then run the following commands:

chown -R opendnssec:opendnssec /etc/opendnssec
ods-enforcer-db-setup
ods-enforcer policy import
rm /etc/opendnssec/prevent-startup
chown opendnssec:opendnssec /var/lib/bind/test.zone
chmod 644 /var/lib/bind/test.zone
ods-enforcer zone add -z test -p default -i /var/lib/bind/test.zone
ods-control start

Edit again the named.conf.local file:

nano /etc/bind/named.conf.local

Replace the value for file with the following filename:

...
    file "/var/lib/opendnssec/signed/test.zone.signed";
...
};

Use rndc to reload BIND:

systemctl restart bind9

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

⚠️ Important: In the Control Panel → TLD Management, click the Enable DNSSEC button. After the keys are created, the DS Record will appear on the same page and should be submitted to IANA or the parent registry.

1.1.3c. Unsigned Zone

Edit the named.conf.local file:

nano /etc/bind/named.conf.local

Add the following zone definition:

zone "test." {
    type master;
    file "/var/lib/bind/test.zone";
    allow-transfer { key "test.key"; };
    also-notify { <slave-server-IP>; };
};

Replace <slave-server-IP> with the actual IP address of your slave server. Replace test with your TLD.

Use rndc to reload BIND:

systemctl restart bind9

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

1.1.4. Enabling Logs

Place the contents below at /etc/bind/named.conf.default-logging and include the file in /etc/bind/named.conf:

logging {
    // General logs (startup, shutdown, errors)
    channel "misc" {
        file "/var/log/named/misc.log" versions 10 size 10m;
        print-time YES;
        print-severity YES;
        print-category YES;
    };

    // Query logs (log every DNS query)
    channel "query" {
        file "/var/log/named/query.log" versions 20 size 5m;
        print-time YES;
        print-severity NO;
        print-category NO;
    };

    // Lame server logs (misconfigured DNS servers)
    channel "lame" {
        file "/var/log/named/lamers.log" versions 3 size 5m;
        print-time YES;
        print-severity YES;
        severity info;
    };

    // Security logs (e.g., unauthorized query attempts)
    channel "security" {
        file "/var/log/named/security.log" versions 5 size 10m;
        print-time YES;
        print-severity YES;
        severity dynamic;
    };

    // DNS updates (useful for dynamic zones)
    channel "update" {
        file "/var/log/named/update.log" versions 3 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Resolver logs (useful for debugging recursive queries)
    channel "resolver" {
        file "/var/log/named/resolver.log" versions 5 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Zone transfer logs (incoming & outgoing transfers)
    channel "xfer" {
        file "/var/log/named/xfer.log" versions 5 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Assign categories to log files
    category "default" { "misc"; };
    category "queries" { "query"; };
    category "lame-servers" { "lame"; };
    category "security" { "security"; };
    category "update" { "update"; };
    category "resolver" { "resolver"; };
    category "xfer-in" { "xfer"; };
    category "xfer-out" { "xfer"; };
};

1.1.5. Validate and Apply Configuration

After completing your configuration, check for syntax errors using named-checkconf and verify your zone file with named-checkzone test /var/lib/bind/test.zone. If everything is correct, restart BIND9 using systemctl restart bind9.

To confirm that your zone has been loaded successfully, run grep named /var/log/syslog and look for a log entry indicating the zone was loaded without errors.

You should see something like: zone test/IN: loaded serial 2025041901 indicating success.

1.2. Knot DNS (with native DNSSEC)

1.2.1. Installation

apt install knot knot-dnsutils

1.2.2. Generate a TSIG key

Generate a TSIG key which will be used to authenticate DNS updates between the master and slave servers. Note: replace test with your TLD.

cd /etc/knot
knotc conf-gen-key test.key hmac-sha256

The output will be in the format that can be directly included in your configuration files. It looks something like this:

key:
  - id: "test.key"
    algorithm: hmac-sha256
    secret: "base64-encoded-secret=="

Copy this output for use in the configuration files of both the master and slave DNS servers. (/etc/knot/knot.conf)

1.2.3. Configure DNSSEC Policy

Add the DNSSEC policy to /etc/knot/knot.conf:

nano /etc/knot/knot.conf

Add the following DNSSEC policy:

policy:
  - id: "namingo-policy"
    description: "Default DNSSEC policy for TLD"
    algorithm: ed25519
    ksk-lifetime: 1y
    zsk-lifetime: 2m
    max-zone-ttl: 86400
    rrsig-lifetime: 14d
    rrsig-refresh: 7d
    dnskey-ttl: 3600
    nsec3: true
    nsec3-iterations: 0
    nsec3-salt-length: 0

1.2.4. Add your zone

Add the zone to /etc/knot/knot.conf:

zone:
  - domain: "test."
    file: "/etc/knot/zones/test.zone"
    dnssec-policy: "namingo-policy"
    key-directory: "/etc/knot/keys"
    storage: "/etc/knot/zones"
    notify: <slave-server-IP>
    acl:
      - id: "test.key"
        address: <slave-server-IP>
        key: "test.key"

Replace <slave-server-IP> with the actual IP address of your slave server. Replace test with your TLD.

Generate the necessary DNSSEC keys for your zone using keymgr:

keymgr policy:generate test.

This will create the required keys in /etc/knot/keys. Ensure the directory permissions are secure:

chown -R knot:knot /etc/knot/keys
chmod -R 700 /etc/knot/keys

Reload Knot DNS and enable DNSSEC signing for the zone:

knotc reload
knotc signzone test.

Generate the DS record for the parent zone using keymgr:

keymgr ds test.

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

⚠️ Important: In the Control Panel → TLD Management, click the Enable DNSSEC button. After the keys are created, the DS Record will appear on the same page and should be submitted to IANA or the parent registry.

1.4. NSD (Advanced)

NSD is a high-performance, authoritative-only name server with no support for dynamic updates, inline signing, or native DNSSEC key management. It is suitable for production environments that prioritize speed and simplicity, but it requires external zone signing.

⚠️ Important: NSD does not support DNSSEC signing or key management internally. You must handle all DNSSEC operations — such as key generation, zone signing, rollover, and DS management — using external tools like ldns-signzone, dnssec-signzone, or OpenDNSSEC.

1.4.1. Prerequisites

Youll need a separate process or automation to:

  • Generate KSK and ZSK keys
  • Sign your zone using ldns-signzone or equivalent
  • Update the .signed file before reloading NSD

Example using ldns-signzone:

ldns-keygen test.
ldns-keygen -k test.
ldns-signzone test.zone Ktest.+* Ztest.+*

This will output a signed zone file, typically named test.zone.signed.

1.4.2. Installation

apt install nsd ldnsutils

1.4.3. Configure NSD to Load Signed Zone

Edit /etc/nsd/nsd.conf and define the zone:

zone:
  name: "test."
  zonefile: "test.zone.signed"

Make sure the signed zone file is placed in /etc/nsd/ or the directory you define as the zone directory. Then restart NSD:

systemctl restart nsd

1.4.4. Automating Zone Signing

Because NSD does not sign zones automatically, you must:

  • Sign zones periodically via cron or a systemd timer
  • Replace the previous .signed file with the new one
  • Reload NSD (nsd-control reload) after each re-signing

Example cron job:

0 */6 * * * /usr/local/bin/sign-and-publish-zone.sh

Configure the Zone Writer in Registry Automation and run it manually the first time.

php /opt/registry/automation/write-zone.php

🧠 Tip: For easier DNSSEC lifecycle management, consider using OpenDNSSEC as the signer and NSD only for serving the signed zones.

1.5. Other Options

You may integrate with PowerDNS, YADIFA, or other servers, but this requires custom adaptation.

2. Setting Up a Public Secondary DNS Using BIND

This section describes how to configure a regular public-facing DNS server using BIND to act as a secondary for your hidden master. It will receive zone transfers (AXFR/IXFR) and serve as the authoritative DNS for your TLDs.

2.1. Installation

apt update
apt install bind9 bind9-utils bind9-doc

2.2. Add the TSIG key to the BIND Configuration

Copy the TSIG key from your hidden master server. The TSIG key configuration should look like this:

key "test.key" {
    algorithm hmac-sha256;
    secret "base64-encoded-secret==";
};

Create a directory to store zone files:

mkdir /var/cache/bind/zones

Edit the named.conf.local file:

nano /etc/bind/named.conf.local

First, define the TSIG key at the top of the file:

key "test.key" {
    algorithm hmac-sha256;
    secret "base64-encoded-secret=="; // Replace with your actual base64-encoded key
};

Then, add the slave zone configuration:

zone "test." {
    type slave;
    file "/var/cache/bind/zones/test.zone";
    masters { 192.0.2.1 key "test.key"; }; // IP of the hidden master and TSIG key reference
    allow-query { any; }; // Allow queries from all IPs
    allow-transfer { none; }; // Disable zone transfers (AXFR) to others
};

Make sure to replace 192.0.2.1 with the IP address of your hidden master server and base64-encoded-secret== with the actual secret from your TSIG key.

2.3. Adjusting Permissions and Ownership

Ensure BIND has permission to write to the zone file and that the files are owned by the BIND user:

chown bind:bind /var/cache/bind/zones
chmod 755 /var/cache/bind/zones

2.4. Enabling Logs

Place the contents below at /etc/bind/named.conf.default-logging and include the file in /etc/bind/named.conf:

logging {
    // General logs (startup, shutdown, errors)
    channel "misc" {
        file "/var/log/named/misc.log" versions 10 size 10m;
        print-time YES;
        print-severity YES;
        print-category YES;
    };

    // Query logs (log every DNS query)
    channel "query" {
        file "/var/log/named/query.log" versions 20 size 5m;
        print-time YES;
        print-severity NO;
        print-category NO;
    };

    // Lame server logs (misconfigured DNS servers)
    channel "lame" {
        file "/var/log/named/lamers.log" versions 3 size 5m;
        print-time YES;
        print-severity YES;
        severity info;
    };

    // Security logs (e.g., unauthorized query attempts)
    channel "security" {
        file "/var/log/named/security.log" versions 5 size 10m;
        print-time YES;
        print-severity YES;
        severity dynamic;
    };

    // DNS updates (useful for dynamic zones)
    channel "update" {
        file "/var/log/named/update.log" versions 3 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Resolver logs (useful for debugging recursive queries)
    channel "resolver" {
        file "/var/log/named/resolver.log" versions 5 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Zone transfer logs (incoming & outgoing transfers)
    channel "xfer" {
        file "/var/log/named/xfer.log" versions 5 size 5m;
        print-time YES;
        print-severity YES;
    };

    // Assign categories to log files
    category "default" { "misc"; };
    category "queries" { "query"; };
    category "lame-servers" { "lame"; };
    category "security" { "security"; };
    category "update" { "update"; };
    category "resolver" { "resolver"; };
    category "xfer-in" { "xfer"; };
    category "xfer-out" { "xfer"; };
};

2.5. Validate and Apply Configuration

After completing your secondary zone setup, check for syntax errors using named-checkconf, then restart BIND9 using systemctl restart bind9 to apply the changes.

To verify that the zone was successfully transferred from the hidden master, check your logs with grep 'transfer of "test."' /var/log/syslog. You should see a log entry confirming the successful zone transfer.