Skip to main content
root/security-operations/detecting-dns-tunnelling-via-resolver-entropy

Detecting DNS Tunnelling via Resolver Entropy

How Shannon entropy scoring, dnstap capture, and PowerDNS Lua hooks catch DNS tunnelling exfiltration that firewall egress rules miss entirely.
Detecting DNS Tunnelling via Resolver Entropy
11/07/2026|10 min read|

A recursive resolver logging ten thousand queries per second cannot afford to run a full protocol decode on every packet, yet that is precisely the volume at which covert command-and-control channels hide inside legitimate-looking DNS traffic. DNS tunnelling detection is not a signature-matching problem; it is a streaming statistics problem, and treating it as the former is why most perimeter firewalls miss exfiltration channels that have been operating in plain sight for years. This article covers the architecture required to run DNS tunnelling detection at line rate using entropy scoring, n-gram frequency analysis, and a stream-processing pipeline that scales independently of query volume.

#The Problem: DNS as an Unmonitored Egress Channel

Most enterprise firewalls apply strict egress filtering to HTTP, HTTPS, and arbitrary TCP ports, but UDP/53 is almost universally permitted outbound without deep inspection because blocking it breaks name resolution entirely. Tools such as dnscat2, iodine, and various Cobalt Strike DNS beacon profiles exploit this by encoding payload data into subdomain labels, using the resolver as a covert transport layer. A single TXT or CNAME query carrying 180 bytes of base32-encoded payload looks structurally identical to a normal DNS lookup at the packet level — the anomaly only becomes visible once you model the statistical shape of the query stream over time.

The core detection signal is information density. Legitimate hostnames are drawn from a constrained vocabulary of dictionary words, brand names, and short alphanumeric identifiers. Tunnelling payloads, by contrast, are the output of an encoding scheme (Base32, Base64, or hex) applied to compressed or encrypted data, which pushes the character distribution of each label toward maximum entropy. Reliable DNS tunnelling detection hinges on capturing that entropy delta at scale without introducing resolver latency.

#Architectural Breakdown

The detection pipeline sits as a passive tap on resolver query logs — never inline with resolution itself, because a false positive that blocks a legitimate lookup is an outage, not a security win. The architecture has four layers: capture, feature extraction, scoring, and enforcement.

#Feature Engineering for DNS Tunnelling Detection

Each query is reduced to a feature vector before it ever reaches a model. The features that carry the most discriminative power are:

  • Shannon entropy of the leftmost label, calculated per query.
  • Label length distribution — tunnelling payloads cluster near the 63-byte DNS label ceiling defined in RFC 1035, whereas organic hostnames rarely exceed 20 characters.
  • Query rate per subdomain apex — a legitimate domain generates dozens of queries per day; a tunnelling channel generates hundreds per minute against the same parent zone.
  • Record type skew — an unusual proportion of TXT, NULL, or CNAME queries relative to A/AAAA baseline traffic for that client.
  • N-gram frequency deviation against a corpus of legitimate second-level domains (trained offline from resolver history or a public list such as the Tranco top-1M).

Shannon entropy is computed as:

1import math
2from collections import Counter
3
4def shannon_entropy(label: str) -> float:
5    if not label:
6        return 0.0
7    counts = Counter(label)
8    length = len(label)
9    return -sum((c / length) * math.log2(c / length) for c in counts.values())
10
11# Legitimate label
12print(shannon_entropy("checkout-api"))   # ~3.02
13
14# Base32-encoded tunnelling payload
15print(shannon_entropy("kbvgs4tfmrqxezlbnzsxg5a"))  # ~4.05

A single entropy score is noisy at the individual query level — some legitimate CDN and ACME DNS-01 challenge labels score high too. Reliable DNS tunnelling detection requires aggregating entropy across a sliding window keyed on the registered domain, not scoring queries in isolation.

DNS tunnelling detection

#Stream Processing Pipeline

