dnsenum is a Perl-based DNS enumeration tool designed to gather as much information as possible about a domain’s DNS infrastructure in a single automated pass. Written by Filip Waeytens and tehaxor, it combines several DNS reconnaissance techniques — direct record lookups, name server and mail server identification, zone transfer attempts, subdomain brute-forcing, Google scraping for additional hostnames, reverse lookups on discovered IP ranges, and WHOIS queries — into one cohesive workflow. It is one of the most complete “all-in-one” DNS enumeration tools available in Kali Linux, and is frequently used as the first active-recon step against any domain in scope for an assessment.
Key capabilities:
- Retrieve A, AAAA, NS, MX, SOA, and TXT records for the domain
- Attempt a zone transfer (AXFR) against every discovered name server — a critical, high-value misconfiguration if successful, since it dumps the entire DNS zone in one request
- Brute-force subdomains using a supplied wordlist, with optional wildcard detection
- Perform reverse DNS lookups (PTR) across discovered netblocks to find additional in-scope hosts
- Query WHOIS for netblock/ownership information tied to discovered IP ranges
- Output results to a file, and optionally in machine-readable XML
Installation
# Kali Linux (preinstalled)
sudo apt update
sudo apt install dnsenum -y
# Verify
dnsenum --version
which dnsenum
Dependencies (installed automatically via apt): Perl modules Net::DNS, Net::IP, XML::Writer, Net::Whois::IP.
Syntax
dnsenum [options] <domain>
Command-Line Options
| Option | Description |
|---|---|
--dnsserver <server> | Use a specific DNS server for lookups instead of the system default |
--enum | Shortcut equivalent to -p 0 -s 0 -o <domain>.xml combined with a fast/light configuration |
-f, --file <wordlist> | Wordlist file to use for subdomain brute-forcing |
| `-u, –update <a | g |
-r, --recursion | Enable recursive brute-forcing on discovered subdomains |
-d, --delay <seconds> | Delay between successive WHOIS requests (default 3s, to avoid rate-limiting) |
-t, --timeout <seconds> | TCP/UDP query timeout (default 10s) |
--threads <n> | Number of threads to use when brute-forcing subdomains |
-s, --subfile <max> | Save the found subdomains’ IPs into a valid Nmap input file |
-w, --whois | Perform a WHOIS query on the class C netblock of discovered IPs (slower, more noise) |
-p, --pages <n> | Number of Google search result pages to process when scraping for extra names |
--noreverse | Skip the reverse DNS lookup phase |
--private | Show private/internal IP addresses discovered during reverse lookups |
-o, --output <file> | Save results to an XML file |
-v, --verbose | Verbose output |
Basic Usage
dnsenum example.com
Expected initial output header:
dnsenum VERSION:1.2.6
----- example.com -----
Host's addresses:
__________________
example.com. 300 IN A 93.184.216.34
Name Servers:
______________
a.iana-servers.net. 172800 IN A 199.43.135.53
b.iana-servers.net. 172800 IN A 199.43.133.53
Practical Examples
Example 1 — Basic domain enumeration (default settings)
dnsenum example.com
Host's addresses:
example.com. 300 IN A 93.184.216.34
Mail (MX) Servers:
mail.example.com. 300 IN MX 10 mail.example.com.
Name Servers:
a.iana-servers.net. 172800 IN A 199.43.135.53
Example 2 — Attempting a zone transfer against every discovered NS
dnsenum --noreverse zonetransfer.me
Trying Zone Transfer for zonetransfer.me on nsztm1.digi.ninja ...
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja.
zonetransfer.me. 7200 IN A 5.196.105.14
www.zonetransfer.me. 7200 IN A 5.196.105.14
mail.zonetransfer.me. 7200 IN A 74.125.206.26
...
[+] Zone transfer successful!
Example 3 — Subdomain brute-forcing with a wordlist
dnsenum -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt example.com
Brute forcing with /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:
_______________________________________________
www.example.com. 300 IN A 93.184.216.34
mail.example.com. 300 IN A 93.184.216.35
dev.example.com. 300 IN A 93.184.216.40
Example 4 — Enabling recursive brute-forcing on discovered subdomains
dnsenum -f subdomains.txt -r example.com
Brute forcing with subdomains.txt:
www.example.com. 300 IN A 93.184.216.34
recursing into www.example.com ...
admin.www.example.com. 300 IN A 93.184.216.41
Example 5 — Saving Nmap-ready IP list of discovered hosts
dnsenum -f subdomains.txt -s 15 example.com
cat example.com_ips.txt
93.184.216.34
93.184.216.35
93.184.216.40
Example 6 — Output to XML for reporting/parsing
dnsenum -f subdomains.txt -o example_com_results.xml example.com
[*] Results being written to example_com_results.xml
xmllint --format example_com_results.xml | head -20
<x ml version=”1.0″ encoding=”U T F -8″?>
<dnsenum >
< domain name=”example. com” >
<host name=”example. com” address=”93. 184.2 16.34″/>
Example 7 — Using a custom DNS server for all queries
dnsenum --dnsserver 8.8.8.8 example.com
Host's addresses:
example.com. 300 IN A 93.184.216.34
Example 8 — WHOIS lookups on discovered netblocks (slower, more thorough)
dnsenum -w example.com
getting netblock for 93.184.216.34 ...
Netblock: 93.184.216.0/24
Owner: EdgeCast Networks
Example 9 — Reverse DNS lookups showing internal/private IPs
dnsenum --private example.com
Performing reverse lookup on 93.184.216.0/24 ...
34.216.184.93.in-addr.arpa. 300 IN PTR example.com.
Example 10 — Full aggressive scan combining zone transfer, brute force, and Google scraping
dnsenum -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
-r -p 5 -s 20 -o full_results.xml example.com
Trying Zone Transfer for example.com on a.iana-servers.net ...
AXFR record query failed: NOERROR
Brute forcing with subdomains-top1million-5000.txt:
www.example.com. 300 IN A 93.184.216.34
shop.example.com. 300 IN A 93.184.216.55
Google search pages processed: 5
Extra names Found:
support.example.com.
Common Use Cases
- Building a comprehensive DNS footprint (all A/MX/NS/TXT records) of a target domain at the start of an external assessment
- Testing every discovered name server for a vulnerable zone transfer (AXFR) misconfiguration — a critical, high-severity finding when successful
- Brute-forcing and discovering “hidden” subdomains (dev, staging, admin, vpn) not linked from the main site
- Expanding the external attack surface map by resolving discovered subdomains to IP addresses and feeding them into
nmap - Identifying netblock ownership via WHOIS to confirm whether discovered IP ranges are actually in-scope for the engagement
Automation with Bash
#!/bin/bash
# dnsenum_pipeline.sh - Enumerate a domain, extract live IPs, then feed straight into nmap
DOMAIN="$1"
WORDLIST="/usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt"
OUTDIR="./dnsenum_${DOMAIN}"
mkdir -p "$OUTDIR"
echo "[*] Running dnsenum against $DOMAIN"
dnsenum -f "$WORDLIST" -s 50 -o "$OUTDIR/${DOMAIN}.xml" "$DOMAIN" | tee "$OUTDIR/${DOMAIN}.txt"
if [ -f "${DOMAIN}_ips.txt" ]; then
mv "${DOMAIN}_ips.txt" "$OUTDIR/"
echo "[*] Feeding discovered IPs into nmap..."
nmap -sC -sV -iL "$OUTDIR/${DOMAIN}_ips.txt" -oA "$OUTDIR/nmap_scan"
fi
echo "[+] Full DNS + port scan pipeline complete. Results in $OUTDIR"
Tips and Best Practices
- Always attempt zone transfer testing first (it’s fast, low-noise, and a successful AXFR gives you the entire zone instantly, making brute-forcing unnecessary).
- Use a tiered wordlist strategy: a small, fast list (top 1,000–5,000) for initial recon, then a much larger list (SecLists’ full subdomain lists) only against domains that appear to have a large/complex DNS footprint.
- Combine
-r(recursion) cautiously — it can cause an explosion in query volume and runtime on domains with many wildcard or auto-generated subdomains. - Cross-reference
dnsenumoutput with passive tools (e.g.,crt.shcertificate transparency logs,Amass,Subfinder) since brute-forcing alone will never find every subdomain. - Always double-check any discovered IP ranges via WHOIS (
-w) before scanning them further — third-party-hosted subdomains (CDNs, SaaS platforms) are frequently out of scope for an assessment.
FAQ
How does dnsenum compare to DNSRecon? Both cover similar ground, but dnsenum’s multithreading gives it an edge in raw brute-force speed, while DNSRecon offers a broader set of specialized scan types (like DNSSEC zone walking) in a more modern, actively maintained codebase.
Is dnsenum still maintained? It’s a mature, stable tool; updates are less frequent than newer Python-based alternatives, but its core functionality remains reliable.
Does dnsenum require root privileges? No, standard DNS and WHOIS queries don’t need elevated permissions.
Can dnsenum find subdomains not in my wordlist? Yes, partially — its Google scraping feature can occasionally surface subdomains outside your wordlist, though this method is inconsistent and shouldn’t be solely relied upon.
Troubleshooting
| Problem | Likely Cause | Solution |
|---|---|---|
Can't connect to WHOIS server | Network/firewall blocking outbound WHOIS (TCP/43) | Skip -w, or run WHOIS lookups manually via a proxy/allowed egress path |
Zone transfer always fails with REFUSED/NOERROR | Zone transfers correctly restricted to authorized secondary servers (expected, secure config) | Note as a negative (good) finding; proceed to brute-forcing |
| Brute-force phase extremely slow | Large wordlist with default single-threaded-like throughput | Increase --threads, or use a smaller curated wordlist |
| Many false-positive subdomains resolving to the same IP | Wildcard DNS record configured on the domain | Manually verify a clearly bogus name (e.g., doesnotexist12345.example.com) resolves the same way; discount wildcard matches accordingly |
Google scraping phase (-p) returns nothing or errors | Google is rate-limiting/blocking automated queries from your IP | Reduce -p value, add delay, or skip Google scraping and rely on brute force + passive sources instead |
References
- Kali Linux tool page: https://www.kali.org/tools/dnsenum/
- Source repository: https://github.com/fwaeytens/dnsenum
- DNS zone transfer (AXFR) background, RFC 5936: https://datatracker.ietf.org/doc/html/rfc5936
- SecLists DNS wordlists: https://github.com/danielmiessler/SecLists/tree/master/Discovery/DNS