Type something to search...
What is DNS tunneling and how do attackers use it?

What is DNS tunneling and how do attackers use it?

DNS tunneling is a technique that hides other data inside DNS queries and responses. Instead of using DNS only to look up names, a program encodes information into the subdomain part of a query, sends it to a domain controlled by whoever runs the tunnel, and receives data back inside the DNS answer. Because almost every network allows DNS traffic out so that devices can resolve names, attackers use tunneling to sneak data past firewalls, to control malware on infected machines, and to steal information without opening an obvious outbound connection.

DNS tunneling isn't a flaw in any particular DNS server. It's an abuse of the fact that DNS is trusted, rarely inspected and allowed almost everywhere. In this article you'll learn how a DNS tunnel works at a high level, why attackers choose it, what legitimate services look similar, and, most importantly, how to detect it in your logs and stop it with resolver and firewall controls.

Why DNS Is Attractive to Attackers

Most networks lock down outbound traffic in some way. A firewall might only allow web traffic through a proxy, or block unknown ports altogether. DNS, however, almost always gets through, because if it doesn't, nothing works.

Several properties make DNS a convenient hiding place:

  • It's allowed everywhere. Even tightly controlled networks, guest Wi-Fi and captive portals usually let DNS queries reach a resolver.
  • It's relayed for you. A device doesn't need to talk to the attacker's server directly. It asks the internal resolver, and the resolver forwards the query across the internet to the authoritative nameserver for the attacker's domain.
  • It's rarely inspected. Many organisations log web traffic in detail but don't look at DNS queries at all.
  • It blends in. A busy network makes millions of lookups a day, so a few thousand extra queries are easy to miss without the right analysis.

How DNS Tunneling Works

A DNS tunnel has two ends: a piece of software on the inside of the network, and an authoritative nameserver on the outside that the tunnel operator controls.

  1. The operator registers a domain, for example example.org, and delegates a subdomain such as t.example.org to a nameserver they run.
  2. Software on the inside encodes data into DNS-safe text, usually Base32 or a similar encoding, because DNS labels can only contain a limited set of characters.
  3. It sends that data as a query. The encoded text becomes the subdomain, so a query looks something like mfrggzdfmztwq2lk.0012.t.example.org.
  4. The internal resolver forwards the query. It doesn't know or care that the name is unusual. It follows the delegation to the operator's nameserver.
  5. The operator's nameserver decodes the query and reads the data inside it.
  6. It replies with data of its own, packed into the answer, often in a TXT, NULL or CNAME record, or encoded into a series of A or AAAA addresses.
  7. The software on the inside decodes the reply, and the cycle repeats.

Because each DNS name is limited to 253 characters and each label to 63, every query carries only a small amount of data. A tunnel therefore needs many queries to move anything meaningful, and that volume is one of the most useful signals for detection.

Why Caching Doesn't Get in the Way

Resolvers cache answers, which would normally stop repeated queries from leaving the network. Tunnels avoid this by making every query unique, usually with a counter or random value in the name. Each new name is a cache miss, so the resolver has to ask the operator's nameserver every time.

How Attackers Use DNS Tunneling

DNS tunneling shows up in several types of attack.

Command and Control

Malware on a compromised machine needs a way to receive instructions. Polling a DNS name every few minutes and reading commands from the reply is quiet and works even on networks that block direct internet access. Several well-documented threat groups and malware families have used DNS for command and control, and the SolarWinds SUNBURST backdoor famously encoded information about victims into subdomains of its command domain.

Data Exfiltration

An attacker who has access to sensitive data can leak it slowly, a few dozen bytes per query, to a domain they control. It's slow, but it can bypass data loss prevention tools that only watch web uploads and email.

Bypassing Network Restrictions

Some tools use DNS tunneling to get general internet access through captive portals or paywalled Wi-Fi that allow DNS before login. This is less harmful than an attack on your organisation, but it's still a sign that a device on your network is evading your policies.

Legitimate Traffic That Looks Like Tunneling