At resolver scale, feature extraction and scoring cannot run synchronously with the resolution path. The standard architectural pattern mirrors the event-driven architectural patterns used in high-throughput observability systems: resolver query logs are shipped as structured events (dnstap or JSON) into a Kafka topic, consumed by a stream processor that maintains per-apex-domain windowed aggregates, and scored against a lightweight statistical model rather than a heavyweight neural classifier, which is unnecessary and adds latency without improving recall for this specific signal class.

1# flink-job-config.yaml — windowed aggregation for DNS tunnelling detection
2job:
3  name: dns-tunnel-entropy-scorer
4  parallelism: 12
5source:
6  type: kafka
7  topic: dnstap.query.raw
8  group-id: entropy-scoring-pipeline
9window:
10  type: sliding
11  size: 60s
12  slide: 10s
13  key-by: registered_domain
14aggregations:
15  - mean_entropy
16  - query_count
17  - unique_label_ratio
18  - txt_query_ratio
19sink:
20  type: kafka
21  topic: dns.tunnel.scores
22thresholds:
23  mean_entropy_gt: 3.8
24  query_count_gt: 120
25  txt_query_ratio_gt: 0.4

#Implementation Logic

Building this out end-to-end follows a fixed sequence:

  • Enable dnstap on the recursive resolver (BIND, Unbound, or PowerDNS) to stream structured query/response pairs without parsing raw pcap.
  • Normalise each event into a common schema: client IP, qname, qtype, response code, response size, and timestamp.
  • Strip the TLD and eTLD+1 using the Public Suffix List so aggregation keys on the correct registrable domain rather than the full FQDN.
  • Compute per-label entropy and maintain a 60-second sliding window of mean entropy, query count, and record-type ratios per registrable domain.
  • Apply threshold or z-score scoring against a rolling 30-day baseline per domain to account for genuinely high-entropy but legitimate services (S3 bucket hostnames, container registry pulls).
  • Emit scored events above threshold to a SOAR queue or directly into a firewall API for automated egress blocking with a human-review grace period.

The baseline step is what separates production-grade DNS tunnelling detection from a demo script. Static thresholds alone produce unacceptable false-positive rates against CDNs, package managers, and telemetry SDKs that legitimately use randomised or encoded subdomains.

#Code and Enforcement Configuration

Once a domain is scored above threshold, enforcement should happen at the resolver layer itself rather than waiting for a downstream firewall sync cycle. PowerDNS Recursor supports Lua hooks for this exact purpose:

1-- pdns-recursor-luascript.lua
2function preresolve(dq)
3  local qname = dq.qname:toString()
4  local entropy = shannon_entropy(qname)
5
6  if entropy > 3.8 and string.len(qname) > 40 then
7    -- log to a dedicated syslog facility for SIEM ingestion
8    pdnslog("HIGH_ENTROPY_QUERY: " .. qname .. " score=" .. entropy, pdns.loglevels.Warning)
9
10    -- optional hard block once confidence threshold is stable
11    -- dq.rcode = pdns.NXDOMAIN
12    -- return true
13  end
14  return false
15end

For network-layer visibility on channels that never touch an internal resolver — clients using hardcoded external DNS servers — a Suricata rule catching oversized or high-entropy TXT queries provides a complementary detection layer:

1alert dns any any -> any 53 (msg:"Possible DNS Tunnelling - Oversized TXT Query"; 
2  dns.query; content:"|00 10 00 01|"; dsize:>200; 
3  classtype:trojan-activity; sid:9000123; rev:2;)

Running both the resolver-side entropy scorer and the network IDS rule in parallel closes the gap between managed and unmanaged DNS egress paths, which is the most common blind spot exploited by red teams during exfiltration exercises.

#Failure Modes and Edge Cases

DNS tunnelling detection built purely on entropy thresholds degrades in several predictable ways:

DNS tunnelling detection

