Welcome to configuring Ubuntu Server 22.04 as a router tutorial series!

  1. Setup Ubuntu Server 22.04 as a NAT Router with Qemu/KVM, Part 1
  2. Setup Ubuntu Server 22.04 as a DHCP Server with Qemu/KVM, Part 2
  3. Setup Ubuntu Server 22.04 as a DNS Server with Qemu/KVM, Part 3

One of the most popular programs for Linux operating systems providing DNS forwarder service is dnsmasq.

Ubuntu 22.04 comes with systemd-resolved which you need to disable since it binds to port 53 which will conflict with dnsmasq port.

Disable the systemd-resolved DNS listeners to free up port 53 by uncommenting DNSStubListener and setting it to no in /etc/systemd/resolved.conf.

DNSStubListener=no

Disable the systemd-resolved DNSSEC, DNSOverTLS, LLMNR, and MulticastDNS by uncommenting them and setting it to no in /etc/systemd/resolved.conf.

DNSSEC=no
DNSOverTLS=no
MulticastDNS=no
LLMNR=no

In order to configure dnsmasq to act as cache for the host on which it is running, uncomment DNS and set it to 127.0.0.1 to force host to perform local DNS lookup.

DNS=127.0.0.1

Restart the systemd-resolved service to apply your changes:

sudo systemctl restart systemd-resolved

Once that is done, install dnsmasq:

sudo apt -y install dnsmasq

To enable DNS forwarder service, you need to configure /etc/dnsmasq.conf.

Set the port on which dnsmasq will listen for DNS requests. This default to UDP port 53.

port=53

Disable forwarding of names without a dot or domain part by uncommenting:

domain-needed

Add a local-only domain:

local=/app/

Restart the dnsmasq service to apply your changes:

sudo systemctl restart dnsmasq

By default, DNS uses TCP and UDP port 53. Open the DNS port, run:

sudo firewall-cmd --zone=public --permanent --add-port=53/tcp
sudo firewall-cmd --zone=public --permanent --add-port=53/udp

Next, you will need to edit your /etc/hosts file and add the local DNS server entries.

172.16.0.100    bulbasaur.app
172.16.0.101    ivysaur.app
172.16.0.102    venusaur.app

Restart the dnsmasq service to apply your changes:

sudo systemctl restart dnsmasq

Install dnsutils package:

sudo apt -y install dnsutils

To test if the local DNS server is working or not, run:

dig bulbasaur.app
dig ivysaur.app
dig venusaur.app

The response should look similar to this:

; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> bulbasaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62416
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;bulbasaur.app.         IN  A

;; ANSWER SECTION:
bulbasaur.app.      0   IN  A   172.16.0.100

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:24:05 UTC 2023
;; MSG SIZE  rcvd: 58


; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> ivysaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33069
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;ivysaur.app.           IN  A

;; ANSWER SECTION:
ivysaur.app.        0   IN  A   172.16.0.101

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:24:05 UTC 2023
;; MSG SIZE  rcvd: 56


; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> venusaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50282
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;venusaur.app.          IN  A

;; ANSWER SECTION:
venusaur.app.       0   IN  A   172.16.0.102

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:24:05 UTC 2023
;; MSG SIZE  rcvd: 57

To test a reverse IP lookup, run:

dig -x 172.16.0.100
dig -x 172.16.0.101
dig -x 172.16.0.102

The response should look similar to this:

; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> -x 172.16.0.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13755
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;100.0.16.172.in-addr.arpa. IN  PTR

;; ANSWER SECTION:
100.0.16.172.in-addr.arpa. 0    IN  PTR bulbasaur.app.

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:26:19 UTC 2023
;; MSG SIZE  rcvd: 81


; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> -x 172.16.0.101
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15516
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;101.0.16.172.in-addr.arpa. IN  PTR

;; ANSWER SECTION:
101.0.16.172.in-addr.arpa. 0    IN  PTR ivysaur.app.

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:26:19 UTC 2023
;; MSG SIZE  rcvd: 79


; <<>> DiG 9.18.12-0ubuntu0.22.04.2-Ubuntu <<>> -x 172.16.0.102
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47090
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;102.0.16.172.in-addr.arpa. IN  PTR

;; ANSWER SECTION:
102.0.16.172.in-addr.arpa. 0    IN  PTR venusaur.app.

;; Query time: 0 msec
;; SERVER: fe80::9a73:37ff:fe90:3457%3#53(fe80::9a73:37ff:fe90:3457%3%3) (UDP)
;; WHEN: Mon Aug 14 13:26:19 UTC 2023
;; MSG SIZE  rcvd: 80

Run the tests on the client computers as well to check if the local DNS server is working or not.