Skip to content

Verifying AWS DNS records with nslookup

Four `nslookup` recipes for verifying that the CNAME, MX, and TXT records you published for CloudFront, ACM, SES DKIM, and SES MAIL FROM actually resolve before AWS does.

Updated May 25, 2026

When AWS won’t validate a record, the question is always the same: is the record actually published? Don’t trust the DNS host’s UI — it shows you what was saved, not what’s resolving. Ask a public resolver instead.

Every recipe below points nslookup at Google’s public resolver (8.8.8.8) so the answer doesn’t come from your laptop’s stale cache or the DNS host’s own resolver, both of which may lie. Run these before you re-poke AWS — both SES DKIM and ACM initial validation give up after 72 hours of unsuccessful polls, after which you have to scrap the identity or cert request and start over. (ACM renewal is a separate clock: it polls through the ~60 days before NotAfter and only stops at the moment of expiry.)

Recipe 1 — Does the apex/subdomain CNAME to CloudFront?

When www.example.com is supposed to front a CloudFront distribution, the CNAME must resolve to the distribution’s *.cloudfront.net hostname:

> nslookup -q=CNAME www.example.com 8.8.8.8

Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
www.example.com    canonical name = xyz.cloudfront.net.

If the answer comes back empty or points at a CNAME you don’t recognize, the record either didn’t propagate or someone else’s record is shadowing it.

Recipe 2 — Does the ACM validation CNAME resolve?

For each ResourceRecord returned in DomainValidationOptions (see 0021 ACM certificate DNS validation · DevOps ), the underscored hash record must point at the matching *.acm-validations.aws. value:

> nslookup -q=CNAME _aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com 8.8.8.8

Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com    canonical name = _bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.xxxxxxxxxx.acm-validations.aws.

If the lookup returns *** can't find ...: Non-existent domain, the most common cause is that the DNS host appended the zone to a record name that already had it, producing _hash.example.com.example.com. Look for the doubled suffix.

Recipe 3 — Does the SES DKIM CNAME resolve?

For each of the three DKIM tokens (see 0019 DKIM verification with AWS SES Easy DKIM · DevOps ), confirm {token}._domainkey.{domain} chains to {token}.dkim.amazonses.com:

> nslookup -q=CNAME abcxyz._domainkey.www.example.com 8.8.8.8

Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
abcxyz._domainkey.www.example.com    canonical name = xyz.dkim.amazonses.com.

Run this for all three tokens — SES rotates between them, and a single missing CNAME causes intermittent signing failures that are nearly impossible to debug from logs alone.

Recipe 4 — Is the SES MAIL FROM setup complete?

A custom MAIL FROM domain (see 0020 Custom MAIL FROM domain in AWS SES · DevOps ) needs both an MX and a TXT record on the subdomain. Check them with two queries:

> nslookup -type=MX mailfrom.example.com 8.8.8.8

Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
mailfrom.example.com    mail exchanger = 10 feedback-smtp.us-east-1.amazonses.com

> nslookup -type=TXT mailfrom.example.com 8.8.8.8

Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
mailfrom.example.com    text = "v=spf1 include:amazonses.com ~all"

If nslookup -type=MX returns more than one mail exchanger for the MAIL FROM subdomain, the setup will fail at SES — a custom MAIL FROM domain must have exactly one MX.

The mental model: a query type per record type

nslookup defaults to A records, which gives you nothing useful here — every record above is a CNAME, MX, or TXT. Picking the wrong type is the most common reason “nslookup says it’s not there”:

What you’re verifyingnslookup flag
CNAME (CloudFront alias, ACM challenge, SES DKIM token)-q=CNAME
MX (SES MAIL FROM bounce route)-type=MX
TXT (SPF, DMARC)-type=TXT