]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: add strict mode for DNS-over-TLS
authorIwan Timmer <irtimmer@gmail.com>
Mon, 18 Feb 2019 19:41:46 +0000 (20:41 +0100)
committerIwan Timmer <iwan.timmer@northwave.nl>
Wed, 19 Jun 2019 11:10:44 +0000 (13:10 +0200)
Add strict mode for DNS-over-TLS, which will require TLS support from the server. Closes #10755

14 files changed:
man/resolved.conf.xml
man/systemd.network.xml
meson.build
meson_options.txt
shell-completion/bash/resolvectl
shell-completion/bash/systemd-resolve
src/resolve/resolved-conf.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dnstls-gnutls.c
src/resolve/resolved-dnstls-openssl.c
src/resolve/resolved-link.c
src/shared/resolve-util.c
src/shared/resolve-util.h
src/systemd/sd-network.h

index c8ab6942c1409f1394bf467193c11a2699f0ecca..a647a4ace7786018a98ac5a74101acef3efbf8b7 100644 (file)
       <varlistentry>
         <term><varname>DNSOverTLS=</varname></term>
         <listitem>
-        <para>Takes false or
-        <literal>opportunistic</literal>. 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 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>
         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"
index d832e68d71c5f781ec4fb52de5096b0aa1302e80..bad673b44e1c54bf460d9c37d51b1cc148d95761 100644 (file)
         <varlistentry>
           <term><varname>DNSOverTLS=</varname></term>
           <listitem>
-            <para>Takes false or
-            <literal>opportunistic</literal>. When set to <literal>opportunistic</literal>, enables
+            <para>Takes a boolean or <literal>opportunistic</literal>.
+            When true, enables
             <ulink
             url="https://tools.ietf.org/html/rfc7858">DNS-over-TLS</ulink>
-            support on the link. This option defines a
-            per-interface setting for
+            support on the link.
+            When set to <literal>opportunistic</literal>, compatibility with
+            non-DNS-over-TLS servers is increased, by automatically
+            turning off DNS-over-TLS servers in this case.
+            This option defines a per-interface setting for
             <citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
             global <varname>DNSOverTLS=</varname> option. Defaults to
             false. This setting is read by
index 19c005141fb98ac82769a54be43e772d982c8d22..0a9b3d5b857e1e679314f8caf8aae9116163eeea 100644 (file)
@@ -1221,7 +1221,7 @@ if skip_deps
         default_dns_over_tls = 'no'
 endif
 if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
-        message('default-dns-over-tls cannot be set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
+        message('default-dns-over-tls cannot be enabled or set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
         default_dns_over_tls = 'no'
 endif
 conf.set('DEFAULT_DNS_OVER_TLS_MODE',
index 494a8de43c487ec17f145ea0a6a411f549267473..b96e49d825782b8caa698e562f4a3da5feb96bdc 100644 (file)
@@ -206,7 +206,7 @@ option('default-dnssec', type : 'combo',
        value : 'allow-downgrade')
 option('default-dns-over-tls', type : 'combo',
        description : 'default DNS-over-TLS mode',
-       choices : ['opportunistic', 'no'],
+       choices : ['yes', 'opportunistic', 'no'],
        value : 'no')
 option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', 'true', 'false'],
        description : 'DNS-over-TLS support')
index 161ac4d3c577a38c8b8b31063c958592b1bcc85e..d4ac339038126371fc8cbc30478b1b555361fdab 100644 (file)
@@ -53,7 +53,7 @@ _resolvectl() {
         [FAMILY]='tcp udp sctp'
         [RESOLVE]='yes no resolve'
         [DNSSEC]='yes no allow-downgrade'
-        [DNSOVERTLS]='no opportunistic'
+        [DNSOVERTLS]='yes no opportunistic'
     )
     local interfaces=$( __get_interfaces )
 
index 84747b7462f31ab9ee45fee48d97b9d2aaa55578..66f0ae04a0a54abd9061df1f0f1039bc808f446e 100644 (file)
@@ -64,7 +64,7 @@ _systemd-resolve() {
                 comps="yes no allow-downgrade"
                 ;;
             --set-dnsovertls)
-                comps="no opportunistic"
+                comps="yes no opportunistic"
                 ;;
         esac
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
index 79e388f8a2d7cefec1f6bbb62d9c81d8fa9ffaa7..7b2938fea3fd97fb84b0c95fc11cddd18715b084 100644 (file)
@@ -394,7 +394,7 @@ int manager_parse_config_file(Manager *m) {
 
 #if ! ENABLE_DNS_OVER_TLS
         if (m->dns_over_tls_mode != DNS_OVER_TLS_NO) {
-                log_warning("DNS-over-TLS option cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+                log_warning("DNS-over-TLS option cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
                 m->dns_over_tls_mode = DNS_OVER_TLS_NO;
         }
 #endif
index 0033de73b4f35eb9636ab3397a70bc14ce510c57..78e5953b3001095e74077678ace923e6e639fcde 100644 (file)
@@ -419,7 +419,7 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
                         log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
                         s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
                 } else if (s->n_failed_tls > 0 &&
-                           DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level)) {
+                           DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
 
                         /* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
                          * if we don't require DNS-over-TLS */
index d824d6ca5acd152def3e0e3ced5b03095ce1b1df..6eef6117a3ae7a1067a3b6f9d080224408c25496 100644 (file)
@@ -54,6 +54,9 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
                 server->dnstls_data.session_data.size = 0;
         }
 
+        if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES)
+                gnutls_session_set_verify_cert(gs, NULL, 0);
+
         gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
 
         gnutls_transport_set_ptr2(gs, (gnutls_transport_ptr_t) (long) stream->fd, stream);
@@ -202,6 +205,10 @@ int dnstls_manager_init(Manager *manager) {
         if (r < 0)
                 return -ENOMEM;
 
+        r = gnutls_certificate_set_x509_system_trust(manager->dnstls_data.cert_cred);
+        if (r < 0)
+                log_warning("Failed to load system trust store: %s", gnutls_strerror(r));
+
         return 0;
 }
 
index 22d579a7f7777fe0c0446bbe326bb0a07d005c8f..85e202ff741d46a09911c1247577ef980f6a2952 100644 (file)
@@ -76,6 +76,17 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
         SSL_set_session(s, server->dnstls_data.session);
         SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb));
 
