]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Resolver query forwarding to DoT-enabled upstream servers
authorAram Sargsyan <aram@isc.org>
Thu, 8 Dec 2022 14:18:22 +0000 (14:18 +0000)
committerAram Sargsyan <aram@isc.org>
Fri, 20 Jan 2023 14:45:30 +0000 (14:45 +0000)
Implement TLS transport usage in the resolver.

Use the configured TLS transport for the forwarders in the resolver.

12 files changed:
bin/delv/delv.c
bin/named/server.c
doc/arm/reference.rst
lib/dns/adb.c
lib/dns/client.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/client.h
lib/dns/include/dns/resolver.h
lib/dns/include/dns/view.h
lib/dns/resolver.c
lib/dns/view.c
tests/dns/resolver_test.c

index 84e808894a861b5788021776e5060ad154ad0bc6..132d5dda346db524099fd2fc8d7a1735bc50e9c4 100644 (file)
@@ -41,6 +41,7 @@
 #include <isc/string.h>
 #include <isc/task.h>
 #include <isc/timer.h>
+#include <isc/tls.h>
 #include <isc/util.h>
 
 #include <dns/byaddr.h>
@@ -85,6 +86,9 @@ static isc_nm_t *netmgr = NULL;
 static isc_loopmgr_t *loopmgr = NULL;
 static isc_taskmgr_t *taskmgr = NULL;
 
+/* TLS */
+static isc_tlsctx_cache_t *tlsctx_client_cache = NULL;
+
 /* Configurables */
 static char *server = NULL;
 static const char *port = "53";
@@ -1835,8 +1839,10 @@ main(int argc, char *argv[]) {
        setup_logging(stderr);
 
        /* Create client */
-       result = dns_client_create(mctx, loopmgr, taskmgr, netmgr, 0, &client,
-                                  srcaddr4, srcaddr6);
+       isc_tlsctx_cache_create(mctx, &tlsctx_client_cache);
+       result = dns_client_create(mctx, loopmgr, taskmgr, netmgr, 0,
+                                  tlsctx_client_cache, &client, srcaddr4,
+                                  srcaddr6);
        if (result != ISC_R_SUCCESS) {
                delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
                         isc_result_totext(result));
@@ -1869,6 +1875,9 @@ cleanup:
        if (style != NULL) {
                dns_master_styledestroy(&style, mctx);
        }
+       if (tlsctx_client_cache != NULL) {
+               isc_tlsctx_cache_detach(&tlsctx_client_cache);
+       }
 
        isc_log_destroy(&lctx);
 
index cf9fe130e9d661033a0a35f87225bb240f01a3d3..9efce19bad72855d23da6327b45dfa90fe81eccf 100644 (file)
@@ -4758,7 +4758,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
        CHECK(dns_view_createresolver(
                view, named_g_loopmgr, named_g_taskmgr, ndisp, named_g_netmgr,
-               resopts, named_g_dispatchmgr, dispatch4, dispatch6));
+               resopts, named_g_server->tlsctx_client_cache,
+               named_g_dispatchmgr, dispatch4, dispatch6));
 
        if (resstats == NULL) {
                CHECK(isc_stats_create(mctx, &resstats,
index 23e55d2f76b66781511d88e066379cb7b47a89ae..bf93f5027267e147902994805dd51313e3b3513a 100644 (file)
@@ -2884,8 +2884,12 @@ authoritative and does not have the answer in its cache.
 
    This specifies a list of IP addresses to which queries are forwarded. The
    default is the empty list (no forwarding). Each address in the list can be
-   associated with an optional port number. A default port number can be set
-   for the entire list.
+   associated with an optional port number and a TLS transport. A default port
+   number and a TLS transport can be set for the entire list.
+
+   If a TLS configuration is specified, :iscman:`named` will use DNS-over-TLS
+   (DoT) connections when connecting to the specified IP address(es), using the
+   TLS configuration referenced by the :any:`tls` statement.
 
 Forwarding can also be configured on a per-domain basis, allowing for
 the global forwarding options to be overridden in a variety of ways.
index d5a17497fd2cb8538dac2f294c7e5e257267d739..7fff6ead7d3b14e2dac53f96f19e1d6bb7ba0a4b 100644 (file)
@@ -49,6 +49,7 @@
 #include <dns/rdatatype.h>
 #include <dns/resolver.h>
 #include <dns/stats.h>
+#include <dns/transport.h>
 
 #define DNS_ADB_MAGIC           ISC_MAGIC('D', 'a', 'd', 'b')
 #define DNS_ADB_VALID(x)        ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
@@ -1321,6 +1322,9 @@ free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
 
        ai->magic = 0;
 
+       if (ai->transport != NULL) {
+               dns_transport_detach(&ai->transport);
+       }
        dns_adbentry_detach(&ai->entry);
 
        isc_mem_put(adb->mctx, ai, sizeof(*ai));
index f160f7650ace716629b7f4f9773d78e0aa0b68d0..5e76b684a177f3645b0fcb3980c297f2c8ac6703 100644 (file)
@@ -204,9 +204,10 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr,
 
 static isc_result_t
 createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr,
-          isc_taskmgr_t *taskmgr, isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr,
-          dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
-          dns_view_t **viewp) {
+          isc_taskmgr_t *taskmgr, isc_nm_t *nm,
+          isc_tlsctx_cache_t *tlsctx_client_cache,
+          dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
+          dns_dispatch_t *dispatchv6, dns_view_t **viewp) {
        isc_result_t result;
        dns_view_t *view = NULL;
 
@@ -222,7 +223,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr,
        }
 
        result = dns_view_createresolver(view, loopmgr, taskmgr, 1, nm, 0,
-                                        dispatchmgr, dispatchv4, dispatchv6);
+                                        tlsctx_client_cache, dispatchmgr,
+                                        dispatchv4, dispatchv6);
        if (result != ISC_R_SUCCESS) {
                goto cleanup_view;
        }
@@ -244,6 +246,7 @@ cleanup_view:
 isc_result_t
 dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
                  isc_taskmgr_t *taskmgr, isc_nm_t *nm, unsigned int options,
+                 isc_tlsctx_cache_t *tlsctx_client_cache,
                  dns_client_t **clientp, const isc_sockaddr_t *localaddr4,
                  const isc_sockaddr_t *localaddr6) {
        isc_result_t result;
@@ -255,6 +258,7 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
        REQUIRE(mctx != NULL);
        REQUIRE(taskmgr != NULL);
        REQUIRE(nm != NULL);
+       REQUIRE(tlsctx_client_cache != NULL);
        REQUIRE(clientp != NULL && *clientp == NULL);
 
        UNUSED(options);
@@ -309,7 +313,8 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
 
        /* Create the default view for class IN */
        result = createview(mctx, dns_rdataclass_in, loopmgr, taskmgr, nm,
-                           client->dispatchmgr, dispatchv4, dispatchv6, &view);
+                           tlsctx_client_cache, client->dispatchmgr,
+                           dispatchv4, dispatchv6, &view);
        if (result != ISC_R_SUCCESS) {
                goto cleanup_references;
        }