Not every long or random-looking DNS name is malicious. Some legitimate products use DNS in similar ways, and you'll need to allow them so your detection doesn't drown in false positives:

  • Security and antivirus products that look up file hashes or URL reputation by encoding them into DNS queries.
  • Email security lookups, such as DNS-based blocklists (DNSBLs), which put reversed IP addresses or hashes in front of a list's domain.
  • Content delivery networks and cloud services that generate unique hostnames per customer, session or device.
  • Telemetry and analytics tools that use DNS as a lightweight signalling channel.

The difference is usually that legitimate services belong to vendors you recognise, and you can list their domains. Treat a domain you've never heard of, registered recently, receiving thousands of unique high-entropy subdomains from a single machine, very differently from a known vendor domain.

Signs of DNS Tunneling

No single signal proves a tunnel exists, but several together are a strong indicator.

SignalWhy it matters
Many unique subdomains under one domainTunnels make every query unique to avoid caching
Long query names, often close to the 253-character limitEach query carries as much data as possible
Random-looking labels (high character entropy)Encoded data doesn't look like human-chosen names
A high share of TXT, NULL or other unusual record typesThese can carry the most data in a reply
Steady, high query volume from one device to one domainMoving data needs many queries
Recently registered or unknown domainsTunnel operators often use fresh, disposable domains
Queries sent directly to external DNS serversMalware may bypass your resolver to avoid logging

Measuring Randomness with Entropy

Shannon entropy is a simple way to score how random a string looks. Ordinary hostnames like www or mail have low entropy, while Base32 or Base64 data has high entropy, usually above about 3.5 bits per character for labels of any length. Entropy alone produces false positives on CDN and cloud hostnames, so it works best combined with the other signals.

How to Detect DNS Tunneling

Detection starts with having DNS logs at all. If your devices use an internal resolver, that resolver is the best place to record every query.

Step 1: Log Queries on Your Resolver

In Unbound, enable query logging in unbound.conf:

server:
    log-queries: yes
    use-syslog: no
    logfile: "/var/log/unbound/unbound.log"

Reload Unbound and you'll see a line for each query:

[1728550000] unbound[812:0] info: 10.0.0.23 mfrggzdfmztwq2lk.0012.t.example.org. TXT IN

On a busy network, query logging generates a lot of data. Ship it to your log platform rather than keeping it on the resolver, and use dnstap if your resolver supports it, as it's more efficient than text logging.

BIND, Windows DNS Server and most commercial DNS security products have equivalent query logging options. Zeek's dns.log is another good source if you capture network traffic.

Step 2: Convert the Log to a Simple Format

The following awk command pulls the client address, query name and record type out of Unbound's log lines:

awk '/ info: [0-9a-f.:]+ / {print $(NF-3), $(NF-2), $(NF-1)}' /var/log/unbound/unbound.log > queries.log

Each line of queries.log now looks like this:

10.0.0.23 mfrggzdfmztwq2lk.0012.t.example.org. TXT
10.0.0.9 www.example.com. A

Step 3: Score Each Domain

This Python script groups queries by domain and flags any domain that matches at least two of the signals described earlier. It uses only the standard library:

#!/usr/bin/env python3
"""Flag domains in a DNS query log that look like DNS tunneling.

Input: a text file with one query per line: "<client_ip> <qname> <qtype>"
"""
import math
import sys
from collections import Counter, defaultdict


def entropy(text):
    if not text:
        return 0.0
    counts = Counter(text)
    total = len(text)
    return -sum((n / total) * math.log2(n / total) for n in counts.values())


def base_domain(qname):
    # Simple heuristic: the last two labels. Use the tldextract package
    # in production so names like example.co.uk are handled correctly.
    labels = qname.rstrip(".").lower().split(".")
    return ".".join(labels[-2:])


