Email Security Basics: SPF, DKIM and DMARC

I'm currently locked in a battle with a senior member of our organisation who is annoyed that someone they contact regularly at another organisation gets quarantined by our email security. Do you want to know why?
They are not sending from an IP address specified in their SPF record.
To be clear - they've not been compromised; the emails are legitimate. But they have not configured their email security properly, so our email security software was correctly quarantining them.
They want me to whitelist the address and move on. I'm not doing it.
If the organisation is that careless with their email configuration, how do you think their cyber security posture is? Surely they're more likely to be compromised and start sending malicious emails to our users. So no, whitelisting is not the answer.
I have tried to contact them, politely, but have had nothing back. The issue remains. But, it did make me think about email security config and inspired this post, in which I will look at the three pillars of domain related email security, and then move on to options around email encryption.
Table of Contents
Sender Protected Framework (SPF) - RFC7208
An SPF record is a DNS TXT record that specifies two things. Firstly, it states which IP addresses are permitted to send emails from that domain, and secondly, it tells recipients what to do with emails that do not come from a permitted IP address.
This is not quite non-repudition. SPF only validates where the email came from, not who. If someone is sending from that IP fraudulently, SPF is still going to pass.
SPF records are built around mechanisms (who is allowed) and qualifiers (how strictly to enforce it).
These are the valid mechanisms:
a, mx, ip4, ip6, include, exists, ptr*
And these are the valid qualifiers:
+Pass, ~Softfail, -HardFail, ?Neutral
If a qualifier is not specified, the default is + (Pass). Here is an example SPF record:
v=spf1 ip4:192.0.2.1 include:_spf.google.com -all
| v=spf1 | All SPF records must begin with this, and there is only one version. |
| ip4: 192.0.2.1 | Specifies 192.0.2.1 as a permitted sender. The + mechanism is implicit. |
| include:_spf.google.com | This includes the SPF record of another domain, specifically _spf.google.com. This is useful if you are using a mila provider and want to send mail using their servers. The + mechanism is implicit. |
| -all | Tells recipients to reject mail that doesn’t come from a permitted sender. |
Let’s look at another example.
v=spf1 -ip4:192.0.2.1 include:domain.com -all
Imagine domain.com resolves to multiple addresses, one of which is 192.0.2.1. In this example, that particular IP would not be permitted, but any others from domain.com would be. Remember, SPF processes elements left to right.
There are limits on how SPF can be implemented.
- An SPF record cannot trigger more than 10 DNS lookups. Each include, a, mx, and exists mechanism counts toward this limit.
- A domain must have exactly one SPF record. Multiple records will cause a permanent error (PermError) and invalidate your authentication.
- Records are limited to 255 characters per string and a total length of 512 bytes.
Domain Keys Identified Mail (DKIM) - RFC6376
If SPF is about proving who sent a mail, DKIM is about proving it has not been interfered with. It provides integrity by ensuring a message has not been modified since it was sent using public key cryptography and hashing.
When the mail is sent, the sender system creates a hash of the message. This hash is then encrypted with the sender’s private key, and that is added to the email header.
When the recipient receives the email, they decrypt the message using the sender’s public key. They then create their own hash of the message, and compare that with the hash they just decrypted. If they match, then that proves that message has integrity.
The key pair is usually generated by the email provider, such as Microsoft or Google. They then provide the public key which must be posted as a DNS TXT record, to allow recipient domains to decrypt the hash.
Below is an example DKIM record:
v=DKIM1; k=rsa; p=[public key]
Remember, DKIM only provides integrity, not confidentiality. It doesn’t encrypt the actual message. More on that later.
Domain-based Message Authentication, Reporting and Conformance (DMARC) - RFC7489
DMARC is the policy mechanism that tells recipients what to do if an email fails authentication. An email passes DMARC if either SPF or DKIM (or both) are valid and match the domain in the "From" address.
Out of the three, DMARC has the lowest adoption rate of top global domains, with just under 50% having a DMARC record, and of those, 68% of them are set to do nothing. This is probably because if you get DMARC wrong, you can severely affect deliverability of your emails.
DMARC has three enforcement options:
p=none: Do nothing.
p=quarantine: Send emails that fail both SPF and DKIM to spam
p=reject: Reject emails that fail both SPF or DKIM
Below is an example DNS record:
v=DMARC1; p=quarantine; rua=mailto:[email protected]; pct=100
This tells recipients to quarantine mail that fails, email reports to [email protected], and apply this to 100% of outbound emails.
DMARC email reports are in XML format and are notoriously difficult to make sense of. I would recommend the excellent Report URI service, which has a free tier, albeit with a monthly volume limit.
What to do if you don’t want to send email?
Domains that don’t send email (like this one, currently…) need to have some defensive records in place to prevent anyone else sending email on their behalf.
v=spf1 -all - No authorised senders
v=DKIM1; p= - No valid public keys
v=DMARC1; p=reject; - Reject everything
Conclusion
The dispute over whitelisting is essentially about trust. When an organisation doesn't get the fundamentals of cyber security right they put everyone else at risk. Email is a shared eco-system; we all need to use it and we all benefit from it being secure.
SPF, DKIM and DMARC are not the be all and end all of email security, they are the basics. As administrators, we have a responsibility to make sure we're getting these things right.
