hunting-for-dns-tunneling-with-zeek skill (Anthropic-Cybersecurity-Skills)

From Public Agent Wiki

What it does. Detects DNS tunneling and covert-channel data exfiltration by analyzing Part of mukul975/Anthropic-Cybersecurity-Skills (817 security skills) (mukul975/Anthropic-Cybersecurity-Skills).

Upstream mukul975/Anthropic-Cybersecurity-Skills
Skill file skills/hunting-for-dns-tunneling-with-zeek/SKILL.md
License Apache-2.0 (skill folder LICENSE)
Author mukul975
Fetched 2026-09-10

Install

  • npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill hunting-for-dns-tunneling-with-zeek, or copy the skill folder into ~/.claude/skills/hunting-for-dns-tunneling-with-zeek/.
  • Raw file: curl -sL https://raw.githubusercontent.com/mukul975/Anthropic-Cybersecurity-Skills/HEAD/skills/hunting-for-dns-tunneling-with-zeek/SKILL.md

SKILL.md (verbatim)

name: hunting-for-dns-tunneling-with-zeek
description: Detects DNS tunneling and covert-channel data exfiltration by analyzing
  Zeek dns.log for high-entropy subdomain queries, excessive query volume, abnormally
  long query lengths, and unusual DNS record types (TXT/NULL/CNAME). Use when hunting
  for DNS-based data exfiltration or C2 covert channels in network traffic, or when
  triaging suspicious DNS query volume/patterns surfaced by Zeek logs.
domain: cybersecurity
subdomain: threat-hunting
tags:
- threat-hunting
- dns-tunneling
- zeek
- data-exfiltration
- covert-channel
- mitre-t1071-004
- network-monitoring
version: '1.0'
author: mahipal
license: Apache-2.0
d3fend_techniques:
- Application Protocol Command Analysis
- Network Isolation
- Network Traffic Analysis
- Client-server Payload Profiling
- DNS Traffic Analysis
nist_csf:
- DE.CM-01
- DE.AE-02
- DE.AE-07
- ID.RA-05
mitre_attack:
- T1046
- T1057
- T1082
- T1083
- T1048

Hunting for DNS Tunneling with Zeek

When to Use

  • When hunting for data exfiltration over DNS covert channels
  • After threat intelligence indicates DNS-based C2 frameworks targeting your industry
  • When dns.log shows unusually high query volumes to specific domains
  • During investigation of suspected data theft where no HTTP/S exfiltration is found
  • When monitoring for tools like iodine, dnscat2, DNSExfiltrator, or DNS-over-HTTPS tunneling

Prerequisites

  • Zeek deployed on network tap or SPAN port capturing DNS traffic
  • Zeek dns.log with full query and response fields
  • SIEM platform for dns.log analysis (Splunk, Elastic)
  • RITA (Real Intelligence Threat Analytics) for automated DNS analysis
  • Passive DNS data for historical domain resolution context

Workflow

  1. Analyze Query Length Distribution: DNS tunneling encodes data in subdomain labels, producing queries significantly longer than normal. Normal DNS queries average 20-30 characters; tunneling queries often exceed 50+ characters. Calculate mean and standard deviation of query lengths per domain.
  2. Calculate Subdomain Entropy: Tunneling encodes data using Base32/Base64, producing high-entropy subdomain strings. Calculate Shannon entropy of subdomain labels -- values above 3.5 bits/character strongly suggest encoded data.
  3. Count Unique Subdomains Per Domain: Legitimate domains have relatively few unique subdomains. DNS tunneling generates hundreds or thousands of unique subdomains under a single parent domain.
  4. Monitor DNS Record Type Distribution: TXT, NULL, CNAME, and MX records can carry more data than A records. Excessive TXT queries to a single domain indicate data transfer via DNS.
  5. Detect High Query Volume: Flag domains receiving more than 100 queries per hour from a single source, especially when combined with high subdomain uniqueness.
  6. Analyze Query Timing: DNS tunneling tools produce regular query patterns (beaconing) or burst patterns (data transfer). Apply frequency analysis to DNS query timestamps.
  7. Cross-Reference with conn.log: Correlate DNS queries with connection metadata to identify the process or endpoint generating suspicious queries.
  8. Validate with Domain Intelligence: Check suspicious domains against WHOIS data, certificate transparency, and threat intelligence feeds.

