Setup DKIM (DomainKeys) for Ubuntu, Postfix and Mailman
I'm running Ubuntu 12.04 with Postfix and Mailman. I want to set up DKIM. DomainKeys Identified Mail, or DKIM, is the successor to Yahoo's "DomainKeys". It incorporates Cisco's Identified Mail.
What are the steps for setting this up?
Is opendkim recommended?
The only reference I have is HowToForge, but I prefer to get help here (even if it is just a confirmation of the steps at that link). Actually, I think the info at HowToForge is outdated because it mentions dkim-filter instead of opendkim.
openDKIM and Postfix on Ubuntu Server 12.04LTS
I'll try to come back and format this better. But since there was a request to post my answer, I wanted to post it now rather than wait until I had time to format it properly. Due to lack of time, I wrapped my entire answer in a blockquote. I hope this solution is helpful.
These are my references:
man opendkim-testkey
man opendkim.conf
- http://www.serveridol.com/2012/02/17/opendkim-configuring-dkim-keys-on-postfix/
- http://stevejenkins.com/blog/2010/09/how-to-get-dkim-domainkeys-identified-mail-working-on-centos-5-5-and-postfix-using-opendkim/
- http://blog.example.com/tag/opendkim/
- http://blog.tjitjing.com/index.php/2012/03/guide-to-install-opendkim-for-multiple-domains-with-postfix-and-debian.html
and Wikipedia has a good entry on the subject
At a minimum you will need:
- Root access to your mail server
- Access to update the dns records for your domain
Install opendkim from the repositories:
# sudo apt-get install opendkim opendkim-tools
You must decide on what “selector” you wish to use. The selector is essentially a word to describe the key you wish to use. Here I am going to use the selector 201205 as the key became valid in May 2012 (cunning eh?). I give two examples for variety, which will hopefully add clarity. You only need to generate ONE key. However, I am giving both examples so you can compare them.
- 201205 (1st key)
- my_selector (2nd key)
My domain will be example.com
, but I'll use a subdomain for my second example:
- example.com (1st key)
- mail.example.com (2nd key)
I decided to work in the following directory:
# mkdir /etc/opendkim/
# cd /etc/opendkim
Generate the keys in the current directory, using your chosen selector and domain.
# opendkim-genkey -s 201205 -d example.com
You may or may not need to change ownership. See details in my example for the 2nd key below for what ownership and permissions should be.
First you should check if there is a opendkim
user (your user/group IDs may be different):
# grep opendkim /etc/passwd
opendkim:x:108:117::/var/run/opendkim:/bin/false
And you probably need to do this:
# chmod 700 /var/run/opendkim
NOTE: These next two commands are NOT needed on Ubuntu 12.04. But if the command above didn't show that user opendkim was set up properly, do it similarly to this:
# useradd -r -g opendkim -G mail -s /sbin/nologin -d /var/run/opendkim -c "OpenDKIM" opendkim
# chown opendkim:opendkim 201205.private
# cat 201205.private
-----BEGIN RSA PRIVATE KEY-----
ABCCXQ...[long string]...SdQaZw9
-----END RSA PRIVATE KEY-----
Now check the public key and notice that there is a bug (in openDKIM 2.5.2 on Ubuntu 12.04)! Where is contains, ;=rsa;
, it should contain ;k=rsa;
. The k
is missing. Please insert it.
# cat 201205.txt
201205._domainkey IN TXT "v=DKIM1;=rsa; p=WIGfM..[snip]..QIDIAB" ; ----- DKIM 201205 for example.com
After being fixed, it will look like this:
201205._domainkey IN TXT "v=DKIM1;k=rsa; p=WIGfM..[snip]..QIDIAB" ; ----- DKIM 201205 for example.com
Furthermore, you probably need to escape the semicolons like this. If you don't want the ending comment, just delete it. Also note that you should add the t=y flag to indicate to receiving servers that you are testing DKIM but not actively using it yet. You are left with a viable resource record:
201205._domainkey IN TXT "v=DKIM1\;k=rsa\;t=y\;p=WIGfM..[snip]..QIDIAB"
You must publish the content of the above public key to your authoritative DNS server. I recommend using a TXT record. There seems to be a bit of controversy on whether to use an SPF record or both types. After a bit of reading, I elected to stick with the TXT record type exclusively, although I don't believe this is the final word on this topic.
You should use a short TTL (time to live) so that you can change the key without waiting ages for it to propagate though DNS. I used 180 seconds.
The second example of generating a key pair was a bit trickier for me. I'll describe what I did. The first element is that I used the domain value "example.com" even though the key will be used for "mail.example.com". I arrived at this via trial and error. It works, while using "mail.example.com" did not work. Unfortunately, I am not aware of the reasons behind this. This is really the only difference I encountered, but it was troubling enough that I felt I should document my experiences with using subdomains. None of the other beginning level tutorials I found did this. Generate a second key:
opendkim-genkey -s my_selector -d example.com
check ownership and permissions of the private key, as above. Here's what they should look like:
# ls -la /etc/opendkim
-rw------- 1 opendkim opendkim 891 May 10 07:44 my_selector.private
After publishing the DNS record, check it with dig
. It should return exactly what you entered in the resource record (RR).
$ dig 201205._domainkey.example.com txt +short
"v=DKIM1\;k=rsa\;t=y\;p=WIGfM..[snip]..QIDIAB"
Now, test the key. The commands below assume you are in the directory where the key resides (/etc/opendkim for me).
# opendkim-testkey -d example.com -s 201205 -k 201205.private -vvv
opendkim-testkey: key loaded from /etc/opendkim/201205.private
opendkim-testkey: checking key '201205._domainkey.example.com'
opendkim-testkey: key not secure
opendkim-testkey: key OK
These results are expected. The "key not secure" does not indicate an error. It is an expected consequence of not using DNSSSEC. DNSSEC is coming, but it isn't ready for prime time yet, according to my reading.
Example with 2nd key:
# opendkim-testkey -d example.com -s my_selector -k /etc/opendkim/my_selector.private -vvvv
opendkim-testkey: key loaded from /etc/opendkim/my_selector.private
opendkim-testkey: checking key 'my_selector._domainkey.example.com'
opendkim-testkey: key not secure
opendkim-testkey: key OK
Note that opendkim is reporting that the key is not secure. This relates to the fact that DNSSEC is not implemented on my DNS server and theoretically somebody could intercept the DNS lookup and replace it with their own key.
Edit the OpenDKIM config file:
# nano /etc/opendkim.conf
# cat /etc/opendkim.conf
# This is a basic configuration that can easily be adapted to suit a standard
# installation. For more advanced options, see opendkim.conf(5) and/or
# /usr/share/doc/opendkim/examples/opendkim.conf.sample.
#
Domain example.com
KeyFile /etc/opendkim/201205.private
Selector 201205
#
# Commonly-used options
Canonicalization relaxed/simple
Mode sv
SubDomains yes
# Log to syslog
Syslog yes
LogWhy yes
# Required to use local socket with MTAs that access the socket as a non-
# privileged user (e.g. Postfix)
UMask 022
UserID opendkim:opendkim
#
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
#
Socket inet:8891@localhost
#EOF
If you are using my 2nd key example, with the targeted domain “mail.example.com” the entry would still only reference the main domain:
Domain example.com
KeyFile /etc/dkim/my_selector.private
Selector my_selector
-----
Note from one of my sources: If you run multiple instances of Postfix you need to add this to the opendkim.conf for each instance (or the ones you want to use opendkim)
Create a file with your text editor /etc/opendkim/TrustedHosts
:
Add domains, hostnames and/or ip’s that should be handled by OpenDKIM. Don’t forget localhost.
127.0.0.1
localhost
example.com
mail.example.com
192.168.1.100 #(IP address of your server, if applicable)
(the last line above probably won't be needed. If you do have an IP address to add, make sure you use your own, not the example above.)
Edit /etc/default/opendkim
:
Uncomment this row and use port 8891:
SOCKET="inet:8891@localhost" # listen on loopback on port
Make sure your firewall (iptables) allows loopback on localhost:
sudo iptables -A INPUT -i lo -j ACCEPT
Next, Create a file with your text editor /etc/opendkim/KeyTable
and add the domain to the KeyTable
Add line:
#EXAMPLE showing my 2nd key:
my_selector._domainkey.example.com example.com:my_selector:/etc/opendkim/my_selector.private
Next Create a file with your text editor /etc/opendkim/SigningTable
and add the domain to the SigningTable
I show both examples. Note that for my 2nd key, I now have to use the full domain name "mail.example.com":
example.com 201205._domainkey.example.com
mail.example.com my_selector._domainkey.example.com
Note that in OpenDKIM 2.0.1 domain names are case sensitive. In this example we're using a newer version of OpenDKIM and this does not appear to be a problem.
Configure postfix. Edit /etc/postfix/main.cf and add the lines to the end
milter_default_action = accept
milter_protocol = 2
smtpd_milters=inet:localhost:8891
non_smtpd_milters=inet:localhost:8891
Also change the hostname:
#myhostname = localhost #original
myhostname = mail.example.com
You should also change the corresponding entry in /etc/hosts.
These changes are effective after a reboot (although you can set it immediately with the command: hostname NEW_NAME
).
Restart postfix and opendkim if you didn't reboot:
# service opendkim restart
Restarting OpenDKIM: opendkim.
# service postfix restart
* Stopping Postfix Mail Transport Agent postfix [ OK ]
* Starting Postfix Mail Transport Agent postfix [ OK ]
Testing
The best way to check that your signed mail is being authenticated and that your DNS records are properly set up is to use one of the free testing services. I used these:
- Brandon Checketts Email Validator - http://www.brandonchecketts.com/emailtest.php (my favorite)
- Send a signed email to: [email protected] (my favorite also)
Send a signed email to: [email protected] (you can put all of the test email addresses in the To: field of a single outgoing message to test)
Send a signed email to: [email protected] <--- BROKEN!!! Don't use this one.
Each of these will tell you if things are working properly, and give you some pointers on troubleshooting if needed.
If you have a Gmail account, you can also send a signed message there for a quick and easy test.
Once you are happy that all is well, you can remove the testing flag in the DNS TXT record and increase TTL.
Done!