125 lines
6.4 KiB
Diff
125 lines
6.4 KiB
Diff
From eec394f10bbfcc3d2fc8504ad8ff5be44231abd5 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
|
|
Date: Tue, 3 Mar 2020 23:31:25 +0000
|
|
Subject: [PATCH] systemd-resolved: use hostname for certificate validation in
|
|
DoT
|
|
|
|
Widely accepted certificates for IP addresses are expensive and only
|
|
affordable for larger organizations. Therefore if the user provides
|
|
the hostname in the DNS= option, we should use it instead of the IP
|
|
address.
|
|
---
|
|
man/resolved.conf.xml | 19 +++++++++++--------
|
|
src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++--------
|
|
src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++----
|
|
3 files changed, 34 insertions(+), 20 deletions(-)
|
|
|
|
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 @@
|
|
<varlistentry>
|
|
<term><varname>DNSOverTLS=</varname></term>
|
|
<listitem>
|
|
- <para>Takes a boolean argument or <literal>opportunistic</literal>.
|
|
- 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 <literal>opportunistic</literal>
|
|
+ <para>Takes a boolean argument or <literal>opportunistic</literal>. 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 <varname>DNS=</varname>
|
|
+ by using the format format <literal>address#server_name</literal> 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.</para>
|
|
+
|
|
+ <para>When set to <literal>opportunistic</literal>
|
|
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.</para>
|
|
|
|
- <para>Server Name Indication (SNI) can be used when opening a TLS connection.
|
|
- Entries in <varname>DNS=</varname> should be in format <literal>address#server_name</literal>.</para>
|
|
-
|
|
<para>In addition to this global DNSOverTLS setting
|
|
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
|
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 <openssl/bio.h>
|
|
#include <openssl/err.h>
|
|
+#include <openssl/x509v3.h>
|
|
|
|
#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) {
|
|
--
|
|
2.26.2
|
|
|