| Tested on | Kali GNU/Linux Rolling 2026.2 (kali-rolling) |
|---|---|
| Package | nmap 7.99+dfsg-1kali1dnsenum 1.3.2-1dnsrecon 1.3.1-3bind9-dnsutils 1:9.20.23-1 |
| Applies to | Kali Linux |
| Lab environment | Kali + Metasploitable 2 on VirtualBox host-only — pentest lab setup |
| Privilege | Normal user for most commands; sudo for package installs |
| Scope | Active DNS enumeration with Nmap NSE scripts, dnsenum, DNSRecon, host, nslookup, and dig against a Metasploitable 2 BIND server. Ordinary record lookups use example.com; zone-transfer, dnsenum, and dns-brute demos use the authorized training zone zonetransfer.me. Covers NS, MX, SOA, A records, subdomain brute force, and AXFR checks. Does not cover passive DNS platforms, full subdomain takeover chains, or exploitation after record discovery. |
DNS enumeration turns a domain name into a map of hosts, mail paths, and nameservers before you run port scans or exploit modules. You query DNS for A, NS, MX, SOA, and other record types, then feed those hostnames into Nmap or vulnerability research.
This guide walks through six command-line tools on Kali Linux against Metasploitable 2 BIND on port 53. Along the way I explain what each step checks and what a good result looks like. It uses example.com for standard record lookups and zonetransfer.me for authorized zone-transfer demonstrations. Every command and output block below was captured on that layout.
What is DNS enumeration in ethical hacking?
The rest of this guide maps hostnames, mail servers, and nameservers from DNS before you port-scan or exploit anything. You collect A, NS, MX, SOA, and related records — reconnaissance, not exploitation by itself.
DNS maps human-readable names to IPs and service metadata. DNS enumeration (sometimes called DNS interrogation) collects that metadata on purpose during reconnaissance:
- Mail servers (MX) for phishing or SMTP testing paths
- Nameservers (NS) for zone-transfer and misconfiguration checks
- Hostnames and subdomains (A, CNAME) that widen the scan target list
- SOA and TXT records that reveal infrastructure hints
Enumeration is not exploitation by itself, but it often precedes banner grabbing and service scanning on the hosts you discover.
Pen testers query these record types most often during active enumeration:
| Record | What it tells you |
|---|---|
| A / AAAA | IPv4 or IPv6 address for a hostname |
| NS | Authoritative nameserver for a zone |
| MX | Mail exchanger hostnames |
| SOA | Start of authority: primary NS, admin contact, serial |
| TXT | Arbitrary text (SPF, DKIM, verification tokens) |
| CNAME | Alias pointing to another hostname |
| SRV | Service location (LDAP, Kerberos, and similar) |
| PTR | Reverse DNS name for an IP (in-addr.arpa) |
Active enumeration means your tools query DNS directly (dnsrecon, host, Nmap dns-brute). That traffic may be logged on the nameserver. Passive methods pull historical data from third-party datasets (SecurityTrails, ViewDNS) without sending new queries to the target zone. This article focuses on active enumeration in a local lab.
Kali lab setup
Set up variables once so Metasploitable fingerprinting, example.com lookups, and zonetransfer.me demos each point at the right nameserver or domain. You end up with DNS_SERVER, DOMAIN, and AXFR targets ready for every tool below.
Before you run the examples:
- Kali Linux with the tools below installed
- Metasploitable 2 on the same host-only or internal network as Kali
- Comfort reading record types and nameserver responses
Install the packages if they are missing on your Kali image:
sudo apt update
sudo apt install -y nmap dnsenum dnsrecon bind9-dnsutilsThe bind9-dnsutils package provides dig, host, and nslookup.
Metasploitable 2 network and DNS variables
| Item | Attacker (Kali) | Target (Metasploitable 2) |
|---|---|---|
| Hypervisor | Oracle VirtualBox (shared) | Same host |
| Lab network | Host-only / internal 192.168.56.0/24 |
Same subnet |
| Lab IP | 192.168.56.115 on eth1 |
192.168.56.114 (DNS_SERVER) |
| Role | Run enumeration tools from here | ISC BIND 9.4.2 on port 53 |
| Record demos | host, nslookup, dnsrecon against example.com |
BIND answers version probes |
| Zone-transfer and brute-force demos | dig, Nmap dns-brute, dns-zone-transfer, dnsenum against zonetransfer.me |
Training zone on nsztm1.digi.ninja |
| Service fingerprint | dig, Nmap dns-nsid, -sV on port 53 |
version.bind returns 9.4.2 |
Substitute your own addresses if VirtualBox assigns a different range. Set the lab nameserver, documentation domain, and AXFR training targets once, then reuse them in every command:
DNS_SERVER=192.168.56.114
DOMAIN=example.com
AXFR_DOMAIN=zonetransfer.me
AXFR_SERVER=nsztm1.digi.ninja
BRUTE_DOMAIN=zonetransfer.me
BRUTE_DNS_SERVER=nsztm1.digi.ninjaRecord lookups for example.com use the IANA reserved documentation domain for single-query host, nslookup, and DNSRecon demos — not subdomain brute force or dnsenum runs. Zone-transfer, dnsenum, and dns-brute examples use zonetransfer.me, a domain provided for AXFR training. The tool sections below reuse these variables — only the enumeration program changes.
Scan port 53 with Nmap
Metasploitable exposes BIND on port 53. Confirm the daemon is up and read its version string before you query records on a domain — that version line feeds CVE research later in this guide.
Confirm BIND with Nmap version detection
Scan port 53 on the lab nameserver:
nmap -Pn -p 53 -sV "$DNS_SERVER"-Pn skips Nmap host discovery and treats the address as online, which helps on lab networks where ICMP may be filtered.
PORT STATE SERVICE VERSION
53/tcp open domain ISC BIND 9.4.2The ISC BIND 9.4.2 string tells you the nameserver software generation. It is intentionally outdated on Metasploitable and worth noting before CVE research.
Read the CH TXT version string with dig
BIND often answers special CH TXT queries on version.bind:
dig @"$DNS_SERVER" version.bind CH TXT +short"9.4.2"That one-line answer matches the Nmap -sV result. hostname.bind on the same server returned metasploitable in this lab, which confirms which VM answered the query.
Pull the version with the Nmap dns-nsid script
The dns-nsid script queries BIND-style version fields:
nmap -Pn -p 53 --script dns-nsid "$DNS_SERVER"PORT STATE SERVICE
53/tcp open domain
| dns-nsid:
|_ bind.version: 9.4.2Use this script when you already have an open port 53 from a wider scan and want a quick BIND version line without a full dig invocation. BIND 9.4.2 is fingerprinted — move on to record enumeration and NSE scripts.
Compare DNS enumeration tools
The sections below walk Nmap scripts, dnsenum, DNSRecon, host, and nslookup against the same lab nameserver and authorized zones. Use this table to pick a path before you scale up brute lists or AXFR attempts.
| Tool | Best for | Typical output |
|---|---|---|
Nmap (dns-nsid, dns-brute, dns-zone-transfer) |
Version fingerprint on port 53; scripted subdomain brute force | Script table lines inside Nmap report |
| dnsenum | One-shot zone with AXFR attempts and optional scraping | Colored sections for A, NS, MX, brute results |
| DNSRecon | Scriptable per-record lines; multiple -t modes |
Timestamped INFO lines per record |
| host | Fast manual lookups by record type | Single-line answers |
| nslookup | Interactive exploration; Windows parity | Server banner plus record answer |
| dig | Precise queries (CH TXT, AXFR, @server) |
Default detailed DNS packet layout |
Start with dig or Nmap on the lab nameserver IP, then run dnsenum or DNSRecon when you need a broader record pass on an authorized domain.
Enumerate with Nmap DNS scripts
Nmap ships multiple DNS NSE scripts under /usr/share/nmap/scripts/. Here we brute-force subdomains on an authorized zone and test zone transfer — outputs land in the Nmap report under script result blocks.
Confirm the three scripts used in this walkthrough:
printf '%s\n' \
/usr/share/nmap/scripts/dns-{brute,nsid,zone-transfer}.nse/usr/share/nmap/scripts/dns-brute.nse
/usr/share/nmap/scripts/dns-nsid.nse
/usr/share/nmap/scripts/dns-zone-transfer.nseNext we run dns-brute for subdomain discovery and dns-zone-transfer for AXFR checks. For broader port and script patterns, see network reconnaissance with Nmap.
Brute-force subdomains with dns-brute
The dns-brute script guesses hostnames against a domain. Run it only against a zone you own or are explicitly authorized to test — not documentation domains such as example.com.
Set the authorized zone and the nameserver that should resolve brute-force queries (often the zone’s authoritative server):
BRUTE_DOMAIN=zonetransfer.me
BRUTE_DNS_SERVER=nsztm1.digi.ninja
nmap -Pn -p 53 --dns-servers "$BRUTE_DNS_SERVER" \
--script dns-brute \
--script-args dns-brute.domain="$BRUTE_DOMAIN" \
"$BRUTE_DNS_SERVER"dns-brute resolves candidate A and AAAA records through Nmap’s configured DNS servers. The --dns-servers "$BRUTE_DNS_SERVER" option forces those lookups through the nameserver you name. Nmap’s DNS library uses DNS servers known to the OS by default; --dns-servers selects an alternate resolver.
Against the training zone, the script returned several resolvable subdomains (trimmed):
| dns-brute:
| DNS Brute-force hostnames:
| www.zonetransfer.me - 5.196.105.14
| vpn.zonetransfer.me - 174.36.59.154
| owa.zonetransfer.me - 207.46.197.32
|_ testing.zonetransfer.me - 5.196.105.14Tune brute force with script arguments such as dns-brute.hostlist, dns-brute.threads, and dns-brute.srv when you need a custom wordlist or SRV lookups.
Test for zone transfers
A misconfigured authoritative nameserver may allow AXFR zone transfers to any client. Query a domain the server actually hosts. Asking Metasploitable BIND to transfer example.com only proves that server is not authoritative for that zone, not that its AXFR policy is secure.
Use a zone you control, or the intentionally transferable training zone zonetransfer.me:
dig @"$AXFR_SERVER" "$AXFR_DOMAIN" AXFROn the training nameserver, a successful transfer dumps the zone (trimmed):
zonetransfer.me. 7200 IN SOA nsztm1.digi.ninja. robin.digi.ninja. 2019100801 172800 900 1209600 3600
zonetransfer.me. 7200 IN A 5.196.105.14
zonetransfer.me. 7200 IN NS nsztm1.digi.ninja.
zonetransfer.me. 7200 IN NS nsztm2.digi.ninja.
www.zonetransfer.me. 7200 IN A 5.196.105.14
;; XFR size: 47 records (messages 1, bytes 1846)Some networks filter AXFR and return Transfer failed or REFUSED even against the training zone. Retry from a network that allows outbound DNS zone transfers.
Run the same check with Nmap’s dns-zone-transfer script, which requires the dns-zone-transfer.domain argument:
nmap -Pn -p 53 --script dns-zone-transfer \
--script-args dns-zone-transfer.domain="$AXFR_DOMAIN" \
"$AXFR_SERVER"When AXFR succeeds, Nmap lists zone records under dns-zone-transfer: on port 53. A transfer blocked by policy or filtering leaves port 53 open with no zone table lines.
Enumerate zones with dnsenum
dnsenum bundles record gathering, zone-transfer attempts, and optional Google scraping in one Perl run. Against zonetransfer.me you get A, NS, and MX sections before AXFR attempts — a full zone sketch in one command.
Because dnsenum automatically attempts AXFR against a domain’s authoritative nameservers, run it against the authorized training zone rather than example.com:
dnsenum --noreverse "$AXFR_DOMAIN"dnsenum VERSION:1.3.1
----- zonetransfer.me -----
Host's addresses:
__________________
zonetransfer.me. 6937 IN A 5.196.105.14
Name Servers:
______________
nsztm1.digi.ninja. 10472 IN A 81.4.108.41
nsztm2.digi.ninja. 10474 IN A 5.196.105.10
Mail (MX) Servers:
___________________
ASPMX.L.GOOGLE.COM. 136 IN A 192.178.211.27
ALT1.ASPMX.L.GOOGLE.COM. 136 IN A 173.194.41.27
Trying Zone Transfers and getting Bind Versions:
_________________________________________________
Trying Zone Transfer for zonetransfer.me on nsztm1.digi.ninja ...The A, NS, and MX sections map the zone before dnsenum attempts AXFR on each authoritative nameserver. On a network that permits transfers, the Trying Zone Transfer step lists the full zone; filtered paths may show REFUSED or stop after the attempt line.
--dnsserver sends dnsenum’s A, NS, and MX queries through the supplied resolver. AXFR and PTR requests are still sent to the domain’s authoritative nameservers, per the dnsenum man page. Metasploitable BIND does not recurse cleanly for zonetransfer.me, so this walkthrough omits a --dnsserver "$DNS_SERVER" example rather than pointing dnsenum at example.com.
Save training-zone output to XML for reporting:
dnsenum --noreverse -o "$AXFR_DOMAIN.xml" "$AXFR_DOMAIN"Collect DNS records with DNSRecon
DNSRecon prints one timestamped line per record in std mode — easy to script. Start with a standard pass against the documentation domain:
dnsrecon -d "$DOMAIN" -t std[*] std: Performing General Enumeration against: example.com...
[*] DNSSEC is configured for example.com
[*] SOA elliott.ns.cloudflare.com 162.159.44.228
[*] NS elliott.ns.cloudflare.com 172.64.35.228
[*] NS hera.ns.cloudflare.com 173.245.58.162
[*] A example.com 104.20.23.154
[*] A example.com 172.66.147.243
[*] Enumerating SRV Records
[*] 0 Records Found
[*] Completed enumeration for domain: example.comDNSRecon prefixes lines with timestamps in live output; the record rows above are trimmed for readability. List other modes with dnsrecon -h (-t brt for brute force, -t axfr for zone transfer only).
Query records with host
When you already know the record type you need, host is the fastest manual check. Each answer line names a hostname, IP, or nameserver you can feed into Nmap next.
Resolve IPv4 A records through your system resolver:
host -t A "$DOMAIN"example.com has address 172.66.147.243
example.com has address 104.20.23.154List authoritative nameservers:
host -t ns "$DOMAIN"example.com name server hera.ns.cloudflare.com.
example.com name server elliott.ns.cloudflare.com.Enumerate MX records:
host -t mx "$DOMAIN"example.com mail is handled by 0 .MX 0 . is a Null MX record (RFC 7505). It explicitly means the domain does not accept email; the dot is not a mail host to scan. On corporate zones, MX rows usually name real mail hosts you can scan next.
Query records with nslookup
nslookup supports one-shot queries and an interactive shell — useful when you want to explore record types without memorizing dig flags. The server banner and answer block show which resolver answered and what records came back.
For a quick NS lookup:
nslookup -type=ns "$DOMAIN"Server: 192.168.0.1
Address: 192.168.0.1#53
Non-authoritative answer:
example.com nameserver = elliott.ns.cloudflare.com.
example.com nameserver = hera.ns.cloudflare.com.Request MX records the same way:
nslookup -type=mx "$DOMAIN"example.com mail exchanger = 0 .For interactive mode, start nslookup, set the query type, then enter the domain:
nslookup> set type=ns
> example.com
Server: 192.168.0.1
Address: 192.168.0.1#53
Non-authoritative answer:
example.com nameserver = elliott.ns.cloudflare.com.
example.com nameserver = hera.ns.cloudflare.com.Type exit to leave the interactive shell.
Map BIND versions to CVE research
Enumeration gives you software versions and exposure — not automatic exploitability. Record BIND 9.4.2 from the lab, then check advisories and confirm patch level before you treat a CVE as applicable.
Record the service, version, and exposure before searching a CVE database:
| Port | Finding | Research result |
|---|---|---|
| 53/tcp | ISC BIND 9.4.2 (dns-nsid, -sV) |
Review the ISC BIND advisory index and NVD entries for 9.4.x; Metasploitable ships an intentionally old build |
A version string is only a clue. BIND 9.4.2 is end-of-life and appears in lab images to practice patching and exposure review, not to imply every 9.4.2 server shares the same flaw set. Confirm patch level, recursion policy, and whether the nameserver is reachable from untrusted networks before you treat a CVE as applicable.
When enumeration reveals a host and port, continue with service scanning and banner grabbing on the IPs you discovered — only on systems you are authorized to test.
Troubleshooting
When host returns SERVFAIL, AXFR is refused, or dns-brute finds nothing, check the table below.
| Symptom | Likely cause | Fix |
|---|---|---|
SERVFAIL from host "$DOMAIN" "$DNS_SERVER" |
Lab BIND does not recurse cleanly for all record types | Use host -t A "$DOMAIN" without a server argument, or query version.bind with dig @"$DNS_SERVER" |
dns-brute reports no hostnames |
Missing dns-brute.domain or wrong resolver |
Set dns-brute.domain="$BRUTE_DOMAIN" and --dns-servers "$BRUTE_DNS_SERVER" on an authorized zone |
AXFR returns Transfer failed or REFUSED on zonetransfer.me |
Outbound AXFR filtered, or wrong nameserver | Query "$AXFR_SERVER" (authoritative for the training zone); confirm the domain is zonetransfer.me, not example.com |
dnsrecon cannot resolve domain |
No network or wrong -n nameserver |
Check routing to the internet or set -n "$DNS_SERVER" when the lab resolver should answer |
| dnsenum hangs on Google scraping | Network blocked or captcha | Omit -p / Google options; use --noreverse and a local wordlist with -f |
Empty dig answer via lab server |
Query type not supported or recursion disabled | Confirm port 53 is open with nmap -Pn -p 53 "$DNS_SERVER"; test version.bind CH TXT |
References
- Nmap
dns-brutescript - Nmap
dns-nsidscript - Nmap
dns-zone-transferscript - Nmap DNS resolution
- ZoneTransfer.me (DigiNinja)
- RFC 7505 — Null MX
- dnsenum man page (Debian)
- ISC BIND advisory index
- dnsenum (GitHub)
- DNSRecon (GitHub)
- ISC BIND
- IANA example domains
- Cloudflare — What is DNS?
- Metasploitable 2 documentation (Rapid7)
Summary
DNS enumeration answers which hostnames and mail paths exist before you spend time on port scans. In this lab you fingerprinted Metasploitable BIND 9.4.2 with Nmap -sV, dig version.bind, and dns-nsid, ran dns-brute against the authorized zonetransfer.me zone, and practiced AXFR on its authoritative nameserver.
dnsenum demonstrates broad record collection and AXFR against zonetransfer.me, while DNSRecon, host, and nslookup use example.com for ordinary record lookups. Treat every nameserver and version string as a hypothesis: verify patch level, recursion policy, and authorization scope before you map findings to CVEs or expand scanning to newly discovered hosts.
On authorized lab targets, chain enumeration into banner grabbing and the Metasploitable 2 exploitation walkthrough. Never run brute-force or AXFR tests against domains or servers you are not permitted to query.