+        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)))
+                        return -ECONNREFUSED;
+        }
+
         ERR_clear_error();
         stream->dnstls_data.handshake = SSL_do_handshake(s);
         if (stream->dnstls_data.handshake <= 0) {
@@ -357,6 +368,9 @@ int dnstls_manager_init(Manager *manager) {
 
         SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION);
         SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION);
+        r = SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx);
+        if (r < 0)
+                log_warning("Failed to load system trust store: %s", ERR_error_string(ERR_get_error(), NULL));
 
         return 0;
 }
index dd8b5a574b003f5ae92902689087f4c790a75ede..96ebb4d23d360020a39eeb98d6f2a7a619d4c1a6 100644 (file)
@@ -384,7 +384,7 @@ void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
 
 #if ! ENABLE_DNS_OVER_TLS
         if (mode != DNS_OVER_TLS_NO)
-                log_warning("DNS-over-TLS option for the link cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+                log_warning("DNS-over-TLS option for the link cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
         return;
 #endif
 
index a5d4a14344f8a160b26c1f487d786815d9b52bb9..b433cd24bca9071bf76ed6a07a8ec3df23dde993 100644 (file)
@@ -25,5 +25,6 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
 static const char* const dns_over_tls_mode_table[_DNS_OVER_TLS_MODE_MAX] = {
         [DNS_OVER_TLS_NO] = "no",
         [DNS_OVER_TLS_OPPORTUNISTIC] = "opportunistic",
+        [DNS_OVER_TLS_YES] = "yes",
 };
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, _DNS_OVER_TLS_MODE_INVALID);
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, DNS_OVER_TLS_YES);
index 5883342e653c2f054c11d277e71ff45bb05bd1e5..6ce250846609982b1a8d462f0411967b5ce0cca8 100644 (file)
@@ -42,6 +42,9 @@ enum DnsOverTlsMode {
          * fallback to using an unencrypted connection */
         DNS_OVER_TLS_OPPORTUNISTIC,
 
+        /* Enforce DNS-over-TLS and require valid server certificates */
+        DNS_OVER_TLS_YES,
+
         _DNS_OVER_TLS_MODE_MAX,
         _DNS_OVER_TLS_MODE_INVALID = -1
 };
index 166c30185a1e67515bb0cf0cd916fcd83abd693a..9ab4426b8b7bf32760e1daea0db7883a6fd7abce 100644 (file)
@@ -127,7 +127,7 @@ int sd_network_link_get_mdns(int ifindex, char **mdns);
 
 /* Indicates whether or not DNS-over-TLS should be enabled for the
  * link.
- * Possible levels of support: strict, no, opportunistic
+ * Possible levels of support: yes, no, opportunistic
  * Possible return codes:
  *   -ENODATA: networkd is not aware of the link
  */