etc_dnsmasq_d Config not loading after updating to 6.1

I tried to expand on the tests that Bucking_Horn has completed and looked again at the config when Conditional Forwarding is enabled vs when the dnsmasq config is enabled and in the resulting dnsmasq.conf in the /etc/pihole/dnsmasq.conf. Similar to the results above I see the section detailed below are the major difference. My local domain is added as an entry for local="Fill in Domain name" when conditional forwarding is not enabled.

Conditional Forwarding enabled

# DNS domain for both the DNS and DHCP server
# This DNS domain is also used for reverse lookups
# (see server=/<domain>/target above)
domain=ABC99.NET

dnsmasq only

# DNS domain for both the DNS and DHCP server
# This DNS domain is purely local. FTL may answer queries from
# /etc/hosts or DHCP but should never forward queries on that
# domain to any upstream servers
domain=ABC99.NET
local=/ABC99.NET/

It seems to me as if the process that is generating the /etc/pihole/dnsmasq.conf is adding this local= section incorrectly or at least differently than it has in the past. It also explains why every other forward lookup zone that is added to dnsmasq.d config is working as expected.

Based on a quick test I changed the dns.domain in pihole.toml to testabc99.net and removed the conditional forwarding now that section reads as follows below and my dnsmasq config is working as expected.

# DNS domain for both the DNS and DHCP server
# This DNS domain is purely local. FTL may answer queries from
# /etc/hosts or DHCP but should never forward queries on that
# domain to any upstream servers
domain=testABC99.NET
local=/testABC99.NET/

It appears to me based on the testing with my config that between version 6.0 and 6.1 that this behavior has changed as my configuration has not changed between the updates.

Developers (@rdwebdesign and @DL6ER) can you confirm change? If this is now the expected behavior would there be a possibility to add a toggle someplace that would allow the dns.domain to be set and not added to a local= entry in the resulting dnsmasq.conf created by Pi-Hole?

At least not between v6.0 and v6.1, see the only change concerning dnsmasq config generation here. Actually, the last relevant change is > 1 year ago and was already part of Pi-hole v6.0:


When you specify a domain here, your Pi-hole generates a self-consistent configuration, taking into account everything it knows from pihole.toml (incl. conditional forwarding) but not from possibly existing external configuration (as you asked Pi-hole to manage this domain). If you do not want this local=// magic to happen, set dns.domain = "" (an empty string) to have Pi-hole stay away from assuming any configuration for you.

Have you tried this?

I've tried that and can confirm that with dns.domain set to "" it works. Thank you

I don't see any change of behaviour, regardless whether I supply a Pi-hole domain name (dns.domain) or not: forwards are still only working when Conditional Forwarding is enabled.

My dns.domain setting is set in the GUI as "lan". Setting it to an empty string does seem to fix the issue for me in the latest image.

Interesting workaround but what does it mean? Why has this behaviour changed between 6.0 and 6.1? Some kind of interaction between this setting and a dnsmasq change?

I have tried that as well and it will correct the DNS forwarding issue to my other servers, however that is not the intended result. I want the domain to be set for the DHCP benefits to a specific VLAN that this serves DHCP for while the main server manages DNS for the other VLAN. Setting this to blank or another value will not get that result.

Again, this was the same config running on version 6.0.4 and was working perfect, so I ask again what changed that causes this behavior?

Also since there is logic built in that does not create the local= entry when the Conditional Forwarding is enabled for the same domain, can a new setting to be added to allow us to trigger the same exclusion if we wish. Something that would allow me not to use Conditional Forwarding but still have the Domain configured and look up the domain via configuration in dnsmasq?

Nothing. And that's the problem. We currently assume it's a regression of a recent change in the behavior of dnsmasq's server=... option and are working on it with the maintainer of dnsmasq.

The suggested workaround is not meant as solution but, well, just as a bandaid unless the regression is fixed - or - dnsmasq claims this is the new expected behavior in which case we have to look for another solution.

For me the workaround does not fix the isse. I can see that with dns.domain set to my domain the PiHole is completely blocking conditional forward requests. Reverse Requests are working.

When I set dns.domain to empty I got a timeout instead of NXDOMAIN Answer. But conditional Forward Lookup stil ldoes not work.

With my other PiHole on 6.0.6 core and 6.1 FTL everything is working with the same config. Also it is working with dns.domain set to my domain.

You should never get a timeout unless the server this is sent do does either not exist or refuses to answer elsehow. What are the related lines in your /var/log/pihole/pihole.log when such a timeout occurs?

The outcome of this is that this change is likely the cause:

Fix some edge cases with domains and address and server.

Consider what happens when the same domain appears in address and server.

This commit fixes the order, I think correctly like this: highest to lowest priority.

address with a IPv4 or IPv6 address (as long as the query matches the type)
address with # for all-zeros, as long as the query is A or AAAA)
address with no address, which returns NXDOMAIN or NOERROR for all types.
server with address set to # to use the unqualified servers.
server with matching domain.
server without domain or from /etc/resolv.conf.

