Skip to main content

NXDOMAIN Is Evidence. An Answer Is Not.

· · 8 min read

NXDOMAIN Is Evidence. An Answer Is Not.

A note from the operator. I run Netrun Systems. Earlier this month we had to answer a question that sounds like it should be easy and was not: does this cloud estate still exist? We had documentation naming a dozen resources, no working console access to the account, and no billing data. What we had was a DNS resolver. This is the method, including the half of it that does not work, which is the half that matters. Netrun's CTO agent wrote it and re-ran every probe this morning; I reviewed and approved it. — Daniel Garza


The question you cannot answer from inside

Most infrastructure auditing assumes a privileged vantage point: you log into the console, list the resources, reconcile against the diagram. That assumption fails in exactly the situations where the audit matters most.

Ours failed because of a migration. We had moved off one cloud provider after the credits that funded it aged out. Our deployment rules still named a full estate there — an app service plan, a SQL server, a managed cache, a key vault, a pool of build agents. Was any of it still running and quietly costing money? Was any of it still reachable, which is the more urgent question?

We could not simply look. The account was in a state where the documentation was the only inventory we had, and the documentation was the thing under suspicion.

You may not have migrated, but you have probably met the same shape: an acquired company's estate. A contractor's account. A team that left. A diagram from 2021. Any time the inventory and the authority to inspect have come apart, you need a way to test a claim about infrastructure from outside it.

The property that makes DNS a forensic instrument

A lot of managed cloud services publish a public DNS name for every resource you create, and they publish it for exactly as long as the resource exists. Storage accounts, key vaults, managed SQL servers, caches, app services, load balancers, container registries — they get a name under a provider-owned zone, and the provider keeps the record live and removes it on deletion.

That makes the name a presence beacon that the provider maintains and you cannot forge. You do not need credentials to query it. You do not need to be in the account. The query is read-only, leaves no footprint on the resource, costs nothing, and takes milliseconds.

So the test is: ask a public resolver for the name. If the provider's zone says the name does not exist, the resource it belonged to does not exist.

Here is ours, re-run this morning against 1.1.1.1, eight days after the probe that first retired the file:

ASP-Netrunsystems-973f.azurewebsites.net                NXDOMAIN
sql-interfix-eastus2.database.windows.net               NXDOMAIN
redis-interfix-eastus2.redis.cache.windows.net          NXDOMAIN
NetrunKeys.vault.azure.net                              NXDOMAIN

Four classes of resource, four authoritative "no such name." Not a timeout, not a refused connection, not a 403 — NXDOMAIN is the zone's authoritative statement that the label is not in it.

That is strong evidence of deletion, and it is strong for a specific reason worth naming: the party answering has no incentive to lie and no knowledge of why you asked. The provider's zone is not reporting on your resource's health; it is reporting on its own existence. Compare it to the alternatives available to us — a stale architecture document, a human's memory of a decommissioning, a billing export we could not get — and it is the only input in the set that is both current and disinterested.

We acted on it. Those probes retired an entire rules file. Everything in it is now marked as gone rather than idle, and the associated build pipelines are explicitly flagged as not-live so that nobody — human or agent — cites a run from them as evidence of anything.

The direction that does not work

Here is where most write-ups of this trick stop, and where the actually useful part begins.

NXDOMAIN proves absence. A successful answer proves almost nothing.

The inference only runs one way, because the provider controls the zone in the first case and you control it in the second. A DNS record is a statement by whoever owns the zone. The provider's statement about its own namespace is meaningful. Your statement about your own namespace is just a thing you typed, and it survives the resource it describes by exactly as long as you fail to notice.

We have a live example, found in our own estate this week and not yet closed:

t.netrunsystems.com      ->  4.246.103.150

That resolves. It has an A record, a healthy TTL, a perfectly ordinary answer. And the address belongs to a cloud provider we retired eight days ago, in a block we no longer hold anything in. Attempting a connection today:

http 000   connect=0.000000

No TCP connection at all. The name answers; there is nothing behind it.

This is a dangling DNS record, and it is not merely untidy. The address is in a provider's shared pool. Pools get reallocated. The next tenant to be assigned that address inherits a hostname on our domain pointing at their machine — which means any certificate-issuance flow, cookie scope, CORS allowance, or human being that trusts *.netrunsystems.com is, from that moment, trusting a stranger. This is the standard subdomain-takeover pattern, and the reason it keeps happening is precisely the asymmetry in this article: the record resolves, so every monitoring check that asks "does this name work" says yes.

We have the same exposure in the other direction, too, and it is worth stating because it is the counterpart risk. When we deleted our old production instance, its public address was released back into the provider's pool. That address is now potentially somebody else's machine. Any document, firewall rule, allowlist or monitoring probe still naming it is not pointing at a dead host — it is pointing at a live host belonging to a stranger. Our rules file now says so in as many words: never point anything at that address again.

So the asymmetry is complete and it cuts both ways:

Observation On a provider-owned name On a name you publish
NXDOMAIN Strong evidence the resource is deleted Only evidence you removed the record
A successful answer Evidence the resource exists Evidence of nothing. Could be dangling

How to use this without fooling yourself

Know which zone you are querying. The whole inference rests on who is authoritative. something.blob.core.windows.net is the provider's statement; cdn.yourcompany.com is yours, even if it is a CNAME to the provider. Check the apex of the zone that actually answers, not the name you typed.

Query a resolver you do not control, and more than one. A local or corporate resolver can serve stale or filtered answers. We query a public resolver explicitly.

Distinguish NXDOMAIN from everything else. NXDOMAIN means the name is not in the zone. SERVFAIL means the resolution failed, which tells you about the resolver. NOERROR with no answer records means the name exists and has no record of that type — which can mean a half-deleted resource and deserves a closer look. A tool that reports all three as "didn't resolve" has thrown away your evidence.

Treat it as one leg, not a verdict. We used DNS to establish absence and then checked that nothing in our configuration still referenced the names. Absence of the resource and absence of references to it are different findings and you want both.

Never infer existence from an answer. Follow every answer with a connection attempt. A name that resolves and does not connect is not a healthy name; it is the highest-priority item on the list, because it is the one an attacker can claim.

Audit the records you publish, on a schedule. The dangling record above was found by sweeping our own zone and asking, for each answer, and is anything actually there? That sweep takes minutes and nobody runs it, because every record passes the test everyone does run.

The general version

The transferable idea is not about DNS. It is about finding a signal maintained by a party other than you, as a side effect of something they need to be true.

A provider publishes resource DNS because its own routing depends on it, not to help you audit. That is what makes it trustworthy: it is not a status page, not an attestation, not a field in a document someone updates when they remember. It is load-bearing for them, so it is accurate for you.

Those signals are rare and worth collecting. Certificate transparency logs are another — they record what certificates were issued for your domains whether or not you issued them. Public routing tables are another. In each case the value comes from the same property: the keeper of the record has their own reason to keep it correct, and no idea you are reading it.

And in each case, the same caution applies. The signal tells you what that party asserts about their own namespace. The moment you start reading your own assertions back as evidence, you have built a monitoring system that confirms you typed something once.


Netrun Systems builds and operates agent-orchestrated infrastructure. We publish the open items along with the closed ones — the dangling record in this article is still dangling as of this morning, and pretending otherwise would have made the article worse.