By Davy Rogers. Use these techniques only in environments you own or have explicit permission to test.

Active Reconnaissance: DNS Enumeration with dig

dig (Domain Information Groper) is a powerful command-line tool for querying DNS servers and gathering information about domains, subdomains, mail servers, name servers, and more. Unlike passive reconnaissance, using dig makes direct queries to DNS servers, leaving traces in logs. It's essential for active reconnaissance and penetration testing.

What You'll Learn

  • What dig is and how it works
  • DNS record types (A, AAAA, MX, NS, TXT, etc.)
  • Basic and advanced dig syntax
  • DNS enumeration techniques
  • Zone transfer attacks (AXFR)
  • Reverse DNS lookups
  • DNS cache snooping
  • Automating DNS reconnaissance
  • Defensive measures

What Is dig?

Overview:

dig = Domain Information Groper

Purpose:
- Query DNS servers
- Retrieve DNS records
- Troubleshoot DNS issues
- Enumerate domains/subdomains

Platform:
- Pre-installed on Linux/macOS
- Windows: Use nslookup or install BIND tools

How It Works:

You → dig → DNS Server → Response

Example:
$ dig example.com

1. dig sends query to DNS server
2. DNS server responds with records
3. dig displays results

Installation

Linux:

# Debian/Ubuntu
sudo apt update
sudo apt install dnsutils

# RHEL/CentOS/Fedora
sudo dnf install bind-utils

# Arch
sudo pacman -S bind-tools

macOS:

# Pre-installed
dig --version

# If not installed (via Homebrew):
brew install bind

Windows:

Option 1: Use nslookup (pre-installed):

nslookup example.com

Option 2: Install BIND tools:

# Download BIND from ISC website
# Or use Windows Subsystem for Linux (WSL)

Basic dig Usage

Simple Query:

dig example.com

Output:

; <<>> DiG 9.18.1 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		3600	IN	A	93.184.216.34

;; Query time: 45 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jan 01 12:00:00 PST 2024
;; MSG SIZE  rcvd: 56

Short Answer Only:

dig example.com +short

Output:

93.184.216.34

DNS Record Types

A Record (IPv4 Address):

dig example.com A

# Or just:
dig example.com

Returns IPv4 address for domain.

AAAA Record (IPv6 Address):

dig example.com AAAA

Returns IPv6 address for domain.

MX Record (Mail Exchange):

dig example.com MX

Returns mail servers for domain:

example.com.  3600  IN  MX  10 mail.example.com.
example.com.  3600  IN  MX  20 mail2.example.com.

Priority: Lower number = higher priority

NS Record (Name Servers):

dig example.com NS

Returns authoritative name servers:

example.com.  3600  IN  NS  ns1.example.com.
example.com.  3600  IN  NS  ns2.example.com.

TXT Record (Text):

dig example.com TXT

Returns text records (SPF, DMARC, verification, etc.):

example.com.  3600  IN  TXT  "v=spf1 include:_spf.google.com ~all"
example.com.  3600  IN  TXT  "google-site-verification=ABC123..."

CNAME Record (Canonical Name):

dig www.example.com CNAME

Returns alias (canonical name):

www.example.com.  3600  IN  CNAME  example.com.

SOA Record (Start of Authority):

dig example.com SOA

Returns zone authority information:

example.com.  3600  IN  SOA  ns1.example.com. admin.example.com. (
                         2024010101 ; serial
                         3600       ; refresh
                         1800       ; retry
                         1209600    ; expire
                         86400 )    ; minimum TTL

PTR Record (Reverse DNS):

dig -x 93.184.216.34

Returns hostname for IP address.

ANY Record (All Records):

dig example.com ANY

⚠️ Note: Many DNS servers now refuse ANY queries due to DDoS abuse.


Advanced dig Techniques

Specify DNS Server:

# Use Google DNS
dig @8.8.8.8 example.com

# Use Cloudflare DNS
dig @1.1.1.1 example.com

# Use specific name server
dig @ns1.example.com example.com

Query Multiple Records:

dig example.com A MX NS

Trace DNS Resolution Path:

dig +trace example.com

Shows full DNS resolution path from root servers down:

.			518400	IN	NS	a.root-servers.net.
com.			172800	IN	NS	a.gtld-servers.net.
example.com.		172800	IN	NS	ns1.example.com.
example.com.		3600	IN	A	93.184.216.34

Reverse DNS Lookup:

# Method 1: -x flag
dig -x 93.184.216.34

# Method 2: Manual PTR query
dig 34.216.184.93.in-addr.arpa PTR

Batch Queries:

# From file
dig -f domains.txt

# domains.txt:
# example.com
# google.com
# github.com

Disable Recursion:

