Skip to content
Note: Navigation options above may not work on this devices screen size, if requiring link access, please switch to Desktop layout for this session.

Email Anti Spoofing - DKIM

Continuing with the second article in our securing Email to stop spoofing series we take a look at DKIM, or Domain Keys Identified Mail, which is an Email authentication method to detect forgeries, it allows the receiving Mail Server to check if an Email that claims to have come from a specific domain, actually did.

it does this is by the senders Mail Server adding a digital signature to each outbound message, then the receivers Mail Server looking up that domains public key in DNS to verify the signature.

One of the big problem that can arise with DKIM however is when using Mailing Lists, because these are on-forwarding systems that often modify headers, adding List tags info to the body, including the subject, it's modifying your message, so when the receiving Mail Server looks up the record it sees this mismatch and takes the appropriate action based on there anti-spam policies, usually, this is just marking the message as spam, some lists however, using Mailman for example, can modify the message by rewriting the sender so the receiver sees it from the List server as generating it and not the original posters Email avoiding some of these problems, regrettably, not too many Lists have enabled this feature, if your interest in DKIM is for business Email, then none of that should concern you since you'd not likely be using company Email for a Mailing List subscription, or as in my case List posts are not of high importance, but DMARC, which we will cover next time, can help here.

If you run Mailman, edit /etc/mailman/mm_cfg.py and set "REMOVE_DKIM_HEADERS = Yes", the OpenDKIM instance on the List server should reject mail that is not signed correctly by the sender in the first instance so there is no need for the headers to be forwarded on breaking signatures. Then configure the List server to use DKIM on outbound Email using the List server domains keys.

Moving forward, we will be using OpenDKIM and Postfix, with a pinch of SpamAssassin and DNS, the provided information should allow you to adapt to most other MTA's.

Since most servers have more than one domain, we are going to use the in-depth multi domain method of configuring OpenDKIM, since that is best practice and how most people set-up OpenDKIM anyway, regardless of if you have one or a thousand and one domains. The simple and very basic single domain method just allows you to put your domain, keyfile and selector references in the main config file, but again that only works for one domain, probably why its not considered best practice so we wont cover it here.

Download OpenDKIM, some distro's may have 2.11 available via their package manager so check their first, if you're installing from source (best method) it's built by running from the extracted source's directory with just one option:
./configure --disable-shared && make && make install 
Next cd into /etc/opendkim, if the directory keys does not exist, create it, then create the keys/yourdomain directory...

Edit /etc/opendkim/opendkim.conf and set
Syslog                  yes
SyslogSuccess    yes
Socket                 inet:8891@localhost
PidFile                 /var/run/opendkim.pid
ReportAddress    postmaster@yourdomain
SendReports       yes
Mode                   sv
SubDomains       yes
Canonicalization    relaxed/simple
KeyTable             /etc/opendkim/KeyTable
SigningTable       refile:/etc/opendkim/SigningTable
InternalHosts      refile:/etc/opendkim/TrustedHosts

# For secondary mx's and other whitelisted servers:
PeerList            refile:/etc/opendkim/PeerList
Now we generate the keys, because there are too many commissioned and forgotten Mail Servers out there, we are still pretty much stuck with RSA, but using 2K signatures for Email at least, is still quite acceptable, well, in 2023 anyway, but first, we need to make the keys directory for "yourdomain"
cd /etc/opendkim
mkdir keys/yourdomain

This next command (all on one line) generates the keys and outputs the contents to files in the keys/yourdomain directory you just created
opendkim-genkey -b 2048 -d yourdomain -D /etc/opendkim/keys/yourdomain -s dkim1 -v

opendkim-genkey: generating private key
opendkim-genkey: private key written to dkim1.private
opendkim-genkey: extracting public key
opendkim-genkey: DNS TXT record written to dkim1.txt
Now login to your primary DNS server and edit your zone file, add the contents of dkim1.txt at the top of your hostname entries, you can if you wish, omit the IN statement, and omit the curly brackets and everything after the last curly bracket as well (semi colon and dashes comment), they are not really needed. Then increment your zone serial, and issue rndc reload.