Key Concepts

Concept Description
T1071.004 Application Layer Protocol: DNS
T1048.003 Exfiltration Over Alternative Protocol: DNS
T1572 Protocol Tunneling
Shannon Entropy Measure of randomness in subdomain strings
Zeek dns.log DNS query/response metadata
RITA Automated DNS tunneling detection from Zeek logs
iodine IPv4-over-DNS tunneling tool
dnscat2 DNS-based command-and-control tool
DNSExfiltrator Data exfiltration tool using DNS requests

Detection Queries

Zeek Script -- DNS Tunnel Detection

@load base/protocols/dns
module DNSTunnel;

export {
    redef enum Notice::Type += { DNSTunnel::Long_DNS_Query };
    const query_length_threshold = 50 &redef;
    const query_count_threshold = 100 &redef;
}

event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) {
    if ( |query| > query_length_threshold ) {
        NOTICE([$note=DNSTunnel::Long_DNS_Query,
                $msg=fmt("Long DNS query detected: %s (%d chars)", query, |query|),
                $conn=c]);
    }
}

Splunk -- DNS Tunneling Indicators from Zeek

index=zeek sourcetype=bro_dns
| rex field=query "(?<subdomain>[^.]+)\.(?<basedomain>[^.]+\.[^.]+)$"
| stats count dc(subdomain) as unique_subs avg(len(query)) as avg_len max(len(query)) as max_len by src basedomain
| where count > 100 AND (unique_subs > 50 OR avg_len > 40)
| sort -unique_subs

Splunk -- High Entropy Subdomain Detection

index=zeek sourcetype=bro_dns
| rex field=query "^(?<subdomain>[^.]+)"
| where len(subdomain) > 20
| eval char_count=len(subdomain)
| stats count dc(query) as unique_queries avg(char_count) as avg_sub_len by src query_type_name basedomain
| where unique_queries > 30 AND avg_sub_len > 25
| sort -unique_queries

RITA Analysis

rita import /path/to/zeek/logs dataset_name
rita show-dns-fqdn-ips-long dataset_name
rita show-exploded-dns dataset_name
rita show-dns-tunneling dataset_name --csv > dns_tunnel_results.csv

Common Scenarios

  1. dnscat2 C2: Encodes command-and-control traffic in DNS CNAME/TXT queries with Base64-encoded subdomain labels. Produces high query volumes with long, high-entropy subdomains.
  2. iodine IPv4 Tunnel: Creates a virtual network interface tunneling all IP traffic through DNS. Generates massive DNS query volumes with NULL record types.
  3. Data Exfiltration via DNS: Sensitive data encoded in subdomain labels (e.g., aGVsbG8gd29ybGQ.exfil.attacker.com), sent as A or TXT queries. Each query carries ~63 bytes of data.
  4. DNS-over-HTTPS Tunneling: Bypasses traditional DNS monitoring by sending DNS queries over HTTPS to public resolvers (8.8.8.8, 1.1.1.1), requiring TLS inspection for detection.
  5. Cobalt Strike DNS Beacon: Uses DNS A/TXT records for C2 communication with configurable subdomain encoding schemes.

Output Format

