Fundamentals

T1566

SPF and DKIM

How email authentication works — SPF, DKIM, and DMARC — why they matter for stopping spoofed mail, how to verify them from the command line, and what happens when they are missing or misconfigured.

View on Graph

What They Are and Why They Matter

SPF and DKIM are how email servers verify a message actually came from who it claims to. Without them, anyone can send mail that looks like it came from your domain. With them, receiving servers can authenticate the sender.

Most phishing campaigns exploit missing or weak SPF and DKIM — it is the difference between a spoofed domain landing in an inbox vs. getting rejected outright.

The Three Layers

LayerWhat It DoesWhere It Lives
SPFLists which mail servers are authorized to send email for your domain.DNS TXT record.
DKIMAttaches a cryptographic signature to each email. Receiving servers verify the signature against a public key in your DNS.DNS TXT record (public key) + email header (signature).
DMARCTells receiving servers what to do when SPF or DKIM fails — allow, quarantine, or reject. Provides reporting so you can see who is sending mail as your domain.DNS TXT record.

SPF — Sender Policy Framework

SPF is a DNS TXT record that lists which servers can send mail for your domain.

Anatomy of an SPF Record

v=spf1 include:_spf.google.com ~all
ComponentMeaning
v=spf1Identifies this as an SPF record (version 1).
include:_spf.google.comDelegates to Google’s mail server list. The receiving server looks up _spf.google.com and checks its SPF record.
ip4:203.0.113.0/24(Optional) Directly authorize a specific IP range to send mail.
include:spf.protection.outlook.com(Optional) Microsoft 365 mail servers.
~allSoft-fail — mark messages from unauthorized servers as suspicious but deliver them.
-allHard-fail — reject messages from unauthorized servers.
?allNeutral — no policy statement.

SPF Mechanisms (in order of evaluation)

MechanismExampleBehavior
all-allMatches any IP. Always the last mechanism.
ip4ip4:192.0.2.0/24Matches an IPv4 address or range.
ip6ip6:2001:db8::/32Matches an IPv6 address or range.
aa:mail.example.comMatches the A/AAAA record of the domain.
mxmxMatches the MX servers of the domain.
includeinclude:_spf.google.comDelegates to another domain’s SPF policy.
existsexists:%{i}._spf.example.comAdvanced — checks a dynamic domain.

Common SPF Mistakes

MistakeImpact
Forgetting to add a new mail-sending serviceAll mail from the new service fails SPF and goes to spam or is rejected.
Exceeding the 10 DNS lookup limitSPF has a maximum of 10 DNS lookups (each include, a, mx, exists counts). Exceeding it causes the entire SPF check to fail (permerror).
Using +all (pass all)Defeats the purpose entirely. Any server can send mail for your domain.
Not using -allWithout a hard fail policy, receiving servers may not reject spoofed mail.
Missing SPF record entirelyAny server can send mail that appears to come from your domain. Receiving servers have no way to authenticate it.

DKIM — DomainKeys Identified Mail

DKIM uses public-key cryptography to sign each outgoing email. The sender’s mail server generates a signature header using a private key. The receiving server looks up the corresponding public key in DNS (via a DKIM TXT record) and verifies the signature.

How DKIM Works

Sender (private key)  ── signs ──>  Email with DKIM-Signature header


Receiver (public key)  <── verifies <── DNS lookup of selector._domainkey.example.com

DKIM Header Example

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=example.com; s=google;
 h=mime-version:from:date:message-id:subject:to;
 bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
 b=GwBkL5hKx7yQz3Xp...
FieldMeaning
v=1DKIM version
a=rsa-sha256Signing algorithm
c=relaxed/relaxedCanonicalization (relaxed allows minor whitespace changes)
d=example.comThe signing domain
s=googleThe selector — tells the receiver which DNS record to query
h=Header fields included in the signature
bh=Body hash (base64)
b=The actual cryptographic signature

DKIM DNS Record Example

The receiving server queries: google._domainkey.example.com

google._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD..."
FieldMeaning
v=DKIM1DKIM version
k=rsaKey type (RSA, or ed25519 for newer deployments)
p=Public key (base64-encoded) — this is the key the receiver uses to verify the signature

DMARC — Domain-based Message Authentication, Reporting & Conformance