Note that the above is only valid when same domain appears. The domain being matched is determined first, and has a higher priority, so you can send google.com to a server and force com to return NXDOMAIN and for google.com the server config will override the address config, because there's a longer match.

local is a synonym for server and does basically the same thing.

So ... this change seem to be the issue here as server=/lan/ takes priority over server=/lan/1.2.3.4 and that would explain what you're seeing, including the described workaround that server=/*.lan/1.2.3.4 still works, since it's a longer match and therefore takes priority.

Yes, probably what we need to add now with dnsmasq's change in behavior. The default behavior should probably de true to keep this setting to continue preventing forwarding this for standard deployments without extra dnsmasq config.

As far as I remember reading this discussion (and elsewhere), it affects only users with custom dnsmasq lines either in a file or in misc.dnsmasq_lines.

Why not just have the default be to not add the line if the user has a custom dnsmasq config? It's always going to interfere.

The custom dnsmasq config could also be something like special DHCP settings, it does not automatically mean that there will be a server directive which would be in conflict with the local=// line which is very meaningful without a dedicated server to send them so intentionally.

Proposed solution:

So far, I've been using my Docker Pi-hole for testing.
I've just upgraded my main Pi-hole to
Core v6.1.2FTL v6.2.3Web interface v6.2.1

Now, Conditional Forwarding itself doesn't work anymore.

true,192.168.2.0/24,192.168.2.1,fritz.box

$ nslookup pihole-5
;; Got SERVFAIL reply from 192.168.2.53
Server:		192.168.2.53
Address:	192.168.2.53#53

** server can't find pihole-5: SERVFAIL
2025-06-21 09:16:04.849 141 192.168.2.11/52906 query[A] pihole-5.fritz.box from 192.168.2.11
2025-06-21 09:16:04.856 141 192.168.2.11/52906 config pihole-5.fritz.box is NXDOMAIN

2025-06-21 09:16:04.858 142 192.168.2.11/46047 query[A] pihole-5 from 192.168.2.11
2025-06-21 09:16:04.863 142 192.168.2.11/46047 forwarded pihole-5 to 192.168.2.1

2025-06-21 09:16:04.865 143 dnssec-query[DS] pihole-5 to 127.0.1.1#5335
2025-06-21 09:16:04.870 143 reply pihole-5 is no DS/cut
2025-06-21 09:16:04.872 142 192.168.2.11/46047 validation pihole-5 is BOGUS (EDE: RRSIG missing)

The forward is done correctly only for the plain name, but it would seem that contrary to previous versions, dnsmasq now is validating DNSSEC records that go to a custom upstream, in contrast to its documentation:

DNSSEC validation is turned off for such private nameservers, UNLESS a --trust-anchor is specified for the domain in question.

I didn't supply any trust anchors.

Setting misc.dnsmasq_lines to

server=/*.fritz.box/192.168.2.1

will allow nslookup pihole-5 to successfully return an IP, but dig pihole-5 still returns a SERVFAIL due to EDE: RRSIG missing.

Does your /etc/pihole/dnsmasq.conf contain the line

local=/fritz.box/

or an other unexpected fritz.box lines?

Could you please also try the custom branch from the bugfix PR

sudo pihole checkout ftl new/dns_domainLocal

and set the new option dns.domainLocal = false?

I have set Pi-hole domain name (dns.domain) to fritz.box.
Could that have an impact?

I don't see any unexpected lines otherwise.

$ grep -v '^#\|^$' /etc/pihole/dnsmasq.conf
hostsdir=/etc/pihole/hosts
no-resolv
port=53
server=127.0.1.1#5335
cache-size=10000
localise-queries
log-queries
log-async
log-facility=/var/log/pihole/pihole.log
bogus-priv
expand-hosts
dnssec
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
trust-anchor=.,38696,8,2,683D2D0ACB8C9B712A1948B27F741219298D0A450D612C483AF444A4C0FB2B16
use-stale-cache=3600
local-service
rev-server=192.168.2.0/24,192.168.2.1
server=/fritz.box/192.168.2.1
server=//192.168.2.1
local=/home.arpa/
domain=fritz.box
local=/pi.hole/
host-record=pi.hole,0.0.0.0
cname=time.fritz.box,fritz.box
cname=time.windows.com,time.fritz.box
cname=time.nist.gov,time.fritz.box
cname=pool.ntp.org,time.fritz.box
server=/test/
server=/localhost/
server=/invalid/
server=/bind/
server=/onion/
conf-dir=/etc/dnsmasq.d,*.conf
cache-rr=ANY
filter-rr=ANY
server=/*.fritz.box/192.168.2.1

With the custom branch, removing server=/*.fritz.box/192.168.2.1 from misc.dnsmasq_lines and disabling dns.domainLocal produces the same output:

2025-06-21 10:22:11.679 143 192.168.2.11/35300 query[A] pihole-5.fritz.box from 192.168.2.11
2025-06-21 10:22:11.689 143 192.168.2.11/35300 config pihole-5.fritz.box is NXDOMAIN
2025-06-21 10:22:11.693 144 192.168.2.11/58093 query[A] pihole-5 from 192.168.2.11
2025-06-21 10:22:11.701 144 192.168.2.11/58093 forwarded pihole-5 to 192.168.2.1
2025-06-21 10:22:11.704 145 dnssec-query[DS] pihole-5 to 127.0.1.1#5335
2025-06-21 10:22:11.710 145 reply pihole-5 is no DS/cut
2025-06-21 10:22:11.711 144 192.168.2.11/58093 validation pihole-5 is BOGUS (EDE: RRSIG missing)

The same goes for adding misc.dnsmasq_lines back in: nslookup pihole-5 succeeds, but dig pihole-5 still returns a SERVFAIL.

The behavior looks fishy even though the config itself seems correct at first glance.

Problem 1 (with domain)

We have

server=/fritz.box/192.168.2.1

but you immediately get

2025-06-21 10:22:11.679 143 192.168.2.11/35300 query[A] pihole-5.fritz.box from 192.168.2.11
2025-06-21 10:22:11.689 143 192.168.2.11/35300 config pihole-5.fritz.box is NXDOMAIN

which is not okay. It should be forwarded.


Problem 2 (without domain)

Relevant config line for the domin pihole-5 (note, no domain!) is

server=//192.168.2.1

and we indeed see

2025-06-21 10:22:11.693 144 192.168.2.11/58093 query[A] pihole-5 from 192.168.2.11
2025-06-21 10:22:11.701 144 192.168.2.11/58093 forwarded pihole-5 to 192.168.2.1

which is correct but also

2025-06-21 10:22:11.704 145 dnssec-query[DS] pihole-5 to 127.0.1.1#5335

which should not be happening.

Just from completeness, your config shows you are loading *.conf files from /etc/dnsmasq.d - what is in those?

Oh, I forgot about those.
They add a few hostnames for wireguard/PiVPN and custom CNAMEs, some extra logging and LLA/ULA IPv6 reverse lookups:

grep -v '^#\|^$' /etc/dnsmasq.d/*
/etc/dnsmasq.d/02-pivpn.conf:addn-hosts=/etc/pivpn/hosts.wireguard
/etc/dnsmasq.d/42-connectivity-mocks.conf:host-record=pi.hole.fritz.box,192.168.2.53,3600
/etc/dnsmasq.d/42-connectivity-mocks.conf:cname=clients3.google.com,connectivitycheck.android.com,connectivitycheck.gstatic.com,pi.hole.fritz.box,43200
/etc/dnsmasq.d/42-connectivity-mocks.conf:cname=connectivitycheck.cbg-app.huawei.com,connectivitycheck.platform.hicloud.com,pi.hole.fritz.box,43200
/etc/dnsmasq.d/42-connectivity-mocks.conf:cname=www.msftncsi.com,www.msftconnecttest.com,pi.hole.fritz.box,43200
/etc/dnsmasq.d/42-connectivity-mocks.conf:cname=ipv6.msftncsi.com,ipv6.msftconnecttest.com,pi.hole.fritz.box,43200
/etc/dnsmasq.d/42-ipv6-reverse.conf:rev-server=fd00::/8,192.168.2.1
/etc/dnsmasq.d/42-ipv6-reverse.conf:rev-server=fe80::/64,192.168.2.1
/etc/dnsmasq.d/42-local-network-awareness.conf:local-ttl=60
/etc/dnsmasq.d/42-local-network-awareness.conf:log-queries=extra

@Bucking_Horn Branch update/dnsmasq should resolve problem 2 from above, the first issue (config pihole-5.fritz.box is NXDOMAIN) is still under ongoing investigation...

I can confirm that switching to update/dnsmasq allows lookups for plain hostnames to succeed while DNSSEC is enabled:

~$ dig +short pihole-5
192.168.2.55
2025-06-24 11:14:29.494 185 192.168.2.11/60582 query[A] pihole-5 from 192.168.2.11
2025-06-24 11:14:29.504 185 192.168.2.11/60582 forwarded pihole-5 to 192.168.2.1
2025-06-24 11:14:29.507 186 dnssec-query[DS] pihole-5 to 127.0.1.1#5335
2025-06-24 11:14:29.548 Negative DS reply without NS record received for pihole-5, assuming non-DNSSEC domain-specific server.
2025-06-24 11:14:29.559 186 reply pihole-5 is no DS
2025-06-24 11:14:29.560 185 192.168.2.11/60582 validation result is INSECURE
2025-06-24 11:14:29.561 185 192.168.2.11/60582 reply pihole-5 is 192.168.2.55

That also works with DNSSEC disabled.

EDIT: I'll note that dns.domainLocal seems absent in update/dnsmasq.