Amavisd-new and DKIM

Currently I’m playing around with amavisd-new and amavis-milter. Trying to analyse a maybe-bug I temporarily disabled DKIM signing. Then I had the glory idea to send an E-Mail to the amavis maillinglist. It sort of caused some mail reporting storm back to me. In this article I’ll show you, how you can configure amavisd-new to do DKIM verification and DKIM signing. But first, here’s one of those reports:

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
Original-Envelope-Id: C3D99A6
Source-IP: x.x.x.x (x.x.x)

I’m (positively) impressed how many on that maillinglist got reporting enabled. Anyway. Disabling DKIM signing temporarily and mailing to a maillinglist was not the brightest idea I had.

DKIM verification

Setting up DKIM Verification in Amavisd-new is as simple as adding:

$enable_dkim_verification = 1;

to your /etc/amavis/conf.d/50-user in case you’re using Debian like I do (I believe it’s the same in Ubuntu). However. The default configuration in Debian added a comment to that setting:

$enable_dkim_verification = 0; #disabled to prevent warning

I have no clue which warning that refers to. I couldn’t find any warning in my logs.

DKIM signing

DKIM signing involves a bit more work. For every Domain you want to have signed you need a key. This key can be generated using amavisd-new genrsa filename length. You might be tempted to use 2048 or 4096 bit – Sadly that does not work with all DNS tools (I’m using nsupdate and it cries if the line is too long) hence I’m just using 1024 for DKIM. Please don’t go lower than 1024.

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

Now we need to add these keys to amavis by adding a dkim_key() entry for every domain to the 50-user configuration file. The dkim_key() entry contains the domainname, an identifier and the path to the key.

Some people suggest to have the identifier random, others simplify it and just increment the identifier like the serial in your DNS SOA record. Whatever you prefer, in my case it looks like this:

dkim_key('', 'dkim20210807', '/var/lib/amavis/dkim/');
dkim_key('', 'dkim20210807', '/var/lib/amavis/dkim/')

In additon you add:

@dkim_signature_options_bysender_maps = (
    '.' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'

Either with a dot like done here, or per domain:

@dkim_signature_options_bysender_maps = (
    '' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'
    '' => {
      ttl => 30*24*3600,
      c => 'relaxed/simple'

Keep dkim_signing disabled for now. Just add the above so that amavisd-new can find the keys. The next step is to add the keys to your DNS. The record is: identifier._domainkey.yourdomain.tld. I created a test-key for this guide to show you how to use nsupdate to set it up. First you get the public key from amavis:

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="

Then you add it using e.g. nsupdate:

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

Now you may use amavisd-new testkeys to see if all your domains are properly signed. amavisd-new testkeys accepts a domain name as argument; so there is no need to check all domains.

root@mail:/etc/amavis/conf.d# amavisd-new testkeys
TESTING#1 => invalid (public key: not available)
TESTING#2 => fail (bad RSA signature)

Once everything is set up correctly (and DNS had some time to catch up) it looks like this:

TESTING#1 => pass
TESTING#2 => pass

Finally you may enable signing of outgoing E-Mails by adding the following to your configuration:

$enable_dkim_signing = 1;

As well as defining the ORIGINATING policy bank. Mine looks like this:

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

  # see:
  # force MTA to convert mail to 7-bit before DKIM signing
  # to avoid later conversions which could destroy signature:
  smtpd_discard_ehlo_keywords => ['8BITMIME'],

If you used my amavis guide, you may want to add smtpd_discard_ehlo_keywords to the INT-MTA policybank as well. You can see in the logs that signing works by looking for dkim_new:

Aug  7 23:47:25 mail amavis[6987]: (06987-01) Passed CLEAN {RelayedOutbound}, ORIGINATING LOCAL []:36766 [] <> -> <>, Queue-ID: 9EB4013FC4B, Message-ID: <>, mail_id: MwVJf0WOWnHU, Hits: 1.986, size: 870, queued_as: 1D15613F99D,, 1775 ms

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.