DKIM with amavis and postfix

DKIM (DomainKeys Identified Mail) is a mechanism to sign emails cryptographically. It can be used to ensure an email was really sent by the domain it claims to come from. Therefore it is an interesting feature in spam checking.

In this post I’m going to describe how I set up DKIM with amavis to sign all outgoing messages with the key of my domain. This works well in my setup with postfix, dovecot and amavis (amavisd-new), for your own setup you might have to change some things.

This is a post from my old blog http://tech.cbjck.de. It has been moved here and slightly edited for better readability. It's also been adjusted to the new layout.
The content however is old and might be outdated.

Setup domainkey and tell amavis about it

Not tested!

I’ve not done it like described here as I already had a pair of keys created by OpenDKIM. See my steps below. However this should work as well:

First you need to create a pair of keys, one public and one private. Amavis can do this for you:

amavisd-new genrsa /var/amavis/dkim/example-foo.key.pem

In /etc/amavis/conf.d/50-user you need at least the following. For using policy banks see below.

  $enable_dkim_verification = 1;
  $enable_dkim_signing = 1;
  dkim_key('cbjck.de', 'foo', '/var/amavis/dkim/example-foo.key.pem');
  @dkim_signature_options_bysender_maps = (
    { '.' => { ttl => 21*24*3600, c => 'relaxed/simple' } } );
  # list your internal networks
  @mynetworks = qw(0.0.0.0/8 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16);

The first two lines just enable the DKIM feature, in the second line you tell amavis whick key to use for signing and then mails from which senders should be signed. If you want to sign also messages from (authenticated) user outside the server have a look at policy banks.

Your public key has to be known to anybody in order to check the signature. You need to create a TXT record for your domain looking like this:

mail._domainkey.cbjck.de IN TXT "v=DKIM1; h=rsa-sha256; k=rsa;p=AySFjB......xorQAB"

How you achieve this depends on your provider / your access to DNS.

Now check if everthing is working as it should:

amavisd-new showkeys

should present you your key,

amavisd-new testkeys

shows OK if checking a signature using the pubkey in DNS is working.

Time to restart amavis and send signed mails:

/etc/init.d/amavis restart

Using and converting opendkim keys

Tested

I’ve taken a different aproach as I already had generated keys with opendkim like this

opendkim-genkey -r -h rsa-sha256 -d example.com -s mail

an had KeyTable looking like this:

cbjck.de cbjck.de:mail:/etc/opendkim/cbjck.de/mail.private

Amavis can convert these using

 amavisd-new convert_keysfile /etc/opendkim/KeyTable

This command will return configuration options to paste in your amavis configuration (/etc/amavis/conf.d/50-user)

As the DNS TXT record already existed I went on with testing:

amavisd-new showkeys
amavisd-new testkeys

Using policy banks

Tested

As you probably also want sign mails you sent from an email client, your mobile etc. you will need a policy bank marking these mails as “local”. This means they are treatted as belonging to your domain even if the ip of the sender does not.

On my server all mails outgoing mails have to be sent over port 587 (submisssion). In my /etc/postfix/master.cf I have the following:

submission inet n       -       n       -       -       smtpd
  -o smtpd_proxy_filter=[127.0.0.1]:10026
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
  -o tls_preempt_cipherlist=yes
  -o milter_macro_daemon_name=ORIGINATING

Incoming mails will be proxied to amavis on port 10026. How they should be treated is defined in /etc/amavis/conf.d/50-user

$inet_socket_port = [9998,10024,10026];
$interface_policy{'10026'} = 'LOCAL';

$policy_bank{'LOCAL'} = {
    originating = 1,
    enable_dkim_signing = 1,
    final_spam_destiny = D_BOUNCE,
    final_virus_destiny = D_REJECT,
    final_banned_destiny= D_PASS,
    final_bad_header_destiny = D_PASS,
    banned_filename_maps = ['MYNETS-DEFAULT'],
    warnbadhsender = 1
};

This defines a policy bank telling what to do with mails coming in on port 10026 (being all mails incoming from authenticated senders as defined for postfix above). The important lines are

    originating = 1,
    enable_dkim_signing = 1,

telling these mails are to be treatetd as belonging the my domain and sign them apropriatly.

References

Leave a Reply

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