In today’s connected world, DNS servers play a crucial role in translating human-friendly domain names into IP addresses that computers use to identify each other on the network. While many rely on public DNS services, setting up your own local DNS server can be beneficial for various reasons, including local development, internal network management, and educational purposes.
Development and Testing: Easily create and manage custom domains for testing web applications.
Educational Purposes: Learn how DNS works and experiment with DNS configurations.
Local Network Management: Manage internal domains within a private network.
Create two HTML files (a.html
and b.html
) in a directory named html-files
. These files will be served when you access a.com
and b.com
Respectively.
<!-- a.com -->
<!DOCTYPE html>
<html>
<head>
<title>A Page</title>
</head>
<body>
<h1>Welcome to A.com</h1>
</body>
</html>
<!-- b.com -->
<!DOCTYPE html>
<html>
<head>
<title>B Page</title>
</head>
<body>
<h1>Welcome to B.com</h1>
</body>
</html>
Next, we’ll create a simple HTTP server using Python’s built-in. http.server
Module to serve the HTML files.
#http_server.py
import http.server
import socketserver
PORT = 8080
DIRECTORY = "html-files"
class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/a.com':
self.path = '/a.html'
elif self.path == '/b.com':
self.path = '/b.html'
return http.server.SimpleHTTPRequestHandler.do_GET(self)
def translate_path(self, path):
return f"./{DIRECTORY}/{path}"
handler_object = MyHttpRequestHandler
my_server = socketserver.TCPServer(("0.0.0.0", PORT), handler_object)
print(f"Serving HTTP on port {PORT}")
my_server.serve_forever()
http.server
: Provides basic HTTP server functionality.
socketserver
: A framework for network servers.
PORT = 8080
: The server will listen on port 8080.
DIRECTORY = "html-files"
: The directory where HTML files are stored.
MyHttpRequestHandler
: Custom request handler class that overrides do_GET
to serve specific files for a.com
and b.com
.
do_GET(self)
: Checks the requested path and maps /a.com
to /a.html
and /b.com
to /b.html
. The http.server.SimpleHTTPRequestHandler
Serves these files.
translate_path(self, path)
: Translates the requested path to the correct file path within the html-files
directory.
socketserver.TCPServer(("0.0.0.0", PORT), handler_object)
: Binds the server to all available interfaces on port 8080.my_server.serve_forever()
: Starts the server to handle incoming requests indefinitely.
We’ll use the dnslib
Library to create a DNS server that resolves a.com
and b.com
to your local machine’s IP address.
from dnslib import DNSRecord, QTYPE, RR, A, DNSHeader
import socket
import socketserver
# Get the local IP address
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
# DNS server configuration
DOMAIN_TO_IP = {
'a.com.': local_ip,
'b.com.': local_ip,
}
class DNSHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
try:
request = DNSRecord.parse(data)
print(f"Received request for: {str(request.q.qname)}")
# Create a DNS response with the same ID and the appropriate flags
reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
qname = str(request.q.qname)
qtype = QTYPE[request.q.qtype]
if qname in DOMAIN_TO_IP:
reply.add_answer(RR(qname, QTYPE.A, rdata=A(DOMAIN_TO_IP[qname])))
print(f"Resolved {qname} to {DOMAIN_TO_IP[qname]}")
else:
print(f"No record found for {qname}")
socket.sendto(reply.pack(), self.client_address)
except Exception as e:
print(f"Error handling request: {e}")
if __name__ == "__main__":
server = socketserver.UDPServer(("0.0.0.0", 53), DNSHandler)
print("DNS Server is running...")
server.serve_forever()
dnslib
: Provides DNS record creation and parsing.
socket
, socketserver
: Modules for network communication.
hostname = socket.gethostname()
: Retrieves the hostname of the local machine.
local_ip = socket.gethostbyname(hostname)
: Resolves the hostname to an IP address.
DOMAIN_TO_IP
: A dictionary mapping domain names to the local machine’s IP address.
DNSHandler
: Custom request handler class for handling DNS requests.
handle(self)
: Processes incoming DNS requests.
data = self.request[0].strip()
: Reads the incoming data.
request = DNSRecord.parse(data)
: Parses the DNS request.
print(f"Received request for: {str(request.q.qname)}")
: Logs the requested domain.
DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q)
: Creates a DNS response with the same ID and appropriate flags.
if qname in DOMAIN_TO_IP
: Checks if the requested domain is in the configuration.
reply.add_answer(RR(qname, QTYPE.A, rdata=A(DOMAIN_TO_IP[qname])))
: Adds an answer to the DNS response.
socket.sendto(reply.pack(), self.client_address)
: Sends the DNS response back to the client.
socketserver.UDPServer(("0.0.0.0", 53), DNSHandler)
: Binds the server to all available interfaces on port 53.server.serve_forever()
: Starts the server to handle incoming requests indefinitely.To access a.com
and b.com
from your mobile device, you need to configure your mobile device to use your local DNS server.
Go to Settings
> Network & Internet
> Wi-Fi
.
Tap on the Wi-Fi network you are connected to.
Tap on Advanced
> IP settings
And change it from DHCP
to Static
.
192.168.1.*
).192.168.1.*
).24
.192.168.1.*
).8.8.8.8
(optional).Go to Settings
> Wi-Fi
.
Tap on the i
Icon next to the connected network.
Configure DNS
.Manual
.192.168.1.*
)Open a web browser on your mobile device, and navigate to:
http://a.com:8080
http://b.com:8080
Ensure you are running the DNS server with root privileges.
Check for errors in the console output.
Ensure your firewall allows incoming connections on ports 53 (DNS) and 8080 (HTTP).
Verify that your local machine and mobile device are on the same network.
Use the dig command to test DNS resolution locally:
dig @127.0.0.1 b.com
Setting up a local DNS server with Python is a powerful way to manage custom domains for development and internal network management. By following this guide, you can create a fully functional local DNS server and serve custom HTML pages from local domains accessible from any device on your network.
I hope this article helps you understand the process and benefits of running your own DNS server.
Next, we’ll discuss security considerations when running your own DNS server.
Happy coding!