Altdns is a specialized subdomain discovery tool that leverages permutation and mutation techniques to identify previously unknown subdomains within a target domain. Unlike traditional brute-force subdomain enumeration, Altdns takes a list of known subdomains and generates variations by applying common naming conventions, abbreviations, and patterns. It then attempts DNS resolution on these generated candidates to discover valid subdomains. This approach is particularly effective for bug bounty programs and penetration testing engagements where maximizing attack surface discovery is critical.
# System requirements
- Python 3.6+
- pip package manager
- Network connectivity for DNS resolution
- DNS resolver (system resolver or custom)
# Install from PyPI
pip install altdns
# Verify installation
altdns --version
# Display help
altdns --help
# Clone repository
git clone https://github.com/infosec-au/altdns.git
cd altdns
# Install dependencies
pip install -r requirements.txt
# Install package
pip install -e .
# Verify installation
python -m altdns --help
# Pull Docker image
docker pull infosecau/altdns
# Run with Docker
docker run --rm infosecau/altdns -i subdomains.txt -w /wordlists/words.txt -o results.txt
# Interactive mode with mounted directory
docker run -it --rm -v $(pwd):/data infosecau/altdns \
-i /data/subdomains.txt \
-w /data/words.txt \
-o /data/results.txt
altdns -i <input_file> -w <wordlist> -o <output_file> [options]
-i, --input Path to file containing known subdomains (one per line)
-w, --wordlist Path to wordlist file for permutation generation
-o, --output Path to output file for discovered subdomains
# Basic subdomain discovery
altdns -i subdomains.txt -w words.txt -o discovered.txt
# Verbose output
altdns -i subdomains.txt -w words.txt -o discovered.txt -v
# Save as CSV format
altdns -i subdomains.txt -w words.txt -o discovered.csv
# Specify custom DNS resolver
altdns -i subdomains.txt -w words.txt -o results.txt --resolver 8.8.8.8
# Use multiple DNS resolvers
altdns -i subdomains.txt -w words.txt -o results.txt \
--resolver 8.8.8.8 1.1.1.1 9.9.9.9
# Use resolvers from file
altdns -i subdomains.txt -w words.txt -o results.txt \
--resolver-file resolvers.txt
# Adjust thread count (default: 5)
altdns -i subdomains.txt -w words.txt -o results.txt -t 20
# Maximum threads for fast resolution
altdns -i subdomains.txt -w words.txt -o results.txt -t 100
# Single-threaded mode (slowest)
altdns -i subdomains.txt -w words.txt -o results.txt -t 1
# With timeout adjustment
altdns -i subdomains.txt -w words.txt -o results.txt \
--timeout 10 -t 50
# Use single wordlist
altdns -i subdomains.txt -w /wordlists/words.txt -o results.txt
# Use multiple wordlists
altdns -i subdomains.txt \
-w /wordlists/words.txt /wordlists/subdomains.txt \
-o results.txt
# Custom wordlist (any permutations)
altdns -i subdomains.txt -w custom_words.txt -o results.txt
| Wordlist | Source | Size | Use Case |
|---|
| words.txt (altdns default) | GitHub | Small | Quick testing |
| SecLists | SecLists repo | Large | Comprehensive enumeration |
| subdomains-top1million-110000.txt | SecLists | Large | Most common subdomains |
| subdomains.txt | Various | Medium | Alternative patterns |
| dns-wordlists | Assetnote | Large | Specialized DNS discovery |
# Extract common subdomain patterns
cat common_subdomains.txt | sort -u > custom_wordlist.txt
# Combine multiple wordlists
cat /wordlists/*.txt | sort -u > combined_wordlist.txt
# Remove duplicates and sort
sort -u input_wordlist.txt -o cleaned_wordlist.txt
# Count words
wc -l wordlist.txt
# View sample
head -20 wordlist.txt
# SecLists repository
git clone https://github.com/danielmiessler/SecLists.git
# Located in SecLists/Discovery/DNS/
# Assetnote DNS wordlists
wget https://wordlists-cdn.assetnote.io/data/automated/subdomains-top1million-5000.txt
# OneListForAll
git clone https://github.com/six2dez/OneListForAll.git
# Create ultimate wordlist
cat SecLists/Discovery/DNS/*.txt | sort -u > ultimate_wordlist.txt
# subdomains.txt (one domain per line)
api.example.com
app.example.com
blog.example.com
admin.example.com
mail.example.com
vpn.example.com
dev.example.com
test.example.com
staging.example.com
cdn.example.com
# From certificate transparency logs
curl -s "https://crt.sh/?q=%25.example.com&output=json" | \
jq -r '.[].name_value' | sort -u > subdomains.txt
# From DNS zone transfer (if allowed)
dig axfr @ns1.example.com example.com | grep -oE '\w+\.example\.com' | sort -u > subdomains.txt
# From previous reconnaissance
cat found_subdomains.txt | sort -u > subdomains.txt
# From multiple sources
cat ct_logs.txt subfinder_output.txt amass_output.txt | sort -u > subdomains.txt
Base subdomain: api.example.com
Generated permutations:
- api-dev.example.com
- api-test.example.com
- api-staging.example.com
- dev-api.example.com
- test-api.example.com
- apidev.example.com
- apiv1.example.com
- api2.example.com
- api3.example.com
- apibeta.example.com
- apialpha.example.com
Prefixes: dev-, test-, prod-, staging-, demo-, old-, new-
Suffixes: -v1, -v2, -api, -web, -admin, -test, -dev, -beta, -alpha, -internal
Numbers: 1, 2, 3, 4, 5 appended or inserted
Abbreviations: Converting api → a, admin → adm
Consolidation: api-dev → apidev, test.dev → testdev
Environment: qa, staging, production, sandbox variants
# Default format (one domain per line)
altdns -i subdomains.txt -w words.txt -o results.txt
# View results
cat results.txt
api-staging.example.com
api-dev.example.com
api-test.example.com
app-dev.example.com
# Generate CSV with metadata
altdns -i subdomains.txt -w words.txt -o results.csv --csv
# Format: domain, ip, record_type, response_code
api-dev.example.com, 10.0.0.1, A, 200
api-test.example.com, 10.0.0.2, A, 200
# JSON formatted results
altdns -i subdomains.txt -w words.txt -o results.json --json
# Sample output structure
{
"subdomains": [
{"domain": "api-dev.example.com", "ip": "10.0.0.1", "cname": null},
{"domain": "api-test.example.com", "ip": "10.0.0.2", "cname": null}
]
}
# Collect subdomains with subfinder
subfinder -d example.com -o subfinder_results.txt
# Feed to altdns
altdns -i subfinder_results.txt -w words.txt -o altdns_results.txt
# Combine results
cat subfinder_results.txt altdns_results.txt | sort -u > all_subdomains.txt
# Enumerate with amass
amass enum -d example.com -o amass_results.txt
# Enhance with altdns
altdns -i amass_results.txt -w words.txt -o enhanced_results.txt
# Merge findings
cat amass_results.txt enhanced_results.txt | sort -u > comprehensive_list.txt
# Gather subdomains with assetfinder
assetfinder --subs-only example.com > assetfinder_results.txt
# Apply altdns mutations
altdns -i assetfinder_results.txt -w words.txt -o mutations.txt
# Unique combined list
cat assetfinder_results.txt mutations.txt | sort -u > final_list.txt
#!/bin/bash
# Complete subdomain discovery workflow
DOMAIN=$1
WORDLIST="words.txt"
echo "[*] Starting reconnaissance for $DOMAIN"
# Step 1: Certificate transparency
echo "[*] Querying certificate logs..."
curl -s "https://crt.sh/?q=%25.${DOMAIN}&output=json" | \
jq -r '.[].name_value' | grep -oE '\w+\.'${DOMAIN} | sort -u > ct_results.txt
# Step 2: Subfinder enumeration
echo "[*] Running subfinder..."
subfinder -d $DOMAIN -o subfinder_results.txt
# Step 3: Combine and deduplicate
echo "[*] Combining results..."
cat ct_results.txt subfinder_results.txt | sort -u > combined.txt
# Step 4: Altdns mutation
echo "[*] Generating permutations with altdns..."
altdns -i combined.txt -w $WORDLIST -o mutations.txt -t 50
# Step 5: Final compilation
echo "[*] Finalizing results..."
cat combined.txt mutations.txt | sort -u > final_subdomains.txt
echo "[*] Reconnaissance complete!"
echo "[*] Results saved to final_subdomains.txt"
wc -l final_subdomains.txt
# Check DNS resolution with nslookup
nslookup api-dev.example.com
# Resolve with dig
dig api-dev.example.com
# Batch resolution with host
while read domain; do
host $domain | grep "has address"
done < results.txt
# Using parallel for speed
cat results.txt | parallel 'host {}'
# Resolve and extract IPs
altdns -i subdomains.txt -w words.txt -o results.txt -r
# Extract unique IPs from results
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' results.txt | sort -u
# Map domains to IPs
while read domain; do
ip=$(dig +short $domain | head -1)
echo "$domain -> $ip"
done < results.txt > domain_ip_mapping.txt
| Parameter | Value | Speed | Thoroughness |
|---|
| Threads (-t) | 5 (default) | Slow | High accuracy |
| Threads (-t) | 20 | Medium | Good |
| Threads (-t) | 100 | Fast | May lose results |
| Timeout | 3 seconds | Very fast | May miss slow DNS |
| Timeout | 10 seconds | Moderate | Better results |
# Aggressive scanning
altdns -i subdomains.txt -w words.txt -o results.txt \
-t 100 --timeout 3 -v
# Multiple DNS resolvers for speed
altdns -i subdomains.txt -w words.txt -o results.txt \
--resolver 8.8.8.8 1.1.1.1 9.9.9.9 8.26.56.26 \
-t 50
# Conservative, accurate scanning
altdns -i subdomains.txt -w words.txt -o results.txt \
-t 5 --timeout 10 -v
# Single resolver for reliability
altdns -i subdomains.txt -w words.txt -o results.txt \
--resolver 8.8.8.8 -t 10
#!/bin/bash
# Complete bug bounty subdomain enumeration
TARGET=$1
echo "[+] Subdomain enumeration for $TARGET"
# Gather initial subdomains
subfinder -d $TARGET -silent > initial.txt
assetfinder --subs-only $TARGET >> initial.txt
crt.sh $TARGET >> initial.txt
sort -u initial.txt -o subdomains.txt
# Apply altdns mutations
altdns -i subdomains.txt -w top-wordlist.txt -o mutations.txt -t 50
# Combine results
cat subdomains.txt mutations.txt | sort -u > all_subdomains.txt
# Probe for live services
echo "[+] Probing live subdomains..."
cat all_subdomains.txt | httprobe -p 80,443,8080,8443 | tee alive_subdomains.txt
# Further enumeration
echo "[+] Technology detection..."
cat alive_subdomains.txt | wappanalyzer > tech_stack.txt
echo "[+] Enumeration complete!"
# Identify all potential targets within scope
echo "[*] Generating comprehensive target list"
# Start with known domains
cat in_scope_domains.txt > targets.txt
# Use altdns for each domain
for domain in $(cat in_scope_domains.txt); do
echo "[*] Processing $domain"
altdns -i <(echo $domain) -w wordlist.txt -o ${domain}_mutations.txt -t 30
cat ${domain}_mutations.txt >> all_mutations.txt
done
# Deduplicate
cat targets.txt all_mutations.txt | sort -u > complete_scope.txt
# Filter out-of-scope
grep -v "exclude\.pattern" complete_scope.txt > final_scope.txt
echo "[*] Scope complete: $(wc -l < final_scope.txt) targets"
#!/bin/bash
# Monitor for new subdomains daily
DOMAIN="example.com"
WORDLIST="words.txt"
LOGDIR="logs"
# Create log directory
mkdir -p $LOGDIR
# Current scan
altdns -i <(subfinder -d $DOMAIN -silent) -w $WORDLIST \
-o $LOGDIR/$(date +%Y%m%d)_subdomains.txt -t 50
# Compare with previous scan
if [ -f "$LOGDIR/previous.txt" ]; then
NEW=$(comm -23 <(sort $LOGDIR/$(date +%Y%m%d)_subdomains.txt) \
<(sort $LOGDIR/previous.txt))
if [ ! -z "$NEW" ]; then
echo "[!] New subdomains discovered:"
echo "$NEW"
# Send alert (email, Slack, webhook, etc.)
fi
fi
# Update previous
cp $LOGDIR/$(date +%Y%m%d)_subdomains.txt $LOGDIR/previous.txt
| Issue | Cause | Solution |
|---|
| No results found | DNS timeout or no valid domains | Increase timeout, verify resolver, check wordlist |
| Slow execution | Too few threads | Increase -t value or add multiple resolvers |
| Memory errors | Large wordlist | Use smaller wordlist or increase system memory |
| DNS resolution failures | Bad resolver | Switch to public DNS (8.8.8.8, 1.1.1.1) |
| Incomplete results | Thread limit reached | Reduce threads or DNS queries timeout |
# Verbose output for troubleshooting
altdns -i subdomains.txt -w words.txt -o results.txt -v -v
# Test DNS resolver
nslookup api.example.com 8.8.8.8
# Check internet connectivity
ping 8.8.8.8
# Monitor process
htop -p $(pgrep -f altdns)
# Verify wordlist format
head wordlist.txt
wc -l wordlist.txt
- Start with multiple reconnaissance sources (CT logs, certificate data, DNS)
- Use comprehensive wordlists matching target organization
- Apply altdns to multiply discovered subdomains
- Verify results with multiple DNS resolvers
- Combine with HTTP probing to identify live services
- Document findings with timestamps
- Only enumerate domains within authorized scope
- Respect robots.txt and .well-known/security.txt
- Avoid overwhelming targets with excessive queries
- Use rate limiting when required
- Document authorization before testing
- Report findings responsibly
# For large-scale operations
altdns -i 10k_subdomains.txt \
-w million_wordlist.txt \
-o results.txt \
--resolver 8.8.8.8 1.1.1.1 9.9.9.9 \
-t 50 \
--timeout 5
# Parallel processing for multiple domains
parallel 'altdns -i {} -w words.txt -o {}.results' ::: *.txt
# Resource-efficient batch processing
for file in *.txt; do
altdns -i "$file" -w words.txt -o "${file}.out" -t 10 --timeout 10
done