DNS & Email Security
Trace SPF chains, DNSSEC validation, MX records, CNAME hops, and detect dangling DNS records.
DNS & Email Security Documentation
You're auditing DNS configurations, validating SPF coverage, and checking DNSSEC deployment.
Quick Triage
Nameserver Inventory
Get all nameservers currently delegated for a domain.
-- Authoritative nameservers for a domain
MATCH (ns:HOSTNAME)-[:NAMESERVER_FOR]->(h:HOSTNAME {name: "microsoft.com"})
RETURN ns.name LIMIT 10
Sample output:
[
{"ns.name": "ns1-39.azure-dns.com"},
{"ns.name": "ns2-39.azure-dns.net"},
{"ns.name": "ns3-39.azure-dns.org"},
{"ns.name": "ns4-39.azure-dns.info"}
]
Tip: Multiple NS records across different TLDs (
.com,.net,.org) is standard practice for fault tolerance. If all NS records are under the same TLD, that's a single point of failure.
Mail Server Inventory
List all mail servers that handle inbound email for a domain.
-- MX records for a domain
MATCH (mx:HOSTNAME)-[:MAIL_FOR]->(h:HOSTNAME {name: "google.com"})
RETURN mx.name
Sample output:
[{"mx.name": "smtp.google.com"}]
Tip: The graph stores MX records as
MAIL_FORedges from the mail server hostname to the domain it serves. Cross-check the mail server's own IP and ASN to verify it's on expected infrastructure.
Deep Dive Investigation
SPF Include Chain Audit
Trace the full tree of SPF includes to understand the complete authorized sender set.
-- Recursive SPF include chain (up to 3 hops)
MATCH (h:HOSTNAME {name: "microsoft.com"})-[:SPF_INCLUDE*1..3]->(inc:HOSTNAME)
RETURN DISTINCT inc.name ORDER BY inc.name LIMIT 20
Sample output:
[
{"inc.name": "_spf-a.microsoft.com"},
{"inc.name": "_spf-b.microsoft.com"},
{"inc.name": "_spf-c.microsoft.com"},
{"inc.name": "_spf-d.microsoft.com"},
{"inc.name": "_spf-ssg-a.microsoft.com"}
]
Tip: The SPF spec caps includes at 10 DNS lookups. Deep include chains close to that limit risk "permerror" for legitimate email. Count the distinct nodes returned to check depth.
SPF IP Authorization
See the exact IP ranges authorized to send mail on behalf of a domain.
-- IP ranges authorized in SPF (direct + one level of includes)
MATCH (h:HOSTNAME {name: "google.com"})-[:SPF_INCLUDE]->(spf:HOSTNAME)
OPTIONAL MATCH (spf)-[:SPF_IP]->(range)
RETURN spf.name, collect(range.name) AS authorized_ranges
Sample output:
[{
"spf.name": "_spf.google.com",
"authorized_ranges": ["74.125.0.0/16", "209.85.128.0/17", "2001:4860:4000::/36", "2404:6800:4000::/36"]
}]
Tip: Broad IP ranges (like
/16or/17) in SPF records mean any server in that range can send as your domain. For a security audit, verify each range actually belongs to the email provider you're using.
Full SPF Mechanism Audit
Get a complete breakdown of all SPF mechanisms for a domain.
-- All SPF mechanisms (include, ip, a, mx, redirect, exists)
MATCH (h:HOSTNAME {name: "microsoft.com"})
-[r:SPF_INCLUDE|SPF_IP|SPF_A|SPF_MX|SPF_REDIRECT|SPF_EXISTS]->(target)
RETURN type(r) AS mechanism, target.name AS authorized LIMIT 20
Sample output:
[
{"mechanism": "SPF_INCLUDE", "authorized": "_spf-a.microsoft.com"},
{"mechanism": "SPF_INCLUDE", "authorized": "_spf-b.microsoft.com"},
{"mechanism": "SPF_INCLUDE", "authorized": "_spf-c.microsoft.com"},
{"mechanism": "SPF_INCLUDE", "authorized": "_spf-d.microsoft.com"},
{"mechanism": "SPF_INCLUDE", "authorized": "_spf-ssg-a.microsoft.com"}
]
Tip: Check for
SPF_REDIRECT— a redirect mechanism replaces the entire SPF policy with another domain's policy. If that target domain has a permissive policy, your effective policy is permissive too.
Domain Hierarchy
Understand the parent-child structure of a domain namespace.
-- Walk the domain hierarchy from a subdomain to its roots
MATCH (h:HOSTNAME {name: "mail.google.com"})-[:CHILD_OF*1..3]->(parent)
RETURN h.name AS subdomain, parent.name AS ancestor LIMIT 10
Sample output:
[
{"subdomain": "mail.google.com", "ancestor": "google.com"},
{"subdomain": "mail.google.com", "ancestor": "com"}
]
Tip: Use this to confirm zone delegation — a subdomain should share the same effective zone as its parent unless it has its own NS records.
Batch Nameserver Audit
Check the nameservers for multiple domains at once.
-- Nameservers for a set of domains
UNWIND ["google.com", "cloudflare.com", "microsoft.com"] AS domain
MATCH (h:HOSTNAME {name: domain})
OPTIONAL MATCH (ns:HOSTNAME)-[:NAMESERVER_FOR]->(h)
RETURN domain, collect(ns.name) AS nameservers
Sample output:
[
{"domain": "google.com", "nameservers": ["ns1.google.com", "ns2.google.com", "ns3.google.com", "ns4.google.com"]},
{"domain": "cloudflare.com", "nameservers": ["bella.ns.cloudflare.com", "chelsea.ns.cloudflare.com", "graham.ns.cloudflare.com"]},
{"domain": "microsoft.com", "nameservers": ["ns1-39.azure-dns.com", "ns2-39.azure-dns.net", "ns3-39.azure-dns.org", "ns4-39.azure-dns.info"]}
]
Tip: Comparing nameservers across an organization's portfolio is a fast way to find outliers — a domain that's still on an old DNS provider after a migration, or a test domain left on a default registrar nameserver.
Who Operates a TLD?
You need to identify the registry operator responsible for a top-level domain — useful when escalating abuse complaints or understanding jurisdiction.
-- Registry operator for a TLD
MATCH (op:TLD_OPERATOR {name: "VeriSign Global Registry Services"})-[:OPERATES]->(tld:TLD)
RETURN op.name AS operator, collect(tld.name) AS tlds
Sample output:
[{"operator": "VeriSign Global Registry Services", "tlds": ["com", "net"]}]
Tip: Most TLD operators run only one or a few TLDs. For abuse escalation, the OPERATES relationship gives you the authoritative registry responsible for the zone.
Check Email Security Posture
Quickly assess whether a domain has SPF configured and DNSSEC enabled.
-- Email security posture: SPF and DNSSEC
MATCH (h:HOSTNAME {name: "stripe.com"})
OPTIONAL MATCH (h)-[:SPF_INCLUDE]->(spf)
OPTIONAL MATCH (h)-[:SIGNED_WITH]->(algo:DNSSEC_ALGORITHM)
RETURN h.name,
count(DISTINCT spf) AS spf_includes,
collect(DISTINCT algo.name) AS dnssec_algorithms
Sample output:
[{"h.name": "stripe.com", "spf_includes": 3, "dnssec_algorithms": []}]
Tip: An empty
dnssec_algorithmslist means DNSSEC signing data was not available for this domain.spf_includesgreater than zero confirms an SPF policy exists. For full SPF coverage detail, use the SPF include chain recipe above.
Splunk equivalents
For SPF/DMARC posture audits and dangling DNS detection in SPL, see Splunk Use Cases. The whisper_spf_chain and whisper_cname_chain macros wrap the same Cypher patterns — see Investigation Macros.