Hi. I've been using OpenWrt for a while -- so far, so good. But I have some questions about my DNS setup.
I own mydomain.tld and want to use some subnames for the local services.
Details of the setup:
Almost all clients in my LAN have their DNS address set as an openwrt router ip (via dhcp or manually).
My dns chain is openwrt --> pihole --> public dns (adguard).
Rebind to local addresses protection is disabled in pihole, and on openwrt there is a mydomain.tld in the whitelist.
My zones subnets have different local domains via modification of /etc/dnsmasq.conf as suggested by this reddit comment. So my hosts can be effectively resolved (by openwrt) via local-service.lan.mydomain.tld, external-service.dmz.mydomain.tld, etc.
The dns hosting of my domain (desec.io) has CNAME records like service.mydomain.tld with the target domain name local-service.lan.mydomain.tld. There are no A records for them.
Hope that this setup makes sense.
I have some glitches here and there when using my local services via specified CNAMEs (especially if the service hasn't been accessed for some time). I have a suspicion that it is caused by the "wrong" resolution of a non-cached name. It looks like this:
You are talking about 2 DNS servers in the mix, and internal one and an external one. The external one is on the Internet and thus must be able to lookup everything available from the root nameservers. (adguard in this case) The internal one you run and basically piggybacks on the external one - it responds to everything inside the way you want it to.
This is the "standard setup" with internal "private" networks connected to external networks on Windows Domain networks. So no, there is nothing fundamentally wrong - in fact you might even say that the people who are NOT doing it this way are fundamentally wrong. And if everyone DIDN'T do it the way your doing it, the DNS network on the Internet would melt down anyway since the Internet is too big now for a single centralized DNS server - it DEPENDS on DNS caching from different private DNS servers
But I'm talking theory, of course. You also asked about implementation. And this is where there's problems:
-You may not use CNAMES to point to a domain or a subdomain, only a host. This is per RFC standard on DNS. You must use A records to point to these- Period. End of Story. Do Not Pass Go Do Not Collect $200-
Funny how I just had this discussion with a customer the other day. They were hell bent on moving their webhosting to a hoster who told them "we are using load balancing so you need to CNAME your domain name wonkulatinggronkulators.com to a wildcard name" which is, of course, an RFC violation. The customer had their domain with me and wanted me to do this ugly hack saying the old "well so and so company will do it" and I told them sorry I will not violate RFCs go find someone else to do it. They appealed to their web designer who admitted point blank it was a violation but also told them to move to the other company. It just kills me that there's people out there who are so hell bent on doing it wrong that when you tell them "no I won't help you drive your car over the cliff and destroy it but there this scumbag over there named Joe who will" and they will run to the scumbag, but there you go.
Anyway, if you want to run your own DNS - which you SHOULD be doing - then you need to be doing it the Standards Way not the way all the idiots on the Internet are doing it. CNAMES are really and truly NOT God's Gift to DNS they are more like Satan's Gift to DNS and if your running your own DNS server you can change A records in a twinkling of an eye, and so you really have little benefit to using a lot of CNAMES just make all your names proper A records and leave the CNAME shenanigans to the morons at marketing companies.
with SNAME being the domain name we are searching for. Thus, in my POV, dnsmasq implements step 4c incorrectly. Or better say it treats the response as 4a. I'm not very familiar with DNS, so I could be wrong.
What do the Pi-Hole logs say about the different queries? Lookup the CNAME and the target hostname against the router IP, then the Pi Hole IP and then the Adguard DNS IP. Who has trouble resolving it?
Well, they all can return CNAME (because it is publicly specified at the domain hosting). And of course pihole and adguard cannot resolve the target hostname because it is leased by dhcp (on openwrt).
Perhaps I wasn't clear enough in the original post.
The CNAME's target hostname is something like my-home-server.lan.mydomain.tld with lan.mydomain.tld being DHCP's local domain for the subnet/zone where the host with name my-home-server lives. Thus, it can only be resolved by the dhcp server (openwrt). And it is actually resolved by openwrt.
Just to simplify the equation, let's forget about pihole. I would set openwrt's upstream dns server directly to adguard now. If it somehow magically resolves the issue, I will write about it here.
Temporarily enable query logging in dnsmasq. Is my-home-server.lan.mydomain.tld a reserved address in your dhcp pool? Is Forward/reverse DNS option checked for the reservation?
dnsmasq won’t be able to resolve a dhcp client name unless it’s already registered the lease, if there are no other static records of that hostname.
It seems it would just be easier to set the CNAME in dnsmasq instead of externally if the external CNAME can never resolve correctly in the public dns.
It always only the first time. The log looks like:
daemon.info dnsmasq[1]: 13002 10.57.57.114/55749 query[A] myservice.mydomain.tld from 10.57.57.114
daemon.info dnsmasq[1]: 13002 10.57.57.114/55749 forwarded myservice.mydomain.tld to 9.9.9.11
daemon.info dnsmasq[1]: 13002 10.57.57.114/55749 reply myservice.mydomain.tld is <CNAME>
daemon.info dnsmasq[1]: 13002 10.57.57.114/55749 reply my-home-server.lan.mydomain.tld is NXDOMAIN
## <...>
daemon.info dnsmasq[1]: 13014 10.57.57.114/61753 query[A] myservice.mydomain.tld from 10.57.57.114
daemon.info dnsmasq[1]: 13014 10.57.57.114/61753 cached myservice.mydomain.tld is <CNAME>
daemon.info dnsmasq[1]: 13014 10.57.57.114/61753 DHCP my-home-server.lan.mydomain.tld is 10.57.14.225
I've enabled it and rebooted openwrt. The log was:
daemon.info dnsmasq[1]: 79 127.0.0.1/42245 /tmp/hosts/dhcp.cfg01411c 10.57.14.225 is my-home-server.lan.mydomain.tld
daemon.info dnsmasq[1]: 96 127.0.0.1/53960 /tmp/hosts/dhcp.cfg01411c 10.57.14.225 is my-home-server.lan.mydomain.tld
## <...>
daemon.info dnsmasq[1]: 149 10.57.57.114/54043 query[A] myservice.mydomain.tld from 10.57.57.114
daemon.info dnsmasq[1]: 149 10.57.57.114/54043 forwarded myservice.mydomain.tld to 9.9.9.11
daemon.info dnsmasq[1]: 149 10.57.57.114/54043 reply myservice.mydomain.tld is <CNAME>
daemon.info dnsmasq[1]: 149 10.57.57.114/54043 reply my-home-server.lan.mydomain.tld is NXDOMAIN
## <...>
daemon.info dnsmasq[1]: 152 10.57.57.114/61055 query[A] myservice.mydomain.tld from 10.57.57.114
daemon.info dnsmasq[1]: 152 10.57.57.114/61055 cached myservice.mydomain.tld is <CNAME>
daemon.info dnsmasq[1]: 152 10.57.57.114/61055 /tmp/hosts/dhcp.cfg01411c my-home-server.lan.mydomain.tld is 10.57.14.225
Also, I've done some tests with other CNAMEs. If CNAME is present on openwrt, it is resolved to the local record/ip, even if the ip is different on the domain hoster. Didn't try for different target hostnames. Seems like it can be effectively used for split dns. Not what I craved for, though.
OK, I understand what's happening now, mostly. On the initial attempt, the query is forwarded to Quad9, and it rightly responds with NXDOMAIN since it cannot resolve the CNAME target. It doesn't send back the CNAME and have dnsmasq try to resolve the A record in a second query. It all comes back at once from Quad9.
Since dnsmasq caches the CNAME, on subsequent attempts it sees the CNAME in the cache and can find the A record in its DHCP config, so it works.
While you have logging enabled, you can run killall -SIGUSR1 dnsmasq and have it dump the cache to the system log just to see what it's storing.
I think it was a stretch to expect this to work in the first place, but the behavior is kind of weird so maybe it's worth a question on the dnsmasq mailing list.
EDIT: Just as a test to try to replicate similar behavior, I took a public DNS name and added a local hosts entry for the CNAME target, pointing to a local IP. The first query correctly resolved the CNAME from public DNS, but once cached, my local records interfered with subsequent queries. Kind of the opposite effect of what you want, but shows how the CNAME resolution behavior changes once the CNAME is cached. The IPv6 AAAA records still came through because I didn't add an IPv6 address in my test.
Yeah, that was my assumption from the very beginning.
Welp, in my opinion (and I could be wrong), there are mostly two kinds of protocols/standards:
Brilliant, to the point that almost no-one even remembers where it is defined. For one, nobody with modern hardware gives a duck whether the ethernet cable is crossover or not. It just works.
Good enough for the overall usage.
And it seems that DNS falls into the second category...
Nah, not worth it in my opinion.
Yeah, this makes DNS resolution somewhat non-idempotent. OTOH, nobody promised it would have an idempotence.
Thanks for your help, @dave14305. I will probably just create CNAMEs at the openwrt, unless I discover the other method.