DMARC tells receiving servers what to do when SPF and/or DKIM fail. It also provides daily reports about who is sending email claiming to be from your domain.

DMARC Record Example

_dmarc.example.com.  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100"
FieldMeaning
v=DMARC1DMARC version
p=noneMonitor only — receive reports but take no action. Start here.
p=quarantineMark failing mail as spam.
p=rejectReject failing mail entirely. The goal state for most orgs.
pct=100Percentage of mail to apply the policy to (100 = all).
rua=mailto:dmarc@example.comAggregated report destination email.
ruf=mailto:dmarc-forensics@example.comForensic (per-message) report destination.
sp=rejectSubdomain policy — applies the policy to subdomains too.
adkim=rDKIM alignment — r (relaxed) allows the DKIM domain to be a subdomain of the From domain.

DMARC Progression Strategy

  1. Monitor — Set p=none. Review reports for 30 days to see what mail is failing authentication.
  2. Quarantine — Move to p=quarantine. Identify legitimate senders that are failing and fix their SPF/DKIM configuration.
  3. Reject — Set p=reject. Only after confirming all legitimate mail passes authentication.

Verification — Command-Line Tools

Verify SPF with nslookup

# Check SPF record for a domain
nslookup -type=TXT example.com

# Expected output (in a working SPF setup):
# example.com  text = "v=spf1 include:_spf.google.com ~all"

# Directly query for SPF (type 99)
nslookup -type=SPF example.com

Alternative with dig (more readable):

dig TXT example.com +short
# "v=spf1 include:_spf.google.com ~all"

Verify DKIM with nslookup

# DKIM records use the format: <selector>._domainkey.<domain>
nslookup -type=TXT google._domainkey.example.com

# Expected output:
# google._domainkey.example.com  text = "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDD..."

Verify DMARC with nslookup

nslookup -type=TXT _dmarc.example.com

# Expected output:
# _dmarc.example.com  text = "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100"

Online Verification Tools

ToolWhat It Does
MXToolbox SPFValidates SPF record syntax and checks for common issues (10 lookup limit, include loops).
DKIM ValidatorSends a test email and shows if DKIM, SPF, DMARC pass.
DMARC AnalyzerMonitors DMARC reports and helps with the p=none → p=reject transition.
DMARC CheckerQuick DMARC record validation.

Walkthrough — Verifying a Domain’s Email Security

Let’s walk through verifying wyzsec.com:

Step 1 — Check SPF:

$ dig TXT wyzsec.com +short
"v=spf1 include:_spf.google.com include:spf.protection.outlook.com -all"

✅ SPF authorizes Google Workspace and Microsoft 365 mail servers. The -all means mail from any other server is rejected.

Step 2 — Check DKIM:

$ dig TXT google._domainkey.wyzsec.com +short
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8..."

✅ DKIM public key published. Selector google matches Google Workspace.

Step 3 — Check DMARC:

$ dig TXT _dmarc.wyzsec.com +short
"v=DMARC1; p=reject; rua=mailto:dmarc@wyzsec.com; pct=100"

✅ DMARC set to reject. Reports are sent to dmarc@wyzsec.com.

Step 4 — Send a test email and check headers:

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of user@wyzsec.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=user@wyzsec.com;
       dkim=pass header.i=@wyzsec.com;
       dmarc=pass (p=REJECT, sp=REJECT)

✅ All three pass.

Detection — Identifying Email Spoofing in Logs

Microsoft 365 Message Trace — Look for:

  • SPF: Fail or DKIM: Fail
  • Authentication-Results header shows spf=softfail or dkim=fail
  • DMARC disposition: delivered but DMARC p=quarantine or p=reject in the dmarc=fail row

Exchange OnlineGet-MessageTrace to see:

  • SPFStatus: Fail
  • DKIMStatus: Fail
  • DMARCStatus: Fail

Suspicious patterns:

  • Email from your CEO but SPF/DKIM both fail
  • Lookalike domains (wyzsec-support.com, wyzsec-verify.com) sending mail that passes their own SPF/DKIM — this is a lookalike domain phishing attack, which SPF/DKIM for your domain does NOT protect against (that requires DMARC reporting and domain monitoring)
  • Sudden increase in DMARC aggregate reports showing many unauthorized senders

Sources