In this post, I would like to show, how to use DKIM together with postfix to enhance the chance, that mails send by your mail server are not marked as spam at the receiver. In my last post, I showed how to set up postfix in front of scalix to filter incoming mails. As also the outgoing mails will use postfix I would like to insert the DKIM header into the mails by postfix. To do this, I will use opendkim on debian. Before I start to explain how to configure it, I would like to explain DKIM.
What is DKIM
DKIM or DomainKeys Identified Mail is a procedure, developed by Yahoo in order do validate the sender of a mail. This can be helpful to detect if the mail is spam or not.
If a mail is send, the sending mail server will add a DKIM header to the mail. This header includes information like the signing domain and a selector, besides other information and the signing key. The receiver will than use both information to query a TXT (DNS) record for this domain to get the public signing key. With the help of this key the receiver of the mail will recalculate the signing key on his own and then compare the one in the mail with the calculated one. If both matches, the mail was not altered during transmission and comes from a trusted source.
Using DKIM with Postfix
To sign outgoing mails and check incoming mails, you can use OpenDkim on debian together with postfix.
The first step is to install OpenDkim on debian:
apt-get install opendkim
After OpenDkim is installed, you need to configure it to work with Postfix. Open the main configuration file for OpenDkim:
The file should look like this:
# 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. # Log to syslog Syslog yes # Required to use local socket with MTAs that access the socket as a non- # privileged user (e.g. Postfix) UMask 002 # Sign for example.com with key in /etc/mail/dkim.key using # selector '2007' (e.g. 2007._domainkey.example.com) #Domain example.com #KeyFile /etc/mail/dkim.key #Selector 2007 # Commonly-used options; the commented-out versions show the defaults. #Canonicalization simple #Mode sv #SubDomains no #ADSPAction continue # Always oversign From (sign using actual From and a null From to prevent # malicious signatures header fields (From and/or others) between the signer # and the verifier. From is oversigned by default in the Debian pacakge # because it is often the identity key used by reputation systems and thus # somewhat security sensitive. OversignHeaders From # List domains to use for RFC 6541 DKIM Authorized Third-Party Signatures # (ATPS) (experimental) #ATPSDomains example.com AutoRestart Yes AutoRestartRate 10/1h SyslogSuccess Yes LogWhy Yes Canonicalization relaxed/simple ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable Mode sv PidFile /var/run/opendkim/opendkim.pid SignatureAlgorithm rsa-sha256 UserID opendkim:opendkim Socket inet:[email protected]
The last part is the interesting one. Save the file. We now need to create some additional files to get it working.
I will start with this file:
This file is used to specify hosts and domains which are not checked but signed. The file could look like this:
127.0.0.1 localhost 10.3.5.0/24 *.flomain.de
According to the content of this file, all mails from localhost, 127.0.0.1 and from the internal network 10.3.5.0/25, where the scalix host is located will not be checked, but signed with the DKIM key. The “*.flomain.de” entry will make sure that not only mails from the root domain are signed, but also mails from sub domains.
The next file is the KeyTable:
This file is used to link the domain selector to the private key which is stored in a file. It could look like this:
The separator is “mail”. You can use any separator as you like.
The last file is the file with the signing table:
This one instructs OpenDkim, which key should be used for which mail address. Basically, every mail user could have their own private key. In reality, this makes no sense and you would specify one key for the domain like this:
We have now everything in place, except the keys. Generating the keys is the next step. The good news is, that OpenDkim already includes the tools to generate the key.
You can create the key in every folder on your server and copy the key then into the key directory or you change to the keys directory now:
You should create sub folders for every domain:
and change into this created directory. To generate the key use this command:
opendkim-genkey -s mail -d floamin.de
Where “s” is the selector and “d” is the domain.
This will generate two files. The key file, which should be kept private by changing the owner to “opendkim” and make it available only for this user, and a txt file which has the txt record the for the DNS server included.
I know have to add the content of the txt file to DNS server as a txt record. For my DNS provider it looks like this:
You can check, if the record is correct by using this site:
You need to insert the selector and the domain and the tool will query your DNS server and check if the record is there and configured correctly.
If this is working, you need to tell postfix to use Opendkim to check and sign messages.
Open this file:
and add this to the end of the file:
Save the file and open the postfix configuration:
Check if those lines are present:
milter_protocol = 2 milter_default_action = accept
and add the following lines:
smtpd_milters = inet:localhost:12301 non_smtpd_milters = inet:localhost:12301
If the two commands above are already there, e.g. if you use milter to connect spamassassin to postfix, simply add the Opendkim milter at the end, separated by a “,”.
After restarting both services, Opendim and postfix, it should work. You can test this by sending a mail to “[email protected]”. You should receive a reply containing the result of the DKIM check like this:
========================================================== Summary of Results ========================================================== SPF check: pass DomainKeys check: neutral DKIM check: pass Sender-ID check: pass SpamAssassin check: ham
If you see “pass” for the DKIM check, than your DKIM configuration is working.
If you look into the source code of your mails and see the DKIM header twice, you should adjust your postfix master config:
You should have an entry like this at the end of the file:
127.0.0.1:10025 inet n - - - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= -o smtpd_restriction_classes= -o smtpd_delay_reject=no -o smtpd_client_restrictions=permit_mynetworks,reject -o smtpd_helo_restrictions= -o smtpd_sender_restrictions= -o smtpd_recipient_restrictions=permit_mynetworks,reject -o smtpd_data_restrictions=reject_unauth_pipelining -o smtpd_end_of_data_restrictions= -o mynetworks=127.0.0.0/8 -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o smtpd_client_connection_count_limit=0 -o smtpd_client_connection_rate_limit=0 -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
Add this to the last line:
After restarting postfix, you should have only one DKIM header in your mails.
If you have any questions, regarding this post or if you would like provide feedback, please use the comment function below.