Is there any way to configure dnsmasq so that when it receives a CNAME record, if the target is in /etc/hosts, it overrides whatever else the public DNS server says about that target and uses /etc/hosts instead?

That is the question, but if you are interested in the full background and details, read on.


I have a domain name, let's call it example.com. I've set the domain for my home network to philadelphia.example.com, and thus hosts within might be host1.philadelphia.example.com and host2.philadelphia.example.com. I have split-horizon DNS set up so these names work both behind the NAT and on the public Internet.

For convenience, I want to access some of these as simply host1.example.com, etc. (without the city name). I created public CNAME records for these. This works fine across the Internet, but not behind my router.

My router (an EdgeRouter Lite, for the record) uses dnsmasq as its DNS server. It automatically adds the records for host1 and host1.philadelphia.example.com to /etc/hosts when it issues the DCHP lease, but not host1.example.com since example.com isn't its domain. Accordingly, when it gets a request for host1.example.com, it forwards it to public DNS.

The public DNS server locates the following records and returns them:

host1.example.com.              3600    IN  CNAME   host1.philadelphia.example.com.
host1.philadelphia.example.com. 3600    IN  A       <Router's external IP>

Actually, I'm not sure if the public DNS server sends the A record automatically or if dnsmasq issues a second request for it. In any case, dnsmasq takes the public DNS server's word and diligently returns my router's public IP address to the original client behind the router, not host1's private IP address from /etc/hosts.

As an additional test, I tried creating a CNAME record for privatehost.example.com -> privatehost.philadelphia.example.com without creating a public A record for it, but my router does have an entry for privatehost.philadelphia.example.com in /etc/hosts. In this case, the public DNS server responds with the CNAME record and then NXDOMAIN when it can't find anything for privatehost.philadelphia.example.com. Even still, dnsmasq takes the server's word and returns NXDOMAIN to the client, even though it does have an entry for privatehost.philadelphia.example.com.

Is there a way to tell dnsmasq to try its own /etc/hosts again after fetching the CNAME, even if it had to go to public DNS to get it?

1 Answer 1


Unfortunately, this is something Dnsmasq cannot do.

When Dnsmasq receives a query, first it tries to respond from local sources, which include the following:

  • /etc/hosts
  • Manually configured entries in its config file
  • Hosts it issued DHCP leases to

If it can't satisfy the query using those sources, then it relays the query to public DNS. Critically, for Dnsmasq, this is an either/or situation. Once Dnsmasq has to consult public DNS, it assumes its own records are useless for the rest of that query. (And vice versa: if Dnsmasq finds any answer locally, it never consults public DNS for that query.)

I'm not sure exactly why Dnsmasq has this limitation. It might be because in practice, situations where this is a problem are rather rare, and Dnsmasq doesn't aim to be a full-blown DNS server anyway. It's only meant for SOHO routers.

In any case, Dnsmasq does support creating CNAME records in its configuration file. If you use that option to recreate the relevant CNAME records locally, Dnsmasq won't ignore /etc/hosts for those queries. It's more work, but really the only way.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .