(this is for unbound 1.5.3, but i don't see it in the list above)
I have the following unbound.conf to act as forwarder to another TLS-over-TCP unbound implementation:
--------
forward-zone:
name: "."
forward-addr: 192.0.2.3@443
server:
ssl-upstream: yes
tcp-upstream: yes
do-daemonize: no
logfile: ""
verbosity: 10
--------
However, there appears to be no verification of the server's certificate -- the server i'm speaking to has a self-signed certificate, and unbound has no way to know about it initially, so i don't see how it could possibly be verifying the cert.
how to verify the cert itself is an interesting question, though: you can't identify the remote host by name (because we don't want to have to have DNS to do the lookup), and we generally discourage X.509 certs with an IP address in the subjectAltNames.
So i think the configuration mechanism should be one of the following options (maybe we can offer :
A)
* forward-fingerprint: an sha256 sum of the Subject Public Key Info of the server's certificate
B)
* forward-name: the name of upstream server (this is like forward-host, except that it is only used for cert validation, and not looked-up before connection)
* forward-cafile: a file containing the certificates of the root certification authorities allowed to issue certs for the forwarded server; (the verification mechanism looks for a valid cert for forward-name (if present) or forward-host).

Hi Daniel,
Yes the ssl-upstream feature wraps traffic in tls, but does not verify certificates. It's documented. For authentication, perhaps we could see what the dprive IETF WG comes up with in their standardisation? They are currently working on dns over tls. I would not want to pre-empt their solution.
I would recommend to use DNSSEC to authenticate the data across this connection.
Best regards,
Wouter

(In reply to Wouter Wijngaards from comment #1)
> Yes the ssl-upstream feature wraps traffic in tls, but does not verify
> certificates. It's documented.
Hm, the documentation of this gap wasn't clear to me. I did not see any mention of lack of verification in unbound.conf (i inferred it from the behavior of the tool)
> For authentication, perhaps we could see
> what the dprive IETF WG comes up with in their standardisation? They are
> currently working on dns over tls. I would not want to pre-empt their
> solution.
Please do not wait on output from dprive; You will not pre-empt anything. If anything, dprive needs input from real-world deployments (which unbound can provide) to drive its decision-making process.
> I would recommend to use DNSSEC to authenticate the data across this
> connection.
That would be a great step as well, though it is perhaps a chicken-and-egg solution (how do we get the DNSSEC info if all we have is a TLS connection to the upstream server?).
Getting started with something simple like (A) or (B) proposed above would be much more straightforward, and could be overridden by a DNSSEC-verification mechanism (maybe via a TLS extension?) in the future.
Would you be interested in a patch for proposal (A)?

Hi Matt, Daniel,
The issue is that there is no good proposal in that list in that document. All of them require some sort of pre-distributed keys (hard-coded keys are a recipe for failure), or in fact pre-coded something else (what you use to look up that DNSSEC stuff). All of that only works for hardcoded 'use this public resolver' and not actually for the normal resolving cases.
I would like to have code that implements authentication. Preferably in a good way (eg. won't cause further problems, I mean keys can change, you know, like X509 certificates allow key changes). It is just that all the current proposals are bad, and a lot a similar, they simply fail to be usable. Because they are all similarly bad, eg. only for public resolvers, not enabled by default, not for 10.0.0.0/8 resolvers, and so on. I don't want to move ahead of the vetted 'this is the correct solution', because I cannot choose and I do not want to choose a bad security solution.
So, anyway, that stuff is in progress. And in the document the actual problem changed to 'public resolver', 'fixed destination' and 'pre-configured parameters'. Which is vastly different from the workgroup mission, DNS privacy, which starts somewhere when you log on. And this has mostly 10.0.0.0/8 (LAN) DNS, with no authenticated components.
So, in summary, I want good security too, but the proposals are bad, and I don't want to implement 'too early' a bad solution.
Best regards, Wouter

For the record, here is how stubby does. It provides the following configuration for SPKI pinsets:
tls_pubkey_pinset:
- digest: "sha256"
- value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
This is used in strict mode: "In 'Strict' mode authentication information (e.g. an authentication name or a SPKI pinset) MUST be provided for each nameserver and DNS queries will only be sent if Stubby can authenticate the namerserver using this information."
If you decide to go for this solution, I guess that a similar configuration option could be added in unbound, eg "forward-ssl-tls-pubkey-pinset"
Best regards, --Martin

i recommend starting by offering the name of the upstream resolver as an authentication mechanism, and only afterward implementing spki pinsets if you think they offer some sort of concrete advantage.
https://tools.ietf.org/html/rfc8310 recommends authentication based on name in several forms.
note that the two largest DNS-over-TLS deployments today offer valid X.509 certificates for their names:
9.9.9.9 → dns.quad9.net
1.1.1.1 → cloudflare-dns.com

Hi Daniel,
The current code repository implements TLS authentication for forwarders.
The syntax is forward-addr: <IP-address>[@port][#tls-authentication-name]
And the ca bundle can be set with: tls-cert-bundle: "ca-bundle.pem"
(or the ca-bundle.crt file).
Example
server:
tls-cert-bundle: "/etc/pki/tls/certs/ca-bundle.crt"
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 9.9.9.9@853#dns.quad9.net
forward-addr: 1.1.1.1@853#cloudflare-dns.com
The hashtag name trick makes it so that the tls authentication name can also be set for eg. stub-zones and with unbound-control forward control commands. It was also easier in the code. There should be no spaces around the '@' and '#'.
The port number is really optional, but defaults to port 53 right now (like for ordinary DNS).
When I tested, the servers for dns.quad9 and cloudflare-dns work.
The code looks easy to change for having tls authentication for authority servers (it probably already works using configuration with stub-addr).
Best regards, Wouter

Hi Daniel, Martin,
Fixed the default, which is now port 853 when you specify a tls authname. (And still 53 for others).
So the examples can be simplified like this
forward-addr: 9.9.9.9#dns.quad9.net
forward-addr: 1.1.1.1#cloudflare-dns.com
Best regards, Wouter

Hi Martin,
I don't know how to get a list of trusted servers. You could try asking the unbound-users mail list to see if other users know them. Two public resolvers are listed in above entries that support DNS-over-TLS.
Best regards, Wouter

Hi Jim,
Do you have openssl 1.1.x? Without that the SSL_set1_host call is not available, and unbound does not do verification. This is detected at configure time, though. But I did not want to stop unbound's compilation in its entirety for that.
You can see what openssl is linked with unbound with unbound -h. You must have an older openssl, for the facts you describe match it.
Best regards, Wouter

That is correct, this is on FreeBSD 11.2 with base OpenSSL which is a patched OpenSSL 1.0.2o. Is there no possible way to verify the host that doesn't require 1.1.x? Or at least a way to log the issue at run-time?
It seems like a bad idea to fail open when configured this way and the user expects the verification to work.
Ideally it should fail to run and print an error that the configured verification is not possible because of the missing function, but at a minimum logging the error rather than silently disabling the check would help the user figure out what is happening.