James's Ramblings

SPF, DKIM, and DMARC

Created: April 01, 2020

Rough notes on SPF, DKIM, and DMARC from various sources.

In brief

  • SPF specifies which IPs
  • DKIM uses asymmetric cryptography to ensure email contents remains the same.
  • DMARC fixes two problems with SPF and DKIM, plus adds reporting.

Validation tools

  • https://dmarcly.com/tools/

Terminology

  • Envelope from address is the address in the SMTP transaction. It is specified by mail from.
  • The header from address is the address specified in the From header field in the data command.

SPF

SPF provides mechanisms, qualifiers, and modifiers to allow domain administrators to specify IP addresses in a highly flexible way.

SPF Example

v=spf1 ip4:192.168.0.1 -all
  • v=spf1 defines the version of SPF. Currently, it’s always “spf1”. Everything that comes after is combinations of mechanisms, qualifiers, and/or modifiers which specify if a host is eligible to send emails.

  • The ip4 mechanism specifies an IPv4 address range allowed to send emails for the domain. In this case, a single IP address 192.168.0.1 is allowed.

  • The -all part at the end specifies that if none of the previous mechanisms matches, the SPF check fails. -all consists of the - qualifier and the all mechanism, which I will explain below.

SPF mechanisms

A mechanism is a way to specify a range of IP addresses. Eight mechanisms are defined:

  • IP4 : If the sender is in a given IPv4 address range, match;
  • IP6: If the sender is in a given IPv6 address range, match:
  • A: If the domain name has an address record (A or AAAA) that can be resolved to the sender’s address, it will match;
  • MX: If the domain name has an MX record resolving to the sender’s address, it will match (i.e. the mail comes from one of the domain’s incoming mail servers);
  • PTR: If the domain name (PTR record) for the client’s address is in the given domain and that domain name resolves to the client’s address (forward-confirmed reverse DNS), match. This mechanism is deprecated and should no longer be used;
  • EXISTS: If the given domain name resolves to any address, match (no matter the address it resolves to). This is rarely used. Along with the SPF macro language it offers more complex matches like DNSBL-queries;
  • INCLUDE: References the policy of another domain. If that domain’s policy passes, this mechanism passes. However, if the included policy fails, processing continues. To fully delegate to another domain’s policy, the redirect extension must be used;
  • ALL: Matches always; used for a default result like -all for all IPs not matched by prior mechanisms.

The SPF specification imposes that the number of mechanisms and modifiers that do DNS lookups must not exceed ten per SPF check, including any lookups caused by the use of the “include” mechanism or the “redirect” modifier. If this number is exceeded during a check, a PermError is returned. The include, a, mx, ptr, and exists mechanisms as well as the redirect modifier do count against this limit. The exp modifier does not count against this limit because the DNS lookup to fetch the explanation string occurs after the SPF record has been evaluated.

If your SPF record exceeds the 10-DNS-lookup limit, SPF authentication returns a permanent error indicating “too many DNS lookups”.

SPF qualifiers

A qualifier specifies the result of a mechanism evaluation. Each qualifier can be combined with any of the mechanisms described above.

  • + for PASS, i.e., the SPF check passes. This can be omitted; e.g., +mx is the same as mx;
  • ? for a NEUTRAL result interpreted like NONE (no policy);
  • ~ (tilde) for SOFTFAIL, a debugging aid between NEUTRAL and FAIL. Typically, messages that return a SOFTFAIL are accepted but tagged;
  • - for FAIL, i.e., the SPF check fails.

SPF modifiers

There are two widely deployed modifiers:

  • exp=some.example.com gives the name of a domain with a DNS TXT record (interpreted using SPF’s macro language) to get an explanation for FAIL results. Rarely used.
  • redirect=some.example.com can be used instead of the all mechanism to link to the policy record of another domain.

SPF modifiers allow for future extensions to the framework.

Note that redirect works in a different way than include:

  • include is a mechanism, and if it fails validation, the next mechanism in the same SPF record will be checked;
  • redirect is a modifier, and the result is the entirely based on the evaluation of the specified domain’s SPF record.