def main(path):
    stats = defaultdict(lambda: {"queries": 0, "subdomains": set(),
                                 "qtypes": Counter(), "clients": set(),
                                 "max_len": 0, "entropy_sum": 0.0})

    with open(path) as log:
        for line in log:
            parts = line.split()
            if len(parts) != 3:
                continue
            client, qname, qtype = parts
            domain = base_domain(qname)
            sub = qname.rstrip(".").lower()[: -len(domain)].rstrip(".")
            s = stats[domain]
            s["queries"] += 1
            s["subdomains"].add(sub)
            s["qtypes"][qtype.upper()] += 1
            s["clients"].add(client)
            s["max_len"] = max(s["max_len"], len(qname))
            s["entropy_sum"] += entropy(sub.replace(".", ""))

    print(f"{'domain':<24}{'queries':>8}{'unique':>8}{'maxlen':>8}"
          f"{'entropy':>9}{'txt%':>6}  reasons")
    for domain, s in sorted(stats.items(), key=lambda kv: -len(kv[1]["subdomains"])):
        unique = len(s["subdomains"])
        avg_entropy = s["entropy_sum"] / s["queries"]
        txt_share = (s["qtypes"]["TXT"] + s["qtypes"]["NULL"]) / s["queries"]
        reasons = []
        if unique >= 50:
            reasons.append("many unique subdomains")
        if s["max_len"] >= 100:
            reasons.append("very long names")
        if avg_entropy >= 3.5:
            reasons.append("random-looking labels")
        if txt_share >= 0.5:
            reasons.append("mostly TXT/NULL")
        if len(reasons) >= 2:
            print(f"{domain:<24}{s['queries']:>8}{unique:>8}{s['max_len']:>8}"
                  f"{avg_entropy:>9.2f}{txt_share * 100:>5.0f}%  {', '.join(reasons)}")


if __name__ == "__main__":
    main(sys.argv[1])

Run it against your log:

python3 dns_tunnel_report.py queries.log

On a sample log containing normal web and mail lookups, 80 CDN-style hostnames and one simulated tunnel, only the tunnel domain is flagged:

domain                   queries  unique  maxlen  entropy  txt%  reasons
example.org                  200     200      76     4.64  100%  many unique subdomains, random-looking labels, mostly TXT/NULL

The CDN-style domain with 81 unique hostnames isn't flagged, because it only matches one signal. That's the point of requiring more than one: a single threshold on its own produces too many false positives.

Treat the thresholds as a starting point. Run the script against a week of normal traffic, add known vendor domains to an allow list, and tune the numbers until the output is short enough to review. For continuous monitoring, the same logic can be built as a scheduled search in your SIEM.

Step 4: Investigate What You Find

When a domain is flagged:

  1. Identify the client. Find which device sent the queries and who uses it.
  2. Look up the domain. Check its registration date, its nameservers and whether threat intelligence feeds know it.
  3. Check the timing. Regular queries at fixed intervals suggest automated command and control, while bursts suggest data transfer.
  4. Inspect the device. Look for unknown processes, scheduled tasks or recently installed software, and follow your incident response process if it's compromised.

How to Prevent DNS Tunneling

Detection tells you a tunnel exists. Prevention makes tunnels harder to set up in the first place.

Force All DNS Through Your Own Resolvers

If devices can send DNS queries straight to any server on the internet, they can avoid your logging and filtering completely. Allow outbound DNS only from your resolvers, and block it from everything else. This nftables example allows DNS from the resolver at 10.0.0.53 and drops it from all other internal hosts:

table inet egress_dns {
    chain forward {
        type filter hook forward priority 0; policy accept;

        ip saddr 10.0.0.53 udp dport 53 accept
        ip saddr 10.0.0.53 tcp dport 53 accept

        udp dport 53 drop
        tcp dport { 53, 853 } drop
    }
}

Port 853 is DNS over TLS. DNS over HTTPS runs on port 443 and can't be blocked by port, so you'll need to block known public DoH endpoints at your proxy or firewall, use browser and operating system policies to turn off built-in DoH, or point devices at your own DoH-capable resolver.

Block Known Bad Domains with RPZ

