The Domain Name System (DNS) is often called the phonebook of the internet. It translates human-readable domain names into IP addresses that computers use to identify each other. Understanding DNS is essential for network engineers, developers, and anyone building internet-facing applications.
In this guide, we’ll explore how DNS works, the various record types, resolution processes, and security best practices.
How DNS Works
The Problem DNS Solves
# Without DNS, you'd need to remember:
ip_addresses = {
"google": "142.250.185.14",
"facebook": "157.240.221.35",
"amazon": "18.164.174.19",
# ... millions of addresses
}
# With DNS, just use:
domain = "google.com" # Much easier to remember!
DNS Hierarchy
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DNS Hierarchy โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Root Zone (.) โ โ
โ โ "." nameservers โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ โ
โ โ .com โ โ .org โ โ .net โ โ
โ โ TLD โ โ TLD โ โ TLD โ โ
โ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โโโโโโฌโโโโโ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Authoritative Nameservers โ โ
โ โ โ โ
โ โ ns1.example.com ns2.example.com ns3.example.comโ โ
โ โ (Your domain's DNS) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
DNS Resolution Process
# Step-by-step DNS resolution
resolution_steps = """
1. Client queries local resolver (ISP or local)
2. Local resolver checks cache
- If cached: return result
- If not: continue to root
3. Query Root Nameserver (.)
- Returns: .com TLD nameserver addresses
4. Query .com TLD Nameserver
- Returns: authoritative nameserver for example.com
5. Query Authoritative Nameserver for example.com
- Returns: 93.184.216.34 (A record)
6. Return result to client
- Cache the result for future requests
"""
DNS Query Types
# Iterative Query (most common)
# Resolver asks each server for the next step
iterative_query = """
Client โ Local Resolver โ Root Server (.com NS)
โ TLD Server (example.com NS)
โ Authoritative (93.184.216.34)
โ Client
"""
# Recursive Query
# Server does all the work
recursive_query = """
Client โ Local Resolver (does all lookups)
โ Root โ TLD โ Auth โ TLD โ Root โ Client
"""
# Both return the same result, but recursion
# is handled by the resolver
DNS Records
A and AAAA Records
# A Record - IPv4 Address
# Maps domain to IPv4 address
example.com. IN A 93.184.216.34
www.example.com. IN A 93.184.216.34
# AAAA Record - IPv6 Address
# Maps domain to IPv6 address
example.com. IN AAAA 2606:2800:220:1:248:1893:25c8:1946
www.example.com. IN AAAA 2606:2800:220:1:248:1893:25c8:1946
CNAME Record
# CNAME - Canonical Name (alias)
# Points one domain to another
blog.example.com. IN CNAME www.example.com.
shop.example.com. IN CNAME shops.shopify.com.
cdn.example.com. IN CNAME example.cloudfront.net.
# Good: blog -> www -> actual server
# CNAME chains are resolved at query time
MX Record
# MX Record - Mail Exchange
# Specifies mail servers for domain
example.com. IN MX 10 mail1.example.com.
example.com. IN MX 20 mail2.example.com.
example.com. IN MX 30 mail.backup-provider.com.
# Priority: Lower number = higher priority
# Client tries 10 first, then 20, then 30
TXT Record
# TXT Record - Arbitrary text
# Used for verification, SPF, DKIM, DMARC
# SPF - Sender Policy Framework
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
# DKIM - DomainKeys Identified Mail
selector._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjAN..."
# DMARC - Domain-based Message Authentication
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
# Google verification
google-site-verification.example.com. IN TXT "google-site-verification=abc123"
NS Record
# NS Record - Nameserver
# Delegates domain to nameservers
example.com. IN NS ns1.example.com.
example.com. IN NS ns2.example.com.
example.com. IN NS ns3.example.com.
SOA Record
# SOA Record - Start of Authority
# Contains admin info and timing
example.com. IN SOA ns1.example.com. admin.example.com. (
2025022101 ; Serial (YYYYMMDDNN)
3600 ; Refresh (1 hour)
1800 ; Retry (30 minutes)
604800 ; Expire (1 week)
86400 ) ; Minimum TTL (1 day)
Other Important Records
# PTR Record - Pointer Record (Reverse DNS)
# Maps IP to domain name
34.216.184.93.in-addr.arpa. IN PTR example.com.
# SRV Record - Service Location
# Defines location of services
_http._tcp.example.com. IN SRV 10 5 80 www.example.com.
# CAA Record - Certification Authority Authorization
# Specifies allowed CAs
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 iodef "mailto:[email protected]"
# DNS TTL (Time To Live)
# How long to cache the record
example.com. IN A 93.184.216.34
3600 ; TTL (1 hour in seconds)
DNS Tools and Commands
dig Command
# Basic lookup
dig example.com
# Specific record type
dig A example.com
dig AAAA example.com
dig MX example.com
dig TXT example.com
dig NS example.com
# Query specific nameserver
dig @8.8.8.8 example.com A
# Reverse DNS lookup
dig -x 93.184.216.34
# Trace resolution path
dig +trace example.com
# Short output
dig +short example.com
# Show TTL values
dig +noall +answer example.com
nslookup
# Basic lookup
nslookup example.com
# Specific record type
nslookup -type=MX example.com
# Query specific server
nslookup example.com 8.8.8.8
# Reverse lookup
nslookup 93.184.216.34
whois
# Domain registration info
whois example.com
# Detailed output
whois -h whois.verisign.com example.com
Python DNS Examples
import dns.resolver
import dns.query
import dns.zone
import dns.name
# Basic DNS lookup
resolver = dns.resolver.Resolver()
# Resolve A record
answers = resolver.resolve('example.com', 'A')
for rdata in answers:
print(f"A record: {rdata}")
# Resolve MX records
answers = resolver.resolve('example.com', 'MX')
for rdata in answers:
print(f"MX: {rdata.preference} {rdata.exchange}")
# Reverse DNS lookup
ip = dns.reversename.from_address('93.184.216.34')
answers = resolver.resolve(ip, 'PTR')
print(f"PTR: {answers[0]}")
# Custom nameserver
resolver = dns.resolver.Resolver()
resolver.nameservers = ['8.8.8.8', '8.8.4.4'] # Google DNS
answers = resolver.resolve('example.com', 'A')
# DNSSEC validation
import dns.resolver
import dns.flags
def validate_dnssec(domain):
resolver = dns.resolver.Resolver()
request = dns.message.make_query(domain, 'A')
request.flags |= dns.flags.AD
response = resolver.resolve(request)
if response.flags & dns.flags.AD:
print(f"DNSSEC validated for {domain}")
else:
print(f"DNSSEC not validated for {domain}")
DNS Resolution in Applications
Python Socket Module
import socket
# Simple hostname to IP
ip = socket.gethostbyname('example.com')
print(f"IP: {ip}")
# Get all IP addresses
ips = socket.getaddrinfo('example.com', 80)
for ip_info in ips:
family, socktype, proto, canonname, sockaddr = ip_info
print(f"IP: {sockaddr[0]}")
# Reverse DNS
hostname = socket.gethostbyaddr('93.184.216.34')
print(f"Hostname: {hostname[0]}")
# Caching with dnspython
from dns.resolver import Cache
cache = Cache()
resolver = dns.resolver.Resolver()
resolver.cache = cache
DNS in Production Applications
# Good practice: Use multiple DNS servers
dns_servers = [
'8.8.8.8', # Google
'8.8.4.4', # Google
'1.1.1.1', # Cloudflare
'1.0.0.1', # Cloudflare
]
# Implement fallback
def resolve_with_fallback(hostname, record_type='A'):
for server in dns_servers:
try:
resolver = dns.resolver.Resolver()
resolver.nameservers = [server]
answers = resolver.resolve(hostname, record_type)
return [str(rdata) for rdata in answers]
except:
continue
raise Exception(f"Failed to resolve {hostname}")
# Health checking with DNS
import socket
import time
def check_dns_health():
test_domains = [
('google.com', 'A'),
('cloudflare.com', 'A'),
('example.com', 'A')
]
for domain, rtype in test_domains:
try:
start = time.time()
socket.gethostbyname(domain)
elapsed = (time.time() - start) * 1000
print(f"{domain}: {elapsed:.1f}ms")
except:
print(f"{domain}: FAILED")
DNS Security
DNS Attacks
# Common DNS attacks
dns_attacks = {
"dns_spoofing": {
"description": "Attacker injects fake DNS records",
"mitigation": "DNSSEC"
},
"dns_amplification": {
"description": "Attacker uses DNS to amplify DDoS",
"mitigation": "Rate limiting, BCP38"
},
"dns_tunneling": {
"description": "Exfiltrating data via DNS queries",
"mitigation": "DNS filtering, monitoring"
},
"dns_hijacking": {
"description": "Redirecting DNS queries to malicious servers",
"mitigation": "DNSSEC, registry locks"
},
"NXDOMAIN_attack": {
"description": "Flooding with fake NXDOMAIN responses",
"mitigation": "RRL (Response Rate Limiting)"
}
}
DNSSEC
# DNSSEC adds cryptographic signatures to DNS
# How it works:
# 1. Zone signs its records with ZSK (Zone Signing Key)
# 2. KSK (Key Signing Key) signs the ZSK
# 3. Chain of trust goes up to root
# Enable DNSSEC in BIND
options {
dnssec-enable yes;
dnssec-validation auto;
};
# DNSSEC key signing
dnssec-keygen -a RSASHA256 -b 2048 -K /etc/bind/keys example.com
dnssec-signzone -S -K /etc/bind/keys example.com
DNS over HTTPS (DoH)
# Traditional DNS (unencrypted)
# Queries sent in plain text over UDP/TCP port 53
# DNS over HTTPS (encrypted)
# Queries sent via HTTPS to DoH server
# Benefits:
# - Encryption hides queries from ISPs
# - Bypasses DNS-based blocking
# - More reliable on some networks
Python DoH Example
import requests
import json
# Cloudflare DoH
DOH_CLOUDFLARE = "https://cloudflare.com/dns-query"
def resolve_doh(domain, record_type='A'):
headers = {
'accept': 'application/dns-json'
}
params = {
'name': domain,
'type': record_type
}
response = requests.get(DOH_CLOUDFLARE,
headers=headers,
params=params)
data = response.json()
results = []
if 'Answer' in data:
for answer in data['Answer']:
results.append({
'type': answer['type'],
'data': answer['data']
})
return results
# Example usage
results = resolve_doh('example.com')
for r in results:
print(r)
DNS Filtering
# Block malicious domains
import re
BLOCKED_DOMAINS = {
'malware.example.com',
'phishing.bad-site.com',
'ads.tracker.com',
}
def should_block(domain):
# Exact match
if domain in BLOCKED_DOMAINS:
return True
# Check subdomains
for blocked in BLOCKED_DOMAINS:
if domain.endswith('.' + blocked):
return True
return False
# Using Pi-hole for network-wide blocking
# Pi-hole is a DNS-level ad blocker
#
# Configure in /etc/dnsmasq.d/:
# address=/doubleclick.net/0.0.0.0
# address=/facebook.com/0.0.0.0
DNS for High Availability
Multiple Nameservers
# Best practice: 3+ nameservers
# Different providers
# Different geographic locations
# Example configuration:
nameservers:
- ns1.cloudprovider.com # Primary (AWS Route 53)
- ns2.cloudprovider.com # Secondary
- ns3.google.com # Tertiary (GCP)
- ns4.google.com # Quaternary
TTL Strategy
# TTL (Time To Live) guidelines
ttl_strategy = {
"standard_records": {
"A": 3600, # 1 hour
"AAAA": 3600,
"CNAME": 3600,
"MX": 86400 # 24 hours (rarely changes)
},
"low_ttl_before_change": {
"description": "Lower TTL before making changes",
"value": 300, # 5 minutes
"when": "24-48 hours before DNS change"
},
"high_traffic": {
"A": 300, # Lower for frequently changing IPs
"CNAME": 300
},
"stable": {
"MX": 86400, # Higher for stable records
"NS": 86400
}
}
Geographic DNS
# Route 53 Geolocation routing
geolocation_config = """
# Direct traffic based on user location
us-east-1 -> 53.40.10.10 # US users
eu-west-1 -> 53.50.20.20 # European users
ap-south-1 -> 53.60.30.30 # Asian users
default -> 53.70.40.40 # Default
# Latency routing
# Route to lowest latency region
latency_config = {
"us-east": {"region": "us-east-1", "ip": "53.40.10.10"},
"eu-west": {"region": "eu-west-1", "ip": "53.50.20.20"}
}
"""
Conclusion
DNS is fundamental to internet infrastructure:
- Resolution: DNS translates names to IPs through hierarchical nameservers
- Records: Different record types serve different purposes (A, AAAA, CNAME, MX, TXT, etc.)
- Security: DNSSEC, DoH, and filtering protect against attacks
- Availability: Multiple nameservers, proper TTLs, and geographic routing ensure reliability
Understanding DNS is essential for network engineers and developers building internet-facing applications.
Related Articles
- HTTP/3 and QUIC: The Future of Transport Protocols
- ARQ Protocols
- TLS/SSL: Transport Layer Security Explained
Comments