4

Email DNS Records Cheatsheet

 3 weeks ago
source link: https://www.netmeister.org/blog/email-dns-records.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

April 12th, 2024

Every so often, I need to chase down some aspect of email validation. This involves a number of DNS records and queries, but I may forget just which ones. So here's a quick cheatsheet for future me to pull up the next time I don't remember which records are used to validate SPF, DMKIM, DMARC, etc.

Cheatsheet

Record / Type Example

MX dig +short MX example.com
SPF dig +short TXT example.com | grep spf
DKIM dig +short TXT selector._domainkey.example.com
DMARC dig +short TXT _dmarc.example.com
MTA-STS dig +short TXT _mta-sts.example.com
curl https://mta-sts.example.com/.well-known/mta-sts.txt
TLS-RPT dig +short TXT _smtp._tls.example.com
DANE dig +short TLSA _port._tcp.example.com
BIMI dig +short TXT default._bimi.example.com

If you're interested in a more in-depth description of all the mechanisms involved, I have series of videos from my SysAdmin class available here. Brief summary below:

MX records

A host- or domain name's MX record defines the set of mail servers responsible for the given name. A single domain may have multiple MX records which may or may not be in the same domain (which itself may or may not be within the original domain):

$ dig +short mx netmeister.org           # <--+ 1 MX
50 panix.netmeister.org.                 # <--+ within the same domain

$ dig +short mx akamai.com               # <--+ 4 MX
20 mx0b-00190b01.pphosted.com.           #    |
10 mxa-00190b01.gslb.pphosted.com.       #    | all in a different domain
10 mxb-00190b01.gslb.pphosted.com.       #    |
20 mx0a-00190b01.pphosted.com.           # <--+

$ dig +short mx twitter.com              # <--+ 5 MX
30 ASPMX3.GOOGLEMAIL.com.                #    + in two different domains
20 alt1.aspmx.l.google.com.              #    | (owned by the same org)
10 aspmx.l.google.com.                   #    |
30 ASPMX2.GOOGLEMAIL.com.                #    +
20 alt2.aspmx.l.google.com.              # <--+

$ dig +short mx whynot.coffee            # <--+ 4 MX
10 mailin.mx-hub.cz.                     #    | in four different domains
10 mailin.mx-hub.eu.                     #    | in four different TLDs
10 mailin.mx-hub.sk.                     #    |
10 mailin.mx-hub.net.                    # <--+
$ 

For results with the same preference, mail servers MUST (per RFC2821) pick one at random; otherwise, the lower preference are preferred.

MX records MUST NOT point to a CNAME, but CNAMEs of the original name are followed:

$ grep mx test.netmeister.org
mx              IN      CNAME   netmeister.org.
mxcname         IN      MX      1 mx
$ sudo rndc reload
[...]
zone test.netmeister.org/IN (unsigned): mxcname.test.netmeister.org/MX
        'mx.test.netmeister.org' is a CNAME (illegal)
$ dig +noall +answer mx mx.test.netmeister.org
mx.test.netmeister.org. 300     IN      CNAME        netmeister.org.
netmeister.org.         10761   IN      MX      50   panix.netmeister.org.

Subdomains may have their own distinct MX records. If a domain name does not have an MX record, but it has A or AAAA records, then one of those addresses is used ("implicit MX"). However, if no records are found, there is no subdomain climbing:

$ dig +short mx implicit-mx.test.netmeister.org
$ dig +short AAAA implicit-mx.test.netmeister.org
2001:470:30:84:e276:63ff:fe72:3900
$ dig +short mx no-mx.test.netmeister.org        
$ dig +short AAAA no-mx.test.netmeister.org
$ dig +short A no-mx.test.netmeister.org   
$ dig +short mx test.netmeister.org
1 panix.netmeister.org.
$ 

In the above example, mail to [email protected] will be delivered, but mail to [email protected] will bounce as undeliverable:

   ----- The following addresses had permanent fatal errors -----
<[email protected]>

   ----- Transcript of session follows -----
550 5.1.2 <[email protected]>... Host unknown
(Name server: no-mx.test.netmeister.org.: no data known)

SPF records

A domain's SPF policy is found in its TXT record:

$ dig +short txt netmeister.org | grep spf
"v=spf1 a -all"
$ 

There are all sorts of surprises lurking here; see this blog post for more details. Mail that passes SPF should indicate as much in its Authentication-Results header:

