Implementing Per-Domain DNS Configuration on Linux Ubuntu Using dnsmasq

Reading time: 41 – 68 minutes

In Linux, managing network traffic is essential for a robust and secure IT infrastructure. In this post, we focus on Ubuntu—whether running on a virtual machine, Windows Subsystem for Linux (WSL), or a physical machine running Ubuntu 24.04. We will configure per-domain DNS rules using dnsmasq. This guide also covers additional considerations for WSL and systems using netplan.

Configuring Ubuntu for Local DNS with dnsmasq

When using Ubuntu, you might be using netplan for network configuration. In that case, you need to configure netplan to use the local DNS server provided by dnsmasq. Make sure your netplan configuration (e.g., /etc/netplan/01-netcfg.yaml) sets the DNS to 127.0.0.1, so that all DNS queries are forwarded to your local dnsmasq server.

Disabling systemd-resolved

Ubuntu often uses systemd-resolved by default, which can interfere with your custom DNS setup. To prevent conflicts, disable and stop systemd-resolved using the following commands:

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved
sudo systemctl daemon-reload

This ensures that systemd-resolved does not override your DNS settings.

Note for WSL Users

If you are running Ubuntu under WSL, you need to prevent WSL from overwriting your DNS settings. Edit or create the file /etc/wsl.conf with the following content:

[network]
generateResolvConf = false

Then, create or edit the /etc/resolv.conf file to include:

nameserver 127.0.0.1

This ensures that your system uses the local dnsmasq server.

Installing and Setting Up dnsmasq

Step 1: Install dnsmasq

First, update your package list and install dnsmasq:

sudo apt update
sudo apt install dnsmasq

Step 2: Enable and Verify the dnsmasq Service

After installing dnsmasq, enable the service and check its status to ensure it is running correctly:

sudo systemctl enable dnsmasq
sudo systemctl daemon-reload
sudo systemctl start dnsmasq
sudo systemctl status dnsmasq

You should see that dnsmasq is active and running. This local DNS server will be used to resolve all DNS queries forwarded from your system.

Step 3: Configure dnsmasq

Edit the /etc/dnsmasq.conf file to set up your DNS rules. Here’s an example configuration:

# Default upstream DNS servers
server=8.8.8.8
server=8.8.4.4

# Domain-specific DNS servers
server=/domain01.tld/172.30.0.1
server=/domain02.tld/172.30.0.2

Explanation:

  • The lines server=8.8.8.8 and server=8.8.4.4 set Google’s public DNS as the default upstream DNS servers. When a query does not match any domain-specific rule, dnsmasq will forward the request to these servers.
  • The lines server=/domain01.tld/172.30.0.1 and server=/domain02.tld/172.30.0.2 specify that queries for any host within domain01.tld and domain02.tld should be resolved by the DNS servers at 172.30.0.1 and 172.30.0.2, respectively.

After making your changes, save the file and restart dnsmasq to apply the new configuration:

sudo systemctl restart dnsmasq

Verifying the DNS Configuration

You can use the dig command to verify that your DNS rules are working as expected. Note that when your system’s resolver is set to use dnsmasq at 127.0.0.1, the dig output will always show SERVER: 127.0.0.1#53. However, dnsmasq will forward the query internally to the appropriate upstream DNS server based on your configuration.

Below are two examples: one for a public domain (google.com) and one for a domain that should be resolved by your custom DNS rule (example01.tld).

Example 1: Verifying a Public Domain (google.com)

Run the following command:

dig google.com

Simulated Output:

; <<>> DiG 9.11.3-1ubuntu1-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;google.com.                    IN      A
;; ANSWER SECTION:
google.com.             300     IN      A       172.217.164.110
google.com.             300     IN      A       172.217.164.78
;; Query time: 23 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 20 10:00:00 UTC 2025
;; MSG SIZE  rcvd: 113

Internal Process:

  • Step 1: The query for google.com is sent to the local dnsmasq server at 127.0.0.1.
  • Step 2: dnsmasq examines its configuration and sees that google.com does not match any domain-specific rules.
  • Step 3: It then forwards the query to the default upstream DNS servers (8.8.8.8 and 8.8.4.4).
  • Step 4: The upstream server resolves google.com and returns the result back to dnsmasq, which then passes it back to the client.

Example 2: Verifying a Domain with a Custom DNS Rule (example01.tld)

Run the following command:

dig example01.tld

Simulated Output:

; <<>> DiG 9.11.3-1ubuntu1-Ubuntu <<>> example01.tld
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 67890
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;example01.tld.               IN      A
;; ANSWER SECTION:
example01.tld.           60      IN      A       172.30.0.1
;; Query time: 25 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Feb 20 10:00:10 UTC 2025
;; MSG SIZE  rcvd: 82

Internal Process:

  • Step 1: The query for example01.tld is sent to dnsmasq at 127.0.0.1.
  • Step 2: dnsmasq checks its configuration and finds a matching domain-specific rule for example01.tld, which directs the query to the DNS server at 172.30.0.1.
  • Step 3: dnsmasq forwards the query internally to 172.30.0.1 without exposing this step in the client’s dig output.
  • Step 4: The upstream server at 172.30.0.1 resolves the query, and dnsmasq returns the answer to the client.

In both cases, while the client sees the query being handled by 127.0.0.1, dnsmasq intelligently directs the queries to the appropriate upstream servers based on your configuration. This seamless internal forwarding is what allows you to manage per-domain DNS resolution effectively.

Conclusion: Why Use Per-Domain DNS Configuration?

Implementing per-domain DNS configuration on Linux Ubuntu is a powerful way to gain granular control over your network’s behavior. This approach is particularly useful for:

  • Enterprise Environments: Where internal domains require different DNS resolutions from external queries.
  • Development and Testing: Allowing developers to redirect domain requests to local or test servers.
  • Security: Enhancing network security by segregating traffic and reducing reliance on external DNS servers.

By configuring dnsmasq with domain-specific rules and ensuring that your system points to the local DNS (especially important when using netplan or running under WSL), you optimize network performance and security tailored to your specific needs.

Scroll to Top