Field Notes · Technical Reality

Everything Speaks DNS

How to move data out of a network that blocks everything, by hiding it in the one protocol nobody dares turn off.

DNS tunneling / exfiltration  ·  appears in the exfiltration

You can firewall a network until almost nothing gets in or out. Block every port, proxy every web request, strip every protocol you don’t recognize. There is one thing you almost certainly leave open, because the network stops working without it: name resolution. Machines have to be able to ask what is the address for this name?

DNS is the dial tone of the internet. And anything that’s always on is a channel.

Why DNS goes everywhere

When a machine deep inside a network resolves mail.corp.local or cdn.example.com, it doesn’t reach the destination directly. It asks its local resolver, which (if it doesn’t know the answer) asks up the chain until the query reaches the authoritative nameserver for that domain. That’s the design: queries for a domain are delivered to whoever runs that domain’s nameserver.

Now own a domain. Point its authoritative nameserver at a box you control. From that moment, anyone in the world who triggers a lookup under your domain is sending you a message, and you get to write the reply.

Hiding data in the question

The query itself is the smuggling compartment. A DNS name is a series of labels separated by dots, and you choose those labels. So you encode your data into them:

# exfiltrate bytes by encoding them into subdomain labels
# (base32 is DNS-safe: case-insensitive, no awkward characters)

MFRGGZDF.NBSWY3DP.01.kh.example      <-- chunk 1, seq 01
ORSXG5BA.MFRGG.02.kh.example         <-- chunk 2, seq 02

Every one of those is a normal-looking lookup. Your nameserver receives each query, strips off the labels, base32-decodes them, and reassembles the stream in sequence. The data left the network the instant the query was made, before any answer came back.

Need to send data in, too? The response carries it. A TXT record can hold arbitrary text; CNAME and NULL records work as well. Command-and-control and file transfer both ride the same channel.

The catch: it’s slow

DNS was not built for throughput, and the limits bite. A single label maxes at 63 bytes; a full name at 255. Base32 inflates your data by 60%. Caching resolvers will collapse repeated queries, so each chunk needs to be unique. Realistically you’re moving kilobytes, not gigabytes.

But exfiltration often isn’t about volume. A private key, a password database, a single sensitive document: those are small. And the trade you’re making is bandwidth for stealth: it’s slow, but it looks exactly like a machine doing the most boring thing a machine does all day.

How it gets caught

DNS tunneling is quiet, not invisible. The tells are statistical:

  • A single domain receiving an unusual volume of queries.
  • Labels that are long, high-entropy, and never repeat. Real hostnames are short and recur.
  • A flood of unique subdomains under one parent.
  • TXT-heavy traffic where you’d expect mostly A records.

Defenses follow from that: log and baseline DNS, alert on those anomalies, force endpoints through internal resolvers (no rogue external DNS), apply response policy zones, and rate-limit. Tools like iodine and dnscat2 exist on the offensive side precisely because defenders so often forget DNS is a data channel at all.

The point

When the obvious doors are welded shut, you stop looking for a door. The data in the book doesn’t blast out through some dramatic open port. It leaves as a patient sequence of lookups, each one indistinguishable from a machine asking a perfectly ordinary question. The network logged every byte of it leaving and filed each query as routine.

The Glass would understand the irony. It sees everything. It just can’t always tell what it’s looking at.