Network Security Spring 2021

The goals of this assignment are to:

  1. Implement a simple DNS recursive resolver
  2. Implement basic defenses against DNS hijacking
  3. Implement basic DNSSEC validation

DNS Server

Recall that a recursive resolver is a DNS server that will recursively query authoritative nameservers in the DNS hierarchy, usually on behalf of a stub resolver. That is, a recursive resolver receives DNS requests on port 53/udp, issues corresponding queries starting from a root name server and following referrals to sub-zone authoritative nameservers, and returns a response that either answers the stub resolver’s query or indicates that a failure has occurred. In this assignment, you will implement a simple recursive resolver.

To bootstrap your solution, a python skeleton has been provided in Canvas that you are free to base your solution off of. This skeleton makes use of asynchronous I/O to provide concurrent service to DNS clients. You are responsible for implementing the resolution process itself with the help of an allowed list of libraries contained in the skeleton’s Pipfile. (Additional libraries can be used if they are explicitly approved.) Pipfiles can be used to easily create virtual environments that contain the dependencies (and dependency versions) needed to run a python program. For example:

$ pipenv sync                       # Lock and install package dependencies
$ pipenv run python dnsd/dnsd.py    # Run the DNS server

The skeleton contains a main file in dnsd/dnsd.py and a server skeleton in dnsd/server.py.

Note that you are free to implement your own solution from scratch. In that case, you should replicate the command-line interface implemented by the skeleton. In addition, you should only use libraries with equivalent functionality as those contained in the skeleton’s Pipfile.

In either case, your service must be packaged as a container image that can be executed with the following invocation:

$ docker run -it --rm -p 1553:1553/udp ${image_name} serve [options...]

Query Hijacking Defenses

In addition to implementing basic DNS recursive resolution, your server must also implement defenses against query hijacking. These defenses are:

  1. Transaction ID randomization
  2. Source port randomization
  3. Bailiwick checking (ensure that glue records are relevant for queries)


Your server should implement optional support for DNSSEC validation, to be enabled when run with the --dnssec flag. Your server will be provided with a DS record as a trust anchor. When DNSSEC support is requested, your server should request and verify RRSIG and DS records along with the queried DNS record.

Public Tests

A public test suite is not available for this assignment. However, any DNS client such as dig or drill is suitable for this purpose. For instance:

$ dig @ -p 1553 +dnssec nsa.gov
$ drill @ -p 1553 -D nsa.gov

Submission Instructions

Package your solution as a gzipped TAR archive. Your solution should have the following structure:

$ tree -F dnsd
├── Dockerfile
└── src/

The root directory must be named dnsd, and the source code to your solution should be contained in src/. Your Dockerfile should produce an image that follows the invocation instructions above.

Submit the solution archive to Canvas.