DNS (Domain Name System) is responsible for translating human-readable domain names (e.g., google.com
) into IP addresses (142.250.180.46
). Python provides several libraries for querying DNS records, resolving domains, and troubleshooting network issues.
Why Perform DNS Queries in Python?
✔ Automate domain lookup tasks
✔ Perform security analysis and reconnaissance
✔ Identify DNS misconfigurations
✔ Monitor DNS records for changes
1. Performing DNS Queries with socket
Python’s built-in socket
module provides basic DNS resolution.
Get the IP Address of a Domain
import socket
domain = "google.com"
ip_address = socket.gethostbyname(domain)
print(f"IP Address of {domain}: {ip_address}")
✔ Resolves a domain to an IPv4 address.
Get All IP Addresses (IPv4 and IPv6)
import socket
domain = "google.com"
addresses = socket.getaddrinfo(domain, None)
for address in addresses:
print(address[4][0])
✔ Retrieves both IPv4 (A) and IPv6 (AAAA) addresses.
2. Advanced DNS Querying with dnspython
The dnspython
library provides more control over DNS queries, including retrieving different record types.
Installing dnspython
pip install dnspython
Querying A (IPv4) Records
import dns.resolver
domain = "google.com"
result = dns.resolver.resolve(domain, "A")
for ip in result:
print(f"A Record: {ip}")
✔ Retrieves IPv4 addresses linked to the domain.
📍 Querying AAAA (IPv6) Records
result = dns.resolver.resolve(domain, "AAAA")
for ip in result:
print(f"AAAA Record: {ip}")
✔ Retrieves IPv6 addresses.
Querying MX (Mail Exchange) Records
result = dns.resolver.resolve(domain, "MX")
for mx in result:
print(f"Mail Server: {mx.exchange}, Priority: {mx.preference}")
✔ Identifies mail servers responsible for handling email for the domain.
Querying NS (Name Server) Records
result = dns.resolver.resolve(domain, "NS")
for ns in result:
print(f"Name Server: {ns}")
✔ Retrieves the authoritative name servers for the domain.
Querying TXT Records
result = dns.resolver.resolve(domain, "TXT")
for txt in result:
print(f"TXT Record: {txt.to_text()}")
✔ Fetches TXT records, often used for SPF, DKIM, and other domain verifications.
3. Reverse DNS Lookup
Perform a reverse lookup to find the domain associated with an IP address.
import socket
ip_address = "8.8.8.8"
domain = socket.gethostbyaddr(ip_address)
print(f"Reverse Lookup for {ip_address}: {domain[0]}")
✔ Finds the domain associated with an IP address.
4. Using scapy
for DNS Queries
scapy
is a powerful networking tool that can be used to send custom DNS queries.
Installing scapy
pip install scapy
Sending a DNS Query
from scapy.all import sr1, IP, UDP, DNS, DNSQR
domain = "google.com"
dns_query = sr1(IP(dst="8.8.8.8")/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname=domain)), verbose=0)
print(f"Response: {dns_query[DNS].summary()}")
✔ Queries a DNS server (Google’s 8.8.8.8) directly.
5. Querying a Custom DNS Server
By default, queries go through the system-configured DNS server. We can specify a custom DNS server like Cloudflare (1.1.1.1) or Google (8.8.8.8).
resolver = dns.resolver.Resolver()
resolver.nameservers = ["1.1.1.1"] # Cloudflare DNS
result = resolver.resolve("google.com", "A")
for ip in result:
print(f"IP Address: {ip}")
✔ Sends queries to Cloudflare’s DNS (1.1.1.1).
6. Checking DNS Propagation
Check if a domain’s DNS records have updated across multiple DNS servers.
dns_servers = ["8.8.8.8", "1.1.1.1", "208.67.222.222"] # Google, Cloudflare, OpenDNS
domain = "google.com"
for server in dns_servers:
resolver.nameservers = [server]
result = resolver.resolve(domain, "A")
for ip in result:
print(f"DNS Server: {server}, IP: {ip}")
✔ Retrieves A records from different public DNS providers.
7. Handling Errors in DNS Queries
Handle exceptions for better fault tolerance.
try:
result = dns.resolver.resolve("nonexistentdomain.xyz", "A")
for ip in result:
print(ip)
except dns.resolver.NXDOMAIN:
print("Domain does not exist.")
except dns.resolver.Timeout:
print("Query timed out.")
except dns.resolver.NoAnswer:
print("No answer received.")
✔ Catches NXDOMAIN (nonexistent domain), timeout, and empty responses.
8. Monitoring DNS Changes
Monitor changes in DNS records over time.
import time
domain = "example.com"
previous_result = None
while True:
result = dns.resolver.resolve(domain, "A")
current_ips = [ip.to_text() for ip in result]
if previous_result and previous_result != current_ips:
print(f"DNS change detected! New IPs: {current_ips}")
previous_result = current_ips
time.sleep(60) # Check every minute
✔ Detects DNS record changes in real-time.