mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-22 23:01:43 -04:00
Use experimental "_ A" minimization in relaxed mode.
qname minimization, even in relaxed mode, can fail on some very broken domains. In relaxed mode, instead of asking for "foo.bar NS" ask for "_.foo.bar A" to either get a delegation or NXDOMAIN. It will require more queries than regular mode for proper NXDOMAINs.
This commit is contained in:
parent
2691e729f0
commit
ae52c2117e
6 changed files with 136 additions and 35 deletions
|
|
@ -21,7 +21,7 @@ else
|
|||
TESTSOCK6=false
|
||||
fi
|
||||
|
||||
TESTSOCK6="$TESTSOCK6"
|
||||
export LANG=C
|
||||
|
||||
. ${TOP}/version
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ def create_response(msg):
|
|||
r.set_rcode(NXDOMAIN)
|
||||
if ugly:
|
||||
r.set_rcode(FORMERR)
|
||||
elif "zoop.boing.".endswith(lqname):
|
||||
elif lqname.endswith("zoop.boing."):
|
||||
r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1"))
|
||||
r.set_rcode(NXDOMAIN)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
|||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "query for .good is properly minimized when qname-minimization is on ($n)"
|
||||
echo_i "query for .good is properly minimized when qname-minimization is in strict mode ($n)"
|
||||
ret=0
|
||||
$CLEANQL
|
||||
$RNDCCMD 10.53.0.6 flush
|
||||
|
|
@ -142,6 +142,37 @@ for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "query for .good is properly minimized when qname-minimization is in relaxed mode ($n)"
|
||||
ret=0
|
||||
$CLEANQL
|
||||
$RNDCCMD 10.53.0.7 flush
|
||||
$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.7 > dig.out.test$n
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
|
||||
sleep 1
|
||||
sort ans2/query.log > ans2/query.log.sorted
|
||||
cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
|
||||
ADDR _.boing.good.
|
||||
ADDR _.zoop.boing.good.
|
||||
ADDR a.bit.longer.ns.name.good.
|
||||
ADDR a.bit.longer.ns.name.good.
|
||||
ADDR ns2.good.
|
||||
ADDR ns3.good.
|
||||
ADDR ns3.good.
|
||||
__EOF
|
||||
cat << __EOF | $DIFF ans3/query.log - > /dev/null || ret=1
|
||||
ADDR _.ptang.zoop.boing.good.
|
||||
ADDR _.icky.ptang.zoop.boing.good.
|
||||
__EOF
|
||||
cat << __EOF | $DIFF ans4/query.log - > /dev/null || ret=1
|
||||
ADDR _.icky.icky.ptang.zoop.boing.good.
|
||||
ADDR icky.icky.icky.ptang.zoop.boing.good.
|
||||
__EOF
|
||||
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "query for .bad fails when qname-minimization is in strict mode ($n)"
|
||||
ret=0
|
||||
|
|
@ -171,17 +202,22 @@ grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n > /d
|
|||
sleep 1
|
||||
sort ans2/query.log > ans2/query.log.sorted
|
||||
cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
|
||||
ADDR _.boing.bad.
|
||||
ADDR _.zoop.boing.bad.
|
||||
ADDR a.bit.longer.ns.name.bad.
|
||||
ADDR a.bit.longer.ns.name.bad.
|
||||
ADDR icky.icky.icky.ptang.zoop.boing.bad.
|
||||
ADDR ns2.bad.
|
||||
ADDR ns3.bad.
|
||||
ADDR ns3.bad.
|
||||
NS bad.
|
||||
NS boing.bad.
|
||||
__EOF
|
||||
echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | $DIFF ans3/query.log - > /dev/null || ret=1
|
||||
echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | $DIFF ans4/query.log - > /dev/null || ret=1
|
||||
cat << __EOF | $DIFF ans3/query.log - > /dev/null || ret=1
|
||||
ADDR _.ptang.zoop.boing.bad.
|
||||
ADDR _.icky.ptang.zoop.boing.bad.
|
||||
__EOF
|
||||
cat << __EOF | $DIFF ans4/query.log - > /dev/null || ret=1
|
||||
ADDR _.icky.icky.ptang.zoop.boing.bad.
|
||||
ADDR icky.icky.icky.ptang.zoop.boing.bad.
|
||||
__EOF
|
||||
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
|
@ -215,17 +251,17 @@ $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.7 > dig.out.test$n
|
|||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n > /dev/null || ret=1
|
||||
sleep 1
|
||||
|
||||
sort ans2/query.log > ans2/query.log.sorted
|
||||
cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || ret=1
|
||||
cat << __EOF | $DIFF ans2/query.log.sorted - > /dev/null || cat ans2/query.log.sorted
|
||||
ADDR _.boing.ugly.
|
||||
ADDR _.boing.ugly.
|
||||
ADDR a.bit.longer.ns.name.ugly.
|
||||
ADDR a.bit.longer.ns.name.ugly.
|
||||
ADDR icky.icky.icky.ptang.zoop.boing.ugly.
|
||||
ADDR ns2.ugly.
|
||||
ADDR ns3.ugly.
|
||||
ADDR ns3.ugly.
|
||||
NS boing.ugly.
|
||||
NS boing.ugly.
|
||||
NS ugly.
|
||||
__EOF
|
||||
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | $DIFF ans3/query.log - > /dev/null || ret=1
|
||||
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | $DIFF ans4/query.log - > /dev/null || ret=1
|
||||
|
|
|
|||
|
|
@ -110,15 +110,20 @@ typedef enum {
|
|||
#define DNS_FETCHOPT_NOCACHED 0x00008000 /*%< Force cache update. */
|
||||
#define DNS_FETCHOPT_QMINIMIZE 0x00010000 /*%< Use qname
|
||||
minimization. */
|
||||
#define DNS_FETCHOPT_QMIN_STRICT 0x00020000 /*%< Do not work around
|
||||
#define DNS_FETCHOPT_NOFOLLOW 0x00020000 /*%< Don't follow
|
||||
delegations */
|
||||
#define DNS_FETCHOPT_QMIN_STRICT 0x00040000 /*%< Do not work around
|
||||
servers that return
|
||||
errors on non-empty
|
||||
terminals. */
|
||||
#define DNS_FETCHOPT_QMIN_SKIP_IP6A 0x00040000 /*%< Skip some labels
|
||||
#define DNS_FETCHOPT_QMIN_USE_A 0x00080000 /*%< Use A type queries
|
||||
instead of NS when
|
||||
doing minimization */
|
||||
#define DNS_FETCHOPT_QMIN_SKIP_IP6A 0x00100000 /*%< Skip some labels
|
||||
when doing qname
|
||||
minimization on
|
||||
ip6.arpa. */
|
||||
#define DNS_FETCHOPT_NOFORWARD 0x00080000 /*%< Do not use forwarders
|
||||
#define DNS_FETCHOPT_NOFORWARD 0x00200000 /*%< Do not use forwarders
|
||||
if possible. */
|
||||
|
||||
/* Reserved in use by adb.c 0x00400000 */
|
||||
|
|
|
|||
|
|
@ -579,6 +579,11 @@ static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
|
|||
static const dns_name_t ip6_arpa =
|
||||
DNS_NAME_INITABSOLUTE(ip6_arpa_data, ip6_arpa_offsets);
|
||||
|
||||
static unsigned char underscore_data[] = "\001_";
|
||||
static unsigned char underscore_offsets[] = { 0 };
|
||||
static const dns_name_t underscore_name =
|
||||
DNS_NAME_INITNONABSOLUTE(underscore_data, underscore_offsets);
|
||||
|
||||
static void destroy(dns_resolver_t *res);
|
||||
static void empty_bucket(dns_resolver_t *res);
|
||||
static isc_result_t resquery_send(resquery_t *query);
|
||||
|
|
@ -4055,6 +4060,14 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
|
|||
if (fctx->minimized && !fctx->forwarding) {
|
||||
unsigned int options = fctx->options;
|
||||
options &= ~DNS_FETCHOPT_QMINIMIZE;
|
||||
/*
|
||||
* In "_ A" mode we're asking for _.domain -
|
||||
* resolver by default will follow delegations
|
||||
* then, we don't want that.
|
||||
*/
|
||||
if ((options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
|
||||
options |= DNS_FETCHOPT_NOFOLLOW;
|
||||
}
|
||||
fctx_increference(fctx);
|
||||
task = res->buckets[bucketnum].task;
|
||||
fctx_stoptimer(fctx);
|
||||
|
|
@ -4157,8 +4170,19 @@ resume_qmin(isc_task_t *task, isc_event_t *event) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (NXDOMAIN_RESULT(result) || result == DNS_R_FORMERR ||
|
||||
result == DNS_R_REMOTEFORMERR || result == ISC_R_FAILURE)
|
||||
/*
|
||||
* If we're doing "_ A"-style minimization we can get
|
||||
* NX answer to minimized query - we need to continue then.
|
||||
*
|
||||
* Otherwise - either disable minimization if we're
|
||||
* in relaxed mode or fail if we're in strict mode.
|
||||
*/
|
||||
|
||||
if ((NXDOMAIN_RESULT(result) &&
|
||||
(fctx->options & DNS_FETCHOPT_QMIN_USE_A) == 0) ||
|
||||
result == DNS_R_FORMERR ||
|
||||
result == DNS_R_REMOTEFORMERR ||
|
||||
result == ISC_R_FAILURE)
|
||||
{
|
||||
if ((fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
|
||||
fctx->qmin_labels = DNS_MAX_LABELS + 1;
|
||||
|
|
@ -7607,7 +7631,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
case DNS_R_CHASEDSSERVERS:
|
||||
break;
|
||||
case DNS_R_DELEGATION:
|
||||
result = ISC_R_SUCCESS;
|
||||
/* With NOFOLLOW we want to pass the result code */
|
||||
if ((fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) {
|
||||
result = ISC_R_SUCCESS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
|
|
@ -7641,10 +7668,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
|
|||
* work to be queued to the DNSSEC validator.
|
||||
*/
|
||||
if (WANTCACHE(fctx)) {
|
||||
result = cache_message(fctx, query->addrinfo, rctx.now);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("cache_message complete", result);
|
||||
rctx_done(&rctx, result);
|
||||
isc_result_t tresult;
|
||||
tresult = cache_message(fctx, query->addrinfo, rctx.now);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
FCTXTRACE3("cache_message complete", tresult);
|
||||
rctx_done(&rctx, tresult);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -9194,18 +9222,21 @@ rctx_referral(respctx_t *rctx) {
|
|||
* reset the fetch context counters.
|
||||
*
|
||||
*/
|
||||
rctx->get_nameservers = true;
|
||||
rctx->next_server = true;
|
||||
rctx->fctx->restarts = 0;
|
||||
rctx->fctx->referrals++;
|
||||
rctx->fctx->querysent = 0;
|
||||
rctx->fctx->lamecount = 0;
|
||||
rctx->fctx->quotacount = 0;
|
||||
rctx->fctx->neterr = 0;
|
||||
rctx->fctx->badresp = 0;
|
||||
rctx->fctx->adberr = 0;
|
||||
if ((rctx->fctx->options & DNS_FETCHOPT_NOFOLLOW) == 0) {
|
||||
rctx->get_nameservers = true;
|
||||
rctx->next_server = true;
|
||||
rctx->fctx->restarts = 0;
|
||||
rctx->fctx->referrals++;
|
||||
rctx->fctx->querysent = 0;
|
||||
rctx->fctx->lamecount = 0;
|
||||
rctx->fctx->quotacount = 0;
|
||||
rctx->fctx->neterr = 0;
|
||||
rctx->fctx->badresp = 0;
|
||||
rctx->fctx->adberr = 0;
|
||||
}
|
||||
|
||||
return (ISC_R_COMPLETE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -10471,9 +10502,28 @@ fctx_minimize_qname(fetchctx_t *fctx) {
|
|||
dns_name_split(&fctx->name,
|
||||
fctx->qmin_labels,
|
||||
NULL, dns_fixedname_name(&fname));
|
||||
result = dns_name_dup(dns_fixedname_name(&fname), fctx->mctx,
|
||||
&fctx->qminname);
|
||||
fctx->qmintype = dns_rdatatype_ns;
|
||||
if ((fctx->options & DNS_FETCHOPT_QMIN_USE_A) != 0) {
|
||||
isc_buffer_t dbuf;
|
||||
dns_fixedname_t tmpname;
|
||||
char ndata[DNS_NAME_MAXWIRE];
|
||||
isc_buffer_init(&dbuf, ndata, DNS_NAME_MAXWIRE);
|
||||
dns_fixedname_init(&tmpname);
|
||||
result = dns_name_concatenate(&underscore_name,
|
||||
dns_fixedname_name(&fname),
|
||||
dns_fixedname_name(&tmpname),
|
||||
&dbuf);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = dns_name_dup(dns_fixedname_name(&tmpname),
|
||||
fctx->mctx,
|
||||
&fctx->qminname);
|
||||
}
|
||||
fctx->qmintype = dns_rdatatype_a;
|
||||
} else {
|
||||
result = dns_name_dup(dns_fixedname_name(&fname),
|
||||
fctx->mctx,
|
||||
&fctx->qminname);
|
||||
fctx->qmintype = dns_rdatatype_ns;
|
||||
}
|
||||
fctx->minimized = true;
|
||||
} else {
|
||||
/* Minimization is done, we'll ask for whole qname */
|
||||
|
|
@ -10482,6 +10532,14 @@ fctx_minimize_qname(fetchctx_t *fctx) {
|
|||
fctx->minimized = false;
|
||||
}
|
||||
|
||||
char domainbuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(&fctx->qminname, domainbuf, sizeof(domainbuf));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(5),
|
||||
"QNAME minimization - %s minimized, qmintype %d "
|
||||
"qminname %s", fctx->minimized ? "" : "not",
|
||||
fctx->qmintype, domainbuf);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11088,6 +11088,8 @@ ns_query_start(ns_client_t *client) {
|
|||
DNS_FETCHOPT_QMIN_SKIP_IP6A;
|
||||
if (client->view->qmin_strict) {
|
||||
client->query.fetchoptions |= DNS_FETCHOPT_QMIN_STRICT;
|
||||
} else {
|
||||
client->query.fetchoptions |= DNS_FETCHOPT_QMIN_USE_A;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue