DNSMasq

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

  1. 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

  1. Edit /etc/hosts. Change the line that looks something like 127.0.1.1 raspberrypi. Replace raspberrypi with your hostname.

    e.g.

     sudo vi /etc/hosts
    
  2. Edit /etc/hostname. Replace the hostname in the file with your new hostname.

    e.g.

     sudo vi /etc/hostname
    
  3. Reboot the Pi:
     sudo shutdown -r now
    
  4. 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:
    1. Restrict what queries the server forwards to upstream servers:
      • domain-needed
      • bogus-priv
    2. Prevent dnsmasq from reading /etc/resolv.conf to get its servers:
      • no-resolv
    3. Specify a port, interface, & interface addresses:
      • port=53
      • listen-address=127.0.0.1,192.168.0.2
      • interface=eth0
    4. 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
      
    5. Configure a domain, such that all entries defined in /etc/hosts will get a domain suffix (e.g. bard becomes bard.local):
      • expand-hosts
      • domain=local
    6. Enable DNS Cache and set a cache-size:
      • cache-size=1000

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
  1. 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
  1. 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
    
  2. 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
Last updated