The ultimate guide to DMARC

The ultimate guide to DMARC
Photo by Liam Truong / Unsplash

DMARC stands for Domain-based Message Authentication, Reporting (and) Conformance. There are plenty of resources out there but no guide bundling everything you need to know, until now!

In a nutshell

DMARC is a set of standards making it standardized to detect and report abuse of mail systems across providers all over the world.

Since reputation is everything in the mailing world, this is a critical thing to ensure your mail reaches the inbox of the receivers.

Not useful on its own

While DMARC handles all the reporting and compliance stuff, it needs a bit of help from two other things. They are not the main focus of this article, but since they basically don't make sense without each other, I will add them here as well.

SPF (Sender Policy Framework)

Specifies which servers (IP addresses) are allowed to send on behalf of the domain. This means any server trying to send a mail from an IP apart from the ones you specified via DNS will be blocked by the receiving server.

You list all your mail servers, service providers (such AWS SES, Mailchimp, etc.). This is quite flexible and easy to use.

Such a record might look like this:

v=spf1 ip4:1.2.3.4 include:mail-ips.thirdparty.com -all   

So let's break this down, we have:

  • v=spf1
    This is the version of the record, currently the only valid value is spf1
  • ip4:1.2.3.4 ย 
    Here we allow the mail server 1.2.3.4 to send mails on our behalf
  • include:mail-ips.thirdparty.com
    Performs and DNS Lookup which can also add information to our SPF record, only use these from trusted sources (like AWS SES anyway)
  • -all
    Prevents every other sending party not listed beforehand

While this already utilizes a lot of the features, I recommend looking up more information about it on the internet (and there are some excellent generators/validators) out there as well.

DKIM (Domain Keys Identified Mail)

So with SPF we covered who can send mails on our behalf. Now it is also time to ensure the content we are sending is not messed with. The principle is simple, you sign the mails when sending them and add the information to the mails. From receiver side it checks if the mails are signed properly and from your servers. This is a simple asymmetric encryption principle.

The DNS record looks pretty simple for this one:

v=DKIM1; p=76E629F05F70...

It consists of two parts:

  • v=DKIM1
    Version for the DKIM record, currently the only valid value is DKIM1
  • p=โ€ฆ
    Contains the public key to use for validating signatures

This is fine, why do I need DMARC?

You implemented SPF, DKIM, and now you are happily sending mails. What could go wrong? โ€” As the world and some humans always tend to be evil and use things for their advantage, people will try to get around your security measures. Or occasionally, a misconfiguration leads to no mails being delivered to the inboxes of the recipients.

This is where DMARC comes in, it specifies how these cases should be handled and where providers can issue reports. To make them also processable by automation (script, analysis) etc. there is also a standardized format that providers should use to tell you what went wrong.

Defining a policy

Policies for DMARC are also published via DNS Records and look like this:

v=DMARC1;p=none;sp=quarantine;pct=100;rua=mailto:[email protected];

Let's also break this one down:

  • v=DMARC1
    The version of the DMARC policy, currently the only valid value is DMARC1
  • p=none
    The policy to apply to mails that fail SPF and / or DKIM
    Valid values are:
    - quarantine - send to Junk folder
    - reject - don't deliver to user
    - none - just report and send to user
    In this case it would just report and don't treat the mail otherwise differently, which is especially useful to start using it without making all mails fail to reach the inboxes
  • pct=100
    The amount in percent to which amount of the traffic to apply the policy to
  • rua=mailto:[email protected]
    Send all aggregate reports to [email protected]. The only valid receiver for reports are mail addresses, and you get a mail with mail deliverability results.

DMARC Reports

So, everything is in place, we have DKIM, SPF and defined a DMARC policy and set up the โ€œrua fieldโ€ to get reports, now it's time to get the best of these reports.

But first we need to understand the reports a bit more.

Types of reports

  • aggregate report - contains a summary of a specific time interval (depending on the provider)
  • failure report - contains a sample of the mail that was sent and some more information (not provided by many providers)

In most cases, the aggregate report is enough and allows you to track how the health of your mail infrastructure is and also get a feeling how many attacks there are. You can also get out of these results if your policy might be too weak and allows an unauthorized server to send mails on your behalf.

