About
The Domain Name System is a hierarchical and distributed naming system for computers, services, and other resources in the Internet or other Internet Protocol networks. It associates various information with domain names assigned to each of the associated entities.
Paul Mockapetris, a UCI alumnus, is the inventor of the Domain Name System (DNS) and his creation of DNS is one of the reasons that we have been able to scale the Internet to as we know it today!
Aim
Computer Networks is not really one of my greatest strengths, and what could be better (and cooler) than getting my hands dirty and implementing my own DNS server!
This project is a basic implementation of a DNS server with the goal of understanding how DNS works, what do the DNS question and response packets look like, and playing around with the dig and nc commands.
Implementation
- Understanding the DNS protocol
-
Understanding the DNS packets
To achieve this, I went through the DNS RFC (Pg 25) to understand the message sections and their respective formats -
Inspecting DNS packets
To understand the DNS packets in practice, I used the nc command to listen to a port, and the dig command with the+noedns
flag to create a query packet
# this records the query packet in query.txt
nc -u -l 1053 > query.txt
dig -p 1053 @127.0.0.1 +noedns google.com # lookup google.com's IP
Then, I used this query packet to record a response packet by sending the same query to Google’s DNS
# this records the response packet in response.txt
nc -u 8.8.8.8 53 < query.txt > response.txt # 53 is the DNS port
To inspect the query and response packets, I used the following commands:
hexdump -C query.txt
hexdump -C response.txt
- Parsing the response packet
Once I had inspected the DNS packets, the next step was parsing the DNS response packet. DNS RFC (Pg 26-29) mention the Header, Question and Record formats. With the help of this specification, I was able to parse the response packets.
- Building a DNS stub resolver
A DNS stub resolver serves as an intermediary between the application requiring DNS resolution, and a recursive DNS resolver.
- Forming Query and Response packets
As I already knew the format of the different sections, I now added writing functionality to support formation of query and response packets in addition to simply reading them.
2.Creating a UDP client
So far, I was able to parse DNS response packets off of the disk. But to build a stub resolver,
I implemented a UDP client to send query packets to and receive response packets from a recursive DNS resolver.
In the image “1” represents the record type A.
- Adding Support for other Record Types
Up to this point, the DNS stub resolver only supported records of type A. In this step, I added support for other major record types such as CNAME, NS, MX and AAAA
- Implementing a DNS Proxy Server
To get one step closer to implementing a recursive DNS resolver, I first implemented a simple DNS proxy server. This server acts as a middleman and simply forwards the query to an actual DNS resolver and returns the response back to the client.
# Send a lookup query to the DNS Proxy Server listening on port 1053
dig -p 1053 @127.0.0.1 +noedns google.com # lookup google.com's IP
With this, my DNS proxy server is up and running and can respond to queries with different record types! 🥳 🎉
- Implementing the DNS recursive resolver
This is the final step of this project where I go about implementing a recursive resolver. So far my server was simply
a proxy server, dependent on another server to actually perform the lookup. In this step, I recursively resolve a domain
starting right from the root servers, resolving the top-level domains first, i.e. when resolving www.google.com
, the
root servers give me the information about com
and tell me where to look next. I perform this lookup recursively till
I end up with the entire domain name that the query was searching for.
# Send a lookup query to the DNS Server listening on port 3053
dig +noedns +norecurse @127.0.0.1 -p 3053 www.google.com # lookup www.google.com's IP
What I learned
I gained a lot of knowledge w.r.t. Computer Networks and DNS while working on this project;
parsing the DNS packets helped me refresh my bit manipulation skills and I worked with sockets once again while
implementing the UDP client.
As I worked on this project independently, I navigated through all the challenges on my own and that helped me boost my
confidence in my skills.