simon-dreher.de

Beginning february Google and Yahoo start to require DMARC. They ramp this up slowly: first only temporary errors, then gradually increasing rejection rate (see Google documentation). Some requirements also only affect large senders with more than 5000 messages per day. Still DMARC is actually a good idea and it doesn't hurt to implement it.

What is DMARC?

First some background on DMARC: actually DMARC builds upon two other security mechanisms that you may already know:

DMARC is then a policy that defines what should happen if a message fails one of the two security mechanisms above. It has the nice feture that failing messages can be reported to a mail address of your choice.

There are also ARC headers that keep the authenticity chain for forwarded messages. Did not yet look too much into it, but maybe there's a follow-up blog post coming about this.

DKIM for Postfix

Signing messages is handled by OpenDKIM. For my configuration I followed the docs in Arch wiki and Debian.

After installing the package with yay -S opendkim, I configured the config files:

# /etc/opendkim/opendkim.conf
# Secure base cofiguration from https://wiki.archlinux.org/title/OpenDKIM#Security
Selector                default
Socket                  local:/var/spool/postfix/opendkim/opendkim.sock
Syslog                  Yes
TemporaryDirectory      /run/opendkim
UMask                   002
UserID                  opendkim

# To tolerate tools that fiddle with headers
Canonicalization    relaxed/simple

# main domain
Domain                  ff02.de
# Config based on https://wiki.archlinux.org/title/OpenDKIM#Multiple_domains
KeyTable                file:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
# /etc/opendkim/KeyTable
default._domainkey.ff02.de ff02.de:default:/etc/opendkim/keys/ff02.de/default.private

Contrary to what the Arch wiki says, you dont need multiple line if you use the same key.

# /etc/opendkim/SigningTable
*@ff02.de default._domainkey.ff02.de
*@simon-dreher.de default._domainkey.ff02.de
# /etc/opendkim/TrustedHosts
127.0.0.1
::1
localhost
37.187.17.172
babaco.ff02.de
opendkim-genkey --restrict --selector default --domain ff02.de --directory /etc/opendkim/keys/ff02.de --bits=2048 --verbose
chown -R opendkim:mail /etc/opendkim
cat /etc/opendkim/keys/ff02.de/default.txt

Then set in default._domainkey TXT in every domain to the output from default.txt (remove the brackets and quotes).

You can test that the DKIM config is correct with sudo -u opendkim opendkim-testkey -vv. Optionally you can also specify a domain with -d simon-dreher.de.

As I run Postfix with a chroot, the socket file needs to be under /var/spool/postfix and therefore needed to create and fix the owner of the file: chown -R opendkim:postfix /run/opendkim/opendkim.sock

In my case I also needed to change the group, as Postfix didn't have he permissions to access the socket file:

# /etc/systemd/system/opendkim.service.d/override.conf
[Service]
# Use the group "postfix", so the socket uses that group and postfix can access it
Group=
Group=postfix

And then we can finally start OpenDKIM:

systemctl daemon-reload
systemctl start opendkim

To make Postfix communicate with OpenDKIM, we add config like this to main.cf:

non_smtpd_milters = unix:/run/opendkim/opendkim.sock
smtpd_milters = unix:/run/opendkim/opendkim.sock
# Also run bounce through milters, so bounces are signed by DKIM
internal_mail_filter_classes = bounce

and systemctl restart postfix.

DMARC

I used the DMARC wizard to generate my DMARC record. You could also do it manually if you want.

For the start I was conservative and used the most permissive policy (none = don't block anything): v=DMARC1; p=none; rua=mailto:postmaster@simon-dreher.de; Then set this record into _dmarc.simon-drher.de TXT.

With multiple domains, you can use a reporting adress of the same domain (easier) or point all of them to the same address (then need whitelisting on the receiving domain).

Test

Finally we also want to validate that DKIM and DMARC now work. The https://www.mail-tester.com that was linked in the Debian docs is really easy to use: generate a mail address, send a test mail to it and see the score. the downside is, that you can only test 3 mails per day for free. Pro tip: Write a bit more that "Test" into your mail, otherwise you get warnings because pyzor thinks that it looks like spam.

It will probably tell you that the List-Unsubscribe header is missing, but this is not relevant if you don't operate a mailing list.

You could also configure to validate DMARC on incoming mail with OpenDMARC, but for now saved this for another weekend project.