Merge branch '1106-interaction-between-dns64-and-rpz-can-cause-unexpected-results' into 'master'

Resolve "Interaction between dns64 and RPZ can cause unexpected results"

Closes #1106

See merge request isc-projects/bind9!2111
This commit is contained in:
Mark Andrews 2019-07-22 14:33:52 -04:00
commit b786171423
10 changed files with 140 additions and 5 deletions

View file

@ -1,6 +1,9 @@
5264. [func] New DNS Cookie algorithm - siphash24 - has been added to
BIND 9, and the old HMAC-SHA DNS Cookie algorithms have
been removed. [GL #605]
5265. [bug] DNS64 and RPZ nodata (CNAME *.) rules interacted badly
[GL #1106]
5264. [func] New DNS Cookie algorithm - siphash24 - has been added
to BIND 9, and the old HMAC-SHA DNS Cookie algorithms
have been removed. [GL #605]
--- 9.15.2 released ---

View file

@ -33,3 +33,8 @@ ns.tld5. A 10.53.0.5
; generate SERVFAIL
servfail NS ns.tld2.
a-only.example A 1.2.3.4
no-a-no-aaaa.example TXT placeholder
a-plus-aaaa.example A 1.2.3.4
a-plus-aaaa.example AAAA ::1

View file

@ -0,0 +1,11 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
. 120 NS ns.
ns. 120 A 10.53.0.1

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*
* DNS64 / RPZ server.
*/
options {
query-source address 10.53.0.9;
notify-source 10.53.0.9;
transfer-source 10.53.0.9;
port @PORT@;
pid-file "named.pid";
statistics-file "named.stats";
session-keyfile "session.key";
listen-on { 10.53.0.9; };
listen-on-v6 { none; };
notify yes;
minimal-responses no;
recursion yes;
dnssec-validation yes;
dns64-server "example.localdomain.";
dns64 64:ff9b::/96 { };
response-policy {
zone "rpz";
}
qname-wait-recurse no ;
include "../dnsrps.conf";
notify-delay 0;
};
logging { category rpz { default_debug; }; };
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." { type hint; file "hints"; };
zone "rpz." {
type master;
file "rpz.db";
notify no;
};

View file

@ -0,0 +1,5 @@
rpz. 28800 IN SOA rpz. hostmaster.rpz. 6 10800 3600 2419200 900
rpz. 28800 IN NS .
a-only.example.rpz. 28800 IN CNAME *.
no-a-no-aaaa.example.rpz. 28800 IN CNAME *.
a-plus-aaaa.example.rpz. 28800 IN CNAME *.

View file

@ -51,6 +51,7 @@ copy_setports ns5/named.conf.in ns5/named.conf
copy_setports ns6/named.conf.in ns6/named.conf
copy_setports ns7/named.conf.in ns7/named.conf
copy_setports ns8/named.conf.in ns8/named.conf
copy_setports ns9/named.conf.in ns9/named.conf
copy_setports dnsrpzd.conf.in dnsrpzd.conf

View file

@ -856,6 +856,33 @@ EOF
grep "status: SERVFAIL" dig.out.$t > /dev/null || setret "failed"
fi
# RPZ 'CNAME *.' (NODATA) trumps DNS64. Test against various DNS64 senarios.
for label in a-only no-a-no-aaaa a-plus-aaaa
do
for type in AAAA A
do
t=`expr $t + 1`
case $label in
a-only)
echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A-only (${t})"
;;
no-a-no-aaaa)
echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with no A or AAAA (${t})"
;;
a-plus-aaaa)
echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A and AAAA (${t})"
;;
esac
ret=0
$DIG ${label}.example -p ${PORT} $type @10.53.0.9 > dig.out.${t}
grep "status: NOERROR" dig.out.$t > /dev/null || ret=1
grep "ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 2$" dig.out.$t > /dev/null || ret=1
grep "^rpz" dig.out.$t > /dev/null || ret=1
[ $ret -eq 0 ] || echo_i "failed"
status=`expr $status + $ret`
done
done
[ $status -ne 0 ] && pf=fail || pf=pass
case $mode in
native)

View file

@ -71,6 +71,7 @@ typedef enum {
DNS_RPZ_POLICY_NXDOMAIN = 5, /* 'nxdomain': answer with NXDOMAIN */
DNS_RPZ_POLICY_NODATA = 6, /* 'nodata': answer with ANCOUNT=0 */
DNS_RPZ_POLICY_CNAME = 7, /* 'cname x': answer with x's rrsets */
DNS_RPZ_POLICY_DNS64, /* Apply DN64 to the A rewrite */
DNS_RPZ_POLICY_RECORD,
DNS_RPZ_POLICY_WILDCNAME,
DNS_RPZ_POLICY_MISS,

View file

@ -265,6 +265,9 @@ dns_rpz_policy2str(dns_rpz_policy_t policy) {
case DNS_RPZ_POLICY_MISS:
str = "MISS";
break;
case DNS_RPZ_POLICY_DNS64:
str = "DNS64";
break;
default:
INSIST(0);
ISC_UNREACHABLE();

View file

@ -2950,6 +2950,7 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
isc_result_t result;
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
bool found_a = false;
REQUIRE(nodep != NULL);
@ -2993,6 +2994,18 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
"rpz_find_p: allrdatasets failed");
return (DNS_R_SERVFAIL);
}
if (qtype == dns_rdatatype_aaaa &&
!ISC_LIST_EMPTY(client->view->dns64)) {
for (result = dns_rdatasetiter_first(rdsiter);
result == ISC_R_SUCCESS;
result = dns_rdatasetiter_next(rdsiter)) {
dns_rdatasetiter_current(rdsiter, *rdatasetp);
if ((*rdatasetp)->type == dns_rdatatype_a) {
found_a = true;
}
dns_rdataset_disassociate(*rdatasetp);
}
}
for (result = dns_rdatasetiter_first(rdsiter);
result == ISC_R_SUCCESS;
result = dns_rdatasetiter_next(rdsiter)) {
@ -3045,7 +3058,11 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
}
return (ISC_R_SUCCESS);
case DNS_R_NXRRSET:
*policyp = DNS_RPZ_POLICY_NODATA;
if (found_a) {
*policyp = DNS_RPZ_POLICY_DNS64;
} else {
*policyp = DNS_RPZ_POLICY_NODATA;
}
return (result);
case DNS_R_DNAME:
/*
@ -6424,8 +6441,10 @@ query_checkrpz(query_ctx_t *qctx, isc_result_t result) {
qctx->rpz = true;
break;
case DNS_RPZ_POLICY_NODATA:
result = DNS_R_NXRRSET;
qctx->nxrewrite = true;
/* FALLTHROUGH */
case DNS_RPZ_POLICY_DNS64:
result = DNS_R_NXRRSET;
qctx->rpz = true;
break;
case DNS_RPZ_POLICY_RECORD:
@ -8235,6 +8254,7 @@ query_nodata(query_ctx_t *qctx, isc_result_t res) {
} else if ((result == DNS_R_NXRRSET ||
result == DNS_R_NCACHENXRRSET) &&
!ISC_LIST_EMPTY(qctx->view->dns64) &&
!qctx->nxrewrite &&
qctx->client->message->rdclass == dns_rdataclass_in &&
qctx->qtype == dns_rdatatype_aaaa)
{