Spammers often try to impersonate third-party domains by spoofing them. The more well-known and trusted the party they impersonate, the greater the chance that a recipient will read the spam.
In addition to the necessary measures such as SPF control, you can use DKIM. DKIM is used to check the validity of the sender of emails. When sending emails, a digital signature is sent with DKIM. This is checked by means of the key that is included in the DKIM record.
DKIM stands for DomainKeys Identified Mail.
In this tutorial we show you how to sign outgoing mail with DKIM on a VPS with Postfix. You can have incoming mail automatically scanned for DKIM with Spamassassin.
# dnf install opendkim opendkim-tools
# cd /etc # vi opendkim.conf Mode sv ReportAddress "Example.com Postmaster" <postmaster@example.com> Selector key #KeyFile /etc/opendkim/keys/default.private KeyTable refile:/etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts Socket inet:8891@localhost
Now we add our domains to the key-table. We have to enter for each one an line. Add to TrustedHosts the IPv6 GUA and the IPv4 address.
# cd opendkim # vi KeyTable mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private # vi SigningTable *@example.com mail._domainkey.example.com # vi TrustedHosts 197........ 2000:...... *.example.com
Now we create the key.
# cd keys # mkdir example.com # cd example.com # opendkim-genkey -s mail -d example.com # ll total 8 -rw-------. 1 root root 916 Sep 18 22:29 mail.private -rw-------. 1 root root 310 Sep 18 22:29 mail.txt # chown opendkim:opendkim /etc/opendkim/keys/ -R # usermod -a -G opendkim postfix
You include the public key in the DNS records of the domains that send mail via your mail server, see the next step.
For each domain you send mail with from your VPS, you need a TXT record that contains the public key. In the previous step, you created a separate .key file containing your public key. Print the contents of this file with the command:
# cat /etc/opendkim/keys/example.com/mail.txt Name: mail._domainkey.example.com. Text: "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpE+iGYcKBPpo8HHbcFfCIIV10....."
This must be accessable for the user that manage the public DNS settings.
When you send mail between users in the same domain dkim can not be tested. So you have to add at the end of the file for your named domain:
# cd /var/named/dynamic # vi example.com $TTL 300 mail._domainkey TXT "v=DKIM1; k=rsa; p==MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQK......." # systemctl restart named
Now we can test is the DNS returns a valid response:
opendkim-testkey -d robkalmeijer.nl -s mail -vvv opendkim-testkey: using default configfile /etc/opendkim.conf opendkim-testkey: checking key 'mail._domainkey.example.com' opendkim-testkey: key not secure opendkim-testkey: key OK
"opendkim-testkey: key not secure" means the key is not received via DNSSEC. The test used the local DNS server which didn't use DNSSEC.
For each domain you have to add the DKIM settings.
Next, create a TXT record in the DNS settings of each domain you send mail for on your VPS using the syntax below.
Save the settings. This can take some time to implement.
You can then test the DKIM key with the command:
# opendkim-testkey -d example.com -s mail -vvv
This will fail if you haven't set the txt record in the local DNS server.
We have to add the dkim settings in postfix. We have to add the milter section.
# cd /etc/postfix/ # vi /main.cf # Milter configuration for DKIM milter_default_action = accept milter_protocol = 6 smtpd_milters = inet:127.0.0.1:8891 non_smtpd_milters = $smtpd_milters # systemctl restart postfix
# systemctl start opendkim # systemctl enable opendkim
We need to send an email to another owned e-mail address that you can use to look at the source.
DKIM-Filter: OpenDKIM Filter v2.11.0 server5.robkalmeijer.nl 5775610200BC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=robkalmeijer.nl; s=mail; t=1726753947; bh=LTP0qq62X9I/BzkTSx/GaNUeWCR7QdQ7PxD0+k4AMDQ=; h=Subject:Date:From:From; b=GvD4PsMQzWN4beDQgSNvGFPJPua7y6gjQwA3YDfL6EmlDrPQ5wool0k/m409gHaNH DkZi4vmyYoPeS6gXG4j3krqcEXsLgprByATmmxw+6kqekt7KWEt8fT8M5oeMwiuGI3 frleXlroGv9UdG3L9aJPTZS4hnuX4jxuYcrZcIOE=