In order for high-profile email servers like Gmail and Outlook to receive emails we send, we need to sign our outgoing emails using DKIM. We use dkimpy-milter to do this.
dkimpy-milter is a milter, or mail filter. Postfix will pass incoming and outgoing emails through this milter, which will:
- Sign outgoing emails using our DKIM key
- Verify the DKIM signature of incoming emails
To install dkimpy-milter, install its Debian package:
# apt install dkimpy-milter
Enabling the service
Like Postfix and Dovecot, dkimpy-milter provides a systemd service which we will enable so the milter is automatically started:
# systemctl enable dkimpy-milter.service
Before configuring dkimpy-milter, we must generate keys which will be used to sign outgoing mail.
First, create and move into the
# install -d -m 0750 /etc/postfix/dkim # cd /etc/postfix/dkim
According to dkimpy-milter's documentation,
Signing keys should be protected (owned by root:root with permissions 600 in a directory that is not world readable).
An easy way to generate a key is to use the
utility that comes with dkimpy-milter:
# dknewkey <keyname>
<keyname> can be anything you want, but it must be the same value used throughout the rest of the configuration.
For simplicity, we use the name
dknewkey(1) will generate a 2048-bit RSA key. If you want a larger key, you must generate it manually using OpenSSL.
We can manually generate a private RSA key using OpenSSL:
# openssl genrsa -out <keyname>.key <keysize> # chmod 600 <keyname>.key
keysize should be 2048 or 4096.
This defines the length (in bits) of the newly generated key.
After generating the private key, we must extract the public key and create the DNS record text:
# printf 'v=DKIM1; k=rsa; h=sha256; p=%s' "$(openssl rsa -pubout -outform DER -in <keyname>.key | openssl base64 -A)" > <keyname>.dns
This will extract the public key, encode it in Base64, and print it with the proper formatting for a DKIM DNS record.
The output will be written to
dkimpy-milter is configured by placing settings in the
The contents are listed below.
All of the options are commented and are fairly easy to understand, so they won't be explained further.
# Log to syslog Syslog yes # Sign mail for kasad.com and subdomains Domain kasad.com SubDomains yes # Specify the keyfile and selector to use KeyFile /etc/postfix/dkim/mail.key Selector mail # Use this server's hostname as the auth server ID when # generating the Authentication-Results header AuthservID HOSTNAME # Listen on localhost on port 12301 # This is the socket Postfix will use to communicate with dkimpy-milter Socket inet:12301@localhost
DKIM uses a selector, which is an arbitrary value that identifies a certain key. The key name and the selector need not match. The selector can be whatever you wish, as long as the same value is used in the DKIM DNS record.
DKIM DNS record
Mail servers that we send emails to will validate our DKIM signature by retrieving our public key from a DNS TXT record.
Define a TXT record for the
<selector>._domainkey.<domain> domain, where
<selector> is the selector defined in the configuration file (
<domain> is your mail server's domain (
kasad.com in our case).
The content of this record should be the content of the
<keyname>.dns file we generated earlier.
If the key used to sign mail is changed, the DNS record must be updated with the new public key. If the selector is changed, but the key remains the same, the record's content can remain and only the first domain component must be changed.
As an example record,
dig TXT mail._domainkey.kasad.com outputs the following:
mail._domainkey.kasad.com. 214 IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxOlorHTT/rsI5WWobgA0/+XRWAav1F5As1YoUVEUknIPbIJDuMIbEbV468XdHsp63PvwF2uz9A3iEefaGIMOpcJrgIcb3X5el0/x89kxK/zDDruiAzpcLwdy6urEmQhdRfoi1stdOhDlo8dNQj5vRORceJ2v5fUJ3VUV9eWd7cGOjhladUWedY" "gdIdiYqsbR6CeYIhpKK1v414 UmtB1sKcxHgxbROm+yjM6iJaSQbF9iLUlBEHOBfRc1vVuw0N+LQpRDNaaHSom0SusrMnXnjb33ANNCFMITwL9fZm9mR+sR+m+2QGvhLyODJMsxRCBKSSZhrjP2Csa80ZnOtNX91QIDAQAB"
Note that the public key is too long to fit in one TXT record, so it is broken into two. I do not know the specifics on how DNS or DKIM clients handle split TXT records. However, this is how most DKIM records look and I have not experienced any compatibility issues so far.