DNS Querying with Python

Loading

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.

Leave a Reply

Your email address will not be published. Required fields are marked *