dig +norecurs example.com @ns1.example.com

Only queries specified server, doesn't recurse.


DNS Enumeration for Penetration Testing

1. Basic Domain Information:

# Get A record
dig example.com +short

# Get all name servers
dig example.com NS +short

# Get mail servers
dig example.com MX +short

# Get TXT records (SPF, DMARC, etc.)
dig example.com TXT +short

2. Subdomain Enumeration:

Brute Force with Wordlist:

#!/bin/bash

DOMAIN="example.com"
WORDLIST="subdomains.txt"

while read subdomain; do
    result=$(dig ${subdomain}.${DOMAIN} +short)
    if [ -n "$result" ]; then
        echo "[+] ${subdomain}.${DOMAIN} -> $result"
    fi
done < $WORDLIST

Common Subdomains to Test:

www
mail
ftp
admin
dev
staging
test
api
vpn
remote
portal
blog
shop

3. Zone Transfer Attack (AXFR):

What is it?

Zone transfer = Copy entire DNS zone

Originally for:
- Replicating zones between name servers

Security issue:
- If misconfigured, anyone can request
- Reveals ALL subdomains
- Massive information disclosure

Attempt Zone Transfer:

# Get name servers first
dig example.com NS +short

# Try zone transfer on each NS
dig @ns1.example.com example.com AXFR
dig @ns2.example.com example.com AXFR

If successful:

example.com.		3600	IN	SOA	...
example.com.		3600	IN	NS	ns1.example.com.
www.example.com.	3600	IN	A	93.184.216.34
mail.example.com.	3600	IN	A	93.184.216.35
ftp.example.com.	3600	IN	A	93.184.216.36
admin.example.com.	3600	IN	A	192.168.1.10
dev.example.com.	3600	IN	A	10.0.0.5
...

Jackpot! All subdomains revealed including internal IPs!

If denied (properly configured):

; Transfer failed.

4. Reverse DNS Enumeration:

# Get IP range for target
whois example.com | grep CIDR

# Reverse lookup each IP in range
for ip in 93.184.216.{1..255}; do
    dig -x $ip +short
done

# Find other domains on same network

5. Cache Snooping:

# Check if domain is cached (no recursion)
dig @8.8.8.8 example.com +norecurs

# If cached, server has recently resolved it
# Can reveal what domains an organization queries

Automating DNS Reconnaissance

Bash Script - Comprehensive DNS Enum:

#!/bin/bash

DOMAIN=$1

if [ -z "$DOMAIN" ]; then
    echo "Usage: $0 <domain>"
    exit 1
fi

echo "[*] DNS Enumeration for: $DOMAIN"
echo ""

echo "[*] A Records:"
dig $DOMAIN A +short
echo ""

echo "[*] AAAA Records:"
dig $DOMAIN AAAA +short
echo ""

echo "[*] MX Records:"
dig $DOMAIN MX +short
echo ""

echo "[*] NS Records:"
NS_SERVERS=$(dig $DOMAIN NS +short)
echo "$NS_SERVERS"
echo ""

echo "[*] TXT Records:"
dig $DOMAIN TXT +short
echo ""

echo "[*] SOA Record:"
dig $DOMAIN SOA +short
echo ""

echo "[*] Attempting Zone Transfer:"
for ns in $NS_SERVERS; do
    echo "  [*] Trying $ns"
    dig @$ns $DOMAIN AXFR
done
echo ""

echo "[*] Done!"

Usage:

chmod +x dns_enum.sh
./dns_enum.sh example.com

Python Script:

import dns.resolver
import dns.zone
import dns.query
import sys

def dns_enum(domain):
    print(f"[*] DNS Enumeration for: {domain}\n")
    
    # A Records
    try:
        answers = dns.resolver.resolve(domain, 'A')
        print("[*] A Records:")
        for rdata in answers:
            print(f"  {rdata}")
    except:
        print("[*] No A records")
    
    # MX Records
    try:
        answers = dns.resolver.resolve(domain, 'MX')
        print("\n[*] MX Records:")
        for rdata in answers:
            print(f"  {rdata.preference} {rdata.exchange}")
    except:
        print("[*] No MX records")
    
    # NS Records
    try:
        answers = dns.resolver.resolve(domain, 'NS')
        print("\n[*] NS Records:")
        ns_servers = []
        for rdata in answers:
            print(f"  {rdata}")
            ns_servers.append(str(rdata))
    except:
        print("[*] No NS records")
        return
    
    # TXT Records
    try:
        answers = dns.resolver.resolve(domain, 'TXT')
        print("\n[*] TXT Records:")
        for rdata in answers:
            print(f"  {rdata}")
    except:
        print("[*] No TXT records")
    
    # Zone Transfer
    print("\n[*] Attempting Zone Transfer:")
    for ns in ns_servers:
        try:
            zone = dns.zone.from_xfr(dns.query.xfr(ns, domain))
            print(f"  [+] Zone transfer successful from {ns}:")
            for name, node in zone.nodes.items():
                print(f"    {name}.{domain}")
        except:
            print(f"  [-] Zone transfer failed from {ns}")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python3 dns_enum.py <domain>")
        sys.exit(1)
    
    domain = sys.argv[1]
    dns_enum(domain)

