Update 2020: A version of this post was published on Fedora Magazine. The Fedora Magazine post was updated slightly to conform to their style guidelines, but the content is the same.

The dnsmasq plugin is a hidden gem of NetworkManager. When using the plugin, instead of using whatever DNS nameserver is doled out by DHCP, NetworkManager will configure a local copy of dnsmasq that can be customized.

You may ask, why would you want to do this? For me personally, I have two use cases:

  1. On my laptop, I run a full OpenShift installation. In order to make this work, I really need to be able to add DNS entries.
    • I could create a VM to run a DNS server or run a DNS server locally, but then I have to change my resolv.conf every single time I change networks (and sometimes more often).
  2. When I’m at home, I want to still be able to access my home network’s DNS entries while on VPN.
    • Many VPNs are configured such that only traffic destined for VPN network gets sent through the tunnel. I can still access all my local network and most traffic goes out the default gateway.
    • This is very nice, as it means I can still access my network printer or listen to music from my media server while doing work. However, the VPN connection overwrites my resolv.conf with DNS servers from the VPN network. Therefore, my home network’s DNS is no longer accessible.

The dnsmasq plugin for NetworkManager solves both of these problems.

For, local DNS entries, the plugin can configure local domains will be available no matter what network I’m connected to.

For the VPN scenario, I can configure dnsmasq to forward requests to my home domain to my home DNS server. The VPN’s DNS is set up a as a forwarder in dnsmasq rather than a primary DNS server, so I can resolve both the DNS entries on the VPN network and my own.

Here’s how to configure it in Fedora 29:

For some context, my domain on my laptop is called laplab and my home domain is .cscc. At home my DNS server is 172.31.0.20. For DNS entries in laplab, most of those are defined in /etc/hosts. DNSmasq can then slurp them up. I also have some additional DNS entries defined for a wildcard DNS and some aliases.

These are the five files that need to be added. NetworkManager uses a config directory. Concievably, you could lay these files out differently if desired:

  • /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
  • /etc/NetworkManager/dnsmasq.d/02-add-hosts.conf
  • /etc/NetworkManager/dnsmasq.d/01-laplab.conf
  • /etc/NetworkManager/dnsmasq.d/00-cscc.conf
  • /etc/hosts
# /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
#
# This enabled the dnsmasq plugin.
[main]
dns=dnsmasq
# /etc/NetworkManager/dnsmasq.d/00-cscc.conf
#
# This file directs dnsmasq to forward any request to resolve
# names under the .cscc domain to 172.31.0.20, my home DNS server.
server=/cscc/172.31.0.20
# /etc/NetworkManager/dnsmasq.d/01-laplab.conf
# This file sets up the local lablab domain and 
# defines some aliases and a wildcard.
local=/laplab/
address=/.ose.laplab/192.168.101.125
address=/openshift.laplab/192.168.101.120
address=/openshift-int.laplab/192.168.101.120
# /etc/NetworkManager/dnsmasq.d/02-add-hosts.conf
# By default, the plugin does not read from /etc/hosts.  
# This forces the plugin to slurp in the file
addn-hosts=/etc/hosts
# /etc/hosts
127.0.0.1   localhost localhost.localdomain 
::1         localhost localhost.localdomain 

192.168.101.120  ose-lap-jumphost ose-lap-jumphost.laplab
192.168.101.121  ose-lap-master1 ose-lap-master1.laplab
192.168.101.122  ose-lap-master2 ose-lap-master2.laplab
192.168.101.123  ose-lap-master3 ose-lap-master3.laplab
192.168.101.125  ose-lap-infnode1 ose-lap-infnode1.laplab
192.168.101.126  ose-lap-infnode2 ose-lap-infnode2.laplab
192.168.101.127  ose-lap-infnode3 ose-lap-infnode3.laplab
192.168.101.128  ose-lap-node1 ose-lap-node1.laplab
192.168.101.129  ose-lap-node2 ose-lap-node2.laplab
192.168.101.130  ose-lap-node3 ose-lap-node3.laplab

After all those files are in place, restart NetworkManager with systemctl restart NetworkManager. If everything is working right, you should see that your resolv.conf points to 127.0.0.1 and a new dnsmasq process spawned.

If everything is working right, you should see that your resolv.conf points to 127.0.0.1 and a new dnsmasq process spawned.

$ ps -ef | grep dnsmasq
dnsmasq   1835  1188  0 08:01 ?        00:00:00 /usr/sbin/dnsmasq --no-resolv 
--keep-in-foreground --no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid 
--listen-address=127.0.0.1 --cache-size=400 --clear-on-reload --conf-file=/dev/null 
--proxy-dnssec --enable-dbus=org.freedesktop.NetworkManager.dnsmasq 
--conf-dir=/etc/NetworkManager/dnsmasq.d

$ cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 127.0.0.1

$ host ose-lap-jumphost.laplab
ose-lap-jumphost.laplab has address 192.168.101.120

This configuration will survive reboots and, in my testing, works with almost every network and VPN I’ve tried it with.