More SPF examples

v=spf1 a mx include:_spf.example.com -all

This record allows the following IP addresses to send emails on behalf of your domain business.com:

  • if business.com has an address record (A or AAAA) that can be resolved, the resolved value is allowed (the a mechanism);
  • if business.com has an MX record that can be resolved, the resolved value is allowed (the mx mechanism);
  • any IP address passing SPF authentication using another domain’s SPF record at _spf.example.com, is allowed (the include:_spf.example.com mechanism);

Note that if you use 3rd-party email delivery services, they usually ask you to add their SPF list to your SPF record using the include mechanism. For example, SendGrid will ask you to add include:sendgrid.net to your SPF record, so that email messages sent from SendGrid will pass SPF authentication.

v=spf1 -all

This record dictates that no IP address be authorised to send emails for the domain.

Publishing an SPF record

SPF is published in a TXT record. The value of the TXT record is the SPF rule.

SPF problems

  • SPF only checks the envelope from address, which is quite a caveat.
  • The envelope from address and header from address can still differ. This can be fixed with DMARC.
  • Another issue is that SPF breaks when an email message is forwarded. This can be fixed with DMARC.

SPF best practices

If you specify blocks of addresses using CIDR notation in your SPF records, only use ranges between /30 and /16 inclusive (example: 10.10.10.0/24) – the higher the number after the slash, meaning a smaller block of addresses, the better. Avoid anything in the range /1 to /15 because some receivers will discount such blocks or even ignore them completely. And never, ever use or include a record with “+all” in it. The only way to productively use “all” is in the “~all” or “-all” mechanisms.

DKIM

  • DomainKeys Identified Mail, is an email authentication method designed to detect forged header fields and content in emails.
  • DKIM enables the receiver to check if email headers and content have been altered in transit.
  • DKIM is based on asymmetric cryptography.

How DKIM works

  • DKIM authentication consists of 2 components: signing and verification.
  • A DKIM-enabled email server (signing server) signs an email message on its way out, using a private key which is part of a generated key pair.
  • When the message arrives, the receiving server (verification server) checks if a DKIM-Signature field exists in the header, and if so, uses the DKIM public key in the DNS to validate the signature.

DKIM selectors

  • A DKIM selector is a string used by the outgoing server to locate the private key to sign the email message, and by the receiving server to locate the public key in the DNS to verify the integrity of the email message.
  • The outgoing server and the receiving server must use the same DKIM selector in order to use the same private/public key pair.
  • Multiple private/public key pairs are required due to the following reasons:
    • DKIM key rotation
    • setting up DKIM with multiple email delivery services on a single domain; each service can have their own separate selectors so that signing/verifying with one service doesn’t interfere with that with another.

DKIM signing

Signing an email message on the originating email server means:

  1. choose which header fields and/or body to be included in the data;
  2. compute the hash sum of the data, including message headers and message body;
  3. encrypt the hash sum with the private key. The result is called the “signature”;
  4. append a DKIM-Signature header containing the signature to the email.

Tags in DKIM-signature

The DKIM-signature header field in an email message header consists of a list of tag=value parts. An example DKIM-signature header field looks like this:

DKIM-Signature: v=1; a=rsa-sha256; d=example.net; s=brisbane;
     c=relaxed/simple; q=dns/txt; t=1117574938; x=1118006938;
     h=from:to:subject:date:keywords:keywords;
     bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;
     b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZVoG4ZHRNiYzR

Here are the tags that can appear in a DKIM-signature header field:

  • v: version;
  • a: signing algorithm;
  • d: domain;
  • s: selector;
  • c: canonicalization algorithm(s) for header and body;
  • q: default query method;
  • t: signature timestamp;
  • x: expire time;
  • h: header fields - list of those that have been signed;
  • bh: body hash;
  • b: signature of headers and body.

Tags in DKIM DNS record

A DKIM record published in the DNS consists of a list of tag=value parts. An example DKIM DNS record looks like this:

