Conditional DNS for multiple intranet upstreams with Dnsmasq Published the 2019-09-11 I recently had the need to use my workplace's internal DNS to access its internal services, but this DNS also forwards queries it can't answer to an upstream DNS. This is annoying, as it bypasses my own intranet's DNS, which gives me access to my own internal services, and also block ads, trackers and bloat through an installed PiHole server. > Note that I ultimately decided to abandon PiHole in favor of raw Dnsmasq, > as written [here](/blog/dns-blocking). My system's DNS client, like most, doesn't support conditional forwarding, so I either have my workplace or my own intranet, but not both. ## What I need I need something lightweight (it will constantly run on my desktop, I don't want to drain my battery or consume power for nothing). I need to have the ability to add a DNS resolver for a given TLD, and add a DNS resolver list for defaults. Additionally, I wanted to also resolve the `local` TLD as `127.0.0.1` for every query. ## Dnsmasq > Dnsmasq provides Domain Name System (DNS) forwarder, Dynamic Host > Configuration Protocol (DHCP) server, router advertisement and network boot > features for small computer networks, created as free software. > > https://en.wikipedia.org/wiki/Dnsmasq We need a DNS forwarder, which is what Dnsmasq does. It bundles a few other features we don't need, but thankfully, we're able to disable them. ## Configuring it The configuration file is located at `/etc/dnsmasq.conf` on my environment. ### General configuration The first thing is to disable every other service than DNS, which is done with `no-dhcp-interface=`. I'll set my general-purpose upstream resolvers in `/etc/resolv.conf`, starting with my PiHole. ``` nameserver 10.0.10.1 nameserver 1.1.1.1 nameserver 1.0.0.1 ``` I want dnsmasq to *always* query my own DNS, and only if not available, to query CloudFlare ones. This can be configured with the key `strict-order` in the Dnsmasq configuration file. That means that, in the rare cases in which I'm not logged onto my intranet's VPN, I'll need to wait for the query to the first nameserver to timeout before getting my DN. Right now, the dnsmasq configuration file looks like this. ``` no-dhcp-interfaces= strict-order ``` ### Mapping TLDs to addresses I'll start by adding the configuration to resolve `.local` domains to `127.0.0.1`. This is done with `address=/local/127.0.0.1`. This is the only TLD I wanted to map to an address, so let's start with conditional upstreams. ### Mapping TLD querying to upstreams The first TLD I want to resolve differently is my workplace's intranet. The other TLD I want to resolve is my own intranet's one. I just need to add the two following clauses to the Dnsmasq configuration file. ``` server=/work/10.0.1.3 server=/space/10.0.10.1 ``` And that is all I need! ## Final configuration file My final `dnsmasq.conf` is the following, and works just fine. ``` no-dhcp-interface= strict-order address=/local/127.0.0.1 server=/work/10.0.1.3 server=/space/10.0.10.1 ```