Potential DNS Tunneling via Long and Unique Subdomains
Identifies a client generating many unique, unusually long DNS query names to the same registered domain within a five-minute window. Malware DNS tunnels and DNS command-and-control commonly encode data in lengthy subdomain portions under one apex domain.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/08/20"
3integration = ["network_traffic", "zeek"]
4maturity = "production"
5updated_date = "2026/08/20"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies a client generating many unique, unusually long DNS query names to the same registered domain within a
11five-minute window. Malware DNS tunnels and DNS command-and-control commonly encode data in lengthy subdomain portions
12under one apex domain.
13"""
14false_positives = [
15 """
16 CDN, cloud load-balancer, software-update, and telemetry hostnames can be long and change often. Recursive
17 resolvers, forwarders, NAT gateways, and localhost DNS listeners can also combine queries from many endpoints under
18 one client address. Validate the apex domain and whether the source is an endpoint before treating the activity as
19 tunneling.
20 """,
21]
22from = "now-9m"
23language = "esql"
24license = "Elastic License v2"
25name = "Potential DNS Tunneling via Long and Unique Subdomains"
26note = """## Triage and analysis
27
28### Investigating Potential DNS Tunneling via Long and Unique Subdomains
29
30DNS tunneling encodes data in query labels and often produces many unique, unusually long subdomains under a single apex
31domain. This rule aggregates network DNS telemetry for that behavioral pattern without relying on threat intelligence
32feeds or machine learning jobs.
33
34Compare overlapping apex domains against the machine learning **DNS Tunneling** rule when that job is enabled.
35
36### Possible investigation steps
37
38- Review `Esql.dns_registered_domain`, `Esql.count_distinct_names`, `Esql.unique_name_ratio`,
39 `Esql.max_subdomain_length`, and sample values in `Esql.sample_names`.
40- Inspect `Esql.dns_question_type_values`. TXT, NULL, CNAME, or MX bursts increase confidence; A/AAAA-only activity can
41 still be tunneling and should not be dismissed on type alone.
42- Use `Esql.first_seen`, `Esql.last_seen`, `Esql.dataset_values`, and `Esql.observer_name_values` to establish the event
43 span and identify the integrations and sensors that contributed to the alert.
44- Confirm whether `Esql.client_ip` is a workstation, server, recursive resolver, forwarder, NAT address, or localhost
45 DNS service. Resolver and localhost sources merge many clients and are a common false-positive pattern.
46- Review `Esql.destination_ip_values` to identify the resolver or authoritative destination observed by the sensor.
47- Pivot on the same client and apex domain in raw DNS events and look for follow-on process, file, or additional C2
48 activity.
49
50### False positive analysis
51
52- CDN, cloud load-balancer, certificate, and software-update services often create long hostnames. Confirm the apex
53 domain reputation and whether the requesting host role normally uses that provider.
54- Security or network appliances performing DNS-based reachability or reputation checks can resemble tunneling. Exclude
55 confirmed appliance addresses after validation.
56- Do not create a global resolver exception until the originating endpoint is known; a shared `Esql.client_ip` can hide
57 a single infected host behind legitimate bulk lookups.
58
59### Response and remediation
60
61- Block the apex domain or forwarding from the affected host at recursive resolvers if malicious activity is confirmed.
62- Isolate the source host and inspect for tunneling tools or malware initiating the queries.
63- Add temporary blocks for the apex domain while scoping additional hosts querying the same name.
64"""
65references = [
66 "https://unit42.paloaltonetworks.com/dns-tunneling-how-dns-can-be-abused-by-malicious-actors/",
67]
68risk_score = 47
69rule_id = "89ed957d-609b-4b00-b8c6-a5cbd187632c"
70setup = """## Setup
71
72This rule requires DNS transaction events from one of the following sources:
73
74- Elastic Network Packet Capture (`network_traffic.dns`) in `logs-network_traffic.dns-*`
75- Elastic Zeek (`zeek.dns`) in `logs-zeek.dns-*`
76- Legacy Packetbeat DNS events in `packetbeat-*` with `event.dataset` set to `dns`
77
78Place the sensor where it observes endpoint-to-resolver DNS traffic. If the sensor is upstream of a recursive resolver,
79or if the captured client is a localhost listener such as `127.0.0.1`, `Esql.client_ip` may identify shared DNS
80infrastructure instead of the originating endpoint.
81
82DNS-over-HTTPS (DoH), DNS-over-TLS (DoT), and other encrypted DNS traffic are not visible to packet capture unless the
83sensor receives decrypted DNS telemetry or equivalent resolver logs mapped to ECS.
84"""
85severity = "medium"
86tags = [
87 "Domain: Network",
88 "Use Case: Threat Detection",
89 "Use Case: Network Security Monitoring",
90 "Rule Type: ESQL",
91 "Tactic: Command and Control",
92 "Tactic: Exfiltration",
93 "Data Source: Network Packet Capture",
94 "Data Source: Network Traffic",
95 "Data Source: Zeek",
96 "Resources: Investigation Guide",
97]
98timestamp_override = "event.ingested"
99type = "esql"
100
101query = '''
102from logs-network_traffic.dns-*, logs-zeek.dns-*, packetbeat-*
103| where
104 (
105 data_stream.dataset in ("network_traffic.dns", "zeek.dns")
106 or event.dataset == "dns"
107 )
108 and dns.question.name is not null
109 and dns.question.registered_domain is not null
110| eval
111 Esql.client_ip = COALESCE(client.ip, source.ip),
112 Esql.dataset = COALESCE(data_stream.dataset, event.dataset),
113 Esql.dns_question_name = TO_LOWER(dns.question.name),
114 Esql.dns_registered_domain = TO_LOWER(dns.question.registered_domain),
115 Esql.dns_question_type = TO_LOWER(dns.question.type),
116 Esql.subdomain_length = LENGTH(Esql.dns_question_name) - LENGTH(Esql.dns_registered_domain) - 1
117| where
118 Esql.client_ip is not null
119 and Esql.subdomain_length >= 50
120 and (Esql.dns_question_type is null or Esql.dns_question_type != "ptr")
121 and not ENDS_WITH(Esql.dns_question_name, ".arpa")
122| eval Esql.time_window = DATE_TRUNC(5 minutes, @timestamp)
123| stats
124 Esql.count_queries = COUNT(*),
125 Esql.count_distinct_names = COUNT_DISTINCT(Esql.dns_question_name),
126 Esql.max_subdomain_length = MAX(Esql.subdomain_length),
127 Esql.avg_subdomain_length = AVG(Esql.subdomain_length),
128 Esql.dns_question_type_values = MV_SLICE(VALUES(Esql.dns_question_type), 0, 9),
129 Esql.destination_ip_values = MV_SLICE(VALUES(destination.ip), 0, 4),
130 Esql.sample_names = MV_SLICE(VALUES(Esql.dns_question_name), 0, 4),
131 Esql.dataset_values = MV_SLICE(VALUES(Esql.dataset), 0, 9),
132 Esql.observer_name_values = MV_SLICE(VALUES(observer.name), 0, 19),
133 Esql.first_seen = MIN(@timestamp),
134 Esql.last_seen = MAX(@timestamp)
135 by Esql.time_window, Esql.client_ip, Esql.dns_registered_domain
136| where Esql.count_queries >= 25 and Esql.count_distinct_names >= 15
137| eval Esql.unique_name_ratio = TO_DOUBLE(Esql.count_distinct_names) / Esql.count_queries
138| keep Esql.*
139'''
140
141
142[[rule.threat]]
143framework = "MITRE ATT&CK"
144[[rule.threat.technique]]
145id = "T1071"
146name = "Application Layer Protocol"
147reference = "https://attack.mitre.org/techniques/T1071/"
148[[rule.threat.technique.subtechnique]]
149id = "T1071.004"
150name = "DNS"
151reference = "https://attack.mitre.org/techniques/T1071/004/"
152
153
154[[rule.threat.technique]]
155id = "T1572"
156name = "Protocol Tunneling"
157reference = "https://attack.mitre.org/techniques/T1572/"
158
159
160[rule.threat.tactic]
161id = "TA0011"
162name = "Command and Control"
163reference = "https://attack.mitre.org/tactics/TA0011/"
164[[rule.threat]]
165framework = "MITRE ATT&CK"
166[[rule.threat.technique]]
167id = "T1048"
168name = "Exfiltration Over Alternative Protocol"
169reference = "https://attack.mitre.org/techniques/T1048/"
170[[rule.threat.technique.subtechnique]]
171id = "T1048.003"
172name = "Exfiltration Over Unencrypted Non-C2 Protocol"
173reference = "https://attack.mitre.org/techniques/T1048/003/"
174
175
176
177[rule.threat.tactic]
178id = "TA0010"
179name = "Exfiltration"
180reference = "https://attack.mitre.org/tactics/TA0010/"
181
182[rule.investigation_fields]
183field_names = [
184 "Esql.client_ip",
185 "Esql.dns_registered_domain",
186 "Esql.time_window",
187 "Esql.count_queries",
188 "Esql.count_distinct_names",
189 "Esql.unique_name_ratio",
190 "Esql.max_subdomain_length",
191 "Esql.avg_subdomain_length",
192 "Esql.dns_question_type_values",
193 "Esql.destination_ip_values",
194 "Esql.sample_names",
195 "Esql.dataset_values",
196 "Esql.observer_name_values",
197 "Esql.first_seen",
198 "Esql.last_seen",
199]
Triage and analysis
Investigating Potential DNS Tunneling via Long and Unique Subdomains
DNS tunneling encodes data in query labels and often produces many unique, unusually long subdomains under a single apex domain. This rule aggregates network DNS telemetry for that behavioral pattern without relying on threat intelligence feeds or machine learning jobs.
Compare overlapping apex domains against the machine learning DNS Tunneling rule when that job is enabled.
Possible investigation steps
- Review
Esql.dns_registered_domain,Esql.count_distinct_names,Esql.unique_name_ratio,Esql.max_subdomain_length, and sample values inEsql.sample_names. - Inspect
Esql.dns_question_type_values. TXT, NULL, CNAME, or MX bursts increase confidence; A/AAAA-only activity can still be tunneling and should not be dismissed on type alone. - Use
Esql.first_seen,Esql.last_seen,Esql.dataset_values, andEsql.observer_name_valuesto establish the event span and identify the integrations and sensors that contributed to the alert. - Confirm whether
Esql.client_ipis a workstation, server, recursive resolver, forwarder, NAT address, or localhost DNS service. Resolver and localhost sources merge many clients and are a common false-positive pattern. - Review
Esql.destination_ip_valuesto identify the resolver or authoritative destination observed by the sensor. - Pivot on the same client and apex domain in raw DNS events and look for follow-on process, file, or additional C2 activity.
False positive analysis
- CDN, cloud load-balancer, certificate, and software-update services often create long hostnames. Confirm the apex domain reputation and whether the requesting host role normally uses that provider.
- Security or network appliances performing DNS-based reachability or reputation checks can resemble tunneling. Exclude confirmed appliance addresses after validation.
- Do not create a global resolver exception until the originating endpoint is known; a shared
Esql.client_ipcan hide a single infected host behind legitimate bulk lookups.
Response and remediation
- Block the apex domain or forwarding from the affected host at recursive resolvers if malicious activity is confirmed.
- Isolate the source host and inspect for tunneling tools or malware initiating the queries.
- Add temporary blocks for the apex domain while scoping additional hosts querying the same name.
References
Related rules
- Potential DNS Rebinding from Public to Private Address
- Potential Self-Signed TLS Certificate Recently Issued on External Connection
- Splunk Enterprise PostgreSQL Backup-to-Restore Potential RCE Sequence
- Splunk Enterprise PostgreSQL Recovery Endpoint Injection Artifacts
- Potential cPanel WHM CRLF Authentication Bypass (CVE-2026-41940)