A Response Policy Zone (RPZ) lets your resolver refuse to resolve specific domains. When you find a tunnel domain, block it and all its subdomains. In BIND, add the policy zone to named.conf:

options {
    response-policy { zone "rpz.local"; };
};

zone "rpz.local" {
    type primary;
    file "/etc/bind/db.rpz.local";
    allow-query { none; };
};

Then list the domains to block in /etc/bind/db.rpz.local:

$TTL 300
@   IN SOA localhost. hostmaster.localhost. ( 1 3600 600 86400 300 )
    IN NS  localhost.

t.example.org      CNAME .
*.t.example.org    CNAME .

A CNAME . entry tells the resolver to answer NXDOMAIN. Check and reload the configuration:

sudo named-checkconf
sudo named-checkzone rpz.local /etc/bind/db.rpz.local
sudo rndc reload

Commercial threat intelligence feeds publish RPZ data, so you can block known malicious domains automatically rather than one at a time.

Use a DNS Security Service

Protective DNS services and DNS firewalls analyse queries as they happen and block domains that show tunneling patterns, newly registered domains, and domains linked to known malware. If you don't have the time to build and tune your own detection, pointing your resolvers at one of these services, or forwarding to one, is a practical option.

Reduce What a Tunnel Can Do

  • Limit which devices can resolve external names at all. Servers that only talk to internal systems often don't need internet DNS.
  • Rate limit queries per client on your resolver, so a single machine can't send thousands of unique queries a minute unnoticed.
  • Alert on unusual record types such as NULL, which ordinary clients rarely request.
  • Keep endpoints protected with up-to-date software and endpoint detection tools, since a tunnel needs software running on the inside to work.

FAQ: DNS Tunneling

The technique itself isn't illegal, and it's sometimes used in authorised security testing. Using it to steal data, control malware or bypass the security of a network you aren't authorised to use is illegal in most countries.

No. DNSSEC proves that DNS answers are genuine, and a tunnel operator can sign their own zone just like anyone else. DNSSEC protects against forged answers, not against someone misusing a domain they control.

It can. If a device sends encrypted DNS directly to a public resolver, your network can't see the queries. That's why you should force devices to use your own resolvers and block or control access to public DoH services.

Slowly compared with a normal connection, because each query carries only a small amount of data. That's enough for command and control or for leaking documents and credentials over hours or days, but the volume of queries it creates is what makes it detectable.

A firewall that only checks ports can't, because tunnel traffic is ordinary DNS on port 53 sent through your own resolver. You need DNS-aware controls such as query logging, RPZ blocking or a DNS security service that inspects query names and patterns.

Block the domain on your resolvers, isolate the device that was sending the queries, and follow your incident response process. Assume that whatever data the device could access may have been exposed until you've confirmed otherwise.


Conclusion

DNS tunneling works because DNS is trusted, allowed everywhere and relayed by your own resolvers on the attacker's behalf. By hiding data in query names and answers, malware can receive commands and leak information without opening any connection a traditional firewall would notice.

The defence is to treat DNS as traffic worth watching. Make every device use resolvers you control, log the queries, look for domains with many unique, long, random-looking subdomains and unusual record types, and block what you find with RPZ or a DNS security service. With those controls in place, a DNS tunnel stops being invisible and becomes one of the easier things to spot in your logs.

Tags :
Share :

Related Posts

What is the difference between an A record and a CNAME record?

What is the difference between an A record and a CNAME record?

The difference between an A record and a CNAME record is what they point to. An A record points a hostname directly at an IPv4 address, such

Dive Deeper
What are the best DNS providers for websites?

What are the best DNS providers for websites?

The best DNS providers for most websites are Cloudflare for a fast, free, easy starting point, Amazon Route 53 if you already run on AWS, **G

Dive Deeper
What are the best public DNS resolvers?

What are the best public DNS resolvers?

The best public DNS resolvers for most people are Cloudflare (1.1.1.1) for speed and privacy, Google Public DNS (8.8.8.8) for reliability and

Dive Deeper