Authentication-Results: receiving-server
        spf=pass [email protected];
        dkim=pass header.d=netmeister.org header.s=2024;
        dmarc=pass header.from=netmeister.org
Received: from panix.netmeister.org (panix.netmeister.org
        [2001:470:30:84:e276:63ff:fe72:3900])
        by receiving-server with ESMTPS id whatever
        (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256)

DKIM records

DomainKeys Identified Mail (DKIM) signatures use a key identified by the DKIM-Signature header, specifically the domain and selector fields of that signature:

DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=netmeister.org;
        s=2024; t=1712883976;
        bh=lcj/Sl5qKl6K6zwFUwb7Flgnngl892pW574kmS1hrS0=;
        h=From:To:Subject:Content-Type:From:To:Subject;
        b=FYHzUvtC+YPb/NZ03PZDj7JsziXgq65oPAw9vAfOc1Eka4C6bpX3KkBoLJQbMZnzI
        BmIl4dG7O3BaipZI95R2iF0eDYLGnxkbv5tAnNU8X2687mKUdzgZbjyJkEJ/zaB7UY
        COPmRe7T6jfs3XPK1vAVT3xu5eZclTJLbOXBUOnA=

To retrieve the key, you combine the selector with the domain:

$ dig +short txt 2024._domainkey.netmeister.org
"v=DKIM1; k=rsa;
p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuVu8/k6e+xV5NBOqXS2BvicodEEMl/3euLvy
MjQ1fdwgKYtaFNGAnItV3OYYEXR/Ni9bhAus+rMSSJ8a72ztf4PPPq2vEERDf07ooY9kPV7ASn/gC
V02lNfmsMcLPjxosBXexi1EgP4Z0NHRfoTdketwRkDeMMLiCnxrcj8/kiwIDAQAB"

DMARC records

How a receiving mail server should treat messages based on the SPF and DKIM results is defined in the DMARC DNS TXT record:

$ dig +short txt _dmarc.netmeister.org
"v=DMARC1; p=reject; pct=100; aspf=s; adkim=s;
rua=mailto:[email protected]; ruf=mailto:[email protected]"

MTA-STS

SMTP MTA Strict Transport Security (MTA-STS) is signaled via yet another TXT record. If such a record is present, the domain in question must serve the actual policy at a "well-known" URL under the hostname constructed by prefixing the domain in question with literal string mta-sts.:

$ dig +short txt _mta-sts.netmeister.org
"v=STSv1; id=20210324T224413"
$ curl https://mta-sts.netmeister.org/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: panix.netmeister.org
max_age: 2419200
$ 

TLS-RPT

A domain's SMTP TLS Reporting policy can be looked up in the TXT record for the _smtp._tls subdomain:

$ dig +short txt _smtp._tls.netmeister.org
"v=TLSRPTv1; rua=mailto:[email protected]"
$ 

SMTP Security via Opportunistic DNS-Based Authentication of Named Entities (DANE) Transport Layer Security (TLS) is discovered using TLSA records. For SMTP, this would look like so:

$ dig +short tlsa _25._tcp.panix.netmeister.org
3 1 1 E83F02AF46A9C48613CC2793778262C6F1CF0C07C381FF1D92DCEF7C FA97750E
3 1 1 F49A707A5987F6E91ED57CEFBD513014B20129A20C454354DAFE3084 81885B9A
$ 

You can verify the TLSA record via:

$ openssl s_client -connect panix.netmeister.org:25 -starttls smtp               \
        -dane_tlsa_domain panix.netmeister.org                                   \
        -dane_tlsa_rrdata                                                        \
        "3 1 1 E83F02AF46A9C48613CC2793778262C6F1CF0C07C381FF1D92DCEF7CFA97750E" \
        2>/dev/null | grep -B2 TLSA
Verification: OK
Verified peername: panix.netmeister.org
DANE TLSA 3 1 1 ...c381ff1d92dcef7cfa97750e matched EE
certificate at depth 0
$ 

Ok, Brand Indicators for Message Identification (BIMI) is stupid, but just for completeness's sake:

$ dig +short txt default._bimi.netmeister.org
"v=BIMI1; l=https://www.netmeister.org/check.svg"

And no, I'm not going to pay for a Really-Honestly-Very-Special certificate, and I don't really care if this works or not. It's stupid.

April 12th, 2024


Links:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK