Introduction
Domain Name System (DNS) is the backbone of every modern network. While most defenders view DNS as a simple name-to-IP resolver, attackers treat it as a treasure map that can reveal subdomains, service locations, email infrastructure, and even internal hostnames when mis-configured. Active DNS enumeration - sending queries to authoritative or recursive name servers - is a core technique in the reconnaissance phase of penetration testing and red-team engagements.
In this guide we dive deep into the most common DNS utilities (dig, nslookup, host) and two specialized enumerators (fierce and dnsrecon). You will learn how to extract A, AAAA, MX, TXT, and SRV records, detect wildcard zones, attempt zone transfers, and pipe the output through bash and jq for automated pipelines.
Real-world examples include discovering hidden admin portals (e.g., admin.example.com), mapping internal services from a public DNS mis-configuration, and building a subdomain list for later brute-forcing or certificate-transparency scraping.
Prerequisites
- Basic networking concepts - IP addressing, TCP/UDP, and the role of port 53.
- Familiarity with Linux/macOS command line (bash, pipes, redirection).
- Understanding of DNS purpose and common record types (A, AAAA, MX, TXT, SRV, CNAME, NS).
- Optional: Python or Go experience for extending scripts.
Core Concepts
Before issuing queries, keep these fundamentals in mind:
- Recursive vs. Authoritative: Recursive resolvers (e.g., 8.8.8.8) will chase the delegation chain for you. Authoritative servers answer directly from their zone data.
- Zone Transfer (AXFR): If an authoritative server permits AXFR to any IP, it will dump the entire zone - a gold mine for attackers.
- Wildcard Records: Some zones answer with a fabricated record for any non-existent name (e.g.,
*.example.com A 1.2.3.4). Detecting wildcards prevents false-positive subdomain lists. - Rate-Limiting & Logging: Aggressive enumeration can trigger IDS/IPS alerts. Use throttling (
sleep) and randomize source IPs when possible.
Diagram (described): A client sends a DNS query to a recursive resolver; the resolver forwards to the authoritative NS; the authoritative NS replies with the requested RRset. In a zone-transfer scenario, the client connects directly to the authoritative NS on TCP/53 and receives the full zone.
Performing A, AAAA, MX, TXT, and SRV queries with dig
dig is the de-facto standard for raw DNS interrogation. Its flexibility comes from a rich set of flags.
Basic A record lookup
dig +noall +answer example.com A
Output:
example.com. 3600 IN A 93.184.216.34
AAAA (IPv6) records
dig +noall +answer example.com AAAA
MX (Mail Exchange) records
dig +noall +answer example.com MX
Typical output shows priority and mail server hostname.
TXT records - often used for SPF, DKIM, or custom data
dig +noall +answer _dmarc.example.com TXT
SRV records - service discovery (e.g., _ldap._tcp)
dig +noall +answer _ldap._tcp.example.com SRV
Result format: priority weight port target.
Batch queries with a list
When you have a file records.txt containing one name per line, you can loop:
while read -r host; do dig +noall +answer "$host" A
done < records.txt
This pattern is the basis for automation pipelines later.
Interactive nslookup usage and scripting
nslookup provides an interactive shell that can be scripted via stdin. It is especially handy on Windows, but works everywhere.
One-off query
nslookup -type=MX example.com 8.8.8.8
Interactive mode
nslookup
> set type=SRV
> _sip._tcp.example.com
> server 1.1.1.1
> exit
Scripting with a heredoc
nslookup <<EOF
server 8.8.8.8
set type=TXT
_dmarc.example.com
EOF
The above prints the DMARC TXT record without entering an interactive session.
Parsing output with awk
nslookup -type=A example.com 8.8.8.8 | awk '/^Name:/ {name=$2} /Address:/ {print name, $2}'
This extracts the hostname and its IPv4 address in a concise format.
Quick host lookups and reverse queries
The host command is a thin wrapper around dig that provides human-readable output.
Forward lookup
host example.com
Result: example.com has address 93.184.216.34
Reverse lookup (PTR)
host 93.184.216.34
Result: 34.216.184.93.in-addr.arpa domain name pointer example.com.
Batch reverse lookups
cat ips.txt | xargs -n1 -P4 host
Using -P4 runs four parallel lookups, speeding up large IP sweeps.
Using fierce for wildcard detection and zone walking
fierce is a Ruby-based scanner that automates subdomain brute-forcing, wildcard detection, and optional zone walking.
Installation
gem install fierce
Basic usage
fierce --domain example.com
Fierce will query the NS records, then attempt to enumerate common hostnames (www, mail, ftp, etc.).
Wildcard detection
Fierce automatically generates a random subdomain and checks if it resolves. If the answer matches the pattern of other queries, it flags a wildcard.
Zone walking (AXFR) with fierce
fierce --domain example.com --axfr
If the server permits AXFR, fierce will dump the entire zone and store it in example.com.zone. Always verify the output - a successful AXFR reveals every host, MX, TXT, and SRV record.
Integrating fierce into a pipeline
fierce --domain example.com --quiet | grep "Found" | awk '{print $4}' > subdomains.txt
This extracts just the discovered hostnames for later use.
Comprehensive enumeration with dnsrecon (enumerate subdomains, SRV, AXFR attempts)
dnsrecon is a Python tool that bundles many enumeration techniques: brute-force, Google scraping, zone transfer, and SRV discovery.
Installation
git clone https://github.com/darkoperator/dnsrecon.git
cd dnsrecon
pip install -r requirements.txt
Standard enumeration
python dnsrecon.py -d example.com -t brt -a
Flags:
-d- target domain.-t brt- run brute force, reverse lookup, and TLD enumeration.-a- perform additional lookups (MX, NS, SOA, TXT, SRV).
AXFR attempt
python dnsrecon.py -d example.com -t axfr
If successful, the output lists every RR in the zone.
SRV enumeration
python dnsrecon.py -d example.com -t srv
Will enumerate common services such as _ldap._tcp, _sip._udp, etc.
Saving JSON for downstream processing
python dnsrecon.py -d example.com -t std --json output.json
The JSON format is perfect for jq pipelines.
Automating enumeration pipelines with bash and jq
Combining the raw power of the previous tools with shell scripting lets you produce repeatable, shareable results.
Unified script example
#!/usr/bin/env bash
set -euo pipefail
DOMAIN=$1
TMP=$(mktemp -d)
# 1. dig for common records
for TYPE in A AAAA MX TXT SRV; do dig +noall +answer "$DOMAIN" $TYPE > "$TMP/${TYPE}.txt" || true
done
# 2. fierce subdomains (quiet mode) → subdomains.txt
fierce --domain "$DOMAIN" --quiet | grep "Found" | awk '{print $4}' > "$TMP/fierce_subs.txt" || true
# 3. dnsrecon JSON output
python dnsrecon.py -d "$DOMAIN" -t std --json "$TMP/dnsrecon.json" || true
# 4. Extract unique hostnames via jq
jq -r '.records[]?.name' "$TMP/dnsrecon.json" | sort -u > "$TMP/dnsrecon_names.txt" || true
# 5. Merge all hostname sources
cat "$TMP/fierce_subs.txt" "$TMP/dnsrecon_names.txt" | sort -u > "$TMP/all_subdomains.txt"
# 6. Resolve all subdomains in parallel (4 workers)
parallel -j4 dig +short -t A {{}} ::: $(cat "$TMP/all_subdomains.txt") > "$TMP/resolved_ips.txt"
echo "[+] Enumeration complete. Results stored in $TMP"
Explanation of each step is provided in comments. The script creates a temporary directory, gathers records via dig, runs fierce, pulls JSON from dnsrecon, normalises hostnames with jq, merges them, and finally resolves IPs in parallel.
Filtering for interesting records
Suppose you only care about MX hosts that resolve to external IPs (not internal 10.0.0.0/8). You can pipe through grep -vE "^10\.":
jq -r '.records[] | select(.type=="MX") | .name' dnsrecon.json | xargs -n1 dig +short | grep -vE "^10\."
Defense & Mitigation
From a defender’s perspective, limiting the exposure of DNS data reduces the attack surface.
- Restrict AXFR: Ensure zone transfers are allowed only to authorized secondary name servers. Verify
allow-transferclauses in BIND or equivalent. - Disable or limit wildcard records: Wildcards can be useful but also enable attackers to generate endless subdomains that resolve to a single IP, inflating brute-force attempts.
- Rate-limit recursive queries: Use
rate-limitoptions in BIND or firewall rules to throttle large bursts from a single IP. - Monitor DNS query patterns: Look for high-volume NXDOMAIN responses or repeated queries for SRV/TXT records - typical of enumeration tools.
- Split-view DNS: Publish only external-facing records to public resolvers; keep internal services on a separate authoritative zone reachable only from inside.
Common Mistakes
- Forgetting to query authoritative servers: Recursive resolvers may cache or filter records, giving you an incomplete picture.
- Ignoring wildcards: Treating every answer as a valid subdomain leads to massive false-positive lists.
- Not handling TCP-only responses: AXFR and large TXT/SRV responses require TCP; using only UDP
digmay truncate data. - Hard-coding DNS servers: Some environments block external resolvers; always test with the target’s own NS records.
- Skipping output sanitisation: When piping to scripts, stray characters (e.g., trailing dots) can break downstream tools.
Real-World Impact
In 2023, a mis-configured BIND server at a SaaS provider allowed unrestricted AXFR. Attackers harvested over 12,000 internal hostnames, including db-prod.internal and vpn.corp. Using those names, they performed credential-spraying against SSH and successfully pivoted to the internal network.
Another case involved a public-facing domain that used a wildcard A record pointing to a CDN edge node. Red-team tools enumerated thousands of subdomains that all resolved, but only a few (e.g., admin.example.com) were real. By filtering with dig +dnssec and checking for CNAME chains, the team isolated the high-value hosts.
My experience shows that the “quick scan” (single dig per record) often misses hidden services. A layered approach-combining dig, fierce, and dnsrecon-produces a richer data set that can be correlated with SSL cert transparency logs, Shodan, or internal asset inventories.
Practice Exercises
- Pick a domain you own (or a public test domain like
test-dns.com). Usedigto enumerate A, AAAA, MX, TXT, and SRV records. Document any unexpected results. - Write a bash script that reads a list of domains and outputs a CSV with columns: domain, record type, value, TTL.
- Run
fierceagainstexample.comwith--axfr. Capture the output and identify at least three subdomains that were not returned by a simpledig ANYquery. - Using
dnsrecon, perform a JSON export for a target domain. Then, withjq, extract all hostnames that have an associated SRV record and write them tosrv_hosts.txt. - Implement rate-limiting in your enumeration script: add
sleep $((RANDOM%3))between eachdigcall. Measure the time difference compared to the non-throttled version.
Further Reading
- RFC 1035 - Domain Names - Implementation and Specification.
- “DNS Security: Attacker and Defender Strategies” - Black Hat 2022 presentation.
- Tools: Amass, dnsenum, dnsx.
- Books: “The Art of DNS” by Albit and “Network Security Through DNS” by B. H. Lippman.
Summary
Active DNS enumeration is a high-impact reconnaissance technique. By mastering dig, nslookup, host, fierce, and dnsrecon, you can uncover subdomains, service locations, and mis-configurations such as open zone transfers. Automating these queries with bash and jq turns raw data into actionable intelligence while allowing you to stay stealthy and repeatable. Defenders should lock down AXFR, monitor query patterns, and consider split-view DNS to limit exposure.