index e5cdf4711ec32eb08b0cdb8b71ce12fdd2df8639..fc50d8f9948a28e7c2872d3810b62c2314bf2681 100644 (file)
@@ -204,8 +204,9 @@ struct dns_adbfind {
 struct dns_adbaddrinfo {
        unsigned int magic; /*%< private */
 
-       isc_sockaddr_t sockaddr; /*%< [rw] */
-       unsigned int   srtt;     /*%< [rw] microsecs */
+       isc_sockaddr_t   sockaddr; /*%< [rw] */
+       unsigned int     srtt;     /*%< [rw] microsecs */
+       dns_transport_t *transport;
 
        unsigned int    flags; /*%< [rw] */
        dns_adbentry_t *entry; /*%< private */
index 0caf154e615f0b6263e978478c8f5911c36b132c..874a609936a92e8626f104374a5ae7064c150e19 100644 (file)
@@ -91,6 +91,7 @@ typedef struct dns_clientresevent {
 isc_result_t
 dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
                  isc_taskmgr_t *taskmgr, isc_nm_t *nm, unsigned int options,
+                 isc_tlsctx_cache_t *tlsctx_client_cache,
                  dns_client_t **clientp, const isc_sockaddr_t *localaddr4,
                  const isc_sockaddr_t *localaddr6);
 /*%<
@@ -113,7 +114,7 @@ dns_client_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr,
  *
  *\li  'nm' is a valid network manager.
  *
- *\li  'timermgr' is a valid timer manager.
+ *\li  'tlsctx_client_cache' is a valid TLS context cache.
  *
  *\li  clientp != NULL && *clientp == NULL.
  *
index ff8397dc947d2fc215b8b96df750e3e49166ff16..cfae9f438e5b9ef0cc3da4315802a48b1241c26d 100644 (file)
@@ -52,6 +52,7 @@
 #include <isc/lang.h>
 #include <isc/refcount.h>
 #include <isc/stats.h>
+#include <isc/types.h>
 
 #include <dns/fixedname.h>
 #include <dns/types.h>
@@ -171,9 +172,9 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t;
 isc_result_t
 dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
                    isc_taskmgr_t *taskmgr, unsigned int ndisp, isc_nm_t *nm,
-                   unsigned int options, dns_dispatchmgr_t *dispatchmgr,
-                   dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
-                   dns_resolver_t **resp);
+                   unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
+                   dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
+                   dns_dispatch_t *dispatchv6, dns_resolver_t **resp);
 
 /*%<
  * Create a resolver.
@@ -193,6 +194,10 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
  *
  *\li  'nm' is a valid network manager.
  *
+ *\li  'tlsctx_cache' != NULL.
+ *
+ *\li  'dispatchmgr' != NULL.
+ *
  *\li  'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL.
  *     If not NULL, 'ndisp' clones of it will be created by the resolver.
  *
index e4dd0d178f48ba07bdf9b9d7154b3c3db1af876c..464114ea6763e2fb66df9d3c5491bf06baebf130 100644 (file)
@@ -390,7 +390,8 @@ isc_result_t
 dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
                        isc_taskmgr_t *taskmgr, unsigned int ndisp,
                        isc_nm_t *netmgr, unsigned int options,
-                       dns_dispatchmgr_t *dispatchmgr,
+                       isc_tlsctx_cache_t *tlsctx_cache,
+                       dns_dispatchmgr_t  *dispatchmgr,
                        dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6);
 /*%<
  * Create a resolver and address database for the view.
@@ -402,7 +403,8 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
  *\li  'view' does not have a resolver already.
  *
  *\li  The requirements of dns_resolver_create() apply to 'taskmgr',
- *     'ndisp', 'netmgr', 'options', 'dispatchv4', and 'dispatchv6'.
+ *     'ndisp', 'netmgr', 'options', 'tlsctx_cache', 'dispatchv4', and
+ *     'dispatchv6'.
  *
  * Returns:
  *
index 973337f2ac9f8ddc07c43264d7d7df825921fd72..d663e2bc89393ce03a559186af6d1fd8bd1bfd49 100644 (file)
@@ -548,6 +548,7 @@ struct dns_resolver {
        dns_view_t *view;
        bool frozen;
        unsigned int options;
+       isc_tlsctx_cache_t *tlsctx_cache;
        dns_dispatchmgr_t *dispatchmgr;
        dns_dispatchset_t *dispatches4;
        dns_dispatchset_t *dispatches6;
@@ -2134,6 +2135,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
        isc_sockaddr_t addr;
        bool have_addr = false;
        unsigned int srtt;
+       isc_tlsctx_cache_t *tlsctx_cache = NULL;
 
        FCTXTRACE("query");
 
@@ -2141,6 +2143,21 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
 
        srtt = addrinfo->srtt;
 
+       if (addrinfo->transport != NULL) {
+               switch (dns_transport_get_type(addrinfo->transport)) {
+               case DNS_TRANSPORT_TLS:
+                       options |= DNS_FETCHOPT_TCP;
+                       tlsctx_cache = res->tlsctx_cache;
+                       break;
+               case DNS_TRANSPORT_TCP:
+               case DNS_TRANSPORT_HTTP:
+                       options |= DNS_FETCHOPT_TCP;
+                       break;
+               default:
+                       break;
+               }
+       }
+
        /*
         * Allow an additional second for the kernel to resend the SYN
         * (or SYN without ECN in the case of stupid firewalls blocking
@@ -2301,9 +2318,9 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
        /* Set up the dispatch and set the query ID */
        result = dns_dispatch_add(
                query->dispatch, 0, isc_interval_ms(&fctx->interval),
-               &query->addrinfo->sockaddr, NULL, NULL, resquery_connected,
-               resquery_senddone, resquery_response, query, &query->id,
-               &query->dispentry);
+               &query->addrinfo->sockaddr, addrinfo->transport, tlsctx_cache,
+               resquery_connected, resquery_senddone, resquery_response, query,
+               &query->id, &query->dispentry);
        if (result != ISC_R_SUCCESS) {
                goto cleanup_udpfetch;
        }
@@ -3679,6 +3696,15 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
                if (result == ISC_R_SUCCESS) {
                        dns_adbaddrinfo_t *cur;
                        ai->flags |= FCTX_ADDRINFO_FORWARDER;
+                       if (fwd->tlsname != NULL) {
+                               result = dns_view_gettransport(
+                                       res->view, DNS_TRANSPORT_TLS,
+                                       fwd->tlsname, &ai->transport);
+                               if (result != ISC_R_SUCCESS) {
+                                       dns_adb_freeaddrinfo(fctx->adb, &ai);
+                                       goto next;
+                               }
+                       }
                        cur = ISC_LIST_HEAD(fctx->forwaddrs);
                        while (cur != NULL && cur->srtt < ai->srtt) {
                                cur = ISC_LIST_NEXT(cur, publink);
@@ -3690,6 +3716,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
                                ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
                        }
                }
+       next:
                fwd = ISC_LIST_NEXT(fwd, link);
        }
 
