Need help understanding bootstrap, fallback and upstream servers in dnsproxy package

I have set up dnsmasq and dnxproxy for DNS over TLS, DNS over HTTPS, and all the other ones it supports. I also uploaded and installed the LuCi app for it.

What I am unsure of, is how the bootstrap, fallback and upstream servers are supposed to interact with each other, and particularly when there are multiple servers per each category. For example...

config dnsproxy 'servers'
        list bootstrap 'tls://9.9.9.9'
        list fallback 'tls://8.8.8.8'
        list upstream 'https://base.dns.mullvad.net/dns-query'

So from what I understand, the "bootstrap" server will be used to resolve any DoH "upstream" server, and then if the "upstream" ever fails, then it will resort to the "fallback". However, what about with something like this...

config dnsproxy 'servers'
        list bootstrap 'tls://9.9.9.9'
        list bootstrap 'tls://149.112.112.112'
        list upstream 'https://base.dns.mullvad.net/dns-query'
        list upstream 'https://dns.adguard-dns.com/dns-query'
        list fallback 'tls://8.8.8.8'
        list fallback 'tls://8.8.4.4'

I am wondering how the logic works with multiple servers specified for each bootstrap, upstream, and fallback category, and if this configuration is even valid. I'm assuming it is since the LuCi app generated it, but it's a little bit unclear about what logic it applies to this list...

Is there some kind of branched-iteration? Because that seems like it would get complicated to grasp... Assuming that any DNS request will iterate through the list of upstream servers, trying the first one listed first? Then, depending on if it's a DoH server, I assume it will then iterate over the list of boostrap servers until it gets an answer back. Then, if it goes through the list of bootstrap servers and doesn't get an answer, then will the first upstream server then iterate through the list of fallback servers to attempt to get an answer? Because it would seem to me if this was the case, that iterating through the upstream servers would be pointless since one of the servers in the fallback would surely succeed before it could ever reach that point?

I don't think that would be a particularly good system so I am wondering instead if each bootstrap, upstream and fallback has a respective counterpart, such as...

config dnsproxy 'servers'
        list bootstrap 'upstream 1's bootstrap'
        list bootstrap 'upstream 2's bootstrap'
        list upstream 'upstream 1'
        list upstream 'upstream 2'
        list fallback 'upstream 1's fallback'
        list fallback 'upstream 2's fallback'

Try upstream documentation.

bootstrap: Used if you need to resolve your upstream servers, which is the case in your configuration.
fallback: Used if all upstream servers fail.

Your configuration is correct.

If your upstream servers don't need name resolutions (by using raw IP addresses), you don't need bootstrap servers.
If you're sure your upstream servers will never fail, you don't need fallback servers.

As for which dns server dnsproxy will use, I believe it's the same logic as upstream_mode, that is, load_balance/parallel/fastest_addr.

I saw that, but I didn't really see any documentation pertinent to what I'm discussing, except for a brief description of the load-balancing options. Is that what you meant?

Okay, but does it only apply that logic to the available upstream_servers?

For example, let's say I need to resolve https://base.dns.mullvad.net/dns-query. It will attempt to resolve that through the bootstrap server, but what if the first one listed doesn't respond? Does it then attempt the second bootstrap server available, or does it merely consider it a failure? If it is a failure, then it will try the fallback servers until it gets a response? I'm assuming if any of the fall-back servers also have a host-name, that will again then try to use the bootstrap servers.

I guess what is confusing to me about this all is why bother with "fallback" servers if you can just make a list of "upstream" servers to try? Wouldn't each successive upstream server in the list be a "fallback"? How does a list of fallback servers actually differ from a list of upstream servers?

Because you may not want to use a protocol/server, unless all of your main upstream servers have failed.

And yes, it will query all available servers until either a valid response is returned or all servers have failed.

load_balance: Arbitrary order.
parallel: Send request to all servers and then wait for the first valid response.
fastest_addr: Start with the fastest server.

1 Like

Okay, that makes more sense! It seems that the documentation encourages adding as many upstream nodes as possible for reliance, but I have found adding too many seems to cause dnsproxy to do a lot more processed and my router can't really keep up.

My new config looks as such...

config dnsproxy 'servers'
        list fallback 'tls://9.9.9.9'
        list fallback 'tls://149.112.112.112'
        list fallback '9.9.9.9'
        list fallback '149.112.112.112'
        list fallback '1.1.1.1'
        list fallback '1.0.0.1'
        list fallback '208.67.220.220'
        list fallback '208.67.222.222'
        list bootstrap 'tls://9.9.9.9'
        list bootstrap 'tls://149.112.112.112'
        list bootstrap 'tls://89.233.43.71'
        list bootstrap 'tls://185.49.141.37'
        list upstream 'https://base.dns.mullvad.net/dns-query'
        list upstream 'https://dnsforge.de/dns-query'
        list upstream 'https://dns.adguard-dns.com/dns-query'

So unless I'm completely misunderstanding the flow of things...

A DNS query will first try to be resolved through the first listed upstream server, which will then need to use one of the bootstrap servers to resolve the host-name. If the first bootstrap server doesn't work, it will go down the list until it find one that does. But it will NOT rely on a fallback server to resolve the upstream server's host-name, but rather move to the next upstream server in the list. Only if it goes through all of the upstream servers will it try a fallback.

So basically with this setup, I'll be trying to query through Mullvad, bootstrapped on Quad9's or PrivacDNS's DoT servers. If that doesn't work, try DNSForge, and finally AdGuard, and finally if none of those don't work, it will try the list of fallback servers which I configured to try Quad9's DoT servers first, and then their normal servers if that doesn't work, then Cloudfare and finally Cisco, with the idea being at least one of these servers never being down.

I think this is a pretty robust list but also doesn't seem to be causing too much extra processing with dnsproxy.