dnsenum: Multithreaded tool for DNS enumeration

dnsenum Multithreaded tool for DNS enumeration

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:

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

OptionDescription
--dnsserver <server>Use a specific DNS server for lookups instead of the system default
--enumShortcut 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 <ag
-r, --recursionEnable 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, --whoisPerform 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
--noreverseSkip the reverse DNS lookup phase
--privateShow private/internal IP addresses discovered during reverse lookups
-o, --output <file>Save results to an XML file
-v, --verboseVerbose 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

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

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

ProblemLikely CauseSolution
Can't connect to WHOIS serverNetwork/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/NOERRORZone transfers correctly restricted to authorized secondary servers (expected, secure config)Note as a negative (good) finding; proceed to brute-forcing
Brute-force phase extremely slowLarge wordlist with default single-threaded-like throughputIncrease --threads, or use a smaller curated wordlist
Many false-positive subdomains resolving to the same IPWildcard DNS record configured on the domainManually 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 errorsGoogle is rate-limiting/blocking automated queries from your IPReduce -p value, add delay, or skip Google scraping and rely on brute force + passive sources instead

References

Exit mobile version