@@ -10095,9 +10122,9 @@ spillattimer_countdown(void *arg) {
 isc_result_t
 dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
                    isc_taskmgr_t *taskmgr, unsigned int ndisp, isc_nm_t *nm,
-                   unsigned int options, dns_dispatchmgr_t *dispatchmgr,
-                   dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
-                   dns_resolver_t **resp) {
+                   unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
+                   dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
+                   dns_dispatch_t *dispatchv6, dns_resolver_t **resp) {
        isc_result_t result = ISC_R_SUCCESS;
        char name[sizeof("res4294967295")];
        dns_resolver_t *res = NULL;
@@ -10109,6 +10136,7 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
        REQUIRE(DNS_VIEW_VALID(view));
        REQUIRE(ndisp > 0);
        REQUIRE(resp != NULL && *resp == NULL);
+       REQUIRE(tlsctx_cache != NULL);
        REQUIRE(dispatchmgr != NULL);
        REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
 
@@ -10122,6 +10150,7 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
                .taskmgr = taskmgr,
                .dispatchmgr = dispatchmgr,
                .options = options,
+               .tlsctx_cache = tlsctx_cache,
                .spillatmin = 10,
                .spillat = 10,
                .spillatmax = 100,
index bd0af302bddfbd916e7590bfcda3e51b59d9cf6e..e8a53aa108ebff94894105f23681f8cc970a979b 100644 (file)
@@ -655,6 +655,7 @@ isc_result_t
 dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
                        isc_taskmgr_t *taskmgr, unsigned int ndisp,
                        isc_nm_t *netmgr, unsigned int options,
+                       isc_tlsctx_cache_t *tlsctx_cache,
                        dns_dispatchmgr_t *dispatchmgr,
                        dns_dispatch_t *dispatchv4,
                        dns_dispatch_t *dispatchv6) {
@@ -672,8 +673,8 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
        isc_task_setname(view->task, "view", view);
 
        result = dns_resolver_create(view, loopmgr, taskmgr, ndisp, netmgr,
-                                    options, dispatchmgr, dispatchv4,
-                                    dispatchv6, &view->resolver);
+                                    options, tlsctx_cache, dispatchmgr,
+                                    dispatchv4, dispatchv6, &view->resolver);
        if (result != ISC_R_SUCCESS) {
                isc_task_detach(&view->task);
                return (result);
index 33914b4d705919b754faa6513b311c9cda9740f8..51b6b35faac4f825a495783bddf2ed4fd790ba8b 100644 (file)
@@ -26,6 +26,7 @@
 #include <isc/print.h>
 #include <isc/task.h>
 #include <isc/timer.h>
+#include <isc/tls.h>
 #include <isc/util.h>
 
 #include <dns/dispatch.h>
@@ -38,6 +39,7 @@
 static dns_dispatchmgr_t *dispatchmgr = NULL;
 static dns_dispatch_t *dispatch = NULL;
 static dns_view_t *view = NULL;
+static isc_tlsctx_cache_t *tlsctx_cache = NULL;
 
 static int
 setup_test(void **state) {
@@ -73,8 +75,10 @@ static void
 mkres(dns_resolver_t **resolverp) {
        isc_result_t result;
 
+       isc_tlsctx_cache_create(mctx, &tlsctx_cache);
        result = dns_resolver_create(view, loopmgr, taskmgr, 1, netmgr, 0,
-                                    dispatchmgr, dispatch, NULL, resolverp);
+                                    tlsctx_cache, dispatchmgr, dispatch, NULL,
+                                    resolverp);
        assert_int_equal(result, ISC_R_SUCCESS);
 }
 
@@ -82,6 +86,9 @@ static void
 destroy_resolver(dns_resolver_t **resolverp) {
        dns_resolver_shutdown(*resolverp);
        dns_resolver_detach(resolverp);
+       if (tlsctx_cache != NULL) {
+               isc_tlsctx_cache_detach(&tlsctx_cache);
+       }
 }
 
 /* dns_resolver_create */