v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnVgd0NyrRE261IIiPqi+0H1baNyKcdj8Kea/VlSP4exzvKx8pJ01EWMwd094FV/6OCBIf7KGKgowMnWl3tW3Z5G++uZHkdgF+6xg7b9PynmX/NTo2kx92hlGgegwyulF5B7d2FM0doaCeoO4rD05jZzwi3cXx/156Gg9Xwd/Z/QIDAQAB

Here are the tags that can appear in a DKIM DNS record:

  • v: version; must be “DKIM1”;
  • g: granularity;
  • h: a list of mechanisms that can be used to produce a digest of message data;
  • n: notes that might be of interest to a human;
  • s: a list of service types to which this selector may apply;
  • q: a list of query methods;
  • l: body length limits;
  • k: a list of mechanisms that can be used to decode a DKIM signature;
  • t: a list of flags to modify interpretation of the selector;
  • p: base64 encoded public key.

Creating a DKIM record

  • If a third-party email delivery service is being used, private/public key management is done by them.

  • Generated records are either TXT or CNAME:

    • a TXT record that looks like this:

      v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnVgd0NyrRE261IIiPqi+0H1baNyKcdj8Kea/VlSP4exzvKx8pJ01EWMwd094FV/6OCBIf7KGKgowMnWl3tW3Z5G++uZHkdgF+6xg7b9PynmX/NTo2kx92hlGgegwyulF5B7d2FM0doaCeoO4rD05jZzwi3cXx/156Gg9Xwd/Z/QIDAQAB
      
    • or a CNAME record that looks like this:

      s1.domainkey.u5021280.wl331.sendgrid.net
      

DKIM keys should be rotated regularly

Notes on DKIM

Unlike SPF which breaks down when an email message is forwarded, DKIM signatures survive email forwarding. This is because the DKIM signature is part of the message header, rather than the SMTP envelope, and only the latter is changed when the email message is forwarded.

DKIM has a caveat though: it doesn’t require the d= value in DKIM-signature to match the header from domain, which end users rely on to tell where the email is from. A spoofer can inject a valid DKIM-signature in an email with a d= value that points to a domain controlled by the spoofer, allowing DKIM to pass while still spoofing the from address visible to the user.

Fortunately, this can be fixed by DMARC identifier alignment. DMARC identifier alignment can ensure that the d= value in DKIM-signature is the same as the header from domain in order for it to pass DMARC authentication. We will discuss identifier alignment in detail in the DMARC section.

DKIM best practices

First, make sure your DKIM keys are at least 1,024 bits long. Signatures made using keys shorter than 1024 bits will often be ignored completely, and this practice will become more widespread as more senders switch to keys of 2,048 bits or longer.

However, let’s not go to the other extreme either. You should not use 4096 bit or longer keys, as these may not fit within a 512-byte DNS UDP response packet. Since some DNS implementations don’t allow packets larger than 512 bytes, using super long keys might cause DKIM to fail.

DKIM is built on cryptographic digital signatures, and the science of cryptology has developed it’s own best practices over time. One of these is to change cryptographic keys regularly, so that bad actors don’t have years and years to try to attack the key. Unfortunately, many email senders are using keys that were created five years ago, and sometimes longer! Instead, you should switch to a new DKIM key, or “rotate” your keys, at least once a year. If you send millions of messages each month, or if they are particularly sensitive messages, you should really consider rotating your keys more often than that.

DMARC

How DMARC works

First you publish a DMARC record for your email domain in the DNS; whenever an email that claims to have originated from your domain is received, the email service provider fetches the DMARC record and checks the email message accordingly; depending on the outcome, the email is either delivered, quarantined, or rejected. Email delivery reports are sent to the email addresses specified in the DMARC record periodically, by email service providers.

There are two major aspects to DMARC:

  • DMARC implements identifier alignment to eliminate the discrepancy between envelope from/header from addresses in SPF, and that between d= value and header from address in DKIM;
  • DMARC adds reporting capabilities to enable email domain owners to gain visibility into email deliverability, and ultimately implement full email protection against email spoofing/phishing.