Hunt ID: TH-DNSTUNNEL-[DATE]-[SEQ]
Source IP: [Internal IP]
Source Host: [Hostname]
Target Domain: [Base domain]
Query Count: [Total queries in window]
Unique Subdomains: [Count]
Avg Query Length: [Characters]
Max Query Length: [Characters]
Subdomain Entropy: [Bits per character]
Primary Record Type: [A/TXT/CNAME/NULL]
Data Volume Estimate: [Bytes exfiltrated]
Risk Level: [Critical/High/Medium/Low]

Other files in this skill

assets/template.md (verbatim)

DNS Tunneling Hunt Template

Hunt Metadata

Field Value
Hunt ID TH-DNSTUNNEL-YYYY-MM-DD-NNN
Analyst
Date
Status [ ] In Progress / [ ] Complete

Hypothesis

Adversaries are using DNS tunneling to establish covert C2 channels or exfiltrate data by encoding information in DNS query subdomain labels.

DNS Tunneling Findings

# Source IP Host Domain Queries Unique Subs Avg Length Entropy Record Types Risk
1

Data Exfiltration Estimate

Domain Total Queries Avg Subdomain Size Estimated Data Volume Assessment

Recommendations

  1. Sinkhole: [DNS domains to sinkhole]
  2. Block: [Domains at DNS resolver and firewall]
  3. Isolate: [Source endpoints for investigation]
  4. Monitor: [Deploy DNS tunneling detection rules]

references/api-reference.md (verbatim)

API Reference: DNS Tunneling Detection with Zeek

Detection Heuristics

Indicator Threshold Score
Shannon entropy > 3.5 +40
Avg subdomain length > 30 chars +30
Tunnel query type ratio > 50% TXT/NULL/CNAME +20
High query volume > 500 queries +10

Zeek dns.log Fields

Index Field Description
0 ts Timestamp
2 id.orig_h Source IP
4 id.resp_h DNS server
9 query Query name
13 qtype_name Query type (A, TXT, etc.)
21 answers Response answers

DNS Tunneling Tools (for detection reference)

Tool Encoding Query Type
iodine Base128 NULL, TXT
dnscat2 Hex/Base64 CNAME, TXT, MX
dns2tcp Base64 TXT
Cobalt Strike Hex A, AAAA, TXT

Shannon Entropy Reference

Data Type Entropy
Normal hostnames 2.0 - 3.0
Base32 encoded 3.5 - 4.0
Base64 encoded 4.0 - 5.0
Hex encoded 3.5 - 4.0

Python Libraries

Library Use
math Entropy calculation
csv TSV log parsing
collections.defaultdict Domain aggregation
dpkt PCAP DNS parsing
dnslib DNS packet construction

Zeek Scripts for DNS Analysis

@load base/protocols/dns
redef DNS::max_pending_queries = 1000;
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count) {
    if (|query| > 50) print fmt("Long query: %s", query);
}

references/standards.md (verbatim)

Standards and References - DNS Tunneling Detection

MITRE ATT&CK References

Technique Name Description
T1071.004 Application Layer Protocol: DNS DNS-based C2 communication
T1048.003 Exfiltration Over Unencrypted Non-C2 Protocol Data theft via DNS
T1572 Protocol Tunneling IP-over-DNS tunneling
T1568.002 Domain Generation Algorithms Algorithmically generated domains
T1132.001 Data Encoding: Standard Encoding Base32/64 in DNS queries

DNS Tunneling Detection Thresholds

Indicator Threshold Rationale
Query length > 50 characters Normal queries average 20-30 chars
Subdomain label length > 30 characters Max label is 63; tunneling uses near-max
Subdomain entropy > 3.5 bits/char Base32/64 encoding produces high entropy
Unique subdomains per domain > 100/hour Legitimate domains have few unique subs
Query volume to single domain > 100/hour Sustained high volume indicates tunneling
TXT record query ratio > 50% to domain TXT queries carry more data
NULL record queries Any volume Rarely used legitimately

DNS Tunneling Tools

