From 3d7103bd2197c3898d066b47a179b29bd77dcc8c Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 28 Sep 2022 09:01:05 +0000 Subject: [PATCH 1/4] Fix dynamic update forwarding when using a TLS-enabled primary Now that the 'dns_request' supports using TLS transport, implement dynamic update forwarding using DoT when the primary server is configured to use a TLS transport. Previously, when using such configuration, the dynamic update forwarding feature was broken. --- lib/dns/zone.c | 78 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index fba7cb4485..9a7ab8f89b 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -717,6 +717,7 @@ struct dns_forward { dns_request_t *request; uint32_t which; isc_sockaddr_t addr; + dns_transport_t *transport; dns_updatecallback_t callback; void *callback_arg; unsigned int options; @@ -18286,6 +18287,9 @@ forward_destroy(dns_forward_t *forward) { if (forward->msgbuf != NULL) { isc_buffer_free(&forward->msgbuf); } + if (forward->transport != NULL) { + dns_transport_detach(&forward->transport); + } if (forward->zone != NULL) { LOCK(&forward->zone->lock); if (ISC_LINK_LINKED(forward, link)) { @@ -18302,20 +18306,22 @@ sendtoprimary(dns_forward_t *forward) { isc_result_t result; isc_sockaddr_t src; isc_dscp_t dscp = -1; + dns_zone_t *zone = forward->zone; + bool tls_transport_invalid = false; - LOCK_ZONE(forward->zone); + LOCK_ZONE(zone); - if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) { - UNLOCK_ZONE(forward->zone); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) { + UNLOCK_ZONE(zone); return (ISC_R_CANCELED); } - if (forward->which >= forward->zone->primariescnt) { - UNLOCK_ZONE(forward->zone); + if (forward->which >= zone->primariescnt) { + UNLOCK_ZONE(zone); return (ISC_R_NOMORE); } - forward->addr = forward->zone->primaries[forward->which]; + forward->addr = zone->primaries[forward->which]; /* * Always use TCP regardless of whether the original update * used TCP. @@ -18324,30 +18330,59 @@ sendtoprimary(dns_forward_t *forward) { */ switch (isc_sockaddr_pf(&forward->addr)) { case PF_INET: - src = forward->zone->xfrsource4; - dscp = forward->zone->xfrsource4dscp; + src = zone->xfrsource4; + dscp = zone->xfrsource4dscp; break; case PF_INET6: - src = forward->zone->xfrsource6; - dscp = forward->zone->xfrsource6dscp; + src = zone->xfrsource6; + dscp = zone->xfrsource6dscp; break; default: result = ISC_R_NOTIMPLEMENTED; goto unlock; } + + if (forward->transport != NULL) { + dns_transport_detach(&forward->transport); + } + + if (zone->primarytlsnames != NULL && + zone->primarytlsnames[forward->which] != NULL) + { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary]; + + result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname, + &forward->transport); + + if (result != ISC_R_SUCCESS) { + /* Log the error message when unlocked. */ + tls_transport_invalid = true; + goto unlock; + } + } + result = dns_request_createraw( forward->zone->view->requestmgr, forward->msgbuf, &src, - &forward->addr, NULL, NULL, dscp, forward->options, - 15 /* XXX */, 0, 0, forward->zone->task, forward_callback, - forward, &forward->request); + &forward->addr, forward->transport, zone->zmgr->tlsctx_cache, + dscp, forward->options, 15 /* XXX */, 0, 0, forward->zone->task, + forward_callback, forward, &forward->request); if (result == ISC_R_SUCCESS) { if (!ISC_LINK_LINKED(forward, link)) { - ISC_LIST_APPEND(forward->zone->forwards, forward, link); + ISC_LIST_APPEND(zone->forwards, forward, link); } } unlock: - UNLOCK_ZONE(forward->zone); + UNLOCK_ZONE(zone); + + if (tls_transport_invalid) { + dns_zone_log(zone, ISC_LOG_ERROR, + "could not get TLS configuration " + "for dynamic update: %s", + isc_result_totext(result)); + } + return (result); } @@ -18487,17 +18522,12 @@ dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, REQUIRE(callback != NULL); forward = isc_mem_get(zone->mctx, sizeof(*forward)); - - forward->request = NULL; - forward->zone = NULL; - forward->msgbuf = NULL; - forward->which = 0; - forward->mctx = 0; - forward->callback = callback; - forward->callback_arg = callback_arg; + *forward = (dns_forward_t){ .callback = callback, + .callback_arg = callback_arg, + .options = DNS_REQUESTOPT_TCP }; ISC_LINK_INIT(forward, link); forward->magic = FORWARD_MAGIC; - forward->options = DNS_REQUESTOPT_TCP; + /* * If we have a SIG(0) signed message we need to preserve the * query id as that is included in the SIG(0) computation. From ae4296729cd6e1f5027617351faf970b5d1b438d Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 28 Sep 2022 09:01:19 +0000 Subject: [PATCH 2/4] Test dynamic update forwarding when using a TLS-enabled primary Add several test cases in the 'upforwd' system test to make sure that different scenarios of Dynamic DNS update forwarding are tested, in particular when both the original and forwarded requests are over Do53, or DoT, or they use different transports. --- bin/tests/system/upforwd/knowngood.after2 | 4 +- bin/tests/system/upforwd/knowngood.after3 | 13 ++++ bin/tests/system/upforwd/ns1/named.conf.in | 2 + bin/tests/system/upforwd/ns3/named.conf.in | 4 +- bin/tests/system/upforwd/tests.sh | 83 ++++++++++++++++++++-- 5 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 bin/tests/system/upforwd/knowngood.after3 diff --git a/bin/tests/system/upforwd/knowngood.after2 b/bin/tests/system/upforwd/knowngood.after2 index eab7a2cf06..04a001f813 100644 --- a/bin/tests/system/upforwd/knowngood.after2 +++ b/bin/tests/system/upforwd/knowngood.after2 @@ -4,8 +4,8 @@ example. 3600 IN NS ns3.example. ns1.example. 3600 IN A 10.53.0.1 ns2.example. 3600 IN A 10.53.0.2 ns3.example. 3600 IN A 10.53.0.3 -unsigned.example. 600 IN TXT "Foo" -unsigned.example. 600 IN A 10.10.10.1 updated.example. 600 IN TXT "Foo" updated.example. 600 IN A 10.10.10.1 +updated-dot.example. 600 IN TXT "Foo" +updated-dot.example. 600 IN A 10.10.10.1 example. 3600 IN SOA n1.example. hostmaster.ns1.example. 3 3600 1200 604800 7200 diff --git a/bin/tests/system/upforwd/knowngood.after3 b/bin/tests/system/upforwd/knowngood.after3 new file mode 100644 index 0000000000..18407f09e6 --- /dev/null +++ b/bin/tests/system/upforwd/knowngood.after3 @@ -0,0 +1,13 @@ +example. 3600 IN SOA n1.example. hostmaster.ns1.example. 4 3600 1200 604800 7200 +example. 3600 IN NS ns2.example. +example. 3600 IN NS ns3.example. +ns1.example. 3600 IN A 10.53.0.1 +ns2.example. 3600 IN A 10.53.0.2 +ns3.example. 3600 IN A 10.53.0.3 +unsigned.example. 600 IN TXT "Foo" +unsigned.example. 600 IN A 10.10.10.1 +updated.example. 600 IN TXT "Foo" +updated.example. 600 IN A 10.10.10.1 +updated-dot.example. 600 IN TXT "Foo" +updated-dot.example. 600 IN A 10.10.10.1 +example. 3600 IN SOA n1.example. hostmaster.ns1.example. 4 3600 1200 604800 7200 diff --git a/bin/tests/system/upforwd/ns1/named.conf.in b/bin/tests/system/upforwd/ns1/named.conf.in index 83ba6040c4..dad7b2ffbf 100644 --- a/bin/tests/system/upforwd/ns1/named.conf.in +++ b/bin/tests/system/upforwd/ns1/named.conf.in @@ -21,8 +21,10 @@ options { notify-source 10.53.0.1; transfer-source 10.53.0.1; port @PORT@; + tls-port @TLSPORT@; pid-file "named.pid"; listen-on { 10.53.0.1; }; + listen-on tls ephemeral { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; notify yes; diff --git a/bin/tests/system/upforwd/ns3/named.conf.in b/bin/tests/system/upforwd/ns3/named.conf.in index 75eed2ed93..abb6770c09 100644 --- a/bin/tests/system/upforwd/ns3/named.conf.in +++ b/bin/tests/system/upforwd/ns3/named.conf.in @@ -16,8 +16,10 @@ options { notify-source 10.53.0.3; transfer-source 10.53.0.3; port @PORT@; + tls-port @TLSPORT@; pid-file "named.pid"; listen-on { 10.53.0.3; }; + listen-on tls ephemeral { 10.53.0.3; }; listen-on-v6 { none; }; recursion no; notify yes; @@ -37,7 +39,7 @@ zone "example" { type secondary; file "example.bk"; allow-update-forwarding { any; }; - primaries { 10.53.0.1; }; + primaries { 10.53.0.1 port @TLSPORT@ tls ephemeral; }; }; zone "example2" { diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh index 6d53af1c61..33227c363d 100644 --- a/bin/tests/system/upforwd/tests.sh +++ b/bin/tests/system/upforwd/tests.sh @@ -78,7 +78,7 @@ digcomp knowngood.before dig.out.ns2 || ret=1 digcomp knowngood.before dig.out.ns3 || ret=1 if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi -echo_i "updating zone (signed) ($n)" +echo_i "checking update forwarding of a zone (signed) (Do53 -> DoT) ($n)" ret=0 $NSUPDATE -y "${DEFAULT_HMAC}:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K" -- - < DoT) ($n)" ret=0 -grep "forwarding update for zone 'example/IN'" ns3/named.run > /dev/null || ret=1 +$NSUPDATE -y "${DEFAULT_HMAC}:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K" -S -O -- - < dig.out.ns1 || ret=1 +if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi +n=`expr $n + 1` + +echo_i "fetching secondary 1 copy of zone after update ($n)" +ret=0 +$DIG $DIGOPTS example.\ + @10.53.0.2 axfr > dig.out.ns2 || ret=1 +if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi + +echo_i "fetching secondary 2 copy of zone after update ($n)" +ret=0 +$DIG $DIGOPTS example.\ + @10.53.0.3 axfr > dig.out.ns3 || ret=1 +if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi +n=`expr $n + 1` + +echo_i "comparing post-update copies to known good data ($n)" +ret=0 +digcomp knowngood.after2 dig.out.ns1 || ret=1 +digcomp knowngood.after2 dig.out.ns2 || ret=1 +digcomp knowngood.after2 dig.out.ns3 || ret=1 +if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi + +echo_i "checking 'forwarding update for zone' is logged twice ($n)" +ret=0 +cnt=$(grep -F "forwarding update for zone 'example/IN'" ns3/named.run | wc -l || ret=1) +test "${cnt}" -eq 2 || ret=1 if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi n=`expr $n + 1` @@ -171,9 +213,9 @@ if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi echo_i "comparing post-update copies to known good data ($n)" ret=0 -digcomp knowngood.after2 dig.out.ns1 || ret=1 -digcomp knowngood.after2 dig.out.ns2 || ret=1 -digcomp knowngood.after2 dig.out.ns3 || ret=1 +digcomp knowngood.after3 dig.out.ns1 || ret=1 +digcomp knowngood.after3 dig.out.ns2 || ret=1 +digcomp knowngood.after3 dig.out.ns3 || ret=1 if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi if $FEATURETEST --enable-dnstap @@ -222,7 +264,7 @@ fi if test -f keyname then - echo_i "checking update forwarding to with sig0 ($n)" + echo_i "checking update forwarding to with sig0 (Do53 -> Do53) ($n)" ret=0 keyname=`cat keyname` $NSUPDATE -k $keyname.private -- - < Do53) ($n)" + ret=0 + keyname=`cat keyname` + $NSUPDATE -k $keyname.private -S -O -- - < dig.out.ns1.test$n + grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 + if [ $ret != 0 ] ; then echo_i "failed"; fi + status=`expr $status + $ret` + n=`expr $n + 1` + + if $FEATURETEST --enable-dnstap + then + echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)" + ret=0 + capture_dnstap + uq_equals_ur || ret=1 + if [ $ret != 0 ] ; then echo_i "failed"; fi + status=`expr $status + $ret` + n=`expr $n + 1` + fi fi echo_i "exit status: $status" From aa4319f2635c6adef408e9202a900d28b488339c Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 28 Sep 2022 09:01:30 +0000 Subject: [PATCH 3/4] Add a CHANGES note for [GL #3512] --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 9bf6f54a32..2d9cd6dbf0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5989. [func] Implement support for DDNS update forwarding using DoT + to TLS-enabled primary servers. [GL #3512] + 5988. [bug] Some out of memory conditions in opensslrsa_link.c could lead to memory leaks. [GL #3551] From 504529dfa9f949d3a1406a9f559b6ce06383b261 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 28 Sep 2022 09:01:39 +0000 Subject: [PATCH 4/4] Add a release note for [GL #3512] --- doc/notes/notes-current.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 5849fd13e8..5776a4aa82 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -40,6 +40,9 @@ New Features - The ``nsupdate`` tool now supports DNS-over-TLS (DoT). :gl:`#1781` +- :iscman:``named`` now supports forwarding Dynamic DNS updates through + DNS-over-TLS (DoT), configured with a TLS-enabled primary server. :gl:`#3512` + - :iscman:`named` now logs the supported cryptographic algorithms during startup and in the output of :option:`named -V`. :gl:`#3541`