Let’s do Postfix slowly and properly – Part 13: DMARC

The mailboxes are from Denmark. That’s the joke.

With DKIM in place, it’s time to tie a bow on it with DMARC in my Postfix series, aka the neverending quest to keep selfhosted email afloat.

DKIM added some extra credibility to the purported identity of the sender of the email. As briefly touched in the last post, adding DKIM will not by itself change the reception your email is likely to get. That part is taken care of by DMARC.

A DMARC policy is a TXT record residing with your domain registrar. Thus there is no actual, technical need to change anything about Postfix or other parts of your server setup in order to have a working DMARC policy for yourself (assuming you already have taken care of SPF and/or DKIM). As usual, however, there are two sides to this coin: The mirror image of having a DMARC policy is repecting that of others. I will save the second part for a future post. This post will discuss what is required for outgoing mail to be ‘DMARC compliant’.

To recap: SPF says whether the SMTP server relaying the message is allowed to send on behalf of the domain; DKIM says whether the contents of the message can be believed to come from the purported sender’s domain.

DMARC, on the other hand, says what I want recipients to do when something looks off about either SPF or DKIM. It is worth noting that in this way, it is a somewhat different tool to the former two. Imagine that I’m a sysadmin and that my one – or at least main – concern is for my organization’s email to get through. I implement SPF not so much to prevent others from pretending to be me, as in order to bolster my own SMTP server’s credibility and assuage any doubts that the recipient may have about accepting the message. Ditto DKIM: I am now also assuring the recipient that the contents of the email have not been tampered with. You can trust me! Let me in! Unlike the former, DMARC doesn’t directly add anything to my trustworthiness as a sender (though indirectly, it speaks to my trust in my own setup). On the contrary, with a strict enough policy it can result in rejected email which should not have been rejected.

Now, obviously most organisations also care about not getting impersonated, especially if they have a brand to protect. And as we shall see, there are ways to defang a DMARC policy completely, at least for now. Still, I think it’s worth being aware that a large part of the motivation for the individual sender for having a DMARC policy is external pressure: Google et al. are using it as a precondition of delivery (for bulk senders). As a counterpoint, MXtoolbox has an article about how DMARC improves delivery which boils down to the fact that you get reports about when delivery fails… because of DMARC 🤔

Widespread use of DMARC is no doubt of benefit to the ecosystem as a whole even if I may or may not directly benefit all that much. Thus encouraged, let’s get on with it.

Record

Implementing DMARC is simply adding a TXT record with your domain registrar. Details will vary depending on who that is. With my registrar, Namecheap, I go to the domain management page, click “Advanced DNS” and then “Add new record” and choose “TXT Record” as type. The host setting (subdomain) is set to _dmarc (corresponding to the FQDN _dmarc.brokkr.net). My value is set to

v=DMARC1; p=none; rua=mailto:xxx@brokkr.net; ruf=mailto:xxx@brokkr.net; sp=none; aspf=s; adkim=s; fo=1;

… and finally TTL is left as Automatic. The highlighted bits are the important ones that I will discuss; the rest are optional. To generate your own record I recommend using a DMARC record generator, just to be sure that it’s correctly formatted. v is for version and AFAIK as of 2024 there is only the one permitted value (DMARC1).

Policy and reports

Setting policy (p=) is the crucial bit of DMARC. It tells recipient servers what you’re asking them to do when checks fail. It can be any of three different settings: none, quarantine and reject. Reject should make the SMTP server bounce the mail, whereas quarantine leaves a little more to the interpretation. Most servers will deliver it but cause it to be put in a spam or undesired email folder. None results in delivery with no marks against the email but you will at least be notified. Basically, this is recommended as a beginner’s setting so that you will be able to spot false positives before they start getting rejected.

Regardless of policy setting, you should supply an email address for the aforementioned reports. This is done using the rua setting. Reports are aggregates (i.e. you don’t get one for each attempt) but they are obviously not aggregated across recipients, so you could get reports from a lot of different servers across the globe, both those you email yourself and those where scammers pretend to be you. Reports are attached as compressed XML formatted text files. They are human readable but downloading ten attachments a day to read an ‘aggregate’ report of that one email you sent is not going to be anybody’s cup of tea. In other words, I would strongly consider directing the reports at a free service that receives all the individual reports and digests it for you into a weekly report. E.g. postmarkapp.

Alignment

The overriding concern when we talk about alignment is whether a sender is exploiting ambiguity in the way that email works. Alignment means that something lines up and corresponds; a lack of alignment means that it does not. We have settings regarding requirements for two types of alignment, SPF alignment (aspf) and DKIM alignment (adkim). In the records we can demand either relaxed or strict alignment.

