In this project, we are going to be using dnsmasq
. There are other options for both a DNS server (such as our BIND9 project) and a DHCP server.
Prerequisites
- This project assumes that you have already followed our Raspberry Pi installation project, and have the resulting configured Raspberry Pi. If you are installing on different hardware or a different OS, these steps may not all be the same for you.
Note: Because I do not need a GUI for this and would like to conserve resources, I installed the ‘Lite’ version of Raspberry Pi OS for this project.
Quick Review: DNS
(D)omain (N)ame (S)ystem
Make DNS queries to lookup DNS records.
Very short explanation of some types of DNS records:
- A: “address”, hostname -> IP address
- AAAA: “address x4” hostname -> IPv6 address
- PTR: “pointer”, IP address -> hostname
- CNAME: “canonical name”, hostname -> hostname
- MX: “mail exchange”
- TXT: “text”
- NS: “nameserver”
Note: This is just a quick review! Check out our DNS knowledge article for more info.
Note: IPv4 32 bits, IPv6 128 bits, 32 x 4 = 128)
Install & Configure
Package installation
Before starting any work, you should always make sure you are fully up to date.
sudo apt update && sudo apt upgrade -y
Install DNSMasq
sudo apt install dnsmasq
Install Other
sudo apt install bind9-dnsutils
Note: bind9-dnsutils
gives us (among other things) the commands nslookup
& dig
. It has a package dependency for bind9-host
which gives us the commend host
. More info about these commands is in the Troubleshooting section below.
Note: dnsutils
is a transitional package for bind9-dnsutils
. So we will not use it here, but you may see dnsutils
used in other guides.
Basic Pi Configuration
Set hostname
-
Edit
/etc/hosts
. Change the line that looks something like127.0.1.1 raspberrypi
. Replaceraspberrypi
with your hostname.e.g.
sudo vi /etc/hosts
-
Edit
/etc/hostname
. Replace the hostname in the file with your new hostname.e.g.
sudo vi /etc/hostname
- Reboot the Pi:
sudo shutdown -r now
- One the host has finished rebooting, check to see if your changes applied:
hostname
Note: You might ask, why not use sudo hostnamectl set-hostname <your-hostname>
? If you are curious, you can run this and then cat
the mentioned files, and see what has changed.
Note: After you set the hostname and before you reboot, it may yell at you about the previous hostname name/service not being known.
Set a static IP
In our case, we will be using NetworkManager to set a static IP.
nmcli
nmcli connection show
Take note of the “Name” of the connection you are using. (NOT the “Device”. Sometimes these will be the same, but not always.)
sudo nmcli con mod "<connection-name>" ipv4.addresses <ip-address>/<subnet-mask>
sudo nmcli con mod "<connection-name>" ipv4.gateway <gateway-ip-address>
sudo nmcli con mod "<connection-name>" ipv4.method manual
sudo nmcli con down "<connection-name>" && sudo nmcli con up "<connection-name>"
nmcli
Note: sudo systemctl restart NetworkManager
will add the new config, but will not remove the old, which is not ideal. This is why we are running the up
and down
commands for the connection. You could also reboot your pi.
Note: Some parts of these commands can be shortened, such as connection
> con
. Some can be shortened even further.
Note: <subnet-mask>
based on the netmask. (subnet mask cheat sheet)
Configure DNS Server
DNSMasq Configuration
Edit /etc/dnsmasq.conf
e.g.
sudo vi /etc/dnsmasq.conf
- Find, uncomment (remove the
#
at the start of the line), and change the following lines based on the values for your setup:- Restrict what queries the server forwards to upstream servers:
domain-needed
bogus-priv
- Prevent dnsmasq from reading
/etc/resolv.conf
to get its servers:no-resolv
- Specify a port, interface, & interface addresses:
port=53
listen-address=127.0.0.1,192.168.0.2
interface=eth0
- Add other name servers (or add your own preferred servers, this is is using Cloudflare’s.):
server=1.1.1.1 server=1.0.0.1
- Configure a domain, such that all entries defined in
/etc/hosts
will get a domain suffix (e.g.bard
becomesbard.local
):expand-hosts
domain=local
- Enable DNS Cache and set a cache-size:
cache-size=1000
- Restrict what queries the server forwards to upstream servers:
Example uncommented lines after all the above changes:
labclub@bard:~ $ cat /etc/dnsmasq.conf | grep -vE "^#" | grep -vE "^$"
port=53
domain-needed
bogus-priv
no-resolv
server=1.1.1.1
server=1.0.0.1
interface=eth0
listen-address=127.0.0.1,192.168.0.2
expand-hosts
domain=local
cache-size=1000
Hosts configuration
Edit /etc/hosts
e.g.
sudo vi /etc/hosts
-
Add hosts
e.g.
192.168.0.100 barbarian 192.168.0.101 cleric 192.168.0.102 druid 192.168.0.103 fighter 192.168.0.104 paladin 192.168.0.105 rogue 192.168.0.106 sorcerer 192.168.0.107 warlock
Apply Changes
Restart the service to apply changes
sudo systemctl restart dnsmasq
And then check the status of the service:
sudo systemctl status dnsmasq
Test the DNS server
dig <domain> @localhost
Using the DNS server
In our case, we will be using NetworkManager to modify our DNS servers.
nmcli
nmcli connection show
Take note of the “Name” of the connection you are using. (NOT the “Device”. Sometimes these will be the same, but not always.)
sudo nmcli con mod "<connection-name>" ipv4.dns "<space-separated-dns-ips>"
sudo nmcli con mod "<connection-name>" ipv4.ignore-auto-dns yes
sudo nmcli con down "<connection-name>" && sudo nmcli con up "<connection-name>"
nmcli
(Optional) Set a search domain
sudo nmcli con mod "<connection-name>" ipv4.dns-search "<domain>"
sudo nmcli con down "<connection-name>" && sudo nmcli con up "<connection-name>"
nmcli
Note: sudo systemctl restart NetworkManager
will add the new config, but will not remove the old, which is not ideal. This is why we are running the up
and down
commands for the connection. You could also reboot your pi.
Configure DHCP Server
DNSMasq Configuration
Edit /etc/dnsmasq.conf
e.g.
sudo vi /etc/dnsmasq.conf
- Set the DHCP range, subnet mask, lease time
dhcp-range=<ip-range-start>,<ip-range-end>,<netmask>,<lease-time>
e.g.
dhcp-range=192.168.0.100,192.168.0.200,255.255.255.0,12h
- Enable ethers:
read-ethers
Note: It is worth mentioning that the default location for leases (which we have not changed here) is /var/lib/misc/dnsmasq.leases
, and if you need to go delete a lease, especially while you are testing things, you can go remove the relevant line in that file.
/etc/ethers Configuration
Edit /etc/ethers
e.g.
sudo vi /etc/ethers
-
Add MAC address / hostname pairings
e.g.
d8:3a:dd:d7:bf:73 druid
Apply Changes
Restart the service to apply changes
sudo systemctl restart dnsmasq
And then check the status of the service:
sudo systemctl status dnsmasq
Configure Firewall
It is recommended to also configure a firewall.
Troubleshooting
Commands to help us test
host
DNS lookup utility (man page)
(e.g. host google.com
)
nslookup
query Internet name servers interactively (man page)
(e.g. nslookup google.com
, nslookup -type=ns google.com
, nslookup google.com 1.1.1.1
)
dig
DNS lookup utility (man page)
(e.g. dig google.com
)
ping
send ICMP ECHO_REQUEST packets to network hosts (man page)
(e.g. ping google.com
, ping google.com -c 4
)
Can you connect to port 53?
telnet <remote-server> 53
e.g.
bash-3.2$ telnet 1.1.1.1 53
Trying 1.1.1.1...
Connected to one.one.one.one.
Escape character is '^]'.
nc -vz -w 1 \<remote-server\> 53
nc -vuz -w 1 \<remote-server\> 53
e.g.
bash-3.2$ nc -vz -w 1 1.1.1.1 53
Connection to 1.1.1.1 port 53 [tcp/domain] succeeded!
bash-3.2$ nc -vuz -w 1 1.1.1.1 53
Connection to 1.1.1.1 port 53 [udp/domain] succeeded!
bash-3.2$
If no, is DNSMasq running on port 53?
ss -tulpn | grep 53
If no, is port 53 open?
sudo netstat -tulpn | grep :53
sudo lsof -Pi | grep LISTEN
sudo nmap -sS localhost
sudo nmap -sU localhost
Have you configured any variety of firewall? And the follow up question, have you configured it to allow DNS / port 53? (e.g. iptables
, nftables
, firewalld
, ufw
)
Status of the dnsmasq service
sudo systemctl is-enabled dnsmasq
sudo systemctl status dnsmasq
sudo journalctl -u dnsmasq