DNS Server Configuration
Tags: linux, dns
Published: 2023-02-23 06:23:33

## Introduction

A DNS service is a system that manages the mapping between domain names and IP addresses, making it possible for computers to locate and connect to websites and other online resources

**DNS ports** 👉 UDP/53 , TCP/53

**Simple Lookup** 👉 Domain name -> IP address 
**Reverse Lookup** 👉 IP Address -> Domain name


**Recursive DNS servers** 👉  Look up information in the DNS hierarchy for clients

**Authoritative DNS servers** 👉 Store and provide information about specific domains

---

## Domain Name Structure

**✨ Hostname:** A name given to a specific device or server on a network, used to identify and distinguish between different devices

**✨ Domain name:** A human-readable label used to identify a website or other online resource, consisting of one or more words separated by periods, with the rightmost label indicating the TLD

**✨ Root domain:** The highest level of the domain name system, represented by a period at the end of a domain name, and serving as the starting point for all domain name resolutions


![Tree](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sj56huqffr5d171cmwaq.png)

---

## DNS record types

**✨ A Record:** An A record maps a domain name to an IPv4 address

**✨ AAAA Record:** An AAAA record maps a domain name to an IPv6 address

**✨ MX Record:** An MX record specifies the mail server responsible for accepting email messages for a specific domain name

**✨ CNAME Record:** A CNAME record maps an alias or nickname for a domain name to the actual domain name

**✨ NS Record:** An NS record specifies the authoritative name servers for a domain

**✨ TXT Record:** A TXT record can contain any text data, and is often used for DNS-based authentication and anti-spam measures

**✨ SRV Record:** An SRV record specifies the location of a service provided by a domain, such as a SIP or XMPP service

**✨ SOA Record:** An SOA record specifies the authoritative name server for a domain, and contains information about how frequently the DNS information should be refreshed

> 💡 Fully Qualified Domain Name is a complete domain name that specifies the exact location of a resource within the Domain Name System (DNS) hierarchy

👉 For example, the FQDN for a website might be "www.example.com", where "www" is the hostname, "example" is the second-level domain, and "com" is the top-level domain. The complete FQDN specifies the full path to the web server, and can be used by client devices to locate and connect to the server

---

![DNS Workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sh6z9rs4awnz9gi5x0x.png)


## Simple hands on

> 💡 I have used 2 Linux VMs in my VMWare workstation to configure 2 DNS servers (1 for backup) (network is 192.168.1.0/24)

We will start by installing the `bind` package on both systems

```bash
yum -y install bind-*
```

After installation, we will go to

```bash
vi /etc/named.conf
```

👉 This file is the main config file for the DNS server


Inside this file I cleared out the comments in this section for clarity

```bash
     12 options {
     13         listen-on port 53 { 127.0.0.1; };
     14         listen-on-v6 port 53 { ::1; };
     15         directory       "/var/named";
     16         dump-file       "/var/named/data/cache_dump.db";
     17         statistics-file "/var/named/data/named_stats.txt";
     18         memstatistics-file "/var/named/data/named_mem_stats.txt";
     19         recursing-file  "/var/named/data/named.recursing";
     20         secroots-file   "/var/named/data/named.secroots";
     21         allow-query     { localhost; };
     22         recursion yes;
     23         dnssec-enable yes;
     24         dnssec-validation yes;
     25         bindkeys-file "/etc/named.root.key";
     26         managed-keys-directory "/var/named/dynamic";
     27         pid-file "/run/named/named.pid";
     28         session-keyfile "/run/named/session.key";
     29 };
```

Inside this file, we will change the 127.0.0.1 into

```bash
listen-on port 53 { any; };
```

👉 We need all of the users to have access to the DNS server

Also need to change this line to accept `any`

```bash
allow-query     { any; };
```

Finally changing recursion to `no`

```bash
recursion no;
```

👉 Setting recursion to `no` will make the recursive query to not go to the cache server. We turn this feature off for security reasons.   

> 💡 In simpler words, we are making the DNS server to not respond to any query that DNS doesn't know instead of searching for it 

This triggers another issue. If we are using a DNS Local server in our network, it won't search for any other DNS name from other DNS servers. This will make the users that are using the local DNS server not able to access any other website outside of the local DNS address pool. 

To solve the above issue we use an ACL rule

```bash
     12 acl AllowRecursion {
     13         127.0.0.1;
     14         <Your-Local-Network-ID>;
     15 };
```

Also adding

```bash
     27         recursion yes;
     28         allow-recursion { AllowRecursion; };
```

Looking at the bottom of the config file

```bash
include "/etc/named.rfc1912.zones";
```
👉 This is where we include our Domain Names that we bought

Also,

```bash
zone "." IN {
        type hint;
        file "named.ca";
};
```

👉 This declares that if the requested address is not found, DNS should look for the requested query from the `named.ca` file. The `named.ca` file contains the DNS server addresses from all over the world

Now we need to include the domain name in the zones file

```bash
vi /etc/named.rfc1912.zones

# Adding the following at the end
zone "waji.com" IN {
        type master;
        file "waji.zone";
        allow-update { 192.168.1.129; };
        allow-transfer { 192.168.1.129; };
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "waji.rev";
        allow-update { 192.168.1.129; };
        allow-transfer { 192.168.1.129; };
};
```
👉 The 192.168.1.129 is the IP address for the backup DNS server

We have just done the DNS settings for forward and reverse lookup

> 💡 We have `master` `slave` and `hint` types for DNS entries. `master` for the main DNS server, `slave` for the backup DNS entry and `hint` for the cache server

> 💡 `waji.zone` and `waji.rev` are the zone files. These files should have the records (A records etc)