Aggregate Report

The aggregate report has plenty of fields, and it can be a bit confusing at first. Here is a list and a brief description of what to expect:

Field Description
report_metadata/org_name The human readable name of the organization that sent you the report
report_metadata/email Sender mail for report
report_metadata/extra_contact_info Homepage or mail to get in touch with the provider
report_metadata/report_id ID of the report unique for the organization that sent the report
report_metadata/date_range/begin Unix timestamp for the start of the first report result
report_metadata/date_range/end Unix timestamp for the end of the last report result
policy_published/domain The top level domain used for validating your policy
policy_published/adkim Raw DKIM DNS record used for DKIM validation
policy_published/aspf Raw SPF DNS record used for SPF validation
policy_published/p The p field from your DMARC policy
policy_published/pct The pct field from your DMARC policy
record[]/row/source_ip IP of the sending mail server
record[]/row/count The amount of mails sent via this server in the given interval
record[]/row/policy_evaluated/disposition The action that has been taken for your mail (none, rejected, quarantine) - This might differ from what you specified to do
record[]/row/policy_evaluated/dkim The result of the dkim check (pass/fail)
record[]/row/policy_evaluated/spf The result of the spf check (pass/fail)
record[]/row/identifiers/headers_from The domain advertised by the sending mail server
record[]/row/identifiers/envelope_from Mail address specified as sender by sending server
record[]/row/identifiers/envelope_to Mail address specified as receiver by sending server
record[]/row/auth_results/dkim/domain The domain that has been tested against the DKIM policy
record[]/row/auth_results/dkim/result Result of the SPF check (pass/fail)
record[]/row/auth_results/dkim/selector Name of the DNS selector wihtout the TLD as specified by the domain field
record[]/row/auth_results/spf/domain The domain that has been tested against the SPF policy
record[]/row/auth_results/spf/result Result of the SPF check (pass/fail)

While all of these should/may be set, never rely on any of these to be exact or even present.

Failure reports

A failure report is basically an email, that might look extremely different depending on the service provider. Most providers out there don't even send them to you.

Since depending on how well known (and used) your mail server is this can be numerous mails (and therefore also cost) think wisely about enabling them.

They are basically a copy of the mail originally sent that failed DKIM and/or SPF.

I haven't found a way yet to automate the analysis of these failure reports, but they are quite handy here and there to get more insights, e.g., on phishing attempts.

Receiving and processing

While there are many service providers out there that provide out of the box solutions, you always have to hand off to some other third party.

Regardless, it totally makes sense to know how to work with reports and how to process them.

These reports may be raw XML as attachment, tar.gz, zip or otherwise archived. But expect some mails to completely fall out of the scope. Some mails are simply sent manually by people trying to break things. But there are also providers simply not complying to the standards.

Implementation on premise (or on your own personal server)

In case you want/need to build this yourself. It is somewhat simple.

The mail address you use for receiving the mail records can be either a piece of code that reacts to incoming mails (e.g., AWS SES + Lambda). You can also create a simple application that connects to the inbox and reads the mails.

The other option is to let it run on a server etc. as a daemon.

There is also a python package / CLI for that!

What I can really recommend in both scenarios is parsedmarc - a python package by Sean Whalem, who did a fantastic job here. It also includes a lot of export options to make use of the data. And if your target is not in the list, you get a standardized output across the reports to route anywhere you like.

This also plays along pretty well with AWS Lambda to create custom CloudWatch Metrics.

Identifier Alignment

Although not in every case you have influence on it (e.g., when using a service provider to send your mails), is that the MAIL FROM, EHLO/HELO domain must also match the domains configured for SPF.

A misconfigured header there can also cause your mails to fail DMARC. So keep this in mind.

You can also find more information about it in RFC7489.

The End

Hopefully, you now have a better understanding of what DMARC takes, why it is useful and how to interpret the results. Furthermore, without needing a dedicated service provider.

Do you miss something or have feedback? You are welcome to leave a comment as always.

Special thanks to @freddieleeman for the feedback on the misunderstanding of failure reports, which I always thought were called forensic reports. Based on his suggestion, I also added the Identifier alignment section.