Issue Let's Encrypt Certificates with TSIG Zone Updates against Knot

en

To issue wildcard certificates, Let's Encrypt requires the use of the DNS validation method (see Certificate Policy §3.2.2). I'm running my own DNS nameserver using Knot DNS, which does not have e.g. a REST API for updating zones. However, Knot supports RFC 2136 zone updates, where a client submits changes in-band via DNS requests signed with a shared key.

TSIG Key Generation

To authenticate the DNS zone changes, the client needs to authenticate the request a transaction signature (or TSIG) key that is shared between server and client.

TSIG keys need to be named, and they need to have a "DNS compatible" name, meaning like domain names, they consist of multiple, .-separated labels. I'll simply choose tsig.s3lph.me. here.

Generating the TSIG key can be done easily with Knot's keymgr tool:

$ keymgr -t tsig.s3lph.me. hmac-sha384
key:
  - id: tsig.s3lph.me.
    algorithm: hmac-sha384
    secret: vIZUSHoSv/n6BZ8/lqoQ5F+GZC2uuy3vU/Por8VUAJhES4WuaOHV80Z7Lv3vHlUL

Knot Configuration

Add the following sections to Knot's configuration file (usually /etc/knot/knot.conf):

# This section should exactly be the output of the `keymgr` command from above.
# If a `key` section already exists, add the new key to it.
key:
  - id: tsig.s3lph.me.
    algorithm: hmac-sha384
    secret: vIZUSHoSv/n6BZ8/lqoQ5F+GZC2uuy3vU/Por8VUAJhES4WuaOHV80Z7Lv3vHlUL

# The ACL describes what the key can be used for.
# In this case the key is authorized to perform zone updates.
# Again, if an `acl` section already exists, add the new entry to the list.
acl:
  - id: acl-update-s3lph.me
    action: update
    key: tsig.s3lph.me.

# Add the ACL to the zones you want to use the key for.
# The `acl` key can be provided multiple times and is interpreted as a list.
zones:
  - domain: s3lph.me.
    ...
    acl: acl-update-s3lph.me

Finally, reload your Knot configuration with e.g. systemctl reload knot.

Client Configuration

To issue Let's Encrypt certificates using TSIG zone updates I'm using the Certbot dns_rfc2136 plugin.

This plugin is not part of the default Certbot installation. On e.g. Debian, it is however packaged as python3-certbot-dns-rfc2136.

The plugin requires an additional config file where the TSIG key and the nameserver are configured. I usually place it in /etc/letsencrypt/tsig.ini:

# Target DNS server
dns_rfc2136_server = 192.0.2.42
# Target DNS port
dns_rfc2136_port = 53
# TSIG key name
dns_rfc2136_name = tsig.s3lph.me.
# TSIG key secret
dns_rfc2136_secret = vIZUSHoSv/n6BZ8/lqoQ5F+GZC2uuy3vU/Por8VUAJhES4WuaOHV80Z7Lv3vHlUL
# TSIG key algorithm
dns_rfc2136_algorithm = HMAC-SHA384

Remember that the TSIG key is a shared secret with which your DNS zone contents can be changed. Protect it accordingly, e.g. through a chmod 0600 /etc/letsencrypt/tsig.ini.

Finally, you can request your Wildcard certificate with e.g.:

# certbot certonly --dns-rfc2136 \
    --dns-rfc2136-credentials /etc/letsencrypt/tsig.ini \
    --dns-rfc2136-propagation-seconds 10 \
    -d '*.s3lph.me'