Welcome to configuring Fedora Server 38 as a router tutorial series!

  1. Setup Fedora Server 38 as a NAT Router with Qemu/KVM, Part 1
  2. Setup Fedora Server 38 as a DHCP Server with Qemu/KVM, Part 2
  3. Setup Fedora Server 38 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.

Fedora Server 38 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

To apply the configuration, run:

sudo firewall-cmd --reload

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 dnf -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.17 <<>> bulbasaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39436
;; 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: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:51:03 WIB 2023
;; MSG SIZE  rcvd: 58


; <<>> DiG 9.18.17 <<>> ivysaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28024
;; 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: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:51:03 WIB 2023
;; MSG SIZE  rcvd: 56


; <<>> DiG 9.18.17 <<>> venusaur.app
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7234
;; 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: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:51:03 WIB 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.17 <<>> -x 172.16.0.100
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24505
;; 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: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:52:03 WIB 2023
;; MSG SIZE  rcvd: 81


; <<>> DiG 9.18.17 <<>> -x 172.16.0.101
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45987
;; 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: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:52:03 WIB 2023
;; MSG SIZE  rcvd: 79


; <<>> DiG 9.18.17 <<>> -x 172.16.0.102
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32116
;; 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: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Wed Aug 16 21:52:03 WIB 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.