Adding DKIM Records with BIND9
  • 20 Jul 2021
  • 5 Minutes to read
  • Contributors
  • Dark
    Light
  • PDF

Adding DKIM Records with BIND9

  • Dark
    Light
  • PDF

Article Summary

DKIM -- short for "DomainKeys Identified Mail" -- is a mechanism that provides integrity controls over parts of an email transmission. More information about the protocol can be found at http://www.dkim.org/, as this article will deal only with the required integration with your DNS.

DKIM is a two-part process: In the first part, the message's originator is responsible for generating a DKIM Signature that is then placed in special headers, such as these:

DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=itverx.com.ve;
    s=alice; t=1342650894;
    bh=pFo6ZYCLWFoBWmva8IlsxprN/QOinqGTGscl1MBI3sQ=;
    h=MIME-Version:Sender:In-Reply-To:References:Date:Message-ID:
    Subject:From:To:Cc:Content-Type;
    b=Fkcgti0ONF9w/F12LwqW1GQjecEZZgohQmQlkDENRQOdWJINF4DaowPc6LM5tAd5/
    kM666teylglDIgJnF2ThGEUrnkmavZvPsHuecWc/ZEYl+3NT7/gb46568UWPjXqbFo
    zQDzLozzqw+GABj+pXlC2fDBscesx++q5fBw5dPA=`

The message's receiver is then expected to complete DKIM processing by validating the signature. This requires looking up the matching Public Key from the specified domain. For the above example, the process would be equivalent to performing the query depicted below:

bind9# dig txt alice._domainkey.itverx.com.ve
...

;; QUESTION SECTION:;alice._domainkey.itverx.com.ve.    IN    TXT
;; ANSWER SECTION:alice._domainkey.itverx.com.ve.    86400 IN TXT    "v=DKIM1\; g=*\; k=rsa\; p=MIGfM
A0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqFGebZAOHfSGy9CWtA4Uads0zaXAy8TWtW9uIFbyIkFNC67fQVFVjsxlmcEg1oFNp2CrTY
F1YNh2gB144c+XY5GVM2fGEYAKx3iBxajWTzsx3SvpQtAZ2Bvf2mV+Te+JtlbpxVuiuiW2Alqwhk1ytTWspf/S3bM73XssV+/mh9wIDA
QAB"
...

As can be seen, DKIM uses the DNS as a trusted mechanism to distribute its public keys to the large and diverse population of mail receivers. Sites wishing to use DKIM will require the publication of their public keys in the corresponding DNS zones, so that receivers can access them.

Managing the DKIM Keys

All DKIM implementations include a specific mechanism to generate the required key pair. Please consult your system's documentation to find the right steps for this task, as they will differ.

Keep your Private Key secure
Keep in mind that the Private key must be kept secure and never shared, as this compromises the effectiveness of DKIM and allows third parties to sign mail in your domain's behalf.

One popular option for implementing DKIM in Open Source environments is dkim-milter, which integrates easily with Sendmail and Postfix using the Milter interface and is also included in leading Linux distributions. When instructions are properly followed, the key generation process will leave you with two files:

mta# ls -l /etc/mail/dkim/keys/alice.*
-r--r----- 1 dkim-filter smmsp 891 Apr 21  2009 /etc/mail/dkim/keys/alice.private
-r--r----- 1 root        smmsp 308 Apr 21  2009 /etc/mail/dkim/keys/alice.txt

These files contain the private and public keys of the pair, respectively. While the private key is required by your signing server, only the public key should be published by your primary name server. The public file, denoted with the .txt extension, contains a valid fragment of a DNS zone, as shown:

mta# cat /etc/mail/dkim/keys/alice.txt
alice._domainkey IN TXT "v=DKIM1; g=*; k=rsa; t=y; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqFGebZAOHfSGy9CWtA4Uads0zaXAy8TWtW9uIFbyIkFNC67fQVFVjsxlmcEg1oFNp2CrTYF1YNh2gB144c+XY5GVM2fGEYAKx3iBxajWTzsx3SvpQtAZ2Bvf2mV+Te+JtlbpxVuiuiW2Alqwhk1ytTWspf/S3bM73XssV+/mh9wIDAQAB" ; ----- DKIM alice for itverx.com.ve

Other tools provide only the value of the key itself (the fragment between the double quotes or even the contents of the p= field). We recommend that you examine the format and contents of your public key file as this is important for actually adding the public key to your DNS zone file, as explained below. Regardless of which method you use to provision your public DKIM key in the DNS, ensure that afterwards it can be looked up by the receivers (ie, the public key is available in the DNS). Then proceed to test the validity of the signing process.

$INCLUDEing the Keys in your DNS Zone

This is the easiest method to use if your DKIM implementation provides a complete TXT record compatible with the zone syntax file, as in the example shown above. The steps are simple.

On your master nameserver, you will be editing the data file that BIND loads for the zone.

  1. If you're using Dynamic Updates in your zone, freeze it first by issuing this command:
rndc freeze <your domain name>

2. Add a $INCLUDE directive to the zone, referring to the corresponding .txt file with the public key. In the example below, we use an absolute path but note that you can also opt for a relative path if this suits your configuration style better.

  1. Increment the serial number of the zone, to ensure a flawless zone transfer to your slave servers after reloading the zone on your master.

  2. If you had frozen the zone in step 1, thaw it now by issuing this command:

rndc thaw <your domain name>
  1. Reload the zone file by issuing this command:
rndc reload <your domain name>

In Step 2 above, we copied the alice.txt file from our DKIM signing server (mta) into the directory where we keep our zone files in our primary DNS server (bind9). We added the following line to the zone file.

$INCLUDE alice.txt

And after the zone reload completes (and the updated zone propagates to all slave servers), the TXT record became available.

Directly Editing your DNS Zone

You might use this method if you prefer to avoid using $INCLUDE in your zone files or if for some other reason, you need to assemble the TXT record. The steps are as follows.

On your master nameserver, you will be editing the data file that BIND loads for the zone.

  1. If you're using Dynamic Updates in your zone, freeze it first by issuing this command:
rndc freeze <your domain name>
  1. Add the required TXT record.
Don't forget to add the _domainkey subdomain after the key selector name
For an example of syntax, see the examples above. Note the lack of trailing dot so that BIND automatically appends the zone $ORIGIN.
  1. Increment the serial number of the zone, to ensure a flawless zone transfer to your slave servers after reloading the zone on your master.

  2. If you had frozen the zone in step 1, thaw it now by issuing this command:

rndc thaw <your domain name>
  1. Reload the zone file by issuing this command:
rndc reload <your domain name>

Again, after reloading the zone, the TXT record should become available.

Dynamically Updating your DNS Zone to add the DKIM Public Key

In scenarios where you intend to maintain a large number of DKIM keys published or if your operation uses Dynamic Updates for your DNS zone maintenance, it is possible to use this mechanism to manage your DKIM public keys with ease. This scheme requires fewer steps and can be easily integrated in automated provisioning schemes.

First, you must ensure that you'll be able to add the DKIM public keys. You'll need a configuration stanza like this in your BIND configuration file:

zone "_domainkey.itverx.com" {
    type master;
    file "db._domainkey.itverx.com";
    update-policy {
      grant dupdates.itverx.com. subdomain _domainkey.itverx.com. TXT;
    };
    allow-transfer { key transfer.itverx.com; };
};

If you added or changed your configuration file according to the example above, you'll have to signal BIND to apply any configuration changes after insuring your new configuration file is correct.

rndc reconfig

Afterwards, a simple session with nsupdate will allow you to simply add keys in real time:

updater# nsupdate -k Kdupdates.itverx.com.+157+59728.private
> update add alice._domainkey.itverx.com. 3600 in txt "v=DKIM1\; g=*\; k=rsa\; CWt..."
> send
> ^D

Removing public DKIM keys in real time is equally easy:

updater# nsupdate -k Kdupdates.itverx.com.+157+59728.private 
> update delete alice._domainkey.itverx.com. 3600 in txt
> send
> ^D

And of course, conditional update operations work as expected. In all cases, the changes are reflected right away.

Note the additional zone definition
In this third example above, unlike the first two, the _domainkey.itverx.com zone has been delegated/separated from the main itverx.com zone so that it can have update controls configured independently of the parent zone.