Merge branch '3512-xot-breaks-ddns-update-forwarding' into 'main'

Resolve "XoT breaks DDNS update forwarding"

Closes #3512

See merge request isc-projects/bind9!6710
This commit is contained in:
Arаm Sаrgsyаn 2022-09-28 10:28:05 +00:00
commit cd32969138
8 changed files with 156 additions and 34 deletions

View file

@ -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]

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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" {

View file

@ -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" -- - <<EOF || ret=1
server 10.53.0.3 ${PORT}
@ -119,9 +119,51 @@ digcomp knowngood.after1 dig.out.ns2 || ret=1
digcomp knowngood.after1 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 ($n)"
echo_i "checking update forwarding of a zone (signed) (DoT -> 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 -- - <<EOF || ret=1
server 10.53.0.3 ${TLSPORT}
update add updated-dot.example. 600 A 10.10.10.1
update add updated-dot.example. 600 TXT Foo
send
EOF
if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi
n=`expr $n + 1`
echo_i "sleeping 15 seconds for server to incorporate changes"
sleep 15
echo_i "fetching primary copy of zone after update ($n)"
ret=0
$DIG $DIGOPTS example.\
@10.53.0.1 axfr > 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 -- - <<EOF
@ -248,6 +290,33 @@ EOF
status=`expr $status + $ret`
n=`expr $n + 1`
fi
echo_i "checking update forwarding to with sig0 (DoT -> Do53) ($n)"
ret=0
keyname=`cat keyname`
$NSUPDATE -k $keyname.private -S -O -- - <<EOF
server 10.53.0.3 ${TLSPORT}
zone example2
update add unsigned-dot.example2. 600 A 10.10.10.1
update add unsigned-dot.example2. 600 TXT Foo
send
EOF
$DIG -p ${PORT} unsigned-dot.example2 A @10.53.0.1 > 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"

View file

@ -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`

View file

@ -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.