unbound
unbound copied to clipboard
forward-first: ssl handshake failed on root nameservers.
Describe the bug With 'forward-first' active, unbound attempts to connect to root nameservers using SSL
<29>1 2025-03-04T08:40:44+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="36"] [1838:3] notice: ssl handshake failed 192.33.4.12 port 53
<27>1 2025-03-04T08:41:03+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="37"] [1838:2] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:03+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="38"] [1838:2] notice: ssl handshake failed 192.112.36.4 port 53
<27>1 2025-03-04T08:41:03+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="39"] [1838:2] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:03+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="40"] [1838:2] notice: ssl handshake failed 2801:1b8:10::b port 53
<27>1 2025-03-04T08:41:04+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="41"] [1838:2] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:04+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="42"] [1838:2] notice: ssl handshake failed 2801:1b8:10::b port 53
<27>1 2025-03-04T08:41:14+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="43"] [1838:3] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:14+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="44"] [1838:3] notice: ssl handshake failed 2001:500:12::d0d port 53
<27>1 2025-03-04T08:41:34+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="45"] [1838:2] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:34+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="46"] [1838:2] notice: ssl handshake failed 2001:dc3::35 port 53
<27>1 2025-03-04T08:41:37+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="47"] [1838:1] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:37+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="48"] [1838:1] notice: ssl handshake failed 198.97.190.53 port 53
<27>1 2025-03-04T08:41:44+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="49"] [1838:3] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:44+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="50"] [1838:3] notice: ssl handshake failed 2001:500:12::d0d port 53
<27>1 2025-03-04T08:41:52+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="51"] [1838:1] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:52+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="52"] [1838:1] notice: ssl handshake failed 198.97.190.53 port 53
<27>1 2025-03-04T08:41:53+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="53"] [1838:1] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:53+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="54"] [1838:1] notice: ssl handshake failed 170.247.170.2 port 53
<27>1 2025-03-04T08:41:53+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="55"] [1838:1] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:41:53+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="56"] [1838:1] notice: ssl handshake failed 170.247.170.2 port 53
<27>1 2025-03-04T08:42:04+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="57"] [1838:2] error: ssl handshake failed: channel closed
<29>1 2025-03-04T08:42:04+00:00 OPNsense.cherrybyte.me.uk unbound 1838 - [meta sequenceId="58"] [1838:2] notice: ssl handshake failed 2001:dc3::35 port 53
To reproduce Steps to reproduce the behavior:
- Configure unbound to use quad9 as the primary resolver for all domains
- Use forward-first to cause unbound to fallback to recursive resolution if quad9 fails
For example using this fragment
# Forward zones
# Forward zones over TLS
server:
tls-cert-bundle: /usr/local/etc/ssl/cert.pem
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 2620:fe::9@853#dns.quad9.net
forward-addr: 149.112.112.112@853#dns.quad9.net
forward-addr: 9.9.9.9@853#dns.quad9.net
forward-addr: 2620:fe::fe@853#dns.quad9.net
forward-first: yes
Unbound appears to be trying to connect to root nameservers using TLS, which they do not support
Expected behavior unbound connects to root nameservers using a non-SSL connection to act as backup (whether when needed, or ahead of time)
System:
- Unbound version: 1.22
- OS: FreeBSD 14.2-RELEASE-p2 stable/25.1-n269670-fd3d1a7d1e1 SMP amd64
unbound -Voutput:
Version 1.22.0
Configure line: --with-libexpat=/usr/local --with-libnghttp2 --with-ssl=/usr/local --enable-dnscrypt --disable-dnstap --with-dynlibmodule --enable-ecdsa --disable-event-api --enable-gost --with-libevent --with-pythonmodule=yes --with-pyunbound=yes ac_cv_path_SWIG=/usr/local/bin/swig LDFLAGS=-L/usr/local/lib --disable-subnet --disable-tfo-client --disable-tfo-server --with-pthreads --prefix=/usr/local --localstatedir=/var --mandir=/usr/local/share/man --infodir=/usr/local/share/info/ --build=amd64-portbld-freebsd14.2
Linked libs: libevent 2.1.12-stable (it uses kqueue), OpenSSL 3.0.16 11 Feb 2025
Linked modules: dns64 python dynlib respip validator iterator
DNSCrypt feature available
BSD licensed, see LICENSE in source package for details.
Report bugs to [email protected] or https://github.com/NLnetLabs/unbound/issues
Additional information
This may relate to forward-tls-upstream - but the primary forward addresses require TLS, it's just the 'forward-first' directive which gets it to use recursive that may be causing an issue
The current impact is that forward-first will not work when TLS is being used for the primary servers for a domain.
Note - I do not have either directive specified in the general server block, only in this server zone configuration
Also possibly related:
- https://github.com/NLnetLabs/unbound/issues/1097
The root name servers do not support DNS over TLS and a forward zone is there so that Unbound sends the DNS requests you make to another upstream server via DNS over TLS e.g. to quad9 as you specified, so you have to add more settings that you need here is an example of options: https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in https://unbound.docs.nlnetlabs.nl/en/latest/
Thanks @aura67 - I took a look at the annotated configuration file, but I couldn't see how I might configure
- primarily lookup using TLS
- fallback to root nameservers & recursion
The forward-first seems to be intended to do this, generally, but it retains the use of TLS - which as you say, and I know, is not supported by the root ns.
So I guess I'm wondering if there's a way to have a fallback (not round robin etc.. only to be used in error cases) to recursion without tls.
It seems not?
no, you can either only talk to the root server with unbound or you configure unbound so that it uses a forward zone with dns over tls with other upstream servers and the option :-> forward-first I would leave on default = no so that unbound can cache the answers that come from the upstream server so that unbound doesn't have to ask every time with quad9 for example that happens if you set forward-first to yes so that it asks every time so just leave it on standard you have to decide for yourself whether you want to talk to a different server or rather to the root servers where the domain is held but if you talk to the root server you can't encrypt anything you can only do that with a forward zone and the configuration of the forward zone never comes at the beginning of an unbound configuration but rather at the end of the config you should add options for this I have linked the examples
Thanks
- I understand the root name servers don't support DNS over TLS
- I understand the forward zone in my case is configured to use TLS as I have forward-tls-upstream (this is intended to protect DNS requests in most cases, plus Quad9 is the primary as it has filtering for the worst malicious sites). I do have 2 ipv4 and 2 ipv6 addresses listed which provides some redundancy, but doesn't handle the case (which has happened) where a provider messes up badly...
- don't see in the example configs (there are many) have an option to configure a DoT forwarder with a fallback to non-TLS recursion. They cover one or the other
- I can leave forward-first off, but in this case I don't have fallback beyond the quad9 servers
I do have a few options I can go with, though none really address what was my hope with forward-first
- Having more servers as part of the forward zone, adding in other DNS providers such as cloudflare -- this will work in general in terms of name resolution, but would be less good from a threat protection perspective (quad9 >> cloudflare) - since I understand the providers aren't in any kind of priority setup (correct?).
- I could have multiple dns servers sent to clients over DHCP - but that hits a similar issue to above since they too don't typically have a priority, but more often will do random, or prioritize on response
- I could use a different DNS server which has this capability (tbh unbound is very good, so this isn't overly appealing!, I do know of some simpler dns forwarders that do allow this though, I suppose I could put them in front of unbound)
- If anyone would want to share a few hints on how this might be possible I'd be happy to look at the code in more depth and see if a PR proposal might be possible.
- or is there something I'm missing in the config that does mean the original scenario is possible?
Many thanks
Same issue here. I'm using OpenWRT 24.10.
- in my understanding the configuration to do a tls-protected dns-request via sticks to that forwarding zone, where it is configured.
- there is no reason to keep TLS protection in case fallback to open recursion kicks in.
- in my case - as above - root servers are contacted via TLS on port 53:
daemon.notice unbound: [30600:0] notice: ssl handshake failed 2001:500:2::c port 53
same Problem here.
The Documentation is very misleading here
If a forwarded query is met with a SERVFAIL error, and this op- tion is enabled, Unbound will fall back to normal recursive res- olution for this query as if no query forwarding had been speci- fied. The default is "no".
at the moment this option just creates a non working setup, when used with a DOT Forwarder
I checked the Logs and the sources. I managed to get a working recursive fallback resolving with this change in iterator.c
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 0bf5523c5..266083caf 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -2141,6 +2141,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
int query_count = 0;
verbose(VERB_ALGO, "No more query targets, attempting last resort");
log_assert(iq->dp);
+ iq->dp->ssl_upstream = 0;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
iq->qchase.qclass, NULL, NULL, NULL)) {
for my use case this last resort is only called if forwarding fails and forward-first is yes.
if the DoT forwarder is available again, it switches back to forwarding and ssl.
As I am not used to the code, maybe someone else could check this and can tell me, what I am destroying with this change?
Hi @loomy,
As I am not used to the code, maybe someone else could check this and can tell me, what I am destroying with this change?
In your very specific example nothing but generally you hardcode a value that may conflict with the one configured in a possible equal stub-zone that may be configured next to the forward-zone, or the global tls-upstream configuration.
But thanks for looking and pointing to the correct location in the code :)
If you want to test it locally you can grab the referenced commits (you can skip the one about testing).
If you want to test it locally you can grab the referenced commits (you can skip the one about testing).
tested and works as expected. thx for the information and the fix
Just noticed the update! Thanks for fixing this!