DMARC uses the domain in the header from address to indicate where an email comes from; this means if an email passes DMARC authentication, it does come from the domain in the From address displayed to the end user, in the email client.

DMARC hardens email authentication as it does not only require SPF or DKIM to pass but it also requires at least one of the domains used by SPF or DKIM to “align with” the domain found in the from header address - the central identity. This is called identifier alignment, sometimes known as domain alignment.

SPF identifier alignment

  • The envelope from address and the header from address must match.

DKIM identifier alignment

  • In the case of DKIM, identifier alignment means that the domain value in the d= field of DKIM-signature in the email header has to align with the domain found in the header from address.

Alignment, strict or relaxed

  • Identifier alignment in DMARC means two domains match.
  • There are two modes in identifier alignment: strict and relaxed.
  • In strict mode, the two domains must be identical in order for them to be in alignment. For example: example.net aligns with example.net in strict mode, while example.net doesn’t align with mail.example.net.
  • In relaxed mode, the two domains don’t have to match exactly: as long as the organizational domains match, they align with each other.

DMARC alignment: authentication hardened!

When either of the following is true of an email message, we say the email is DMARC aligned:

  • it passes SPF authentication, and SPF has identifier alignment;
  • it passes DKIM authentication, and DKIM has identifier alignment.

DMARC policy

A DMARC policy tells the email receiver how to handle an email message if it doesn’t pass DMARC authentication. There are 3 options:

  • none, also called the monitoring mode, in which no action is taken;
  • quarantine; the email is moved to the spam folder (quarantined);
  • reject; the email is rejected outright - the recipient will never see it.

You can specify the DMARC policy in a DMARC record, where the policy appears in the p tag, like p=none.

DMARC record

A DMARC record is a TXT record published to the DNS for your domain, under _dmarc.yourdomain.com, where “yourdomain.com” is replaced with your actual domain (or subdomain). It tells the email receiver what to do when an email message fails DMARC authentication, and also where to send reports on email delivery statistics.

A DMARC record consists of a list of DMARC tags. The table below shows what each tag possibly found in a DMARC record means:

  • v: DMARC protocol version. The default is “DMARC1”;
  • p: Apply this policy to email that fails the DMARC check. This policy can be set to ‘none’, ‘quarantine’, or ‘reject’. ‘none’ is used to collect the DMARC report and gain insight into the current emailflows and their status;
  • rua: A list of URIs for email service providers to send aggregate reports to. NOTE: this is not a list of email addresses. DMARC requires a list of URIs of the form ‘mailto:test@example.com’;
  • ruf: A list of URIs for ISPs to send forensic reports to. NOTE: this is not a list of email addresses. DMARC requires a list of URIs of the form ‘mailto:test@example.org’;
  • sp: This policy should be applied to email from a subdomain of this domain that fail the DMARC check. Using this tag domain owners can publish a ‘wildcard’ policy for all subdomains;
  • fo: Forensic options. Allowed values: ‘0’ to generate reports if both DKIM and SPF fail, ‘1’ to generate reports if either DKIM or SPF fails to produce a DMARC pass result, ‘d’ to generate report if DKIM has failed or ‘s’ if SPF failed;
  • rf: The reporting format for forensic reports;
  • pct: The percentage tag instructs ISPs to only apply the DMARC policy to a percentage of failing email’s. ‘pct = 50’ will tell receivers to only apply the ‘p = ‘ policy 50% of the time against email’s that fail the DMARC check. NOTE: this will not work for the ‘none’ policy, but only for ‘quarantine’ or ‘reject’ policies;
  • adkim: Specifies the ‘Alignment Mode’ for DKIM signatures, this can be either ‘r’ (Relaxed) or ‘s’ (Strict). In Relaxed mode also authenticated DKIM signing domains (d=) that share a Organizational Domain with an emails From domain will pass the DMARC check. In Strict mode an exact match is required;
  • aspf: Specifies the ‘Alignment Mode’ for SPF, this can be either ‘r’ (Relaxed) or ‘s’ (Strict). In Relaxed mode also authenticated SPF domains that share a Organizational Domain with an emails From domain will pass the DMARC check. In Strict mode an exact match is required;
  • ri: The reporting interval for how often you’d like to receive aggregate XML reports. This is a preference and ISPs could (and most likely will) send the report on different intervals (normally this will be daily).

