How to localize, not forward queries for a domain name?
Hi all,
I own a turris router and let's assume I own a domain name example.org. My router's external interface has a public IP. I setup a dynamic DNS record for the router home.example.org. Any unknown sub-domain DNS record like x.y.example.org resolves to IP of example.org.
Now I want a local DNS overlay provided by knot resolver (dnsmasq supports this feature). All my devices at home get an non-public network IP address like:
host1.lan.example.org
host2.lan.example.org
host3.lan.example.org
Every internal network client gets an internal DNS name with the suffix lan.example.org. knot-resolver automatically sets up the hostnames from DHCP leases provided by odhcpd.
I was unable to localize the queries for my local network. By localizing I mean that knot resolver resolves the quieries locally from it's "DHCP cache", but does not forward them to the upstream DNS servers.
Solution that fail to work:
- Always forwarding: unknown (local) hostname like "does-not-exist.lan.example.org" returns external IP of example.org (instead of NXDOMAIN)
- Blocking lan.example.org: If I used POLIC.DENY to block resolving hosts with suffix lan.example.org then "does-not-exist.lan.example.org" get NXDOMAIN, but all other hosts fail to resolve, too :-/
- I tried using Policy.PASS for lan.example.org (in order to just look-up the DNS name up from "hints cache"), but that did not work properly. Either queries are not properly answered (not resolved against hints cache) or the DNS requests are send to the upstream DNS again (getting an reply with the external IP).
It's been a while since I spent time troubleshooting my setup. Please tell me what information you need. I read a lot of your documentation, but failed to find a solution.
My custom.conf for kresd (aka. knot-resolver):
-- Comment
--local trace_rule = policy.add(policy.suffix(policy.QTRACE, {todname('lan.example.org.')}))
--policy.del(trace_rule.id)
--table.insert(policy.rules, 1, trace_rule)
-- local hints_rule = policy.add(policy.suffix(policy.all(kres.YIELD),{todname('lan.example.org.')}))
local hints_rule = policy.add(policy.suffix(function(state, req)
local qry = req:current()
--print('Local DNS ',qry.sname,' hints "','"')
--print('Local DNS "',ffi.string(qry.sname,sizeof(qry.sname)), '" hints ""')
--print('Local DNS ',qry.sname,' hints "',hints.get(qry.sname),'"')
--ffi.C.knot_dname_is_sub(qry.sname, todname('ip6.arpa.'))
--if hints.get(qry.sname) == '{ result: [] }' then
return policy.DENY
--else
-- return policy.PASS
--end
end
,{todname('lan.example.org.')}))
--local hints_rule = policy.add(policy.suffix(policy.FLAGS('',kres.query.ALWAYS_CUT),{todname('lan.example.org.')}))
policy.del(hints_rule.id)
table.insert(policy.rules, 1, hints_rule)
--policy.add(policy.all(policy.FORWARD({ '<upstream IPv4 DNS>' })))
Current Knot DNS Resolver, version 1.5.1 (turris OS v3.9.6).