content:en_us:kb_howtos_using_dkim_to_sign_and_validate_mail

Using DKIM to Sign and Validate Mail

Background

Domain Keys Identified Mail (DKIM) is an email authentication method designed to detect email spoofing. It allows the receiver to check that an email claimed to have come from a specific domain was indeed authorized by the owner of that domain. It is intended to prevent forged sender addresses in emails, a technique often used in phishing and email spam. - Wikipedia

Requirements

In order to implement DKIM you need your own domain and a functioning SMTP Server (postfix) for the domain. I will use mydomain.com as an example domain.

Methods

There are two methods of signing in this howto. The first is using Amavis which you will already have if you have the the ClearOS Anti-spam filter. The second method (the original method in this howto) uses OpenDKIM.

Signing with Amavis

Make the folder for your keys:

mkdir /etc/amavisd/dkim/

To set up the key I suggest using date type identifier in the format YYYYMM, using the current month e.g. 202105. In the guide replace YYYYMM with the identifier you have chosen.

Create your key:

amavisd genrsa  /etc/amavisd/dkim/YYYYMM.example.com.pem 4096
chown amavis:amavis /etc/amavisd/dkim/YYYYMM.example.com.pem

You can change the 4096 to 2048 for a shorter key. If you leave it off, the default is 1024 bits.

If you do not have an /etc/amavisd/override.conf, create one with the following in it:

## User modifications

##------------ Do not modify anything below this line -------------
#1;  # insure a defined return

Add the following to /etc/amavisd/override.conf somewhere before the last couple of lines:

$enable_dkim_verification = 1;
$enable_dkim_signing = 1;
dkim_key('example.com', 'YYYYMM', '/etc/amavisd/dkim/YYYYMM.example.com.pem');
@dkim_signature_options_bysender_maps = (
{ '.' => { ttl => 21*24*3600, c => 'relaxed/simple' } } );
@mynetworks = qw(127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16);  # list your internal networks

You can tweak mynetworks to suit your environment if you want but this should be a safe default of all the private address space.

Save your file and then do:

amavisd showkeys

You will get something like:

[root@server ~]# amavisd showkeys
; key#1 4096 bits, i=YYYYMM, d=example.com, /etc/amavisd/dkim/YYYYMM.example.com.pem
YYYYMM._domainkey.example.com.        3600 TXT (
  "v=DKIM1; p="
  "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3mnsD2b0dl7uSWbZIFxf"
  "58QCX7okP0uGzxBvVqEeK7kUWCl8fxzDWqOI4RSOd4GQW2C+0KWQPlJ6VknrI+7a"
  "pVwZDiOP8iw60E1T+N326aDbHieeR6DrnLUNMGponDqkeKsezdC9DS5hLY5zH0aG"
  "DbJLAfwd3RQ2ODMNDoaBePj3i9etRVFDT2DfugSMmcPr9pQ0thwXrkz0Ut8d0gs5"
  "NfFjd3dDATpQ8GAnkqBJmzTr+WdTitw9iVTfkXxH95a4sGmQR1KtIrK6dol6cdDZ"
  "60dl1lo7U75an9mnzSzJ/SsEHcxaYpoPlqLZBe2CnUbCE3Tr1o5nN55p63DQXw4c"
  "gsxAQY5ueJMAn1I3Dup1iA1Y874lQSdJlBXlofn/Efn1EJUN7bVGpvZxjVNvOIAD"
  "vJcDDfkINECpU+Qi2XuRsjwme2MlbgBSYP5vh3yLuH8Hluf7dHT93c/gQt3xDAba"
  "Fpz6dj+bO+io19QC8kgTLnBjAHOA0gb49tGC+0yQsQ1Zc/o2CCtyho/3FQJiOSPD"
  "mZsbZJRsumAcAlgD0jLhm31qcrsq47/ZCzYCs7tl2w15SaZ7+YqJZmoZ/mXoIlgh"
  "uASxDnKrlTbc4DHdWsAGDJdER83d8/UPeSWpGCgSdVUlvbEhaD3hw36aswVug3Oj"
  "2/ZbAZvQcbhGRth5AWPVApUCAwEAAQ==")

