Domain-based Message Authentication, Reporting and Conformance (DMARC) is an enhancement to existing mail systems that relies on Sender Policy Framework (SPF) and Domain Keys Identified Mail (DKIM) and performs additional checks by combining the two.
SPF and DKIM must be implemented for DMARC to work correctly and the following pages offer the guidelines necessary for implementing them:
DMARC requires an additional DNS TXT record to be added next to the SPF and DKIM ones. Just like the former, the TXT record for DMARC has a specific format with various options.
Given a mail server with a domain:
mydomain.tld
the TXT
record would be created:
_dmarc.mydomain.tld
with the following configuration:
v=DMARC1; p=reject; rua=mailto:dmarc@mydomain.tld; ruf=mailto:dmarc@mydomain.tld; fo=1; adkim=s; aspf=s; rf=afrf; pct=100; rl=86400; sp=reject"
where:
v=DMARC1
is the DMARC version (currently v1 makes sense),p=reject
indicates the policy and suggests to the destination mail server to reject any mails that do not pass the DMARC check. Possible options are none
and quarantine
(treat mails that fail the DMARC check as suspicious).rua=mailto:dmarc@mydomain.tld
specifies an address to which DMARC aggregate reports should be sent to.ruf=mailto:dmarc@mydomain.tld
specifies an address to which forensic reports should be sent. These reports contained detailed information about failed DMARC verifications.fo=1
indicates that failure reports should be generated if either SPF or DKIM verification failed. Other possible values are:0
- generate a report if both SPF and DKIM tests faileds
- generate a report if the SPF verification failedd
- generate a report if the DKIM test failedadkim=s
tells DMARC to be strict about interpreting DKIM results. The other possible value passed to adkim
can be r
for relaxed verification.aspf=s
similar to the antecedent check for DKIM, but for SPF.rf=afrf
the report format currently set to "Authentication Failure Reporting Format"; other possible value is "Accident Object Description Exchange Format"pct=100
the percentage of mail from the mydomain.tld
that should be checked by other mail servers (the default, if omitted is 100%, all mail is going to be checked).rl=86400
the time interval in seconds for report generation (the default, if omitted is 86400, one day).sp=reject
similar to p=reject
, sp
is the policy for subdomains of mydomain.tld
.
On Debian, opendmarc
is an implementation of DMARC and can be installed with:
aptitude install opendmarc
and then configured by editing /etc/opendmarc.conf
.
The defaults are safe, but a good addition would be an IgnoreHosts
configuration parameter:
## Ignore hostnames and networks IgnoreHosts /etc/opendmarc-ignore.hosts
that allows all hosts, subnets and IP addresses listed in the file /etc/opendmarc-ignore.hosts
to be exempt from any DMARC checks - this can be useful in settings where mydomain.tld
would be a relay for a different mail server.
The contents of /etc/opendmarc-ignore.hosts
could possibly be:
localhost 192.168.0.0/24
in order to exclude localhost
and the 192.168.0
local network (this could be set to the trusted internal network).
Finally, /etc/default/opendmarc
and enable a socket configuration key, for instance:
SOCKET=inet:12345@localhost
where:
12345
is the port to listen on,localhost
is the address to listen on.
It is a good idea to specify localhost
in the socket configuration in case the mail server and OpenDMARC reside on the same server in order to prevent unauthorized connections.
In order to prevent opendmarc to verify authenticated clients, add to /etc/opendmarc.conf
:
## Skip authenticated clients. IgnoreAuthenticatedClients true
such that any authenticated user does not have to pass DMARC verfications.
With OpenDMARC configured, the last step is to tell Postfix to use OpenDMARC as a milter. In order to accomplish that, edit /etc/postfix/main.cf
and locate the smtpd_milters
and non_smtpd_milters
that were used whilst setting up DKIM.
There should be a configuration along the lines of:
smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891
to which the DMARC milter should be appended, like so:
smtpd_milters = inet:localhost:8891,inet:localhost:12345 non_smtpd_milters = inet:localhost:8891,inet:localhost:12345
where the milters will be called in-order: first DKIM and then DMARC.
Finally, reload or restart Postfix, for instance by issuing:
/etc/init.d/postfix reload
The OpenDMARC package is broken on Debian and does not read /etc/default/opendmarc
. As a workaround, edit /lib/systemd/system/opendmarc.service
and replace by the following:
[Unit] Description=OpenDMARC Milter Documentation=man:opendmarc(8) man:opendmarc.conf(5) After=network.target nss-lookup.target [Service] Type=forking PIDFile=/var/run/opendmarc/opendmarc.pid User=opendmarc PermissionsStartOnly=true ExecStartPre=/usr/bin/install -d -o opendmarc -g opendmarc -m 0750 /var/run/opendmarc ExecStart=/usr/sbin/opendmarc -p inet:12345@127.0.0.1 -u opendmarc -P /var/run/opendmarc/opendmarc.pid Restart=on-failure ExecReload=/bin/kill -USR1 $MAINPID [Install] WantedBy=multi-user.target
the added directives are:
PermissionsStartOnly
- makes ExecStartPre
run as root.ExecStartPre
- in order to make sure that /var/run/opendmarc
directory is created,-p inet:12345@127.0.0.1
is the socket to listen on corresponding to /etc/default/opendmarc
since the latter is not being read properly under Debian.When mail is forwarded by upstream servers, it is possible for the sever that forwards the mail to also modify its content. If the headers are modified, then upstream servers or the destination server may perform DMARC verifications that may fail.
[ server ] --> [ server ] -- forward --> [ server ] ^ + ^ | | DMARC? | DMARC? +--------------+-------------------------+
There is no definite solution to this problem - except to either send the mail to the destination server directly or to relax the DMARC policy by setting sp=quarantine
(or sp=none
) instead of sp=reject
.
The easiest way is to write an E-mail from the mail server being set up to an external mailbox and then check the raw message to see all the headers. Amongst the other headers, there should be a dmarc=pass
in the Authentication-Results
header:
smtp.mailfrom=me@mydomain.tld; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=mydomain.tld