Email Signing and Verification with Amavisd-new and DKIM

I recently had a moment of “why did I do that?” when I temporarily disabled DKIM signing on my mail server. A quick email to a mailing list triggered a flood of DMARC authentication failure reports. It was a clear reminder that a surprising number of administrators have DMARC and DKIM reporting enabled.

Here’s a sample of what those reports look like:

This is an authentication failure report for an email message received from IP
x.x.x.x on Sat,  7 Aug 2021 20:48:17 +0200 (CEST).


Feedback-Type: auth-failure
Version: 1
User-Agent: OpenDMARC-Filter/1.3.2
Auth-Failure: dmarc
Authentication-Results: x.x.x; dmarc=fail header.from=jeanbruenn.info
Original-Envelope-Id: C3D99A6
Original-Mail-From: amavis-users-bounces+apprenti=x.x@amavis.org
Source-IP: x.x.x.x (x.x.x)
Reported-Domain: jeanbruenn.info

Disabling DKIM signing was definitely not my brightest idea, but it provided an excellent reason to write this guide for configuring DKIM verification and signing with Amavisd-new.

DKIM Verification

Enabling DKIM verification in Amavisd-new is straightforward. In your configuration file (/etc/amavis/conf.d/50-user on Debian/Ubuntu), simply set the $enable_dkim_verification variable to 1.

$enable_dkim_verification = 1;

It’s worth noting that some default configurations may have this setting disabled with a comment about preventing a warning. While I haven’t encountered this specific warning in my logs, I recommend enabling it for stronger security.

DKIM Signing: Key Generation and Configuration

DKIM signing requires a bit more effort, starting with the key management. For each domain you want to sign, you need a unique key. You can generate this key with the amavisd-new genrsa command.

While it may be tempting to use a larger key size like 2048 or 4096 bits for enhanced security, this can cause issues with older DNS tools like nsupdate due to line length limitations. For this reason, I’m using a 1024-bit key. It’s crucial not to use a key smaller than 1024 bits.

Generating Keys and Setting Permissions

root@mail:~# mkdir /var/lib/amavis/dkim
root@mail:~# amavisd-new genrsa /var/lib/amavis/dkim/no-uce.de 1024
Private RSA key successfully written to file "/var/lib/amavis/dkim/no-uce.de" (1024 bits, PEM format)
root@mail:~# amavisd-new genrsa /var/lib/amavis/dkim/jeanbruenn.info 1024
Private RSA key successfully written to file "/var/lib/amavis/dkim/jeanbruenn.info" (1024 bits, PEM format)
root@mail:~# chown amavis:amavis /var/lib/amavis/dkim -R

Adding Keys to Amavis Configuration

Next, add these keys to your Amavis configuration. The dkim_key() entry includes the domain name, a selector (the identifier), and the path to the key file. I prefer using a date-based selector for simplicity and versioning—a common practice in Configuration Management.

dkim_key('no-uce.de', 'dkim20210807', '/var/lib/amavis/dkim/no-uce.de');
dkim_key('jeanbruenn.info', 'dkim20210807', '/var/lib/amavis/dkim/jeanbruenn.info');

You also need to set the signature options. You can apply this globally or per-domain.

@dkim_signature_options_bysender_maps = (
  {
    '.' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'
    }
  }
);
# Alternatively, configure per-domain:
@dkim_signature_options_bysender_maps = (
  {
    'jeanbruenn.info' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'
    },
    'no-uce.de' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'
    }
  }
);

Publishing the Public Key to DNS

At this point, keep DKIM signing disabled. The final step is to add the public key to your DNS. The record format is selector._domainkey.yourdomain.tld. To get the public key from Amavis, use the showkeys command.

root@mail:/etc/amavis/conf.d# amavisd-new showkeys test
; key#3 1024 bits, i=test, d=test, /var/lib/amavis/dkim/test
test._domainkey.test.	3600 TXT (
  "v=DKIM1; p="
  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmWmVv2boll50tKy8Hb/7aU78A"
  "mWdJ8PITTdntxMimV+MGzpNEKKZDdkzcP6W9n9kPTmEpRI24rPIMwrTd5kW1Qj3d"
  "5goOqx7JKuStXvO7RGxD3zJZ5rLgiOupi4nKc/quOPbABmMISE+6RJQxyOLBW+JU"
  "XHyudJPpsAtuJ2bfWwIDAQAB")

Now, add the key to your DNS using nsupdate.

root@ns3:~# nsupdate -l
> zone jeanbruenn.info
> update add dkim20210807._domainkey.jeanbruenn.info. 3600 IN TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmWmVv2boll50tKy8Hb/7aU78AmWdJ8PITTdntxMimV+MGzpNEKKZDdkzcP6W9n9kPTmEpRI24rPIMwrTd5kW1Qj3d5goOqx7JKuStXvO7RGxD3zJZ5rLgiOupi4nKc/quOPbABmMISE+6RJQxyOLBW+JUXHyudJPpsAtuJ2bfWwIDAQAB"
> send

Verification and Final Activation

After giving DNS time to propagate, verify your configuration with amavisd-new testkeys.

TESTING#1 no-uce.de: dkim20210807._domainkey.no-uce.de => pass
TESTING#2 jeanbruenn.info: dkim20210807._domainkey.jeanbruenn.info => pass

Once all your domains pass the test, you can enable DKIM signing:

$enable_dkim_signing = 1;

To ensure outgoing mail is signed correctly, you’ll need to define an ORIGINATING policy bank in your Amavis configuration.

$policy_bank{'ORIGINATING'} = { 
  originating => 1,
  forward_method => 'smtp:[127.0.0.1]:10025',
  notify_method => 'smtp:[127.0.0.1]:10025',
  terminate_dsn_on_notify_success => 0,

  # see: https://www.ijs.si/software/amavisd/amavisd-new-docs.html#dkim
  # force MTA to convert mail to 7-bit before DKIM signing
  # to avoid later conversions which could destroy signature:
  smtpd_discard_ehlo_keywords => ['8BITMIME'],
};

You can verify that signing works by looking for dkim_new in your logs:

Aug  7 23:47:25 mail amavis[6987]: (06987-01) Passed CLEAN {RelayedOutbound}, ORIGINATING LOCAL [91.11.178.107]:36766 [91.11.178.107] <himself@jeanbruenn.info> -> <xxx@gmail.com>, Queue-ID: 9EB4013FC4B, Message-ID: <24940b30-5b69-0917-7882-35a68c5a7877@jeanbruenn.info>, mail_id: MwVJf0WOWnHU, Hits: 1.986, size: 870, queued_as: 1D15613F99D, dkim_new=dkim20210807:jeanbruenn.info, 1775 ms

See Also

  • RFC 6376. DomainKeys Identified Mail (DKIM) Signatures. https://www.rfc-editor.org/rfc/rfc6376
  • Amavisd-new. Amavisd-new documentation on DKIM. https://www.ijs.si/software/amavisd/amavisd-new-docs.html#dkim
  • Perl documentation. Amavisd-new-conf(5). https://manpages.debian.org/stable/amavisd-new/amavisd-new-conf.5.en.html
  • DMARC.org. DMARC, SPF, and DKIM. https://dmarc.org/

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.