Can I add more than one DNS resolver to Knot?

Background
Usually I specify 3 DNS resolvers for use by the router,
1.1.1.1, 9.9.9.9, 8.8.8.8
and exclude the ISP’s DNS server.

In Gargoyle and GliNet/Luci, this is available from the gui,

And then in the config file used in Gargoyle/Openwrt I can see:
/etc/config/network

 config interface 'wan'
  option dns '9.9.9.9 1.1.1.1 8.8.8.8'
  option peerdns '0'

The Problem Here
The reForis interfaces only allows the selection of 1 DNS server for the router.
and checking the config files, I see in /etc/config/resolver

  option forward_upstream '1'
  option forward_custom '99_cloudflare'

Could I add a 2nd option forward_ , and would it be recognised / ignored / crash?
The documentation in wiki.turris.cz/en/public/dns_knot_misc
provides no guidance, it just talks of adding one DNS service.

OR, as an alternative possibility,
what would happen if i added lines to /etc/config/network such as:

 config interface 'wan'
  option dns '9.9.9.9 1.1.1.1 8.8.8.8'
  option peerdns '0'

A post from 2017 suggests this worked then, but it may no longer be the case:
https://forum.test.turris.cz/t/how-to-configure-knot-resolver-to-use-specific-dns-servers/1755

Would the Knot Resolver use them or would they be ignored?

Grateful for any guidance. It has taken me days of study to get to this point :sweat_smile: :cry: :sweat_smile: :cry:

If you click “add custom forwarder”, you can select 2 IPv4 + 2 IPv6 addresses. They don’t need to be “from the same company”.

Thanks vcunat, I tried it, but while I can add a custom forwarder, i can still choose only one forwarder.

ah, wait, i understand what you are saying now. Let me try it!

ok, I tried it.
Problem is while it allows 2 IPv4 + 2 IPv6 addresses, it only allows one hostname.
The result is that /tmp/kresd.config looks like this:

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'
},{'9.9.9.9'
,hostname='cloudflare-dns.com'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
}}))})
user('kresd','kresd')

so must be that the wrong certificate will be used for the 2nd entry.
The only way around this is to specify no TLS, which means we have unencrypted
and MITM-able DNS - seems like a bad idea.

I could edit the file by hand to put in the correct host name, but of course it is just a tmp file so will be recreated whenever a crow flies overhead.

You could add your own config file, put these forwarding instructions in there (even 4 should work) and in reForis uncheck forwarding so that it doesn’t clash.

EDIT: I don’t think I’ve seen that done, but I believe that the combined config should be OK.

Ah, thanks, I saw that, but I couldn’t grasp what format to use.

Would I simply add lines to /etc/config/resolver
of the same format as
option forward_custom ‘99_cloudflare’
so it would look like:

option forward_custom ‘99_cloudflare’
option forward_custom ‘99_quad9_filtered’
option forward_custom ‘99_google’

OR
would I put in /etc/kresd/custom.conf
an entry of the form:

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’},

{‘9.9.9.10’,hostname=‘dns.quad9.net’,
ca_file=‘/etc/ssl/certs/ca-certificates.crt’},

{‘8.8.8.8’,hostname=‘dns.google’,
ca_file=‘/etc/ssl/certs/ca-certificates.crt’}
}))})

This one. (it’s easy to miss syntax details, but it looks OK at a glance)

yes, I had to put on 2 pairs of glasses to write it. :joy:
Will try tomorrow.
Assuming it doesn’t crash / lock up, key problem will be how to work out if all 3 DNS servers are actually being used. I believe Leaktest is the standard way.

If all servers work well, the fastest one will be preferred.

I tested today for about 8 hours over all possible configurations
and documented my test results.

No matter what I do, or what configuration I use, the router uses Cloudflare for DNS.
It seems to be either hard-coded somewhere
or there is another overriding config file somewhere.

To summarise the many tests into just two key results:

1 even if I set to Google (or Quad 9) in the GUI
and dont include a config file - the router still uses Cloudflare.

I checked /etc/config/resolver has
option forward_custom '99_google'

and /tmp/kresd.config has

table.insert(policy.special_names, { count = 0, cb = policy.all(
policy.TLS_FORWARD(
{{'8.8.8.8',hostname='dns.google'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
},{'8.8.4.4',hostname='dns.google'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
}}))})