Installation:

pip install dnspython

Usage:

python3 dns_enum.py example.com

Defensive Measures

For DNS Administrators:

1. Disable Zone Transfers to Unauthorized Hosts:

BIND (named.conf):

zone "example.com" {
    type master;
    file "/etc/bind/zones/db.example.com";
    
    // Only allow zone transfers to specific IPs
    allow-transfer { 
        192.168.1.10;  // Secondary NS
        192.168.1.11;  // Another secondary
    };
};

Windows DNS:

1. Open DNS Manager
2. Right-click zone → Properties
3. Zone Transfers tab
4. Select "Only to the following servers"
5. Add authorized secondary servers only

2. Use DNSSEC:

DNSSEC = DNS Security Extensions

Benefits:
- Authenticates DNS responses
- Prevents cache poisoning
- Verifies data integrity

Implementation:
- Sign DNS zones
- Publish DNSKEY and RRSIG records
- Chain of trust from root

3. Rate Limiting:

Prevent DNS enumeration via rate limiting:
- Limit queries per IP
- Throttle suspicious patterns
- Block after threshold

4. Monitor DNS Logs:

Watch for:
- Zone transfer attempts
- Excessive queries from single IP
- Queries for non-existent subdomains (enumeration)
- Unusual query patterns

Tools:
- dnstop (real-time DNS monitoring)
- DNS logging to SIEM

5. Split-Horizon DNS:

Internal view:
- Full DNS info for internal clients

External view:
- Limited DNS info for internet
- Only public-facing records
- Hide internal infrastructure

dig vs nslookup vs host

Comparison:

dig:
✓ Most detailed output
✓ Best for troubleshooting
✓ Flexible query options
✓ Standard on Linux/macOS

nslookup:
✓ Simple queries
✓ Interactive mode
✓ Cross-platform (Windows!)
✗ Less detailed

host:
✓ Simplest output
✓ Quick lookups
✓ Good for scripts
✗ Fewer options

Examples:

dig:

dig example.com +short

nslookup:

nslookup example.com

host:

host example.com

Try It Yourself

Exercise 1: Basic DNS Queries

# A record
dig google.com +short

# MX records
dig google.com MX

# Name servers
dig google.com NS

# TXT records (SPF, DKIM, etc.)
dig google.com TXT

Exercise 2: Trace DNS Resolution

dig +trace google.com

# Observe path from root servers down

Exercise 3: Zone Transfer

# Find a vulnerable zone (for practice):
# zonetransfer.me is intentionally vulnerable

dig @nsztm1.digi.ninja zonetransfer.me AXFR

# See all subdomains revealed!

Exercise 4: Subdomain Enumeration

# Create wordlist
echo -e "www\nmail\nftp\nadmin\ndev\ntest" > subs.txt

# Test each
while read sub; do
    dig ${sub}.example.com +short
done < subs.txt

Quick Reference

Basic Queries:
dig domain.com                    # A record
dig domain.com MX                 # Mail servers
dig domain.com NS                 # Name servers
dig domain.com TXT                # TXT records
dig domain.com +short             # Short output

Advanced:
dig @8.8.8.8 domain.com           # Specific DNS server
dig +trace domain.com             # Trace resolution
dig -x IP_ADDRESS                 # Reverse lookup
dig @ns1.domain.com domain.com AXFR  # Zone transfer

Batch:
dig -f domains.txt                # Query multiple

Output Control:
dig domain.com +short             # Short
dig domain.com +noall +answer     # Only answer section

Resources

Documentation:

Tools:

  • dnsutils (Linux): apt install dnsutils
  • bind-tools (RHEL): dnf install bind-utils
  • dnspython (Python): pip install dnspython

Practice:

  • zonetransfer.me: Intentionally vulnerable for zone transfer practice
  • DNS Dumpster: https://dnsdumpster.com (online DNS recon)

Reading:


Next Steps

  1. Master basic dig queries for all record types
  2. Practice subdomain enumeration with wordlists
  3. Attempt zone transfers (authorized targets only!)
  4. Automate DNS reconnaissance with scripts
  5. Combine with other tools (nmap, sublist3r, amass)

DNS enumeration is a critical first step in penetration testing. Master dig to uncover target infrastructure!