CS 457 – Fall 2015 Project 3: DNS Resolver
Version 1.0
Date assigned: Thursday, October 29, 2015
Date due: Sunday, November 22, 2015 at 11:59 PM
Note: this project counts as 20% of your total semester grade, so this project is equivalent to the midterm
Objective and Sample Output
The objective of this project is to implement a DNS resolver in Python. The resolver should query the appropriate chain of DNS authoritative servers to resolve a domain name for any requested record type, include A records, AAAA records, MX records, TXT records, etc. Each answer retrieved should also include associated DNSSEC RRSIG or NSEC data. The resolver does NOT have to actually do the cryptographic operations to validate the signatures. The resolver should store answers in a cache, and retrieve answers from cache if present. Each step of the resolution should be timed so that we can get the latency for each step of the resolution as well as overall latency to get the final answer.
The resolver program should read a file specified as an argument in the command line.
myresolver commandfile
This file will contain a series of the following 3 commands:
• resolvedomainnameRRTYPE • printcache
• quit
An example command file might look like this (the actual test file will be posted within 2 weeks):
resolve www.nlnetlabs.nl AAAA resolve www.cs.colostate.edu A resolve secure64.com MX print cache
quit
The resolver should issue a series or iterative queries to obtain the DNS answer along with any DNSSEC signatures (RRSIG records) for this domain name. Note: not all domain names will have DNSSEC data. If a CNAME is encountered, the resolver must then resolve the CNAME (or chain of CNAMEs) to get the final answer.
Several examples:
Executing a command for resolving www.nlnetlabs.nl for an AAAA record should print the answer obtained from each iteration along with the elapsed time for that
iteration. Each step of the resolution will print output similar to the ANSWER section of a DIG command. The final answer will look something like this:
www.nlnetlabs.nl. 10151 IN AAAA 2a04:b900::1:0:0:10 www.nlnetlabs.nl. 10151 IN RRSIG AAAA 8 3 10200 20141112005013 20141015005013 42393 nlnetlabs.nl. mFhiqFsSAD+DID7wTKfDCP5/cvR/dlzLGPc8dvRsaRcSrLNsH8gFTF7m HvFHHPuTAT9235c14f3FT+qc+RB7dwjr/94WzOcLimZBACbif+gXILiV 7dtGiLQmO90MleG/MaiYm7HX5o+/aGoH973lda9zyofqcid08HEfPRTt uDo=
elapsed time for this iteration: 50.30 milliseconds total latency: 242.44 milliseconds
As another example, running the command to resolve www.cnn.com A should produce output for the final answer similar to the following. (Note, no RRSIG records were available). Don’t forget, you must print something like this for each step of the iteration!
cnn-56m.gslb.vgtf.net. 30 IN A cnn-56m.gslb.vgtf.net. 30 IN A cnn-56m.gslb.vgtf.net. 30 IN
elapsed time for this iteration: 32.30 milliseconds total latency: 376.55 milliseconds
www.cnn.com. 600 IN CNAME www.cnn.com.vgtf.net. www.cnn.com.vgtf.net. 30 IN CNAME cnn- 56m.gslb.vgtf.net.
cnn-56m.gslb.vgtf.net. 30 IN A
157.166.249.11 157.166.248.10 157.166.248.11 A 157.166.249.10
Your resolver should be able to handle the following situations and print appropriate output:
- The domain name may not exist (NXDOMAIN) or may get a SERVFAIL.
- The domain name exists, but no data is available for the requested record type
(e.g. ask for MX record, but there are onlyA or AAAA record(s) are associated
with the domain name)
- The A or AAAA record(s) exist, but are not signed
- There may be many multiple records associated with the domain name
- The original domain name resolves to a CNAME or chain of CNAMEs which
must each be resolved to obtain a final answer
Note that some queries may encounter servers that are down or other problems. Normally there are several redundant servers for each DNS zone. If one server is down, you should try a different server. Only if all servers are down can you report the name could not be resolved.
PRINT CACHE
The print cache command should display the current contents of your cache. This should be in a format similar to the following:
Domain_name: RRType: RRSET with list of RDATA
RRSET with list of RDATA RRType: RRSET with list of RDATA RRSET with list of RDATA
Here is sample output from an initialized cache. Your output should be similar.
Cache Contents:
g.root-servers.net : A : ['192.112.36.4']
b.root-servers.net : A : ['192.33.4.12']
.:
NS : [‘b.root-servers.net’, ‘g.root-servers.net’]
Helpful RFCs and other documents (use search engines to find stuff)
As seniors and grad students, you should learn to read RFC’s. To be successful with this project will need to read RFC documents to determine how to construct and interpret DNS packets. The good news is that you will be using a python library that constructs the packet for you. I want you to learn how to write an application-level protocol and not have to worry writing the low-level code itself. But that still means you need to UNDERSTAND the low-level details.
The DNS resolution algorithm is discussed in RFC 1034. The format for DNS query and response messages can be found in: RFC 1035 and RFC 3596. You should pay particular attention to the section on message compression, but you won’t actually have to code it; the library takes care of compression for you.
A very important point is to realize that questions and answers are comprised of one or more RRSETs which are comprised of one or more RDATAs. If you look at the examples above, the answer for www.cnn.com contains 2 RRSets (CNAME and A). The A RRSET contains multiple RDATA records, one for each A record.
The format of the RRSIG record and additional information needed to request signatures can be found in: RFC 4033. RFC 4034. RFC 4035. A careful reading of these RFCs should make it obvious that you do not have to do a separate DNS query to obtain the signatures.
Another helpful document available on the web regarding low-level formats is
http://www.ccs.neu.edu/home/amislove/teaching/cs4700/fall09/handouts/project1-primer.pdf
Programming Requirements and Restrictions
You must use PYTHON and the PYTHON DNS library available at www.dnspython.org. No other programming languages will be accepted. You may have to download the library and install it with the command “sudo python setup.py install”. Make sure you know how to use python lists and dictionaries; this will make your cache easier to write. Import sys and use sys.arg or something similar to get the command line argument (testfile name). Use google liberally to learn how to read lines from a file or any other task you need to do. Simply search for “python read file” will give you lots of advice.
Python has string manipulation such as string.split(“ “) for very easy parsing of the commands.
The python DNS library has multiple sections that are documented in the web pages under “stable documentation”. You should look at the methods and class structures especially the class for “message”. You will likely have to use the following and more:
import dns.message
import dns.query
import dns.name
query = dns.message.make_query(domainName, “A”, other parameters)
response = dns.query.udp(query, dnsServer) print response.answer.to_text()
Your resolver may issue only iterative queries. Since you are only allowed to send iterative DNS queries, your resolver will likely need to start by sending a query to a root server.
You configure your resolver with a list of IP addresses of the DNS root servers. These should be hard-coded into the program and initialized in the cache. To obtain a list of root servers, try the command dig . NS and then get the A record for several of the servers listed.
Although not a requirement, you should learn how to structure python programs using classes. Classes isolate namespaces, and can contain data and methods. You should write the resolver as a class and create an instance of the class. As an example:
class Resolver(): def __init__(self):
self.cache = .....
self.something = 123 def putSomethingIntoCache(self): def resolve(self, query):
blah blah def printCache(self):
blah blah
resolver = Resolver() resolver.resolve(“abc.com”) resolver.printCache()
Do Not Copy Other People’s code. You are expected to design and implement your own DNS resolver code. Hopefully this does not apply to anyone in this course, but a student found simply copying code (either from other students or from sources outside of CSU) will receive a zero on the project and will be reported to the Dean for cheating. Note that the instructor is very familiar with various DNS software and you will get caught if you try to cheat.
I suggest you write the program
What to turn in
- The python program
- A file containing the output from running the program using the posted test file
(available in about 1 to 2 weeks. In the meantime you should use your own test
file).
- A README file: Here you should put anything you want the TA to know to grade
your project. For example, you may indicate if your project works as intended or if there are bugs. If you did not complete your project, tell the TA how far you are, and what does not work.
Method: Individual Work or Teams of 2
Note: This project may be performed as an individual assignment or in teams of two people. In the case of teams, you will each be given the identical grade. If there is a complaint that “my partner didn’t do much work, I had to do most of it” we will ask each individual to explain the project individually and each person will then be graded individually. So play fair!
REMOTE STUDENTS: if you want to work on a team with someone, use the CANVAS forum to inquire if anyone is interested in working in partnership, and then exchange email to confirm the partnership.
WARNING: Use computers that can reach an outside world connection to port 53.
Many of the computers in the lab are restricted to using CSU’s DNS servers. Make sure you have an outside world connection when you run your programs.