You then need to copy everything between the ( and ) and edit it to remove the quote marks, spaces at the beginning and end of each line and any line breaks, so you will end up with something like which is the value you need for your DNS entry:

v=DKIM1; p=
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA3mnsD2b0dl7uSWbZIFxf58QCX7okP0uGzxBvVqEeK7kUWCl8fxzDWqOI4RSOd4GQW2C+0KWQPlJ6VknrI+7apVwZDiOP8iw60E1T+N326aDbHieeR6DrnLUNMGponDqkeKsezdC9DS5hLY5zH0aGDbJLAfwd3RQ2ODMNDoaBePj3i9etRVFDT2DfugSMmcPr9pQ0thwXrkz0Ut8d0gs5NfFjd3dDATpQ8GAnkqBJmzTr+WdTitw9iVTfkXxH95a4sGmQR1KtIrK6dol6cdDZ60dl1lo7U75an9mnzSzJ/SsEHcxaYpoPlqLZBe2CnUbCE3Tr1o5nN55p63DQXw4cgsxAQY5ueJMAn1I3Dup1iA1Y874lQSdJlBXlofn/Efn1EJUN7bVGpvZxjVNvOIADvJcDDfkINECpU+Qi2XuRsjwme2MlbgBSYP5vh3yLuH8Hluf7dHT93c/gQt3xDAbaFpz6dj+bO+io19QC8kgTLnBjAHOA0gb49tGC+0yQsQ1Zc/o2CCtyho/3FQJiOSPDmZsbZJRsumAcAlgD0jLhm31qcrsq47/ZCzYCs7tl2w15SaZ7+YqJZmoZ/mXoIlghuASxDnKrlTbc4DHdWsAGDJdER83d8/UPeSWpGCgSdVUlvbEhaD3hw36aswVug3Oj2/ZbAZvQcbhGRth5AWPVApUCAwEAAQ==

You then need to add the key to your DNS record at your DNS provider as a TXT key. The name of the key will be “YYYYMM._domainkey” and the text value the big long string you have just created starting “v=DKIM1; p=”

Now wait a few minutes for the DNS to propagate your key and then you should be able to do:

amavisd testkeys

and you should get a response like:

[root@server ~]# amavisd testkeys
TESTING#1 example.com: YYYYMM._domainkey.example.com => pass

If you don't check what you've done so far.

If all has gone OK, restart amavis with:

systemctl restart amavisd

Now go to Testing Your key to check your key is working.

Signing with OpenDKIM

Install opendkim:

yum install opendkim

To set up the key I suggest using date type identifier in the format YYYYMM, using the current month e.g. 201801. In the guide replace YYYYMM with the identifier you have chosen.

Generate the key:

mkdir /etc/opendkim/keys/mydomain.com
cd /etc/opendkim/keys/mydomain.com
opendkim-genkey -r -h sha256 -b 2048 -d mydomain.com -s YYYYMM -v
chown -R opendkim:opendkim /etc/opendkim/keys/mydomain.com

Add to '/etc/opendkim/KeyTable':

YYYYMM mydomain.com:YYYYMM:/etc/opendkim/keys/mydomain.com/YYYYMM.private

Add to '/etc/opendkim/SigningTable':

*@mydomain.com	YYYYMM

Edit the file '/etc/opendkim.conf' and:

  • Change “Mode” to “sv”
  • Change “SoftwareHeader” to “no” but can leave as “yes”. no cuts down the header a bit.
  • Comment out “KeyFile”
  • Uncomment KeyTable
  • Uncomment SigningTable
  • Uncomment ExternalIgnoreList
  • Uncomment InternalHosts
  • Add:
    AutoRestart             Yes
    AutoRestartRate         10/1h
    RemoveOldSignatures	True

You should end up with a file like (comments and blank lines removed):

PidFile /var/run/opendkim/opendkim.pid
Mode    sv
Syslog  yes
SyslogSuccess   yes
LogWhy  yes
UserID  opendkim:opendkim
Socket  inet:8891@localhost
Umask   002
SendReports     yes
SoftwareHeader  no
Canonicalization        relaxed/relaxed
Selector        default
MinimumKeyBits  1024
KeyTable        /etc/opendkim/KeyTable
SigningTable    refile:/etc/opendkim/SigningTable
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts   refile:/etc/opendkim/TrustedHosts
OversignHeaders From
AutoRestart             Yes
AutoRestartRate         10/1h
RemoveOldSignatures     True

