- Fix queries for nameservers under a stub leaking to the internet.

git-svn-id: file:///svn/unbound/trunk@4154 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2017-05-12 15:10:10 +00:00
parent 893159454f
commit 1db056b19c
3 changed files with 103 additions and 11 deletions

View file

@ -1,6 +1,7 @@
12 May 2017: Wouter
- Adjust servfail by iterator to not store in cache when serve-expired
is enabled, to avoid overwriting useful information there.
- Fix queries for nameservers under a stub leaking to the internet.
9 May 2017: Ralph
- Add 'c' to getopt() in testbound.

View file

@ -1576,28 +1576,26 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
/** see if last resort is possible - does config allow queries to parent */
static int
can_have_last_resort(struct module_env* env, struct delegpt* dp,
struct iter_qstate* iq)
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
uint16_t qclass)
{
struct delegpt* fwddp;
struct iter_hints_stub* stub;
int labs = dname_count_labels(nm);
/* do not process a last resort (the parent side) if a stub
* or forward is configured, because we do not want to go 'above'
* the configured servers */
if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*)
name_tree_find(&env->hints->tree, dp->name, dp->namelen,
dp->namelabs, iq->qchase.qclass)) &&
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
/* has_parent side is turned off for stub_first, where we
* are allowed to go to the parent */
stub->dp->has_parent_side_NS) {
verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL");
return 0;
}
if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) &&
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
/* has_parent_side is turned off for forward_first, where
* we are allowed to go to the parent */
fwddp->has_parent_side_NS) {
verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL");
return 0;
}
return 1;
@ -1624,9 +1622,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "No more query targets, attempting last resort");
log_assert(iq->dp);
if(!can_have_last_resort(qstate->env, iq->dp, iq)) {
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
iq->qchase.qclass)) {
/* fail -- no more targets, no more hope of targets, no hope
* of a response. */
verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
@ -1711,6 +1711,19 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
/* see if we can issue queries to get nameserver addresses */
/* this lookup is not randomized, but sequential. */
for(ns = iq->dp->nslist; ns; ns = ns->next) {
/* if this nameserver is at a delegation point, but that
* delegation point is a stub and we cannot go higher, skip*/
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
(ie->supports_ipv4 && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
iq->qchase.qclass)) {
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
"because it is also a stub/forward,",
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
if(ie->supports_ipv6) ns->done_pside6 = 1;
if(ie->supports_ipv4) ns->done_pside4 = 1;
continue;
}
/* query for parent-side A and AAAA for nameservers */
if(ie->supports_ipv6 && !ns->done_pside6) {
/* Send the AAAA request. */

View file

@ -8,6 +8,9 @@ stub-zone:
stub-zone:
name: "example.com"
stub-addr: 10.0.1.1
stub-zone:
name: "example.net"
stub-addr: 10.0.5.1
CONFIG_END
SCENARIO_BEGIN Test stub zone leaking to the internet on last resort fallback
@ -18,7 +21,7 @@ RANGE_BEGIN 0 100
; root prime
ENTRY_BEGIN
MATCH
MATCH qname qtype
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
@ -45,6 +48,7 @@ subzone.example.com. IN A
SECTION AUTHORITY
subzone.example.com. IN NS sub-ns1.example.com.
subzone.example.com. IN NS sub-ns2.example.com.
subzone.example.com. IN NS example.net.
SECTION ADDITIONAL
sub-ns1.example.com. IN A 10.0.2.3
sub-ns2.example.com. IN A 10.0.2.4
@ -92,6 +96,44 @@ ENTRY_END
RANGE_END
; stub server for example.net
RANGE_BEGIN 0 100
ADDRESS 10.0.5.1
ENTRY_BEGIN
MATCH opcode question
ADJUST copy_id copy_query
REPLY QR AA NOERROR
SECTION QUESTION
example.net. IN NS
SECTION ANSWER
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 10.0.5.1
ENTRY_END
ENTRY_BEGIN
MATCH opcode question
ADJUST copy_id copy_query
REPLY QR AA NOERROR
SECTION QUESTION
example.net. IN A
SECTION ANSWER
example.net. IN A 10.0.5.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode question
ADJUST copy_id copy_query
REPLY QR AA NOERROR
SECTION QUESTION
example.net. IN AAAA
SECTION AUTHORITY
example.net. 300 SOA master.example.net etc 1 2 3 4 300
ENTRY_END
RANGE_END
; stub server for subzone.example.com
RANGE_BEGIN 0 100
ADDRESS 10.0.2.3
@ -120,16 +162,52 @@ SECTION ANSWER
ENTRY_END
RANGE_END
; stub server for subzone.example.com
RANGE_BEGIN 0 100
ADDRESS 10.0.5.4
; match anything, servfail
ENTRY_BEGIN
MATCH opcode
ADJUST copy_id copy_query
REPLY QR SERVFAIL
SECTION QUESTION
subzone.example.com. IN A
SECTION ANSWER
ENTRY_END
RANGE_END
; fetch the delegation point for example.net in cache.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
example.net. IN NS
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
example.net. IN NS
SECTION ANSWER
example.net. IN NS ns.example.net.
SECTION ADDITIONAL
ns.example.net. IN A 10.0.5.1
ENTRY_END
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
whatever.subzone.example.com. IN A
ENTRY_END
; recursion happens here.
; the query should not leak subzone ns queries to the internet
STEP 10 CHECK_ANSWER
STEP 30 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA SERVFAIL