# A6 - DNS Server

{% hint style="info" %}

### Run the server (your implementation)

```bash
python3 -m a6_dns_server
```

{% endhint %}

How many web pages do you visit in a day? Would you be able to remember all their IP addresses? Probably not. It turns out that humans are bad at remembering arbitrary sequences of numbers, but reasonably good at remembering names. By assigning names to IP addresses, web browsing becomes doable for humans. Instead of having to remember the sequence `216.58.211.110`, you only need to remember `www.google.com`. Your browser automatically translates this into the correct IP address.

However, this automated translation increases the complexity of the system, which now needs to translate a name into an IP address before it can establish a connection. It would be infeasible for every computer to keep a local, up-to-date copy, of all name-to-address mappings. Instead, computers depend on a globally distributed system called the Domain Name System (DNS) to look up these mappings dynamically.

This system contains a large hierarchy of servers called DNS servers. A DNS server is a computer that keeps track of IP addresses and their associated domain names. DNS servers can ask each other for the IP address matching a certain domain name. It then resolves, or translates, this name into an IP address by looking it up in its local database, or by contacting other DNS servers higher up in the hierarchy.

***

## Assignment

Your task is to implement your own DNS server that adheres to this protocol and performs recursive queries. Your server should be able to resolve both IPv4 and IPv6 addresses. All the information you need is specified in [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt) and [RFC 3596](https://datatracker.ietf.org/doc/html/rfc3596).

Start by reading section 2.1 (RFC 1035. Overview). It will give you a high-level operational model of your future DNS server. Then, to get a high-level overview of what DNS responses, requests, and communication between the other DNS servers are see sections 7.1 (RFC 1035. Transforming a user request into a query), 7.2 (RFC 1035. Sending the queries), and 7.3 (RFC 1035. Processing responses).

To construct a DNS request or parse a DNS response, read the structure of a DNS message in section 4 (RFC 1035 message). Every message contains a set of records called `RR`s. There you will find the most interesting information regarding the requested resource. Read how it is structured in section 3.2 (`RR` definitions). Each record has its type, and your server should support at least `NS`, `A`, `CNAME`, `MX`, and `AAAA`.&#x20;

Your DNS has to implement mail requests. Check section 8 (Mail Support) and in particular section 8.1 (Mail Exchange Binding). Finally, your server should implement caching as it is prescribed in sections 7.1, 7.2, and 7.3. However, there are exceptions to this rule described in section 7.4 (Use of cache).

***

## Requirements

Your assignment must present basic DNS server features. In short, your server should implement functionality that enables basic domain name resolving. We define the following requirements as a smaller specification based on the RFC to guide your development process.

{% hint style="danger" %}
Your implementation must resolve requests by communicating with the root server and the servers it lists in its replies. You cannot pass the assignment if you simply forward requests to another DNS server that performs recursive queries.
{% endhint %}

{% tabs %}
{% tab title="Protocol" %}
Your assignment must implement a subset of the features prescribed in [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt) and [RFC 3596](https://datatracker.ietf.org/doc/html/rfc3596). The following requirements describe the functionality that should be present in your server implementation:

1. The server must support both **IPv4** and **IPv6** requests.
2. The server must support the following records: `NS`, `A`, `CNAME`, `MX`, and `AAAA`.
3. The server must support mail exchange requests.
   {% endtab %}

{% tab title="Algorithms" %}
To create a working DNS server, your assignment must implement several algorithms specific to domain name processing. Below is a list of criteria that your implementation must meet regarding algorithmic considerations.

1. The server must maintain a cache of recently resolved requests.
2. Stale cache entries must be removed after a set amount of time.
3. The server must be able to perform recursive DNS queries.
   {% endtab %}
   {% endtabs %}

***

## Resources

To test your DNS server, you will need to use the [dig](https://linux.die.net/man/1/dig) (*domain information groper*) command. Depending on your system, you might have to install dig using your package manager. To run dig with your DNS server and perform a DNS resolve request, execute the following in your terminal:

```bash
dig @0.0.0.0 -p 8000 vu.nl +short
```

Below is a list of free, popular, and public DNS servers. You can analyze their responses to learn more about how to implement your server.

* Google (8.8.8.8 and 8.8.4.4)
* Quad9 (9.9.9.9 and 149.112.112.112)
* OpenDNS (208.67.222.222 and 208.67.220.220)

You can find the addresses of the DNS root servers at <https://www.iana.org/domains/root/servers>.