Tool Protocol Record Types Data Rate Detection Difficulty
iodine IP-over-DNS NULL, TXT, CNAME, A ~100 Kbps Medium
dnscat2 C2 over DNS TXT, CNAME, MX ~10 Kbps Medium
DNSExfiltrator Exfil over DNS TXT, A ~5 Kbps Medium-Hard
Cobalt Strike DNS C2 A, TXT Variable Hard
dns2tcp TCP-over-DNS TXT, KEY ~50 Kbps Medium
Heyoka DNS exfiltration All types Variable Hard

Zeek Log Fields for DNS Analysis

Field Description Tunnel Relevance
query Full DNS query name Length and entropy analysis
qtype_name Query record type TXT/NULL/CNAME anomalies
answers Response content Response size analysis
rcode_name Response code NXDOMAIN patterns
id.orig_h Source IP Source identification
AA Authoritative answer Non-authoritative responses
rejected Query rejected Filtering effectiveness

references/workflows.md (verbatim)

Detailed Hunting Workflow - DNS Tunneling with Zeek

Phase 1: Query Length and Volume Analysis

Step 1.1 - Identify Domains with Long Queries

index=zeek sourcetype=bro_dns
| eval query_len=len(query)
| where query_len > 50
| rex field=query "\.(?<basedomain>[^.]+\.[^.]+)$"
| stats count avg(query_len) as avg_len max(query_len) as max_len dc(query) as unique_queries by id.orig_h basedomain
| where count > 50
| sort -avg_len

Step 1.2 - High Volume DNS to Single Domain

index=zeek sourcetype=bro_dns
| rex field=query "\.(?<basedomain>[^.]+\.[^.]+)$"
| bin _time span=1h
| stats count by id.orig_h basedomain _time
| where count > 100
| sort -count

Phase 2: Entropy Analysis

Step 2.1 - Shannon Entropy Calculation

import math
from collections import Counter

def shannon_entropy(text):
    if not text:
        return 0.0
    counts = Counter(text)
    length = len(text)
    return -sum((c/length) * math.log2(c/length) for c in counts.values())

# Flag subdomains with entropy > 3.5

Step 2.2 - Splunk Entropy Approximation

index=zeek sourcetype=bro_dns
| rex field=query "^(?<subdomain>[^.]+)"
| where len(subdomain) > 20
| eval has_numbers=if(match(subdomain, "[0-9]"), 1, 0)
| eval has_mixed_case=if(match(subdomain, "[A-Z]") AND match(subdomain, "[a-z]"), 1, 0)
| stats count avg(len(subdomain)) as avg_sub_len sum(has_numbers) as numeric_count by id.orig_h basedomain
| eval numeric_ratio=numeric_count/count
| where avg_sub_len > 25 AND numeric_ratio > 0.3

Phase 3: Record Type Analysis

Step 3.1 - Unusual Record Types

index=zeek sourcetype=bro_dns
| where qtype_name IN ("TXT", "NULL", "CNAME", "MX", "KEY", "SRV")
| rex field=query "\.(?<basedomain>[^.]+\.[^.]+)$"
| stats count dc(query) as unique by id.orig_h basedomain qtype_name
| where count > 50
| sort -count

Phase 4: RITA Automated Analysis

# Full Zeek log import and DNS analysis
rita import /opt/zeek/logs/current dns_hunt
rita show-dns-tunneling dns_hunt
rita show-exploded-dns dns_hunt | sort -k2 -n -r | head -20

Phase 5: Correlation and Response

Step 5.1 - Map DNS Source to Endpoint

Correlate dns.log source IPs with DHCP logs or endpoint inventory to identify affected hosts and processes.

Step 5.2 - Response Actions

  1. DNS sinkhole the identified tunneling domain
  2. Block at DNS resolver and firewall
  3. Isolate source endpoint
  4. Capture memory and disk forensics
  5. Assess scope of data exfiltration

Back to mukul975/Anthropic-Cybersecurity-Skills (817 security skills) or Agent skills.