
In this tutorial we will be going through how to setup and configure BIND9 RFC2136 for your Public DNS Server.
What is RFC2136 Dynamic Updates?
Dynamic Updates in the Domain Name System (DNS) is a mechanism that allows authorized clients to add, delete, or modify DNS records within a zone without manually editing zone files or restarting the DNS server. This method is used with the DNS-01 challenge for domain validation.
Let’s Encrypt supports several verification methods, including:
- HTTP-01 challenge
- DNS-01 challenge
- TLS-ALPN-01 challenge
- TLS-SNI-01 challenge (deprecated)
Prerequisites
In order to follow this guide, you will need two name servers, ns1 and ns2. If you haven’t set them up yet, please do so first.. You can follow the following guide How to setup BIND9 Authoritative Name Servers on Ubuntu/Debian
Setting up ns1 for Dynamic Updates.
Log into ns1 via SSH and go to the following location.
cd /etc/bind/
We now need to edit named.conf and add a file called include “/etc/bind/named.conf.certbot”;
nano named.conf
include "/etc/bind/named.conf.certbot";
Save and exit. CTRL X. Y to save.
Next step, create a HMAC Key.
In newer versions of Ubuntu and Debian dnssec-keygen -a HMAC-SHA256 will give an error dnssec-keygen: fatal: unknown algorithm HMAC-SHA256, so we will use rndc-confgen instead.
rndc-confgen -a -A hmac-sha256 -k "certbot." -c /etc/bind/certbot.key
Output file will show the following,
key "certbot." {
algorithm hmac-sha256;
secret "here is the secret";
};
Please note, make sure you keep this key secret and do not let other use the key as they will be able to write to zones in /var/lib/bind.
Now create a file called named.conf.
certbot. Within this file, copy the key that was generated. This new zone will include both the HMAC key and the zones located under /var/lib/bind
.
The reason we are doing this, instead of allowing dynamic updates to the forward zones, is due to security. Newer versions of Ubuntu use a security module called AppArmor, which restricts dynamic updates to zones located in /etc/bind/
. To work around this, we place the acme_challenge
zones under /var/lib/bind
.
Make sure to remove certbot.key from /etc/bind/.
nano named.conf.certbot
key "certbot." {
algorithm hmac-sha256;
secret secret "here goes the secret from the .key file";
};
zone "_acme-challenge.domain.uk" {
type master;
file "/var/lib/bind/db._acme-challenge.domain.uk";
allow-query { any; };
allow-transfer { 1.2.3.4; };
also-notify { 1.2.3.4; };
update-policy {
grant certbot name _acme-challenge.domain.uk. txt;
grant certbot name _acme-challenge.*.domain.uk. txt;
};
};
Allow transfer and also-notify should be set to the IP address of ns2.
You’ll notice that we specify *.domain.uk
to grant the certbot name _acme-challenge
— this is necessary for generating a wildcard certificate.
We run dynamic DNS for the zones on ns1, but we also specify ns2 because Let’s Encrypt performs a second verification. That verification will fail if the _acme-challenge
zones are not transferred to ns2.
Save and exit. CTRL X. Y to save.
Set the permissions for named.conf.certbot
chmod 600 /etc/bind/named.conf.certbot
Creating _acme-challenge Zone
cd /var/lib/bind/
nano db._acme-challenge.domain.uk
Add the following, Be sure to append date as YYYYMMDDnn
$ORIGIN .
$TTL 300 ; 5 minutes
_acme-challenge.domain.uk IN SOA ns1.domain.uk. noc.domain.uk. (
2025061401 ; serial
10800 ; refresh (3 hours)
3600 ; retry (1 hour)
604800 ; expire (1 week)
86400 ; minimum (1 day)
)
NS ns1.domain.uk.
NS ns2.domain.uk.
Save and exit. CTRL X. Y to save.
We now need to check syntax and load the new _acme-challenge zone.
named-checkzone _acme-challenge.domain.uk. /var/lib/bind/db.domain.uk
zone _acme-challenge.domain.uk/IN: loaded serial 2025061401
OK
named-checkconf
Now load the zone as follows,
rndc reconfig
Next log into ns2 via SSH and go to the following location.
/etc/bind/
We now need to add our _acme-challenge.domain.uk zone to ns2. Edit named.conf.local
nano named.conf.local
zone "_acme-challenge.domain.uk" {
type slave;
file "db._acme-challenge.domain.uk";
allow-query { any; };
masters { 1.2.3.4; };
};
masters { 1.2.3.4; }; is the IP Address of ns1.
Save and exit. CTRL X. Y to save.
Now reload the config so the Zone gets transferred from ns1.
rndc reconfig
After completing the steps above, I recommend verifying that the _acme-challenge
zones are properly delegated on both name servers. To test this, you can use a utility called dig
. So lets test the delegation.
dig _acme-challenge.domain.uk NS
By using the NS
option at the end of the dig
command, you can query both name servers to verify delegation.
The output of the above command should display the following:
dig _acme-challenge.domain.uk NS
; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> _acme-challenge.domain.uk NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32120
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;_acme-challenge.domain.uk. IN NS
;; ANSWER SECTION:
_acme-challenge.domain.uk. 300 IN NS ns1.domain.uk.
_acme-challenge.domain.uk. 300 IN NS ns2.domain.uk.
Subdomain Zones
If you want _acme-challenge
zones for subdomains such as www
, mail
, webmail
, etc., you can create separate zones for those as well.
nano named.conf.certbot
key "certbot." {
algorithm hmac-sha256;
secret secret "here goes the secret from the .key file";
};
zone "_acme-challenge.domain.uk" {
type master;
file "/var/lib/bind/db._acme-challenge.domain.uk";
allow-query { any; };
allow-transfer { 1.2.3.4; };
also-notify { 1.2.3.4; };
update-policy {
grant certbot name _acme-challenge.domain.uk. txt;
grant certbot name _acme-challenge.*.domain.uk. txt;
};
};
zone "_acme-challenge.www.domain.uk" {
type master;
file "/var/lib/bind/db._acme-challenge.www.domain.uk";
allow-query { any; };
allow-transfer { 1.2.3.4; };
also-notify { 1.2.3.4; };
update-policy {
grant certbot name _acme-challenge.www.domain.uk. txt;
};
};
cd /var/lib/bind/
nano db._acme-challenge.www.domain.uk
Add the following,
$ORIGIN .
$TTL 300 ; 5 minutes
_acme-challenge.www.domain.uk IN SOA ns1.domain.uk. noc.domain.uk. (
2025061401 ; serial
10800 ; refresh (3 hours)
3600 ; retry (1 hour)
604800 ; expire (1 week)
86400 ; minimum (1 day)
)
NS ns1.domain.uk.
NS ns2.domain.uk.
On ns2.
nano named.conf.local
zone "_acme-challenge.domain.uk" {
type slave;
file "db._acme-challenge.domain.uk";
allow-query { any; };
masters { 1.2.3.4; };
};
zone "_acme-challenge.www.domain.uk" {
type slave;
file "db._acme-challenge.www.domain.uk";
allow-query { any; };
masters { 1.2.3.4; };
};
Test Subdomain Delegation,
dig _acme-challenge.www.domain.uk NS
; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> _acme-challenge.www.domain.uk NS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32120
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;_acme-challenge.www.domain.uk. IN NS
;; ANSWER SECTION:
_acme-challenge.www.domain.uk. 300 IN NS ns1.domain.uk.
_acme-challenge.www.domain.uk. 300 IN NS ns2.domain.uk.
Implementation with Certbot
We now need to configure Certbot to use our HMAC key and grant it permission to write to the _acme-challenge
zones.
Install Certbot and the required Plugins.
apt install python3-certbot-dns-rfc2136
Now configure Certbot credentials.
cd /etc/letsencrypt
nano dns_rfc2136_credentials.txt
# Target DNS server
dns_rfc2136_server = 1.2.3.4
# Target DNS port
dns_rfc2136_port = 53
# TSIG key name
dns_rfc2136_name = certbot
# TSIG key secret
dns_rfc2136_secret = here goes the secret from the .key file
# TSIG key algorithm
dns_rfc2136_algorithm = HMAC-SHA256
Save and exit. CTRL X. Y to save.
Set permissions for dns_rfc2136_credentials.txt.
chmod 600 /path/to/dns_rfc2136_credentials.txt
We have now configured Certbot to use our HMAC key. When generating an SSL certificate for a wildcard or for subdomains, it will allow Let’s Encrypt to create temporary TXT records in zones such as _acme-challenge.domain.uk
or _acme-challenge.www.domain.uk
, and so on.
When generating a SSL Certificate first, It is recommended to run a –stage due to rate limits. You should now be able to generate Certificates for both Widlcard as well as Subdomains.
Certificate Commands.
Generating a Stage Certificate.
certbot certonly --staging --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns_rfc2136_credentials.txt --dns-rfc2136-propagation-seconds 60 -d domain.uk -d *.domain.uk -d
Once the test certificate is generated successfully, you can go on and generate a production certificate but first I would recommend revoking the staging Certificate.
certbot delete domain.uk
Generating Production Certificates Wildcard.
certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns_rfc2136_credentials.txt --dns-rfc2136-propagation-seconds 60 -d domain.uk -d *.domain.uk
Generating Production Certificates with Subdomains
certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns_rfc2136_credentials.txt --dns-rfc2136-propagation-seconds 60 -d domain.uk -d www.domain.uk
Certbot Post Hooks.
Now with Post hooks, we can configure Certbot to reload services such as nginx, postfix, dovecot etc.
certbot certonly --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns_rfc2136_credentials.txt --dns-rfc2136-propagation-seconds 60 -d domain.uk -d *.domain.uk --post-hook "service nginx reload
With the above command, –post-hook “service nginx reload” this tell certbot to reload the service called nginx. If you are using Nginx as a Reverse Proxy or as a Web Server this will automatically reload the service nginx when the SSL Ceritifcate renews.
Post hook list.
–post-hook service nginx reload
–post-hook service postfix reload
–post-hook service dovecot reload
–post-hook systemctl restart apache2
Here is a example for certbot for nginx, postfix and dovecot.
certbot certonly --cert-name mail --dns-rfc2136 --dns-rfc2136-credentials /etc/letsencrypt/dns_rfc2136_credentials.txt -d *domain.uk --post-hook "service postfix reload && service dovecot reload && service nginx reload"
To view Certificates,
sudo certbot certificates
That’s it. Hope this tutorial helps you build your own DNS Authorative Name Servers. Please don’t hesitate to Contact if you have any problems.