2 If I add a /etc/kresd/custom.conf,
with just Google and Quad9
the same - Uses Cloudflare.
I tested with both
option forward_custom '99_quad9_filtered'
and no option forward_custom statement
in /etc/config/resolver.

Testing Hygiene matters:
3 I confirmed that Leaktest was working correctly by setting
my laptop’s DNS to 1.1.1.1 9.9.9.9 8.8.8.8.
Leaktest correctly showed all the DNS servers being used.
But If I set the laptop’s DNS to the ip of the router,
only Cloudflare gets used.

4 Between every change I rebooted to ensure that everything relevant got restarted.
Every other device in the network was turned off,
so no chance of other random DNS requests interfering.

What have I missed?

I don’t know. My Omnia behaves as expected with https://www.dnsleaktest.com/

1 Like

Yes, I know leaktest works properly here also,
when I configure dns in my laptop, they show correctly in leaktest.

The problem is, while all the internal files look correct,

/etc/config/dhcp
/etc/config/resolver
/etc/config/network
/tmp/resolv.conf	
/tmp/kresd.config

and the gui is correct,
the router is only accessing cloudflare.

Any other files I should check?
Any debugging method you can suggest?

I would start from the fact that in general systems use secondary DNS only when the first doesnt respond in time. Dnsleak is doing some tricks to discover all of them configured

ok, I did a FACTORY RESET
made no other changes,
then in the GUI set the DNS server to Quad9-Filtered.
then did a leaktest and got:
one unknown (possibly Quad9) response and the rest Cloudflare responses.

I then changed the DNS server to Google.
did another Leaktest, and all results were Cloudflare.

so, it seems that Cloudflare is hard-coded somewhere.

Is it possible that there is some error in Google or Quad9 setup
(eg the certificates are expired)
and the system falls back to Cloudflare?

On which machine/system are you testing with dnsleaktest? Maybe the problem doesnt lay in Omnia. If its android then there is setting “Private DNS” somewhere in settings and it has hardcoded Cloudflare

No, I managed that carefully.
I tested with all other machines/phones/devices off except the router and the testing laptop,
and the laptop was set to get its dns from the router
(easy to confirm with ‘resolvectl status’ or nmcli).

BUT
one funny thing happened today.
I had set the DNS server to Google
(in case there was a problem with Quad9) - but still got Cloudflare.
I then turned off DNSSEC in the reForis gui
and then the leaktest gave me Google !!!

However after turning DNSSEC on again , then off, and rebooting,
it went back to Cloudflare
and no turning on/off DNSSEC gave me back Google.

Honestly I find it likely that it’s something around your systemd-resolved.

You can inspect /tmp/kresd.config (the generated configuration). There’s no hard-coding for forwarding anywhere in the code. Only fallback for root server addresses (non-forwarding mode).

? Not sure how that is possible?
systemd-resolved is not in the openwrt repos,
it is not installed on my machine (and of course it is not running)

service systemd-resolved status
	Service "systemd-resolved" not found
netstat -ulpn
udp        0      0 0.0.0.0:53              0.0.0.0:*                           27247/kresd
udp        0      0 0.0.0.0:67              0.0.0.0:*                           27031/dnsmasq
...
udp        0      0 224.0.0.251:5353        0.0.0.0:*                           3520/umdns
udp        0      0 192.168.111.1:5353      0.0.0.0:*                           3520/umdns
udp        0      0 ::1:514                 :::*                                2800/syslog-ng
udp        0      0 :::546                  :::*                                4470/odhcp6c
udp        0      0 :::547                  :::*                                1898/odhcpd
udp        0      0 :::547                  :::*                                1898/odhcpd
udp        0      0 :::53                   :::*                                27247/kresd

However dnsmasq is running, I understand that is providing dhcp service.

(chuckle) of course I am watching this like 1,000 gold coins.
It always shows what I have configured,
currently quad9:

...
hints.use_nodata(true)
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=true
cache.open(20*MB)
table.insert(policy.special_names, { count = 0, cb = policy.all(
policy.TLS_FORWARD(
{{'9.9.9.9'
,hostname='dns.quad9.net'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
},{'149.112.112.112'
,hostname='dns.quad9.net'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
},{'2620:fe::fe'
,hostname='dns.quad9.net'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
},{'2620:fe::9'
,hostname='dns.quad9.net'
,ca_file='/etc/ssl/certs/ca-certificates.crt'
}}))})
user('kresd','kresd')