Legitimate high-entropy traffic. ACME DNS-01 validation, Kubernetes-generated pod hostnames, and CDN edge-node routing (Akamai, Cloudflare, Fastly) all produce subdomains with entropy scores comparable to genuine tunnelling payloads. Without a maintained allowlist keyed on registrable domain, these generate a sustained false-positive rate that erodes SOC trust in the alert queue within weeks.

Encrypted DNS bypass. DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT), as defined in RFC 7858, remove the resolver’s visibility entirely if a client is configured to use an external DoH endpoint directly. A tunnelling implant using hardcoded DoH (e.g. against Cloudflare’s 1.1.1.1 or Google’s 8.8.8.8 DoH endpoints) is invisible to on-prem dnstap capture. Mitigation requires either forcing DoH/DoT traffic through a decrypting proxy at the egress boundary or blocking known public DoH IP ranges outright and forcing clients onto the monitored resolver.

Low-and-slow channels. Sophisticated tunnelling implementations throttle themselves below the query-rate threshold, spreading exfiltration over days rather than minutes. Sliding-window aggregation with a 60-second granularity misses this pattern entirely; catching it requires a secondary long-window model (24-hour or 7-day rolling aggregate) scoring cumulative entropy-weighted byte volume per client-domain pair, at the cost of significantly higher state storage in the stream processor.

NXDOMAIN storms. Some tunnelling tools deliberately generate NXDOMAIN responses as part of the covert channel’s acknowledgement protocol. A detection pipeline that filters out NXDOMAIN responses before feature extraction — a common optimisation to reduce processing volume — will silently drop this entire detection class.

#Scaling and Security Trade-offs

Deploying DNS tunnelling detection across a multi-site enterprise resolver fleet forces several architectural decisions with measurable trade-offs:

  • Full capture vs sampled capture: full dnstap capture at a 50,000 QPS resolver generates roughly 4-6 TB/day of raw log volume; 1-in-10 sampling cuts storage cost by 90% but drops recall on low-and-slow channels below acceptable SOC thresholds.
  • Centralised vs distributed scoring: a single centralised Flink cluster simplifies baseline management but introduces a single point of failure and cross-region log-shipping latency of 200-400ms; distributed per-site scoring reduces latency but fragments the 30-day baseline, increasing false positives during regional traffic shifts.
  • Inline blocking vs passive alerting: inline NXDOMAIN enforcement at the resolver stops exfiltration in real time but risks breaking legitimate high-entropy services if the allowlist lags behind infrastructure changes; passive alerting avoids outages but extends attacker dwell time by the length of the SOC triage cycle.
  • Model complexity vs explainability: gradient-boosted or neural classifiers marginally improve precision over threshold-based entropy scoring, but SOC analysts cannot audit a black-box score during an incident response call; a rules-and-thresholds model, tuned against a rolling baseline, remains the more defensible choice for compliance-driven environments.
  • Resolver-side vs network-side enforcement: resolver hooks (PowerDNS Lua, Unbound Python module) catch managed-client tunnelling cheaply, but miss any client bypassing the internal resolver; network IDS rules catch the bypass case but cannot decrypt DoH, leaving encrypted tunnelling as a persistent residual risk regardless of which layer you enforce at.

None of these trade-offs eliminate the fundamental limitation: DNS tunnelling detection is a statistical arms race, and any threshold tuned against today’s encoding schemes will require recalibration as attackers adapt their entropy profile to sit just under the alerting line.

Reader Interaction

Comments

Add a thoughtful note on Detecting DNS Tunnelling via Resolver Entropy. Comments are checked for spam and held for moderation before appearing.

Loading comments...

Loading anti-spam check...

Eleanor Hayes

Written By

Eleanor Hayes

Dr Eleanor Hayes is a veteran cryptography researcher and enterprise security architect specialising in zero-trust network implementations. Having spent a decade securing critical national infrastructure, she now designs identity-aware proxy perimeters and mutual TLS topologies for highly distributed environments. She holds multiple GIAC certifications and regularly consults on mitigating advanced persistent threats within microservice ecosystems.