DNS C2 Detection API Reference
MITRE ATT&CK Mapping
| Technique |
ID |
Description |
| Application Layer Protocol: DNS |
T1071.004 |
C2 communication over DNS protocol |
| Exfiltration Over Alternative Protocol |
T1048 |
Data exfiltration via DNS tunneling |
| Dynamic Resolution: Domain Generation Algorithms |
T1568.002 |
DGA-based C2 infrastructure |
| Protocol Tunneling |
T1572 |
Tunneling arbitrary traffic through DNS |
| Encrypted Channel |
T1573 |
Encrypted C2 payloads in DNS records |
DNS Record Types Used in C2
| Record Type |
Typical C2 Use |
Max Data Per Query |
| A |
Beacon check-in, small responses (IP-encoded) |
4 bytes (IPv4 address) |
| AAAA |
Beacon check-in, slightly larger responses |
16 bytes (IPv6 address) |
| TXT |
Command delivery, large payload transfer |
~255 bytes per string, multiple strings |
| CNAME |
Data exfiltration in subdomain, response tunneling |
~253 bytes |
| MX |
Data tunneling via preference + exchange fields |
~253 bytes |
| NULL |
Iodine tunnel primary record type |
~65535 bytes |
| SRV |
C2 with port/priority metadata |
~253 bytes |
Shannon Entropy Thresholds
| Entropy Range |
Classification |
Typical Source |
| 0.0 - 2.0 |
Very low |
Single-character or trivial labels |
| 2.0 - 3.0 |
Normal |
Common English-based domain labels |
| 3.0 - 3.5 |
Elevated |
Long or mixed-case labels, some CDNs |
| 3.5 - 4.0 |
Suspicious |
Hex-encoded data, base32 encoding, DGA |
| 4.0 - 4.5 |
High |
DNS tunneling (Iodine, dnscat2, dns2tcp) |
| 4.5+ |
Very high |
Encrypted or base64-encoded payloads |
Known Tunneling Tool Signatures
Iodine
- Encoding: Base32, Base64, Base128, Raw
- Record types: NULL (primary), TXT, CNAME, MX, A
- Subdomain pattern: Long alphanumeric strings (50+ chars)
- Entropy range: 3.8 - 4.2
- Detection: High query volume to single domain, NULL record type queries
dnscat2
- Encoding: Hex-encoded, encrypted
- Record types: TXT, CNAME, MX, A
- Subdomain pattern: Hex strings (16+ chars), optional
dnscat. prefix
- Entropy range: 3.5 - 4.5
- Detection: Consistent query intervals, hex-only subdomain labels
dns2tcp
- Encoding: Base32
- Record types: TXT, KEY
- Subdomain pattern: Base32 strings (20+ chars)
- Entropy range: 3.6 - 4.0
- Detection: KEY record type usage, base32 character set
Cobalt Strike DNS Beacon
- Encoding: Hex-encoded metadata
- Record types: A, AAAA, TXT
- Subdomain pattern: Short hex strings (8-20 chars)
- Entropy range: 3.2 - 4.0
- Detection: Regular beacon intervals (default 60s), A-record check-ins followed by TXT downloads
Sliver DNS C2
- Encoding: Base32/custom
- Record types: A, TXT
- Subdomain pattern: Alphanumeric strings (30+ chars)
- Entropy range: 3.5 - 4.2
- Detection: High subdomain length variance, mixed record types
| Feature |
Description |
DGA Indicator |
| Shannon entropy |
Bits per character of domain label |
> 3.5 |
| Label length |
Character count of domain (excl. TLD) |
> 15 unusual |
| Consonant ratio |
Consonants / total alphabetic chars |
> 0.7 |
| Digit ratio |
Digits / total characters |
> 0.3 |
| Vowel-consonant ratio |
Vowels / consonants |
< 0.3 |
| Bigram frequency score |
Average English bigram match frequency |
< 0.002 |
| Hex character ratio |
Hex chars / total chars |
> 0.8 |
| Max consecutive consonants |
Longest consonant run |
> 4 |
| Unique character ratio |
Unique chars / total chars |
< 0.4 |
| Has dictionary words |
Whether label contains English words |
No = DGA indicator |
Beaconing Detection Parameters
| Parameter |
Typical Threshold |
Description |
| Interval regularity |
Jitter < 10% of mean interval |
Low variance indicates automated beaconing |
| Min queries |
> 50 queries to same domain |
Sufficient data for statistical analysis |
| Time span |
> 1 hour |
Beacon must persist across time |
| Consistent query size |
Std dev < 5 bytes |
Tunnel payloads have consistent sizes |
| Night-time activity |
Queries during 00:00-06:00 |
Unusual for legitimate user browsing |
| Single source |
1-3 source IPs per domain |
C2 typically from compromised host only |
Zeek DNS Log Fields
| Field |
Type |
Forensic Use |
| ts |
time |
Query timestamp |
| uid |
string |
Connection UID |
| id.orig_h |
addr |
Source IP (compromised host) |
| id.resp_h |
addr |
DNS resolver IP |
| query |
string |
Full queried domain name |
| qtype_name |
string |
Query type (A, TXT, NULL, CNAME) |
| rcode_name |
string |
Response code (NOERROR, NXDOMAIN) |
| answers |
vector |
Response records |
| TTLs |
vector |
TTL values for answers |
| rejected |
bool |
Whether query was rejected |
Suricata EVE DNS Fields
| Field |
Type |
Forensic Use |
| timestamp |
string |
Event timestamp (ISO 8601) |
| src_ip |
string |
Source IP |
| dest_ip |
string |
Destination IP (resolver) |
| dns.type |
string |
"query" or "answer" |
| dns.rrname |
string |
Queried domain name |
| dns.rrtype |
string |
Record type |
| dns.rcode |
string |
Response code |
| dns.answers |
array |
Response answer records |
| dns.tx_id |
int |
Transaction ID |
Suricata Rules for DNS C2
Splunk SPL Queries
Python API - Key Functions
References