Back to Articles

ShuffleDNS: Why Smart Wildcard Detection Matters More Than Raw DNS Speed

[ View on GitHub ]

ShuffleDNS: Why Smart Wildcard Detection Matters More Than Raw DNS Speed

Hook

Most subdomain enumeration tools will confidently report thousands of 'discoveries' that are actually wildcard DNS tricks. ShuffleDNS solves this by watching patterns, not just resolving names.

Context

Subdomain enumeration is a critical first step in security reconnaissance, bug bounty hunting, and asset discovery. The challenge isn't just finding subdomains—it's finding real ones. DNS wildcards create a massive false positive problem: a single wildcard record like *.example.com can make your enumeration tool report millions of 'valid' subdomains that all resolve to the same IP address. Early tools like fierce and dnsrecon were accurate but slow, processing queries sequentially. Then massdns arrived and changed the game with asynchronous C-based resolution capable of millions of queries per second. But speed created a new problem: at scale, wildcard filtering became the bottleneck.

Most reconnaissance workflows now chain multiple tools—passive discovery via certificate transparency with subfinder or amass, then active bruteforcing with wordlists. But when you're validating 100,000+ subdomain candidates against a target, you need both speed and intelligence. Run massdns directly and you'll drown in wildcards. Add naive wildcard filtering and you'll wait hours for validation checks. ShuffleDNS emerged from ProjectDiscovery's reconnaissance toolkit to solve this specific problem: wrap massdns's performance in Go, add threshold-based wildcard detection that only validates when patterns emerge, and create a pipeline-friendly tool that plays nicely with other utilities.

Technical Insight

Wildcard Analysis

ShuffleDNS Core

bruteforce

resolve

filter

candidate list

DNS responses

track IPs

threshold exceeded

confirmed wildcards

non-wildcard only

Input Source

Wordlist/Stdin/Raw File

Operation Mode

Subdomain Generator

Cartesian Product

Wildcard Detector

IP Threshold Tracker

MassDNS Engine

C-based Resolver

IP→Count Map

Threshold: 10

Random Subdomain

Validation

Filtered Results

Valid Subdomains

System architecture — auto-generated

The architectural genius of shuffledns lies in its lazy wildcard detection. Unlike tools that check for wildcards upfront by querying random subdomains, shuffledns monitors resolution patterns during enumeration and only triggers validation when suspicious behavior emerges. It maintains an in-memory map tracking how many subdomains resolve to each IP address. When this count exceeds a threshold (default: 10), it suspects a wildcard and performs multi-level validation by generating random subdomains and checking if they resolve to the same IP.

Here's a typical bruteforce workflow that demonstrates its pipeline integration:

# Generate subdomain candidates from wordlist
shuffledns -d example.com -w wordlist.txt -r resolvers.txt -o valid.txt

# Chain with subfinder for passive + active enumeration
subfinder -d example.com -silent | shuffledns -d example.com -r resolvers.txt -mode resolve -o confirmed.txt

# Filter existing massdns output
massdns -r resolvers.txt -t A -o S -w raw.txt candidates.txt
shuffledns -d example.com -mode filter -i raw.txt -o filtered.txt

The three operation modes reveal thoughtful design. In bruteforce mode, shuffledns generates the full cartesian product of wordlist terms and the target domain, feeds them to massdns, then filters results. The resolve mode skips generation and directly validates a provided subdomain list—perfect for confirming discoveries from passive sources. The filter mode processes raw massdns output, adding wildcard intelligence to data you've already collected.

The wildcard detection algorithm operates in tiers. First-level detection uses random string generation—if randomstring123.example.com resolves, the domain likely has a wildcard. Second-level detection generates multiple random subdomains and compares their resolved IPs. If they cluster on the same addresses, it establishes a wildcard IP set. During result processing, any subdomain resolving to these wildcard IPs gets filtered out. This approach is computationally cheaper than validating every result individually.

Resolver management is another critical feature. The tool accepts a list of DNS resolvers and distributes queries across them with configurable rate limiting:

# Use custom resolvers with rate limiting
shuffledns -d example.com -w wordlist.txt -r resolvers.txt -rl 1000 -o output.txt

# Strict wildcard filtering for higher accuracy
shuffledns -d example.com -w wordlist.txt -r resolvers.txt -sw -o output.txt

The -rl flag controls queries per second, preventing resolver throttling or blacklisting. The -sw flag (strict wildcard) enables additional validation passes, trading speed for fewer false positives. Internally, shuffledns spawns massdns as a child process, streaming results via stdout and parsing them in real-time. This approach keeps memory usage low even when processing millions of candidates—results are filtered and written incrementally rather than buffered entirely in RAM.

The Go implementation provides better error handling and retry logic than raw massdns. When queries fail, shuffledns can automatically retry with different resolvers or adjust rate limits. It also normalizes massdns output into clean formats (JSON, plain text, or raw) without requiring manual parsing of massdns's native output format.

One underappreciated feature is the -nw flag (no wildcard filtering), which disables all wildcard detection. This seems counterintuitive until you encounter CDN scenarios where legitimate subdomains share IPs with wildcards, or when you're specifically hunting for wildcard behavior as part of your reconnaissance. The tool gives you control over the tradeoff between false positives and false negatives.

Gotcha

The massdns dependency is shuffledns's biggest operational friction. You can't just go install and run—you need to compile massdns separately, ensure it's in your PATH, and manage version compatibility. Different massdns versions output different formats, and shuffledns parsing can break across updates. In containerized environments, this means maintaining multi-stage builds and tracking two separate projects. The official Docker image helps, but adds its own complexity for users who want to customize builds.

Wildcard detection fundamentally requires the -d domain flag. If you're processing a heterogeneous list of subdomains across multiple root domains, shuffledns can't build the wildcard IP maps correctly. You'd need to split your input by domain and run separate invocations, or accept unfiltered results. This limitation hits users who integrate shuffledns into broader asset discovery pipelines where subdomain lists naturally span many domains. The tool also can't detect semantic wildcards—cases where a wildcard record returns different IPs based on geographic location or time of day. If *.example.com round-robins across 50 IPs, the threshold-based detection might miss it entirely, reporting all variants as valid.

Verdict

Use shuffledns if you're running large-scale subdomain enumeration (10,000+ candidates) where wildcard domains are common, especially in bug bounty or red team scenarios where false positives waste time on manual verification. It excels in automated pipelines where you're chaining passive discovery tools with active validation and need reliable filtering without babysitting the process. The performance justifies the massdns dependency when you're routinely processing wordlists with millions of permutations. Skip it if you're working on ad-hoc queries with small wordlists—dnsx gives you 90% of the value with zero external dependencies. Also skip if your target list spans many root domains without clear domain grouping, since wildcard detection requires per-domain context. For one-off investigations or environments where installing compiled binaries is restricted, the operational overhead outweighs the benefits.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/cybersecurity/projectdiscovery-shuffledns.svg)](https://starlog.is/api/badge-click/cybersecurity/projectdiscovery-shuffledns)