"Selective DNS Forwarding" not working when using "DNS Forwarding"

I’m trying to setup a selective DNS forwarding rule for kresd to resolve my tailscale DNS names (foo.ts.net) over the tailscale DNS server (100.100.100.100). Just in case, tailscale is working properly on the router and the router clients can reach out the rest of the tailscale hosts via IP, but I wanted to add the ability to reach them via hostname.

After reading Knot resolver (i.e. kresd) - DNS advanced settings for Omnia and MOX [Turris wiki] I’ve created the custom.conf file as:

policy.add(policy.suffix(policy.FORWARD('100.100.100.100'), {todname('foo.ts.net.')}))

But after a resolver restart it doesn’t work. I think it is because the “DNS Forwarding” setup on Reforis DNS - Turris Documentation takes precedence over the custom one as the generated kresd.config file looks like:

--Automatically generated file; DO NOT EDIT
modules = {
    'hints > iterate'
  , 'policy'
  , 'stats'
  , predict = { window = 0, period = 0 }
}
hints.use_nodata(true)
policy.add(policy.rpz(policy.DENY, '/etc/kresd/adb_list.overall'))
hints.config('/tmp/kresd/hints.tmp')
net.listen('0.0.0.0', 53, { kind = 'dns' })
net.listen('0.0.0.0',   853, { kind = 'tls' })
net.listen('::', 53, { kind = 'dns' })
net.listen('::',   853, { kind = 'tls' })
trust_anchors.remove('.')
trust_anchors.add_file('/etc/root.keys', true)
net.bufsize(1232)
net.ipv4=true
net.ipv6=false
cache.open(20*MB)
cache.clear()
table.insert(policy.special_names, { count = 0, cb = policy.all(
policy.TLS_FORWARD(
{{'1.1.1.1'
,hostname='cloudflare-dns.com'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
},{'1.0.0.1'
,hostname='cloudflare-dns.com'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
}}))})

--- Included custom configuration file from: ---
--- /etc/kresd/custom.conf
policy.add(policy.suffix(policy.FORWARD('100.100.100.100'), {todname('foo.ts.net.')}))
user('kresd','kresd')

Do I need to inject the policy.add stuff before the DNS Forwarding?If that’s so… how?
:slight_smile:

I’ve also tried this Kresd custom DNS forwarding rule before "Use forwarding" rule - #2 by dpdrown approach but it still doesn’t work.

Any hints?

Thanks!

Perhaps just uncheck forwarding and write all of it the way you want it.

I unchecked forwarding and just added the forward policy as:

policy.add(
	policy.suffix(
		policy.FORWARD('100.100.100.100'), {todname('foo.ts.net.')}
	)
)

to the custom.conf file but still no luck.

The rendered kresd.conf file looks like:

--Automatically generated file; DO NOT EDIT
modules = {
    'hints > iterate'
  , 'policy'
  , 'stats'
  , predict = { window = 0, period = 0 }
}
hints.use_nodata(true)
policy.add(policy.rpz(policy.DENY, '/etc/kresd/adb_list.overall'))
hints.config('/tmp/kresd/hints.tmp')
net.listen('0.0.0.0', 53, { kind = 'dns' })
net.listen('0.0.0.0',   853, { kind = 'tls' })
net.listen('::', 53, { kind = 'dns' })
net.listen('::',   853, { kind = 'tls' })
trust_anchors.remove('.')
trust_anchors.add_file('/etc/root.keys', true)
net.bufsize(1232)
net.ipv4=true
net.ipv6=false
cache.open(20*MB)
cache.clear()

--- Included custom configuration file from: ---
--- /etc/kresd/custom.conf
policy.add(
	policy.suffix(
		policy.FORWARD('100.100.100.100'), {todname('foo.ts.net.')}
	)
)
user('kresd','kresd')

Any hints?
Thanks.

There should be a list of addresses, i.e. braces around it. I’m not sure if it works without them. Either way, I’m not very good in syntax-checking. Reading error logs might help, too.

I used an example from Forwarding — Knot Resolver 5.7.1 documentation

policy.add(policy.suffix(policy.FORWARD('192.0.2.1'), {todname('example.com.')}))

I enabled debug and somehow it seems the issue is the tailscale DNS cannot be reached:

Mar 29 10:55:54 turris kresd[5077]: [iterat][56387.07]   'example.foo.ts.net.' type 'A' new uid was assigned .10, parent uid .00
Mar 29 10:55:54 turris kresd[5077]: [plan  ][56387.10]   plan 'ts.net.' type 'DS' uid [56387.11]
Mar 29 10:55:54 turris kresd[5077]: [iterat][56387.11]     'ts.net.' type 'DS' new uid was assigned .12, parent uid .10
Mar 29 10:55:54 turris kresd[5077]: [cache ][56387.12]     => no NSEC* cached for zone: net.
Mar 29 10:55:54 turris kresd[5077]: [cache ][56387.12]     => skipping zone: net., NSEC, hash 0;new TTL -123456789, ret -2
Mar 29 10:55:54 turris kresd[5077]: [cache ][56387.12]     => skipping zone: net., NSEC, hash 0;new TTL -123456789, ret -2
Mar 29 10:55:54 turris kresd[5077]: [resolv][56387.12]     => id: '27615' querying: '.'@'100.100.100.100#00053' zone cut: 'net.' qname: 'ts.net.' qtype: 'DS' proto: 'udp'
Mar 29 10:55:55 turris kresd[5077]: [worker][56387.14]     => connection to '100.100.100.100#00053' failed (internal timeout)
Mar 29 10:55:55 turris kresd[5077]: [select][56387.14]     => id: '55123' noting selection error: '.'@'100.100.100.100#00053' zone cut: 'net.' error: 4 TCP_CONNECT_TIMEOUT
Mar 29 10:55:55 turris kresd[5077]: [iterat][56387.14]     'ts.net.' type 'DS' new uid was assigned .15, parent uid .10
Mar 29 10:55:55 turris kresd[5077]: [resolv][56387.15]     => id: '34998' querying: '.'@'100.100.100.100#00053' zone cut: 'net.' qname: 'ts.net.' qtype: 'DS' proto: 'tcp'
Mar 29 10:55:55 turris kresd[5077]: [worker][56387.15]     => connecting to: '100.100.100.100#00053'

However dig works:

dig @100.100.100.100 example.foo.ts.net

; <<>> DiG 9.18.16 <<>> @100.100.100.100 example.foo.ts.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54291
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;example.foo.ts.net.	IN	A

;; ANSWER SECTION:
example.foo.ts.net. 600 IN	A	100.X.Y.Z

;; Query time: 0 msec
;; SERVER: 100.100.100.100#53(100.100.100.100) (UDP)
;; WHEN: Fri Mar 29 12:01:52 CET 2024
;; MSG SIZE  rcvd: 88

OK. I don’t remember everything.

Now this log is very useful. 100.100.100.100 doesn’t reply to perfectly legitimate queries. Perhaps it’s confused by any DNSSEC, I don’t know. You may want to use STUB instead of FORWARD. I’m sorry I don’t feel like exactly analyzing your individual needs of this.