Now you need to update your DNS records. Open the file '/etc/opendkim/keys/mydomain.com/YYYYMM.txt'. In your DNS records, create a new TXT record with a subdomain as the first field in the file which you can just copy. In this case it is “YYYYMM._domainkey”. For TXT Data copy and paste everything between the first and last set of quotes, excluding the first and last quotes and removing the middle quotes and whitespace between them.

As an example for the TXT record (shortened as real one breaks the howto formatting):

YYYYMM._domainkey	IN	TXT	( "v=DKIM1; h=sha256; k=rsa; s=email; "
	  "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8"
	  "4CbTaxZtzVcoVrkrHUTo" )  ; ----- DKIM key YYYYMM for mydomain.com

becomes:

v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ84CbTaxZtzVcoVrkrHUTo

Now start OpenDKIM and set it to start automatically:

systemctl start opendkim.service
systemctl enable opendkim.service

Test your DNS record and signing:

dig -t any YYYYMM._domainkey.mydomain.com
opendkim-testkey -d mydomain.com -s YYYYMM -vvv

The first command should return your TXT record you have just created. The second should give a “key OK” message.

Set up SMTP Server (postfix) by adding to /etc/postfix/main.cf:

smtpd_milters           = inet:127.0.0.1:8891
non_smtpd_milters       = $smtpd_milters
milter_default_action   = accept
milter_protocol		= 6

You can put this anywhere in the file. The usual practice is to put it after the smtpd_recipient_restrictions entry.

Please make sure there is a new line at the end of the /etc/postfix/main.cf or you could be making problems for yourself later.

Then restart postfix:

systemctl restart postfix.service

Testing your Key

After this you can also send a test e-mail to check-auth@verifier.port25.com and you should get an automatic reply with a few test results including DKIM testing. Alternatively, use the service at DKIMValidator.

Periodic Maintenance

Periodically you should be generating and using new keys. Best practice says to do this monthly. Semi-yearly should be the minimum. This is why we have generated keys in the YYYYMM format. To change keys, you should:

  • Generate a new key
  • Add a new line to /etc/opendkim/KeyTable
  • Change the line in /etc/opendkim/SigningTable to the new YYYYMM
  • Create a new DNS TXT record with the data in the new YYYYMM.txt file. Do not remove the old record yet
  • Validate the new record with opendkim-testkey

If the new key validates correctly:

  • Restart OpenDKIM and Postfix
  • Validate your new key by sending a test e-mail to check-auth@verifier.port25.com and checking the reply.
  • A couple of weeks later you can then delete the old DNS TXT record from your DNS as all mail in transit will have been delivered.

Optional

Author Domain Signing Practices (ADSP)

You can add an ADSP policy to your domain saying that all emails from your domain should be DKIM-signed. It’s done with another TXT record for your mail domain _adsp._domainkey.domain in your domain with a value of dkim=all or dkim=discardable. You don’t need to set this up, but, if you do, it makes it harder for anyone to forge email from your domains because recipient mail servers will see the lack of a DKIM signature and reject the message.

Wikipedia ADSP reference
Wizard to create ADSP TXT record

Domain Message Authentication, Reporting & Conformance (DMARC)

DMARC is a way of publishing a policy which advises receiving mail servers how to treat e-mail failing DKIM and/or SPF validation. It uses another DNS record to do this but the implementation is not covered by this guide. It also gives the recipient an e-mail address to report e-mails failing the DMARC policy.

dmarc.org
Sonicwall explanation of DMARC
Wizard to create DMARC TXT record
SPF Wizard

The DMARC policy states that if a DMARC record exists then it takes priority over an ADSP policy and over the SPF policy

search?q=clearos%2C%20mail%2C%20email%2C%20postfix%2C%20smtp%2C%20opendkim%2C%20dmarc%2C%20adsp%2C%20howto%2C%20kb%2C%20maintainer_nhowitt&btnI=lucky

content/en_us/kb_howtos_using_dkim_to_sign_and_validate_mail.txt · Last modified: 2022/01/26 18:05 by 62.30.63.90