*if we are not using DDNS, we won't need `allow-update` line*

I am not using DDNS so the above becomes,

```bash
zone "waji.com" IN {
        type master;
        file "waji.zone";
        allow-transfer { 192.168.1.129; };
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "waji.rev";
        allow-transfer { 192.168.1.129; };
};
```

> 💡 Never use `any` in `allow-transfer`. We are allowing transferring the zone file that contains record names. If this file gets out to any anonymous person, he/she can exploit that file details to harm us

👉 We only have to allow the Slave DNS server. In my case `192.168.1.129` is our slave DNS server

Now, we need to go to 

```bash
cd /var/named
```

Here, we need to create the files 

```bash
cp named.localhost waji.zone
cp named.localhost waji.rev
```

In the `waji.zone` file

```bash
$TTL 1D
@       IN SOA  ns1.waji.com.         root(
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        IN      NS      ns1.waji.com.
ns1     IN      A       192.168.1.128
www     IN      A       192.168.1.128
aaa     IN      CNAME   www.waji.com.
```

👉 Here we have set it so that if the client searches for `ns1.waji.com`, the server will reply to 192.168.1.128

> `@` -> is translated to the domain name (origin)

Now, in the `waji.rev` file

```bash
$TTL 1D
@       IN SOA  ns1.waji.com.    root(
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        IN      NS      ns1.waji.com.
128     IN      PTR     ns1.waji.com.
128     IN      PTR     www.waji.com.
```

We need to change the ownership for the files and directories under `/var/named` to `named` for the DNS to actually work

```bash
# Current owner
-rw-r----- 1 root  root   198  2월 23 13:28 waji.rev
-rw-r----- 1 root  root   222  2월 23 13:09 waji.zone

# Changing the group ownership
chown .named ./waji.*

-rw-r----- 1 root  named  198  2월 23 13:28 waji.rev
-rw-r----- 1 root  named  222  2월 23 13:09 waji.zone
``` 

Now, we just need to enable and start the service

```bash
systemctl start named
systemctl enable named
```

Finally, adding the service to the firewall

```bash
firewall-cmd --permanent --add-service=dns
firewall-cmd --reload
```

We successfully configured the master DNS server. 

👉 From the unconfigured slave DNS server we will test if the master was configured correctly

From the slave DNS server,

```bash
nslookup
> server 192.168.1.128   
Default server: 192.168.1.128
Address: 192.168.1.128#53

> www.waji.com
Server:		192.168.1.128
Address:	192.168.1.128#53

Name:	www.waji.com
Address: 192.168.1.128
```

We can test the other domain name

```bash
> ns1.waji.com
Server:		192.168.1.128
Address:	192.168.1.128#53

Name:	ns1.waji.com
Address: 192.168.1.128
```

Or we can reverse lookup

```bash
> 192.168.1.128
128.1.168.192.in-addr.arpa	name = ns1.waji.com.
128.1.168.192.in-addr.arpa	name = www.waji.com.
```
Now to configure the slave DNS server,

```bash
vi /etc/named.conf

listen-on port 53 { any; };
allow-query     { any; };
```

Configuring inside the `/etc/named.rfc1912.zones` file

```bash
zone "waji.com" IN {
        type slave;
        file "slaves/waji.zone.slave";
        notify yes;
        masterfile-format text;
        masters { 192.168.1.128; };
};

zone "1.168.192.in-addr.arpa" IN {
        type slave;
        file "slaves/waji.rev.slave";
        notify yes;
        masterfile-format text;
        masters { 192.168.1.128; };
};
```
👉 We don't need the `masterfile-format text` configuration in actual setup as it is vulnerable to attacks. The files should be saved in 'binary' which is the default. I am just using this setting to actually check the file contents for this hands on.

Going back to the Master DNS server and adding few lines 

```bash
zone "waji.com" IN {
        type master;
        file "waji.zone";
        allow-transfer { 192.168.1.129; };
        also-notify { 192.168.1.129; };
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "waji.rev";
        allow-transfer { 192.168.1.129; };
        also-notify { 192.168.1.129; };
};
```

👉 We needed to allow the `notify` capability from the master as we configured `notify yes;` in our slave DNS server

Lastly, still from the Master DNS,

```bash
vi /etc/named.rfc1912.zones

$TTL 1D
@       IN SOA  ns1.waji.com.   root(
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        IN      NS      ns1.waji.com.
        IN      NS      ns2.waji.com.
ns1     IN      A       192.168.1.128
ns2     IN      A       192.168.1.129
www     IN      A       192.168.1.128
aaa     IN      CNAME   www.waji.com.
```

And the for the reverse lookup

```bash
vi /var/named/waji.rev

$TTL 1D
@       IN SOA  ns1.waji.com.    root(
                                        0       ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        IN      NS      ns1.waji.com.
        IN      NS      ns2.waji.com.
128     IN      PTR     ns1.waji.com.
129     IN      PTR     ns2.waji.com.
128     IN      PTR     www.waji.com.
```

Restarting the service

```bash
systemctl restart named
```

👉 Back to the slave DNS server,

```bash
systemctl start named
systemctl enable named
```

If we navigate to `/var/named/slaves`

```bash
ls -l /var/named/slaves/
total 8
-rw-r--r-- 1 named named 408 Feb 23 14:55 waji.rev.slave
-rw-r--r-- 1 named named 380 Feb 23 14:55 waji.zone.slave
```
✔ We can confirm that the DNS information is present in the slave DNS server

---

✨ We looked at what DNS server is and how it works by doing a short hands on using Virtual Machines. We also linked the Master-slave DNS servers that provides redundancy and fault tolerance