18 KiB
Challenges and Extensions
Beginner Challenges
Challenge 1: Add DNSSEC Validation
Goal: Verify DNSSEC signatures on DNS responses.
Current State: The tool retrieves records but doesn't validate signatures. Line resolver.py:200-201 just fetches data without cryptographic verification.
Implementation Tasks:
- Enable DNSSEC in resolver (
resolver.py:91-107)
resolver = dns.asyncresolver.Resolver()
resolver.use_edns(0, dns.flags.DO, 4096) # Request DNSSEC records
- Check RRSIG records in responses
- Validate signatures against DNSKEY records
- Walk chain of trust from root to target domain
Resources:
- RFC 4033, 4034, 4035 (DNSSEC specs)
- dnspython DNSSEC validation examples
- Test with
dnssec-tools.org(signed domain)
Security Impact: Prevents accepting forged DNS responses. Critical for high-security environments.
Challenge 2: Implement DNS Query Logging
Goal: Log all queries to a file for analysis.
What to Log:
- Timestamp
- Domain queried
- Record types requested
- DNS server used
- Response time
- Number of records returned
Implementation:
- Create logger in
resolver.py:213-250 - Log before query:
logging.info(f"Querying {domain} for {record_types}") - Log after query:
logging.info(f"Got {len(result.records)} records in {result.query_time_ms}ms") - Add CLI flag:
--log-file queries.log
Analysis Ideas:
- Which domains take longest to resolve?
- Which record types fail most often?
- Time series analysis of response times
Security Application: Detect reconnaissance by analyzing query patterns.
Challenge 3: Add CSV Output Format
Goal: Export results to CSV for spreadsheet analysis.
Current State: JSON output exists (output.py:379-410), but CSV would be more useful for some workflows.
Implementation:
- Add
results_to_csv()function inoutput.py - Flatten nested structure:
domain,record_type,value,ttl,priority,query_time_ms
example.com,A,93.184.216.34,86400,,45.2
example.com,MX,mail.example.com,3600,10,45.2
- Handle multiple records per domain
- Add
--csvflag to commands
Use Case: Import into Excel/Google Sheets for analysis, sorting, filtering.
Intermediate Challenges
Challenge 4: Subdomain Enumeration
Goal: Discover subdomains through various techniques.
Techniques to Implement:
1. Brute Force (cli.py:266-350 as starting point)
common_subdomains = ['www', 'mail', 'ftp', 'admin', 'test', 'dev', 'staging']
for sub in common_subdomains:
fqdn = f"{sub}.{domain}"
result = await lookup(fqdn, [RecordType.A])
if result.records:
print(f"Found: {fqdn}")
2. Certificate Transparency Logs Query crt.sh API for domains in SSL certificates:
import requests
response = requests.get(f"https://crt.sh/?q=%.{domain}&output=json")
3. DNS Zone Transfer (AXFR)
try:
zone = dns.zone.from_xfr(dns.query.xfr(nameserver, domain))
for name in zone:
print(f"{name}.{domain}")
except:
print("Zone transfer refused")
Security Note: Zone transfers are often blocked. Only test on domains you own.
Real World: Subdomain enumeration is first step in reconnaissance (MITRE T1590.002).
Challenge 5: DNS Monitoring and Alerting
Goal: Continuously monitor domains and alert on changes.
Architecture:
Periodic Queries (every 5 min)
↓
Compare to Previous State
↓
Detect Changes
↓
Send Alerts (email/Slack/webhook)
What to Monitor:
- A/AAAA record changes (infrastructure moved)
- MX record changes (email routing modified)
- NS record changes (DNS provider changed)
- New/removed records
Implementation:
- Store previous state in SQLite database
- Query on schedule (use
schedulelibrary or cron) - Compare current vs previous
- Trigger alerts on differences
Security Application: Detect DNS hijacking attempts. If NS records suddenly change, someone might have compromised the registrar account.
Real Incident: MyEtherWallet (2018) - BGP hijack changed DNS to point to phishing site. Monitoring would have detected this.
Challenge 6: DNS Performance Analysis
Goal: Measure and visualize DNS resolver performance.
Metrics to Track:
- Query latency percentiles (p50, p95, p99)
- Success rate by record type
- Timeout frequency
- Resolver comparison (8.8.8.8 vs 1.1.1.1 vs ISP)
Implementation:
- Extend
DNSResultwith more metrics - Query same domains from multiple resolvers
- Store results in time-series database (InfluxDB)
- Visualize with Grafana
Add to resolver.py:
@dataclass
class DNSResult:
# ... existing fields ...
resolver_ip: str | None = None
tcp_fallback: bool = False
truncated: bool = False
Analysis Questions:
- Which resolver is fastest for your location?
- Does performance vary by time of day?
- Which domains have the longest resolution times?
Advanced Challenges
Challenge 7: DNS Tunnel Detection
Goal: Identify DNS tunneling for data exfiltration.
DNS Tunneling Characteristics:
- High volume of queries to a single domain
- Large TXT record queries/responses
- Unusual subdomain lengths
- Base64/hex-encoded subdomains
- Regular query intervals
Implementation:
1. Entropy Analysis
import math
from collections import Counter
def calculate_entropy(subdomain: str) -> float:
"""High entropy suggests encoded data"""
counter = Counter(subdomain)
length = len(subdomain)
return -sum((count/length) * math.log2(count/length)
for count in counter.values())
# Legitimate: www.example.com (low entropy)
# Tunneling: aGVsbG8=.attacker.com (high entropy)
2. Query Volume Detection
# Track queries per domain
query_counts = defaultdict(int)
for domain in queries:
query_counts[domain] += 1
if query_counts[domain] > threshold:
alert(f"Possible tunneling: {domain}")
3. Subdomain Length Analysis
if len(subdomain) > 63: # DNS label limit
alert("Suspicious long subdomain")
Real Malware: Houdini worm, Feederbot, DNScat2 all use DNS tunneling.
References:
- CWE-406: Insufficient Control of Network Message Volume
- MITRE T1071.004: Application Layer Protocol: DNS
Challenge 8: Passive DNS Database
Goal: Build a historical database of DNS resolutions.
Architecture:
DNS Queries (from monitoring/batch)
↓
Store in Database
↓
Query Historical Data
Schema:
CREATE TABLE dns_records (
id INTEGER PRIMARY KEY,
domain TEXT,
record_type TEXT,
value TEXT,
ttl INTEGER,
first_seen TIMESTAMP,
last_seen TIMESTAMP,
seen_count INTEGER
);
CREATE INDEX idx_domain ON dns_records(domain);
CREATE INDEX idx_value ON dns_records(value);
Queries to Support:
- When did example.com first resolve to 1.2.3.4?
- What domains have resolved to this IP?
- How often does this domain change IPs?
Security Application: Track malware C2 infrastructure. Malicious domains often change IPs frequently.
Commercial Examples: VirusTotal, PassiveTotal, Farsight DNSDB.
Challenge 9: Real-time DNS Query Stream Analysis
Goal: Analyze live DNS query streams (from router/firewall logs).
Input Sources:
- pcap files from network captures
- Syslog from DNS servers
- Netflow/IPFIX data
- Cloud DNS query logs (AWS Route53, Google Cloud DNS)
Detection Patterns:
1. DGA (Domain Generation Algorithm)
def is_dga(domain: str) -> bool:
"""DGA domains are often random-looking"""
labels = domain.split('.')
if len(labels) < 2:
return False
sld = labels[-2] # second-level domain
# High consonant ratio
consonants = sum(1 for c in sld if c in 'bcdfghjklmnpqrstvwxyz')
if consonants / len(sld) > 0.7:
return True
# No dictionary words
# Low vowel ratio
# High entropy
return False
2. Fast Flux Detection Many IPs for one domain, changing frequently:
# Track A records over time
if len(unique_ips_for_domain) > 10 and avg_ttl < 300:
alert("Possible fast flux")
3. C2 Beaconing Regular periodic queries:
# Calculate query intervals
intervals = [queries[i+1].time - queries[i].time
for i in range(len(queries)-1)]
# If intervals are suspiciously regular
if std_dev(intervals) < threshold:
alert("Possible C2 beaconing")
Tools to Study: Zeek (formerly Bro), Suricata DNS analysis modules.
Challenge 10: DNS Firewall / Sinkhole
Goal: Block malicious domains by serving fake responses.
Architecture:
Client Query
↓
Your DNS Server
↓
Check Blocklist
↓
If Blocked: Return 0.0.0.0
If Allowed: Forward to Upstream Resolver
Implementation:
1. Basic DNS Server (use dnslib library)
from dnslib import DNSRecord, RR, QTYPE, A
from dnslib.server import DNSServer
class BlocklistResolver:
def __init__(self, blocklist):
self.blocklist = set(blocklist)
def resolve(self, request, handler):
qname = str(request.q.qname)
if qname.rstrip('.') in self.blocklist:
# Return sinkhole IP
reply = request.reply()
reply.add_answer(RR(qname, QTYPE.A, rdata=A("0.0.0.0")))
return reply
else:
# Forward to real resolver
return proxy_request(request)
2. Blocklist Sources
- Malware domain lists (abuse.ch)
- Phishing feeds (PhishTank)
- Ad/tracker lists (EasyList)
- Threat intel feeds
3. Logging and Analytics
- Track blocked query attempts
- Identify infected machines
- Measure effectiveness
Real Products: Pi-hole, AdGuard Home, Cisco Umbrella.
Expert Challenges
Challenge 11: DNS Amplification Attack Detection
Goal: Detect when your DNS server is being used for amplification attacks.
Attack Pattern:
- Attacker sends queries with spoofed source IP (victim's address)
- Your server sends large responses to victim
- Victim gets flooded
Detection Signals:
# 1. High volume from single IP
queries_per_ip = defaultdict(int)
# 2. Queries for large record types
if record_type in [RecordType.TXT, RecordType.ANY]:
suspicious_count += 1
# 3. Responses much larger than queries
if response_size / query_size > 50:
alert("High amplification factor")
# 4. No follow-up queries (victim doesn't actually want data)
if client_ip in one_shot_queries:
alert("Possible spoofed source")
Mitigation:
- Rate limit queries per IP
- Disable ANY queries (RFC 8482)
- Response rate limiting (RRL)
- BCP38 filtering (prevent spoofed source IPs)
Challenge 12: Custom DNS Record Types
Goal: Add support for newer/specialized record types.
Record Types to Add:
CAA (Certification Authority Authorization)
# In resolver.py:24-33
class RecordType(StrEnum):
# ... existing types ...
CAA = "CAA" # RFC 8659
Specifies which CAs can issue certificates for domain. Security-critical.
SSHFP (SSH Fingerprint)
SSHFP = "SSHFP" # RFC 4255
Publishes SSH server key fingerprints in DNS for verification.
TLSA (DANE/TLSA)
TLSA = "TLSA" # RFC 6698
DNS-based Authentication of Named Entities. Publishes TLS certificate hashes.
DNSKEY, DS, RRSIG (DNSSEC records) For challenge 1 (DNSSEC validation).
Challenge 13: Geographic DNS Analysis
Goal: Determine where DNS servers are located and analyze geographic distribution.
Implementation:
1. GeoIP Lookup
import geoip2.database
reader = geoip2.database.Reader('GeoLite2-City.mmdb')
for nameserver_ip in result.nameserver_ips:
response = reader.city(nameserver_ip)
print(f"{nameserver_ip}: {response.city.name}, {response.country.name}")
2. Latency-based Geolocation Ping from multiple vantage points, use speed-of-light calculations to estimate location.
3. Anycast Detection If same IP resolves to different locations, it's anycast (like root servers, Google DNS, Cloudflare DNS).
Security Analysis:
- Is DNS infrastructure geographically diverse? (resilience)
- Are responses coming from unexpected countries? (hijacking)
- Latency analysis for optimal resolver selection
Challenge 14: DNS Covert Channel Communication
Goal: Implement bidirectional communication over DNS (for research/education only).
How It Works:
Client → Server (via queries)
Encode message in subdomain:
aGVsbG8=.tunnel.attacker.com
Server → Client (via responses)
Encode response in TXT record:
"d29ybGQ="
Implementation:
def encode_query(data: bytes, domain: str) -> str:
"""Encode data in subdomain"""
encoded = base64.b64encode(data).decode()
# Split into DNS labels (63 char max)
labels = [encoded[i:i+63] for i in range(0, len(encoded), 63)]
return '.'.join(labels) + '.' + domain
def decode_response(txt_record: str) -> bytes:
"""Decode data from TXT record"""
return base64.b64decode(txt_record)
Challenges:
- DNS has size limits (512 bytes UDP, 4096 TCP)
- Must handle fragmentation
- Packet loss requires retransmission
- High latency (1-2s per request)
Countermeasures to Study:
- Entropy analysis (challenge 7)
- Query volume limits
- Subdomain length restrictions
- TXT record size monitoring
Ethical Note: Only test on infrastructure you own. DNS tunneling without authorization is illegal.
Challenge 15: Build a Recursive DNS Resolver
Goal: Implement a full recursive resolver from scratch (like BIND, Unbound).
What It Does:
- Accept queries from clients
- Iterate through DNS hierarchy (like trace command)
- Cache results
- Return answers
Core Components:
1. Cache
from functools import lru_cache
import time
class DNSCache:
def __init__(self):
self.cache = {}
def get(self, key):
if key in self.cache:
value, expiry = self.cache[key]
if time.time() < expiry:
return value
return None
def set(self, key, value, ttl):
self.cache[key] = (value, time.time() + ttl)
2. Recursive Resolution (extend trace_dns() from resolver.py:293-426)
3. Server Loop
from dnslib.server import DNSServer
class RecursiveResolver:
def resolve(self, request, handler):
qname = str(request.q.qname)
# Check cache
cached = self.cache.get(qname)
if cached:
return cached
# Perform recursive resolution
result = trace_and_resolve(qname)
# Cache result
self.cache.set(qname, result, ttl=300)
return result
resolver = RecursiveResolver()
server = DNSServer(resolver, port=5353)
server.start_thread()
Challenges:
- Handle CNAME chains
- Implement negative caching (NXDOMAIN)
- Deal with timeouts and retries
- DNSSEC validation
- Handle TCP fallback for large responses
Testing:
dig @localhost -p 5353 example.com
Research Challenges
Challenge 16: Machine Learning for Malicious Domain Detection
Goal: Train ML model to classify domains as malicious or benign.
Features to Extract:
- Domain length
- Character entropy
- N-gram frequencies
- Vowel/consonant ratio
- TLD (.com vs .xyz vs .tk)
- Registration age (from WHOIS)
- Subdomain count
- Historical IP changes
- ASN reputation
Training Data:
- Benign: Alexa/Majestic top sites
- Malicious: abuse.ch, PhishTank, malware feeds
Models to Try:
- Random Forest
- XGBoost
- Neural networks for sequence data
Evaluation:
- Precision/recall on test set
- False positive rate (critical for blocklists)
- Performance on DGA domains
Challenge: Low false positives while catching novel threats.
Challenge 17: DNS Privacy Analysis
Goal: Measure information leakage from DNS queries.
What Leaks:
- Browsing history from query logs
- Location from resolver choice
- Device type from query patterns
- App usage from CDN queries
Experiments:
1. Reconstruct Browsing Session Collect DNS queries for 1 hour. Can you infer:
- Which websites visited?
- Which apps used?
- User's interests/demographics?
2. DNS Fingerprinting Different devices make different queries:
- Android queries android.googleapis.com
- iOS queries apple.com services
- Windows queries microsoft.com
3. Correlation Attacks Even with DoH, timing analysis can reveal sites:
# Time between query and HTTP request
# Query pattern (images, scripts, API calls)
# Size of responses
References:
- "The Effect of DNS on Tor's Anonymity" (research paper)
- CWE-201: Information Exposure Through Sent Data
Challenge 18: Develop DNS Benchmarking Suite
Goal: Create comprehensive DNS performance testing toolkit.
Benchmarks:
1. Latency
- Measure p50, p95, p99 query latency
- Test from multiple geographic locations
- Compare resolvers (Google, Cloudflare, Quad9)
2. Throughput
- Queries per second capacity
- Concurrent query handling
3. Reliability
- Success rate over 24 hours
- NXDOMAIN handling
- Timeout frequency
4. Privacy
- Query minimization support (RFC 7816)
- DNSSEC validation
- DoH/DoT support
5. Censorship Resistance
- Are queries filtered?
- Are results manipulated?
Tools to Build:
- Automated test runner
- Result aggregation and visualization
- Historical tracking
- Alerting on degradation
Public Service: Publish results like DNSPerf.com
Wrap-Up
Each challenge builds specific skills:
- Challenges 1-3: Tool development, output formats
- Challenges 4-6: Security monitoring, performance analysis
- Challenges 7-10: Threat detection, defensive tools
- Challenges 11-15: Advanced DNS concepts, covert channels
- Challenges 16-18: Research, ML, measurement studies
Next Steps:
- Pick challenges matching your skill level
- Start with beginner challenges to learn codebase
- Progress to security-focused intermediate challenges
- Tackle advanced challenges for deep expertise
Resources:
- DNS RFCs (1034, 1035, and extensions)
- OWASP Testing Guide (DNS sections)
- MITRE ATT&CK Framework (T1590, T1071.004, T1584.002)
- DNSViz for visualizing DNSSEC
- Wireshark for packet analysis
Happy hacking! Remember: only test on systems you own or have explicit permission to test.