It is important to verify this is set-up correctly, you can do that by running (on linux obviously)
host  -t  txt  dkim1._domainkey.yourdomain  ns1.yourdomain
Now back on the Mail Server, edit /etc/opendkim/Keytable and add your domain as below (again all on one line), so OpenDKIM knows where the keys are, why it doesn't do these next couple of steps itself is a question for the authors of OpenDKIM :-|
yourdomain  yourdomain:dkim1:/etc/opendkim/keys/yourdomain/dkim1.private
Now create or edit /etc/opendkim/SigningTable and add yourdomain into it as follows
*@yourdomain   yourdomain
If you are intending to send Email using sub-domains, you will need to repeat the above process for each sub-domain, it is also important to note than your DNS TXT entry for sub-domains needs to reference the sub-domains, as an example lets say your domain is example.net but need to send using helpdesk.example.net and salesforce.example.net, you enter their respective public keys in DNS as follows
dkim1._domainkey IN  TXT ( "v=DKIM1; k=rsa......

dkim1._domainkey.helpdesk  IN  TXT ( "v=DKIM1; ...

dkim1._domainkey.salesforce  IN TXT ( "v=DKIM1; ...
Moving on, we next edit /etc/opendkim/TrustedHosts to include your servers IP and Domain
127.0.0.1
*.yourdomain
OK, we are nearly done in this part of the set-up, we just need to edit /etc/opendkim/PeerList and enter one entry per line, the IP addresses of your secondary MX's and other external servers you wish to whitelist, if you're dual stack, don't forget to include your IPv6 addresses as well. If you see some rot about transport errors, it's bound to be that virus systemd again, dictating to you what it wants to do, overriding what you want the system to do, check socket variable in /etc/default/opendkim to match opendkim.conf.

Nearly there, now we need to tell postfix to pass to OpenDKIM for signing, we do this by adding inet:127.0.0.1:8891 to our smtpd_milters in main.cf, and by adding it into the submission and smtps sections in master.cf (doing this means postfix wont try run other inbound-style milters when authenticated users are sending outbound messages), eg...
(in main.cf)  
smtpd_milters = inet:127.0.0.1:8891

(in master.cf) 
submission inet  n  -  n  -  -  smtpd
   ...other options...
   -o smtpd_milters=inet:127.0.0.1:8891

smtps inet  n  -  n  -  -  smtpd
   ...other options...
   -o smtpd_milters=inet:127.0.0.1:8891

Edit your postfix start-up script to add OpenDKIM just after it starts postfix
echo -n "Start OpenDKIM..."
/usr/local/sbin/opendkim -x /etc/opendkim/opendkim.conf 
issue postfix reload, then start OpenDKIM.

If in the future you add additional domains, or sub-domains, once you've edited the appropriate files, rather than restarting opendkim, you can instead have it reload its configuration by issuing a SIGUSR1, eg...
killall -USR1 opendkim

Congrats, you should now be signing your outbound Email.

If you use amavisd, edit amavisd.conf and set $enable_dkim_signing = 0; and if you're using SpamAssassin, you'll also want to set $enable_dkim_verification = 0; as well in amavisd.conf. When you installed SpamAssassin, one of the modules it would have installed is Mail::DKIM, just for this very purpose, it will use the test results in adjusting scoring of your received Emails, chances are, you have already been doing this without knowing.

I know adding DKIM seems a bit of work, and I agree a few steps should be handled automatically by OpenDKIM, but when you're done, you'll realise it's nowhere near as daunting as it might first appear.

To get the best out of DKIM, you also need to configure DNSSEC, this further increases its strength, not doing so will be evident to everyone by stating "unprotected"
Authentication-Results: mail.server;
    dkim=pass (2048-bit key; unprotected) header.d=opensourcerers.net

Next time, we continue the series with DMARC.

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

Simmo on :

pretty easy to follow, was curious to why you added stuff into master.cf but reread the comment, makes sense, I guess poostfix would know whats in and out bound but declaring it simplifies it.

Add Comment

E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Standard emoticons like :-) and ;-) are converted to images.
Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Form options

Multiple DNSBL checks will be performed on submission of your comments.
Accepted comments will then be subject to moderation approval before displaying.