DNS forgets nothing (if someone was listening)

A live DNS lookup tells you where a domain points right now. That is almost never the question an investigator has. You want to know where it pointed last Tuesday when the phishing email landed, what else pointed at that server, and where the operator moved after the takedown.

Passive DNS (pDNS) answers those questions. It is a historical record of observed DNS resolutions: this name resolved to this address, first seen on this date, last seen on that date, observed N times. No current lookup can give you that, and no attacker can retroactively erase it.


How passive DNS is collected

The concept dates back to Florian Weimer's 2005 work on tracking botnets. Sensors sit above recursive resolvers, watching the cache-miss traffic between a resolver and the authoritative name servers. When any client behind a participating resolver looks up a name, the answer is logged, deduplicated, and stored as a tuple:

rrname:      login-secure-portal.com
rrtype:      A
rdata:       185.220.x.x
first_seen:  2026-03-02 14:11:08
last_seen:   2026-04-19 09:52:41
count:       1493

Three properties matter for investigators:

  • It is observation, not registration. A record only exists if someone, somewhere behind a sensor, actually resolved the name. This means pDNS captures reality, including subdomains no registry knows about.
  • It is privacy-preserving by design. Collection happens above the resolver, so the record says that a name resolved, never who asked. Individual client IPs are not part of the dataset.
  • It is append-only. The attacker can change the DNS zone today; they cannot change what sensors saw yesterday.

Coverage depends on sensor placement. Large pDNS providers aggregate from ISPs, enterprises, and public resolvers worldwide, but no database sees everything. Absence of a record is weak evidence of anything.


What resolution history exposes

Attacker infrastructure is a supply chain: domains get registered, parked, activated for a campaign, burned, and re-pointed. Each stage leaves DNS residue.

Timeline reconstruction. A domain that resolved to a parking IP for six months, then jumped to a VPS three days before your phishing wave, tells you when the operation went live and how long it was staged.

Shared infrastructure. Reverse pDNS (querying by IP instead of by name) lists every hostname observed on an address. Attackers reuse servers, so one confirmed C2 address frequently reveals sibling domains from the same operator.

Operational habits. Some actors reuse name servers, keep distinctive subdomain schemes (mail., cpanel., api2.), or migrate whole domain sets between providers on the same day. These patterns cluster activity even when every individual indicator is new.


A worked pivot: from one domain to a campaign

Say a user reports a credential phishing page at secure-invoice-view.com. A live lookup shows it already NXDOMAINs. Dead end? Not with history.

Step 1: Get the resolution history. pDNS shows secure-invoice-view.com resolved to 45.93.x.24 from June 2 to June 9.

Step 2: Reverse the IP. Query 45.93.x.24 for the same window. Eleven other hostnames resolved there, all matching a pattern:

secure-invoice-view.com     2026-06-02  ->  2026-06-09
invoice-portal-check.com    2026-06-03  ->  2026-06-10
docview-secure-mail.com     2026-06-05  ->  2026-06-12
secure-doc-invoice.net      2026-06-08  ->  2026-06-15
...

Step 3: Filter the noise. Before treating all eleven as malicious, check whether the IP is shared hosting. If hundreds of unrelated names sit on it, the pivot is worthless. Here the address hosts only these lookalikes plus the provider's default reverse record: strong signal it is attacker-dedicated.

Step 4: Follow the movement. Two of the newer domains stopped resolving to 45.93.x.24 on June 12 and started resolving to 91.207.x.181. Reverse that second IP: five more domains, three of which have first-seen dates in the future of your incident. Those are the operator's staged infrastructure for the next wave.

Step 5: Act on the full set. You started with one dead domain and finished with roughly twenty, including some not yet used against anyone. Block proactively, retro-hunt your mail and proxy logs for the historical set, and write a detection for the naming pattern.

This loop (name to IP, IP to names, repeat, filter) is the core move. Everything else is discipline about when to stop.


Pivot quality checklist

Not every pDNS overlap means shared ownership. Before you extend a cluster, ask:

Check Good pivot Bad pivot
Names on the IP A handful, thematically related Thousands (shared hosting, CDN)
Time overlap Resolutions overlap or chain tightly Names hosted years apart
IP ownership Small VPS provider, dedicated server Cloudflare, AWS ranges, Google front-ends
Record type A/AAAA to attacker-controlled hosts Sinkhole IPs, parking pages, RFC 1918 leakage
Direction Multiple independent overlaps A single shared attribute

The CDN case deserves emphasis: millions of domains resolve to Cloudflare addresses. An IP overlap behind a CDN or a big cloud load balancer proves nothing except that both parties use the same popular service.


Limits and gotchas

  • Coverage gaps. A domain resolved only inside one victim network may never cross a sensor. First-seen dates are lower bounds on activity, not registration dates.
  • Sinkholes and takedowns. After a takedown, malicious domains resolve to researcher or law-enforcement sinkholes. Pivoting on a sinkhole IP will "cluster" thousands of unrelated malware families. Learn the well-known sinkhole ranges.
  • Fast flux and short TTLs. Botnets that rotate A records every few minutes generate enormous, low-value resolution sets. Look at name server history instead; NS records rotate far less.
  • Wildcard DNS. A zone with a wildcard answers for any subdomain, so pDNS may contain garbage names generated by scanners and typos. Volume counts help separate real use from noise.
  • Stale conclusions. IP addresses get reallocated. A VPS that hosted a C2 in 2024 may host a bakery today. Always anchor pivots to the relevant time window, never to "ever resolved to".

Tooling the loop

Doing this by hand across multiple pDNS sources is tedious, which is why resolution history belongs inside your enrichment path rather than in a separate tab. When you look up a domain or IP on mlab.sh, the enrichment includes passive DNS history alongside reputation, geolocation, and related indicators, so the "what else lived here?" question is answered in the same view where triage happens. For automated pipelines, the same data is available through the API documented at doc.mlab.sh.

However you tool it, record your pivots. A cluster is an argument, and an argument you cannot replay ("we linked these 20 domains because...") is one you cannot defend when someone asks why a domain was blocked.


Attackers can burn a domain in seconds, but they cannot burn the record of where it pointed. Passive DNS is memory, and memory wins investigations.