NAME

danectl - DNSSEC DANE implementation manager

SYNOPSIS

 usage: danectl [options] command [arg...]

 options:
  -h, --help                             - Show the usage message
  -V, --version                          - Show the name and version
  -q, --quiet                            - Quiet mode (pass -q to certbot)
  -v, --verbose                          - Verbose mode (announce actions)
  -n, --test                             - Test mode (don't perform actions)
  -g, --group groupname                  - Refer to a subgroup of certificates
  -1, --oneline                          - Output long RRs on a single line
  -s, --spaces                           - Include spaces in --oneline output

 commands:
  help                                   - Show the manual page
  aliases                                - Show the command aliases

  certbot [run|certonly] <options...>    - Record certbot auth/install details
  adopt <certname>                       - Adopt an existing cert as current
  new <domain...>                        - Create a new original/current cert
  dup <domain...>                        - Create a new duplicate/next cert
  add-tlsa <certname> <_#._tcp[.host]..> - Add port/pro/host for TLSA output
  del-tlsa <certname> <_#._tcp[.host]..> - Delete port/pro/host for TLSA output
  show-tlsa <certname>                   - Show port/pro/host for TLSA output
  tlsa-current <certname...>             - Output TLSA RRs for the current key
  tlsa-next <certname...>                - Output TLSA RRs for the next key
  tlsa-check [<certname...>]             - Check that TLSA RRs are published
  add-reload <certname> <service...>     - Add services to reload on rollover
  del-reload <certname> <service...>     - Delete services to reload on rollover
  show-reload <certname>                 - Show services to reload on rollover
  reload <certname...>                   - Reload services affected by rollover
  rollover <certname...>                 - Perform a key rollover
  status                                 - Show current/next status

  sshfp <domain>                         - Output SSHFP RRs for localhost
  sshfp-check <domain>                   - Check that SSHFP RRs are published
  openpgpkey <emailaddress>              - Output OPENPGPKEY RR for an email
  openpgpkey-check <emailaddress>        - Check OPENPGPKEY RR is published
  smimea <smimecert.pem>                 - Output SMIMEA RR for a certificate
  smimea-check <smimecert.pem>           - Check SMIMEA RR is published

WHAT IS DANE?

DANE is DNS-based Authentication of Named Entities. It means securely letting the world know in advance what your public encryption keys are by publishing them as DNS records (TLSA SSHFP OPENPGPKEY SMIMEA) in your DNSSEC-enabled internet domain zone. This is the simplest and most secure way to let the world know what keys to expect when connecting to your servers. This can apply to TLS keys, SSH host keys, and OpenPGP and S/MIME keys. This makes it possible to prevent impersonation or man-in-the-middle attacks. It's mostly used with mail servers. Eventually, it could render certificate authorities unnecessary. DNSSEC has become very easy these days.

INTRODUCTION

Danectl is a DNSSEC DANE implementation manager. It uses certbot(1) to create and manage pairs of keys for use with a TLSA 3 1 1 current + next workflow. It generates TLSA records for your TLS services for you to publish in the DNS, checks that they are correctly published, and performs key rollovers.

Danectl can also generate and check SSHFP records for the local SSH server. Danectl can also generate and check an OPENPGPKEY record for a GnuPG key. Danectl can also generate and check an SMIMEA record for an S/MIME certificate.

DESCRIPTION

Danectl lets you create a pair of certbot certificate lineages to be used with DANE-aware TLS clients. They are referred to as the "original" and the "duplicate", or as the "current" and the "next". The current and next will repeatedly swap places between the original and the duplicate certificate lineages as the key rolls over from one to the other (with a new "next" key being created after each rollover).

If you already have a certbot certificate lineage that you want to use with DANE, then instead of creating both certificate lineages, you can adopt the existing one for DANE use, and then just create the duplicate.

After that, certbot automatically renews both certificates every few months, but the underlying keys won't change, and the TLSA records (see below) can remain stable.

You then configure danectl with the set of port/protocol/host combinations that you need TLSA records for. Danectl can then output the TLSA records, in zonefile format, and you need to publish them in the DNS (somehow). Danectl can then check that the TLSA records have been published in the DNS.

You also need to configure danectl with the list of TLS services that need to be reloaded when the key rolls over. This is needed even when certbot is configured to do it with deploy hooks, because those hooks are only run when a certificate is renewed. Service reloads also need to happen when there's a DANE key rollover, and that doesn't necessarily happen at the same time as automatic certbot certificate renewals.

You then need to configure your TLS services to use the "current" certificate in /etc/letsencrypt/current/<cert-name>, and then reload them. This is like following instructions for using a certbot certificate, but replacing "/etc/letsencrypt/live" with "/etc/letsencrypt/current".

Periodically, you can perform key rollovers on a schedule that suits you (e.g., annually). An emergency key rollover is exactly the same.

At any time, you can show the status (which certificate lineages are "current", which are "next", which new TLSA records are not yet published in the DNS, and which old TLSA records have not yet been removed from the DNS).

In addition to TLSA records, you can also generate SSHFP, OPENPGPKEY, and SMIMEA records, and check that they are published in the DNS.

OPTIONS

-h, --help

This outputs danectl's usage message, then exits.

-V, --version

This outputs danectl's name and version, then exits.

-q, --quiet

This enables quiet mode, causing danectl to pass -q to certbot. This only affects the "new", "dup", and "rollover" commands, and is probably a good idea, as it makes the output tidier (especially for cronjobs).

-v, --verbose

This enables verbose mode, causing danectl to print actions before performing them.

-n, --test

This enables test mode, preventing danectl from performing any changes. It implies verbose mode, causing danectl to print the actions that would have been performed.

-g, --group groupname

This specifies a name for a subgroup of certificate lineages that are to be treated in the same way as each other.

By default, danectl assumes that all certificate lineages have the same key type and the same authentication and installation details when it invokes certbot. In other words, the certbot command line options that are specified and saved with danectl's "certbot" command apply to all certificate lineages.

If your requirements are more heterogeneous, with either a different type of key needed for different certificate lineages (for different domains or for the same domains), or if different certificate lineages require different authentication or installation methods, use the --group option to specify groups of certificate lineages that are homogeneous within the group.

Each group is identified by the groupname option argument. Note that every certificate lineage within a group must have the same key type, authentication method, and installation method.

If you need the --group option, it must be used for all danectl commands pertaining to the certificate lineages within a group. The groupname option argument should only contain characters that are suitable for use in a filename. The default configuration file for danectl is ~/.danectlrc. When the --group option is used, a separate configuration file is used. Its name will look like ~/.danectlrc.groupname.

Even when the --group option is used, it is still possible to use danectl without the --group option and use the default configuration file for some certificate lineages. This can be viewed as an unnamed default group.

Note: If you need multiple key types for the same domain(s), you will need to create the second certificate lineage directly with certbot using its --duplicate command line option, and then use danectl's "adopt" command. If you try to use danectl's "new" command instead, certbot will refuse to create the new certificate lineage for domains that already have a certificate lineage.

-1, --oneline

This causes each long DNS record to be output on a single very long line, rather than on multiple lines enclosed by parentheses ("(" and ")"). This only applies to OPENPGPKEY and SMIMEA records. Each TLSA and SSHFP record is always output on a single line.

-s, --spaces

This implies the --oneline option, and causes space characters (" ") to be included in the output of long, single line DNS records (one every 56 characters). This only applies to OPENPGPKEY and SMIMEA records. There's probably no real need for this.

COMMANDS

Danectl can show you this manual page:

  danectl help

You can also show the aliases for all of the commands:

  danectl aliases

Before you can use danectl to do anything interesting for TLS, you might need to supply any command line command and/or options that certbot will need when it creates new certificate lineages. This is for authentication and installation. Don't use quotes and don't put spaces inside arguments (e.g., webroot paths must not contain spaces).

  danectl certbot --apache

The default is "--apache" to use the apache plugin, if /etc/apache2 exists. Otherwise, the default is "--nginx" to use the nginx plugin, if /etc/nginx exists. Otherwise, the default is "--standalone" to use the standalone plugin.

When the apache or nginx plugin is used, the default certbot command used is "run", which installs the certificate lineage to the web server configuration after authentication. Otherwise, the default certbot command used is "certonly", which only authenticates, and doesn't install the certificate lineage to any web webserver configuration. This only applies to danectl's "new" command (see below). Danectl's "dup" command (see below) always uses certbot's "certonly" command.

Certbot's "run" command must only be used when the new certificate is to be installed. Otherwise, certbot's "certonly" command must be used instead. If danectl's default certbot command is wrong for your needs, you can override it by putting "run" or "certonly" before any certbot command line options.

This might be useful if you have apache or nginx, but don't want the certificate installed automatically, or if you use a third-party plugin that is capable of installing the certificate, but danectl doesn't know that. Danectl naively assumes that all third-party plugins do not install, but that isn't always true.

  danectl certbot certonly --nginx
  danectl certbot run --third-party-plugin-details

Danectl's "certbot" command modifies your ~/.danectlrc (or ~/.danectlrc.*) file.

If you already have a certbot certificate lineage, you can adopt it for DANE use:

  danectl adopt example.org

Note that you must use an existing certificate's cert-name, not the list of certified domains. To see all of your cert-names, run "certbot certificates", or look in /etc/letsencrypt/live.

This will create a symlink in /etc/letsencrypt/current to the adopted certificate lineage.

If you want to create a new certbot certificate lineage for DANE instead, use:

  danectl new example.org www.example.org mail.example.org

Note that you must provide the complete list of domain names to certify. The cert-name of the new certificate lineage will be the first domain in the list. It should be a base domain name.

This will create a symlink in /etc/letsencrypt/current to the new certificate lineage.

Either way, you then need to create an additional duplicate certificate lineage for the same set of domains:

  danectl dup example.org www.example.org mail.example.org

Note that you must provide the complete list of domain names to certify. It must be identical to the list of domains in the adopted or new original certificate lineage. The cert-name will be the first domain in the list followed by "-duplicate". You won't need to use that suffix with danectl, but you will need to use it when using certbot directly.

This will create a symlink in /etc/letsencrypt/next to the duplicate certificate lineage.

Once a pair of certificate lineages is set up, certbot will start renewing them automatically, but the underlying keys won't change. That means that the TLSA records (see below) can remain stable for longer than just a few months.

Most of the remaining commands below require the base cert-name as their first argument. Not the list of domain names, just the first domain, or cert-name, without any "-duplicate" suffix.

You then need to specify all of the port/protocol/host combinations that you will want TLSA records for:

  danectl add-tlsa example.org _443._tcp _443._tcp.www
  danectl add-tlsa example.org _25._tcp.mail
  danectl add-tlsa example.org _465._tcp.mail _587._tcp.mail
  danectl add-tlsa example.org _110._tcp.mail _143._tcp.mail
  danectl add-tlsa example.org _993._tcp.mail _995._tcp.mail

Do not include the base cert-name in the port/protocol/host combinations. It will be appended automatically when TLSA records are output.

But if the certificate lineage certifies multiple base domains, and you need to specify a host that is not in the domain indicated by the base cert-name, then specify the complete hostname terminated by a dot ("."). The trailing dot prevents the base cert-name from being automatically appended.

However, it's best to use a separate certificate lineage for each base domain. Otherwise, when danectl outputs TLSA records for a key, you will probably (depending on how you publish DNS records) need to separate the output for different zonefiles based on their base domains.

You can also remove port/protocol/host combinations:

  danectl del-tlsa example.org _110._tcp.mail _143._tcp.mail

The "add-tlsa" and "del-tlsa" commands modify your ~/.danectlrc (or ~/.danectlrc.groupname) file.

You can also show which port/protocol/host combinations will be included for TLSA records:

  danectl show-tlsa example.org

To output all TLSA records for the current key:

  danectl tlsa-current example.org

To output all TLSA records for the next key:

  danectl tlsa-next example.org

Initially, you need to publish the TLSA records for both the current and next keys in the DNS (somehow).

To check that all TLSA records for the current and next keys are correctly published in the DNS:

  danectl tlsa-check example.org

If no cert-name is supplied, then all cert-names are checked, and the --reuse-key status of each certificate lineage is checked, and restored if it is unset for any reason.

All TLSA records for the current and next keys must be published in the DNS before you configure your services to use the current key.

To specify the services that need to be reloaded when a key rolls over:

  danectl add-reload example.org apache2 postfix dovecot

A service name can be: an absolute path to an executable file; or anything recognized as a service name by systemctl(1), service(8), or rcctl(8) (depending on the local operating system); or an executable file in /etc/init.d, /etc/rc.d, or /usr/local/etc/rc.d. When services are reloaded, the $CERTNAME environment variable will contain the relevant certificate name. When the service is an absolute path, the executable is invoked with "reload" as its first command line argument ($1), and with the certificate name as its second argument ($2). Also, the absolute path must not contain any whitespace characters.

They can also be removed:

  danectl del-reload example.org postfix # Postfix looks after itself

The "add-reload" and "del-reload" commands modify your ~/.danectlrc (or ~/.danectlrc.groupname) file.

You can also show which services will be reloaded when a key rolls over:

  danectl show-reload example.org

At any point, you can reload the services that need to be reloaded when the key rolls over:

  danectl reload example.org

But this shouldn't be necessary. It's automatic when a key rolls over. Although it might be useful in certbot renewal hooks.

Occasionally (e.g., annually), perform a key rollover:

  danectl rollover example.org

This will redesignate the "next" key as the "current" key (and vice versa), reload affected services, and create a new key/certificate as the new next key. It also outputs the old TLSA records for the old current key that you need to remove from the DNS (somehow). And it outputs the new TLSA records for the new next key that you need to publish in the DNS (somehow).

Note that the rollover command will refuse to proceed if the tlsa-check command would report any problems. This is to prevent attempts to perform a rapid series of rollovers before the necessary TLSA records for the next key have been published in the DNS. But since tlsa-check only checks with the local DNS resolver, this precaution doesn't completely guarantee that all DNS resolvers everywhere that have cached your TLSA records will have the necessary TLSA records for the next key. The solution is to be aware of your zone TTLs and not rollover too often. For example, if the zone TTL is one hour, then don't rollover until at least two hours after the TLSA records for the most recent rollover have been published in the DNS. But if you need to absolutely guarantee that you can never rollover prematurely, then consider using danebot(1) instead. It takes a user-specified TTL into account.

At any time, you can show the status of all certificate pairs:

  danectl status

This will show, for each base cert-name, which certificate lineage is "current" (original or duplicate), and which is "next". It will also show any new TLSA records that should be, but are not, published in the DNS. It will also show any old TLSA records that are published in the DNS, but should no longer be.

If any of the symlinks in /etc/letsencrypt/{current,next} target certificate lineages that no longer exist in /etc/letsencrypt/live, this is also mentioned, and they are deleted. This indicates that the certificate lineage was previously deleted with certbot.

If any of the certificate lineages no longer have their --reuse-key status set for any reason, this is also mentioned, and it is restored.

You can also output SSHFP records for the local SSH server:

  danectl sshfp example.org

If you want to authorize your local SSH server's host keys to clients via DNSSEC, you will need to publish these SSHFP records in the DNS (somehow). You will also need to set VerifyHostKeyDNS to "yes" or "ask" in the ssh(1) client configuration (ssh_config(5)).

To check that SSHFP records for the local SSH server are published in the DNS:

  danectl sshfp-check example.org

You can also output an OPENPGPKEY record for the key that is associated with an email address in your GnuPG public keyring:

  danectl openpgpkey user@example.org

The email address must be a valid argument for gpg(1)'s --export option. If you want your correspondents to find the key, you will need to publish the OPENPGPKEY record in the DNS (somehow), and they will need to add "dane" to their auto-key-locate list.

To check that the OPENPGPKEY record for the email address is published in the DNS:

  danectl openpgpkey-check user@example.org

You can also output an SMIMEA record for an S/MIME certificate:

  danectl smimea smimecert.pem

The S/MIME certificate file must be in PEM format. If you want your correspondents to find the certificate, you will need to publish the SMIMEA record in the DNS (somehow), and they will probably need to consult their mail client documentation.

To check that the SMIMEA record for an S/MIME certificate is published in the DNS:

  danectl smimea-check smimecert.pem

FILES

  /etc/letsencrypt/live    - Certbot certificate lineages
  /etc/letsencrypt/current - Current keys/certificates
  /etc/letsencrypt/next    - Next keys/certificates
  ~/.danectlrc             - Default configuration file
  ~/.danectlrc.*           - Group-specific configuration file(s)

The ~/.danectlrc configuration file is technically a shell script. But danectl's additions and removals are purely a single name="value" line at a time. Bear that in mind if you modify it manually. It must be owned by the user, and it must not be group- or world-writable.

CAVEAT

If you need to add or remove any domains from a pair of certificate lineages, you will need to do it with certbot, and you will need to do it for both the original and the duplicate certificate lineages (e.g., example.org and example.org-duplicate), and you will need to use certbot's --cert-name command line option. Since there will be two certificate lineages with the same set of domains, it would be ambiguous otherwise. There may be other things that you will need to use certbot directly for. Keep things in sync.

BUGS

Danectl relies entirely on certbot. This isn't a bug. It's a choice. This choice was made so as to make danectl easy to implement, and because it's pragmatic. The same key can be used with DANE-aware or PKIX-aware clients. You don't need to know which. And you don't need to exclude any clients.

But it means that it only works with keys that are created by certbot, and with certificates that are issued by a Certificate Authority (CA). If you want to use DANE so as to avoid the CA ecosystem entirely, danectl won't help you do that.

On the other hand, only a single CA is involved, LetsEncrypt, not the entire ecosystem, and danectl only generates TLSA 3 1 1 records, which only refer to the local public key itself. There is no reliance on any keys belonging to the CA. That's good because those keys can and will change on a schedule that is beyond your control. But your own keys are under your control.

So danectl is opinionated and inflexible. Other things can be done with TLSA records, but they can't be done with danectl. But what can be done with danectl can be done easily. If you need greater flexibility, you'll need to find it elsewhere.

For OPENPGPKEY usage, if your public keyring contains multiple keys with the same email address keyid, danectl will only output the first one that gpg exports. Let me know if this is a problem.

For SMIMEA usage, only SMIMEA 3 0 0 records are supported. This isn't really a bug, as they seem to be the most/only useful ones.

Danectl doesn't actually publish or remove any DNS records for you. This isn't really a bug. It's a limitation. There are too many ways to publish records in the DNS. But danectl does try to make it easy for you to handle that yourself by outputting records in the well-known BIND9 zonefile format. When performing a key rollover, and when performing any of the checks, any superfluous records that are to be removed are output in the form of comments where the leading semicolon (";") is not followed by a space (" "). That makes them easy to identify with grep (i.e., grep '^;[^ ]' for superfluous records to be removed, and grep -v '^;[^ ]' for missing records to be published). In either case, the grep output includes a comment that can be removed by piping through grep -v '; ' as well. Perhaps a plugin system could be added to automate updates for different DNS server software and different DNS service providers, but it should be easy enough to write a separate script to read the output of danectl and do what you need with it. Danectl comes with two such scripts: danectl-zonefile(1), which reads the output from danectl, then backs up and modifies the BIND9 zonefile given on its command line, replacing old records with new ones; and danectl-nsupdate(1), which reads the output from danectl and transforms it into input for the nsupdate(1) dynamic DNS update utility.

REQUIREMENTS

Danectl is written in Bourne shell, and should work on any platform that has the following prerequisites.

In all cases, danectl requires /bin/sh and host (or drill).

On systems like Solaris, /usr/xpg4/bin/sh is used instead of /bin/sh.

For TLSA usage, danectl also requires ls, sed, grep, readlink, certbot, openssl, sha256sum, and root privileges (for certbot).

For SSHFP usage, danectl also requires sed, perl and ssh-keygen.

For OPENPGPKEY usage, danectl also requires perl and gpg.

For SMIMEA usage, danectl also requires perl and openssl.

For non-ASCII domain names, danectl also requires GNU idn2.

The danectl-zonefile output adapter requires perl.

The danectl-nsupdate output adapter requires perl.

For reloading affected services on key rollover, any system with systemctl, service, rcctl, or service scripts in /etc/init.d, /etc/rc.d, or /usr/local/etc/rc.d should work.

LICENSE

Danectl is released under the terms of the GPLv2+ https://www.gnu.org/licenses.

SEE ALSO

certbot(1), ssh(1), ssh_config(5), gpg(1), openssl(1), danectl-zonefile(1), named(8), danectl-nsupdate(1), nsupdate(1), danebot(1), RFC6698, RFC7671, RFC7672, RFC4255, RFC7929, RFC8162.

AUTHOR

20230718 raf <raf@raf.org>

URL

  https://raf.org/danectl
  https://github.com/raforg/danectl
  https://codeberg.org/raforg/danectl