Here are a few DMARC record examples:

  • v=DMARC1; p=none; rua=mailto:5b06a123456f1@ag.dmarcly.com; set DMARC policy to monitoring mode (p=none), which allows you to monitor email delivery, without sending emails to spam or rejecting them; also, send aggregate reports to 5b06a123456f1@ag.dmarcly.com;
  • v=DMARC1; p=quarantine; rua=mailto:5b06a123456f1@ag.dmarcly.com; set DMARC policy to quarantine mode (p=quarantine), which allows you to monitor email delivery, and send emails that fail DMARC authentication to spam; also, send aggregate reports to 5b06a123456f1@ag.dmarcly.com;
  • v=DMARC1; p=reject; rua=mailto:5b06a123456f1@ag.dmarcly.com; set DMARC policy to reject mode (p=reject), which allows you to monitor email delivery, and reject emails that fail DMARC authentication; also, send aggregate reports to 5b06a123456f1@ag.dmarcly.com. This offers complete email protection against spoofing.

External destination verification

When you use a rua tag and publish a DMARC record like this:

v=DMARC1; p=none; rua=mailto:aggregate@reporting.com;

you are requesting compliant email service providers to send aggregate reports to the specified email address aggregate@reporting.com. However, the owner of aggregate@reporting.com must grant you the permission before you can do so. Otherwise, these reports won’t be sent to that particular email address. This is called external destination verification (EDV).

EDV is a TXT record.

External destination verification works like this:

  • the owner of reporting.com publishes an EDV record at:

    example.com._report._dmarc.reporting.com
    

    with the value v=DMARC1 to the DNS, in order to enable EDV;

  • before an email service provider sends an aggregate report to aggregate@reporting.com, it needs to check if reporting.com has allowed reports on example.com to be sent to it. It does this by looking example.com._report._dmarc.reporting.com up in DNS. If this record exists, and it’s value is v=DMARC1, the report will be sent; otherwise not.

Note that the above EDV record is per domain, i.e., it only allows reports on example.com to be sent to aggregate@reporting.com. If you want reports on anotherexample.com to be sent to aggregate@reporting.com, you will need to publish an EDV record for anotherexample.com.

If you want to allow reports on any domain to be sent to aggregate@reporting.com, publish a wildcard EDV record at:

*._report._dmarc.reporting.com

The value of the record should be “v=DMARC1”.

Publishing a DMARC record

  • A DMARC record is a TXT record.
  • The record has a name: _dmarc
  • The value is the DMARC rule.

DMARC reports

  • DMARC can send 2 types of reports upon request: aggregate reports and forensic reports.
  • DMARC aggregate reports provide information about percentages of email passing/failing SPF, DKIM and DMARC checks. Although they do not come with much information about individual email messages, aggregate reports can provide valuable visibility into the health of your email program, and help you identify potential authentication issues and/or malicious activity.
  • You can use the rua tag in the DMARC record to specify the recipient of aggregate ports.
  • In contrast, DMARC forensic reports are generated by email service providers almost immediately after an email message fails DMARC authentication. The forensic report contains message header fields, including source IP, authentication results, To and From email addresses, as well as the message body.
  • You can use the ruf tag in the DMARC record to specify the recipient of forensic ports.

DMARC best practices

DMARC best practices

Start using DMARC in p=none first. You’ll benefit from the reporting it provides, and it allows you to signal to email service providers that they should identify messages using your domain that don’t pass authentication.

Then gradually progress to p=quarantine and ultimately to p=reject. This means fraudulent messages using your domain can be identified and blocked, which will help protect your employees and customers while improving your domain’s reputation.

Setting up reverse DNS records (PTR records)

  • PTR records need to be in place otherwise email can be rejected.