diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml index 0f70ced5b5..37161ebcbc 100644 --- a/man/resolved.conf.xml +++ b/man/resolved.conf.xml @@ -193,11 +193,17 @@ DNSOverTLS= - Takes a boolean argument or opportunistic. - If true all connections to the server will be encrypted. Note that - this mode requires a DNS server that supports DNS-over-TLS and has - a valid certificate for it's IP. If the DNS server does not support - DNS-over-TLS all DNS requests will fail. When set to opportunistic + Takes a boolean argument or opportunistic. If + true all connections to the server will be encrypted. Note that this + mode requires a DNS server that supports DNS-over-TLS and has a valid + certificate. If the hostname was specified in DNS= + by using the format format address#server_name it + is used to validate its certificate and also to enable Server Name + Indication (SNI) when opening a TLS connection. Otherwise + the certificate is checked against the server's IP. + If the DNS server does not support DNS-over-TLS all DNS requests will fail. + + When set to opportunistic DNS request are attempted to send encrypted with DNS-over-TLS. If the DNS server does not support TLS, DNS-over-TLS is disabled. Note that this mode makes DNS-over-TLS vulnerable to "downgrade" @@ -214,9 +220,6 @@ resolver is not capable of authenticating the server, so it is vulnerable to "man-in-the-middle" attacks. - Server Name Indication (SNI) can be used when opening a TLS connection. - Entries in DNS= should be in format address#server_name. - In addition to this global DNSOverTLS setting systemd-networkd.service8 also maintains per-link DNSOverTLS settings. For system DNS diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c index aad3bb4481..ef90a7d5ae 100644 --- a/src/resolve/resolved-dnstls-gnutls.c +++ b/src/resolve/resolved-dnstls-gnutls.c @@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { } if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { - stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; - if (server->family == AF_INET) { - stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; - stream->dnstls_data.validation.size = 4; - } else { - stream->dnstls_data.validation.data = server->address.in6.s6_addr; - stream->dnstls_data.validation.size = 16; + if (server->server_name) + gnutls_session_set_verify_cert(gs, server->server_name, 0); + else { + stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; + if (server->family == AF_INET) { + stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; + stream->dnstls_data.validation.size = 4; + } else { + stream->dnstls_data.validation.data = server->address.in6.s6_addr; + stream->dnstls_data.validation.size = 16; + } + gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); } - gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); } if (server->server_name) { diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c index 8f58efacbd..7763cbcb5a 100644 --- a/src/resolve/resolved-dnstls-openssl.c +++ b/src/resolve/resolved-dnstls-openssl.c @@ -6,6 +6,7 @@ #include #include +#include #include "io-util.h" #include "resolved-dns-stream.h" @@ -80,13 +81,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { X509_VERIFY_PARAM *v; - const unsigned char *ip; SSL_set_verify(s, SSL_VERIFY_PEER, NULL); v = SSL_get0_param(s); - ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; - if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) - return -ECONNREFUSED; + if (server->server_name) { + X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0) + return -ECONNREFUSED; + } else { + const unsigned char *ip; + ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; + if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) + return -ECONNREFUSED; + } } if (server->server_name) {