Skip to content

Instantly share code, notes, and snippets.

@xavier83ar
Last active December 20, 2024 07:38
Show Gist options
  • Select an option

  • Save xavier83ar/aee05e7364dd50fc0c97b3ce9a768463 to your computer and use it in GitHub Desktop.

Select an option

Save xavier83ar/aee05e7364dd50fc0c97b3ce9a768463 to your computer and use it in GitHub Desktop.
Setting up dnsmasq + NetworkManager + systemd-resolved to support wildcard domain resolution for development Ubuntu 20.04

Motivation

The goal is to have our local dns resolution resolves to localhost any host name ended by certain tld (top level domain), e.g. if we want to use *.loc as tld, then example.loc should resolve to localhost, as well as any hostname ending by .loc.

This is very convenient for local development, having the chance to use different host names resolving localhost without the need of setting them up individually.

Background

Ubuntu, as of version 20.04, uses systemd-resolved as name resolution service, and NetworkManager to handle pretty much everything related to connectivity. NetworkManager includes dnsmasq which in the past used to be enabled by default, but as now name resolution is handled by systemd-resolved, is disabled by default.

So, in order to achieve our goal, we'll enabled dnsmasq on NetworkManager and tell systemd-resolved to used it as local dns. The idea is to have systemd-resolved still handling name resolution, so everything just work as it was meant to.

Enabling Dnsmasq

To enable dnsmasq we'll have to bind it to a different IP to avoid conflicts on port 53 with systemd.

/etc/NetworkManager/NetworkManager.conf

In this file, add dns=dnsmasq at the end of [main] section. This will enable dnsmasq in NetworkManager.

[main]
plugins=ifupdown,keyfile
dns=dnsmasq

[ifupdown]
managed=false

[device]
wifi.scan-rand-mac-address=no

/etc/NetworkManager/dnsmasq.d/dnsmasq.conf

This file shouldn't exist so we'll need to create it.

listen-address=127.0.0.2
bind-interfaces

This way will listen on 53 but binded to a 127.0.0.2, avoiding conflict with systemd.

/etc/NetworkManager/dnsmasq.d/dot-loc.conf

This could be in the same previous file, but is better organized this way if want to add different rules in the future.

address=/loc/127.0.0.1

All host names ended by .loc resolves 127.0.0.1

/etc/default/dnsmasq

Finally there is another file that I'm not totally sure that's needed, you could try skip this step, and instead just do it only if there is any trouble or missbehavior. This is to avoid dnsmasq overwriting /etc/resolv.conf (or reading it, not sure) and prevent it from conflicting with systemd-resolved wich is the one that manages it.

IGNORE_RESOLVCONF=yes

Setting up systemd-resolved to work with dnsmasq

To tell systemd-resolved to use other dns, we have to edit next file.

/etc/systemd/resolved.conf

Uncomment those lines

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See resolved.conf(5) for details

[Resolve]
DNS=127.0.0.2
#FallbackDNS=
Domains=~loc
#LLMNR=no
#MulticastDNS=no
#DNSSEC=no
#DNSOverTLS=no
#Cache=no-negative
#DNSStubListener=yes
#ReadEtcHosts=yes

It's important to note that here, in Domains we must use the same tld that we setup previously, in this case loc. The ~loc means "everything that ends with loc. This way systemd-resolved will use that dns when resolving hostname that matches.

Restart services

Once everything is done, we should restart both services.

user@computer:/$ systemctl restart NetworkManager.service
user@computer:/$ systemctl restart systemd-resolved.service 

Now every .loc host name should resolve to 127.0.0.1, you can check it:

user@computer:/$ nslookup example.loc
Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   example.loc
Address: 127.0.0.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment