DNSSEC Validating Resolver on OpenWRT
I have been running bind
in resolver mode, with DNSSEC
validation enabled on my home computer for some years. The home router was not set up to point the rest of the devices to that, so they all used non-validating dnsmasq
on the router.
Recently I got a new router and installed fresh version of openwrt
. It has unbound
in the default app repo so I soon switched off the DNS part of dnsmasq and enabled unbound
instead.
This has a drawback of not having the local network served by dynamic dns of dnsmasq
, so I could no longer access mobile devices by their names. It is not such a big deal, but it irritated me. So I decided to chain the two dns servers together, to have both a validating resolver and a properly handled domain for the home network.
Unfortunately, the build of unbound
on openwrt
is quite rough. It is not integrated with Luci
, and does not even work out of the box until you manually disable the dns functionality of dnsmasq
by setting the listen port to 0
. There is a howto on the web on chaining unbound “behind” dnsmasq. I wanted it the other way around, something that the guy could not achieve.
First, we want to put dnsmasq
on the side. The easiest way is to change the listening port to something non-standard. This can be done from the GUI:
Network -> DHCP and DNS -> Advanced Settings
set DNS Server Port
to 5553
, and hit Save&Apply;
. (At this point DNS
will stop working on your network until you configure and launch unbound
.)
Now, to the magic part. We will be configuring unbound
to serve all the world as a normal caching resolver, except the local domain and the reverse zone for the local network, for which it will act as a forwarder. In the examples we assume that the local domain is ‘lan
’ and the local network is 192.168.<something>
. We will need to add something to the configuration file “/etc/unbound/unbound.conf
”.
First, the basic forwarding directives:
forward-zone:
name: "lan."
forward-addr: 127.0.0.1@5553
forward-zone:
name: "168.192.in-addr.arpa."
forward-addr: 127.0.0.1@5553
These are self-explanatory. But this is not enough. We have to add a number of directives to the server section. First, unbound
refuses to send DNS
requests to localhost
by default. To persuade it, we need this directive:
do-not-query-localhost: no
Then, by default, unbound
will try to establish trust chain. Serving a query in the “lan.
” domain, it will try to get the DS
record form the parent domain, in this case “.
”. Of course the Internet root servers have no idea about our local “lan.
” domain and will respond with NXDOMAIN
. Which will break the trust chain. To prevent unbound
from attempting to build the trust chain, we need to write these directives (second is for the reverse zone):
domain-insecure: "lan."
domain-insecure: "168.192.in-addr.arpa."
Next, by default, unbound
refuses to return A
s and AAAA
s that point to private (RFC1918) addresses. We have such addresses in the “lan.
” domain, so tell it to unbound
:
private-domain: "lan."
On the other side, unbound
refuses to deal with PTR
s that come from private addresses, so we must override that too:
local-zone: "168.192.in-addr.arpa" nodefault
That’s all. Now save the file, “Enable
” and “Start
” the “unbound
” service in System -> Startup
and it should work.
Should you need to troubleshoot, run "unbound -vvv"
and "logread -f"
. With some luck, the messages will hint to the problem.