Long time Let's Encrypt user (http-01 challenge with an acme client python script), first time certbot user with dns-01 challenge via dns-rfc2136 plugin.
I'm attempting to switch over to using certbot and the dns-rfc2136 plugin to issue/renew my certificates. I have a BIND DNS server configured to allow updates like so:
zone "calenhad.com" {
type master;
[snip]
update-policy {
grant "certbot" name _acme-challenge.calenhad.com. txt;
};
};
And I have verified that I can dynamically update this record using nsupdate
on a different machine:
named[7720]: client @0x7ff6744cf080 [redacted]#33304/key certbot: updating zone 'calenhad.com/IN': adding an RR at '_acme-challenge.calenhad.com' TXT "test ddns update"
However, attempting to use certbot fails:
gibmat@manwe:~$ sudo certbot --dry-run certonly -d manwe.calenhad.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-rfc2136, Installer None
Account registered.
Simulating a certificate request for manwe.calenhad.com
Performing the following challenges:
dns-01 challenge for manwe.calenhad.com
Cleaning up challenges
Encountered exception during recovery: certbot.errors.PluginError: Received response from server: REFUSED
Received response from server: REFUSED
Looking at more verbose output:
Performing the following challenges:
dns-01 challenge for manwe.calenhad.com
No authoritative SOA record found for _acme-challenge.manwe.calenhad.com
No authoritative SOA record found for manwe.calenhad.com
Received authoritative SOA response for calenhad.com
Encountered exception:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 70, in handle_authorizations
resps = self.auth.perform(achalls)
File "/usr/lib/python3/dist-packages/certbot/plugins/dns_common.py", line 57, in perform
self._perform(domain, validation_domain_name, validation)
File "/usr/lib/python3/dist-packages/certbot_dns_rfc2136/_internal/dns_rfc2136.py", line 87, in _perform
self._get_rfc2136_client().add_txt_record(validation_name, validation, self.ttl)
File "/usr/lib/python3/dist-packages/certbot_dns_rfc2136/_internal/dns_rfc2136.py", line 148, in add_txt_record
.format(dns.rcode.to_text(rcode)))
certbot.errors.PluginError: Received response from server: REFUSED
Poking at the code where the exception is raised, it appears that certbot is attempting to construct a TXT record for _acme-challenge.manwe.calenhad.com
, not _acme-challenge.calenhad.com
as I would expect from the docs for the rfc2136 plugin and numerous blog posts about setting up certbot for dns-01 challenges.
BIND correctly refuses this update. But is this correct certbot behavior? Will I have to add a ton of additional grants in my BIND zone for each and every host that I want to issue a specific certificate for? While a wildcard cert can work in several instances, I have some servers that need a specific, single-host certificate.
certbot version: 1.10.1
OS: Debian 10
certbot config files:
gibmat@manwe:~$ cat /etc/letsencrypt/cli.ini
# Because we are using logrotate for greater flexibility, disable the
# internal certbot logrotation.
max-log-backups = 0
key-type = rsa
rsa-key-size = 4096
email = [redacted]
authenticator = dns-rfc2136
dns-rfc2136-credentials = /etc/letsencrypt/rfc2136.ini
dns-rfc2136-propagation-seconds = 10
gibmat@manwe:~$ sudo cat /etc/letsencrypt/rfc2136.ini
# Target DNS server
dns_rfc2136_server = [redacted]
# Target DNS port
dns_rfc2136_port = 53
# TSIG key name
dns_rfc2136_name = certbot
# TSIG key secret
dns_rfc2136_secret = [redacted]
# TSIG key algorithm
dns_rfc2136_algorithm = HMAC-SHA512