(Sidenote: The naming here is unfortunate because it invites confusion with the similar choice with regards to DKIM canonicalization (relaxed or simple). Just to be clear: Alignment and canonicalization have absolutely nothing to do with each other. You should also note that with regards to alignment, the opposite of relaxed is strict, not simple.)

Here’s the crux of the matter: When you open up an email, you see a From: email address. Technically, that is one of the “originator fields” defined in RFC5322. We really don’t want anybody to be able to spoof that From: address because the unwitting user will see it and trust it. But here’s the shocker: Neither the DKIM nor SPF checks actually concern themselves directly with this address. SPF checks whether the IP address of the connecting SMTP server is allowed to send on behalf of the domain name in… the other header containing the sender’s email address, Return-Path: Example from a recent (spam) email:

Return-Path: <amanda-9888@magicsonic.com.cn>

The Return-Path header is a last-minute addition to your email. It is added to the top of the email upon delivery to the SMTP server that is the MX host for the domain, specifically for the purpose of clearly signalling where rejections should be sent (e.g. in the case the recipient user doesn’t exist).

DKIM checks whether the signature matches the public certificate of the the domain name in… the DKIM d= variable. Again from Amanda’s email:

DKIM-Signature: a=rsa-sha256; b=J5ire/cip7Imv1MkalMNabJet5kVpKz9J3B2VbpCvNKOA0imfRC7I6bDuXF3M5q0bfkGEHULgSey+wXi95xTiKmsU2O8OVZRUobAfuHXh21cRuGiH92or8DDf3Vwf53T5QWNyZjhKsNtou1GjaRzu/J6Wefh+hcIHh81yTiNKfw=; c=relaxed/relaxed; s=default; d=magicsonic.com.cn;

So it would be possible to pass both DKIM and SPF checks but still present the user with fraudulous information, namely the From: field. Alignment checks exist to close this loophole.

The common denominator for both alignment checks is that they test if the domain that they have each verified (Return-Path domain for SPF, d= domain for DKIM) match up with the domain from the RFC5322 From field…

From: Amanda Liu <amanda-9888@magicsonic.com.cn>

If the domain in From matches the Return-Path domain, we have SPF alignment. If it matches up with the one from the d= variable, we have DKIM alignment. The example I have used checks both boxes.

Note that I write ‘matches up with’ rather than ‘matches’. If the alignment is only required to be relaxed (aspf=r or adkim=r) a subdomain can still get a pass. I believe this is beyond most selfhosting needs so I won’t go into details. I will just note that I think it is not very clear which of the domains is allowed to be a subdomain of the other, nor is it apparant if the answer is the same for the two types of alignment. Short version: I would stick to strict (aspf=s or adkim=s) unless subdomains were absolutely indispensable.

What do I actually need (or what can I get away with)?

The record value I cited at the beginning is the one I use currently and would recommend (though the policy of none should obviously be upgraded to quarantine or reject once I’m assured that I’m not getting false positives). My settings are about as ‘DMARC compliant’ as can be. But what if some parts – the DKIM and SPF checks, the alignment requirements – are too onerous? Do I have to do it all?

Well, it depends. Also that it’s often not very well stated and kind of confusing. Basically, in order for DMARC to pass you have to pass either SPF or DKIM authentication and the related alignment check. In other words, either of the following dots have to pass completely in order for a DMARC pass…

  • SPF: IP address of originating SMTP server matches SPF record for Return-Path domain AND email Return-Path domain matches with email’s From: field domain.
  • DKIM: Email’s DKIM signature matches public cert for d= domain (found at indicated s= selector) AND d= domain matches matches with email’s From: field domain.

The way I have seen it stated is that a non-existent check and a failed check are equivalent. So a failed SPF check – i.e. sending from unauthorized servers – is neither better nor worse than if I had had no SPF record at all. As long as the same email passed the DKIM check plus DKIM alignment, the email should still be considered as passing DMARC – despite the SPF violations. This is apparently a feature and not a bug. It also deserves mention that it’s recommended to end SPF records with ~all rather than -all, in other words making non-listed IP addresses softfail, not hardfail. The reason for this is precisely that DMARC can pass despite SPF failures but some setups may simply terminate the SMTP connection if SPF hardfails.

I tested this second-attempt policy with a deliberately bad DKIM signature – one that did not match the public certificate – and got the following confirmation from learndmarc.com:

Note also that DKIM alignment is not tested after the auth check has failed. This makes sense on multiple levels, but not least that the DKIM check – according to the rules listed above – has failed logically and cannot be salvaged by correct alignment (“AND”).

So, the answer is that yes, you can ignore DKIM completely, only do an SPF record, and as long as your SPF record chekcs out and you use the same email address in both header fields, you will be fine. I do suspect, though, that that would be living on borrowed time.

Two red post boxes mounted in brown concrete wall © Kristina Tripkovic, Unsplash license

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.