A. Schulze via Unbound-users:
Am 14.02.2017 um 15:00 schrieb W.C.A. Wijngaards via Unbound-users:
Unbound 1.6.1rc3 is available:
compiled Debian Jessie+Stretch without warnings.
"log-replies:yes" is cool :-)
Now, some days later, I like to announce the rc3 not only compile but
also run fine:-)
Work without problems on my testlab systems...
On note:
I included again a patch that implement nsec_aggressiveuse [1]
Works as expected but only for nsec, not nsec3.
Andreas
[1] https://tools.ietf.org/html/draft-ietf-dnsop-nsec-aggressiveuse-07
Description: enable aggressive nsec use for nxdomain
URL: http://member.wide.ad.jp/~fujiwara/files/unbound.diff
Author: Fujiwara
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
Index: unbound-1.6.1~rc3/validator/val_neg.c
===================================================================
--- unbound-1.6.1~rc3.orig/validator/val_neg.c
+++ unbound-1.6.1~rc3/validator/val_neg.c
@@ -927,6 +927,107 @@ static int neg_closest_data(struct val_n
}
}
+struct packed_rrset_data* val_neg_lookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
+ uint16_t qtype, uint16_t qclass, struct rrset_cache* rrset_cache, time_t now)
+{
+ /* lookup closest zone */
+ struct val_neg_zone* zone;
+ struct val_neg_data* data;
+ int labs;
+ struct ub_packed_rrset_key* nsec;
+ struct packed_rrset_data* d;
+ uint32_t flags;
+ uint8_t* wc;
+ struct query_info qinfo;
+ if(!neg) return NULL;
+
+ log_nametypeclass(VERB_ALGO, "negcache lookup", qname,
+ qtype, qclass);
+
+ labs = dname_count_labels(qname);
+ lock_basic_lock(&neg->lock);
+ zone = neg_closest_zone_parent(neg, qname, len, labs, qclass);
+ while(zone && !zone->in_use)
+ zone = zone->parent;
+ if(!zone) {
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+ log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0,
+ zone->dclass);
+
+ /* DLV is defined to use NSEC only */
+ if(zone->nsec3_hash) {
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+
+ /* lookup closest data record */
+ (void)neg_closest_data(zone, qname, len, labs, &data);
+ while(data && !data->in_use)
+ data = data->parent;
+ if(!data) {
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+ log_nametypeclass(VERB_ALGO, "negcache rr", data->name,
+ LDNS_RR_TYPE_NSEC, zone->dclass);
+
+ /* lookup rrset in rrset cache */
+ flags = 0;
+ if(query_dname_compare(data->name, zone->name) == 0)
+ flags = PACKED_RRSET_NSEC_AT_APEX;
+ nsec = rrset_cache_lookup(rrset_cache, data->name, data->len,
+ LDNS_RR_TYPE_NSEC, zone->dclass, flags, now, 0);
+
+ /* check if secure and TTL ok */
+ if(!nsec) {
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+ d = (struct packed_rrset_data*)nsec->entry.data;
+ if(!d || now > d->ttl) {
+ lock_rw_unlock(&nsec->entry.lock);
+ /* delete data record if expired */
+ neg_delete_data(neg, data);
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+ if(d->security != sec_status_secure) {
+ lock_rw_unlock(&nsec->entry.lock);
+ neg_delete_data(neg, data);
+ lock_basic_unlock(&neg->lock);
+ return NULL;
+ }
+ verbose(VERB_ALGO, "negcache got secure rrset");
+
+ /* check NSEC security */
+ /* check if NSEC proves no DLV type exists */
+ /* check if NSEC proves NXDOMAIN for qname */
+ qinfo.qname = qname;
+ qinfo.qtype = qtype;
+ qinfo.qclass = qclass;
+ if(!nsec_proves_nodata(nsec, &qinfo, &wc) &&
+ !val_nsec_proves_name_error(nsec, qname)) {
+ /* the NSEC is not a denial for the DLV */
+ lock_rw_unlock(&nsec->entry.lock);
+ lock_basic_unlock(&neg->lock);
+ verbose(VERB_ALGO, "negcache not proven");
+ return NULL;
+ }
+ /* so the NSEC was a NODATA proof, or NXDOMAIN proof. */
+
+ /* no need to check for wildcard NSEC; no wildcards in DLV repos */
+ /* no need to lookup SOA record for client; no response message */
+
+ lock_rw_unlock(&nsec->entry.lock);
+ /* if OK touch the LRU for neg_data element */
+ neg_lru_touch(neg, data);
+ lock_basic_unlock(&neg->lock);
+ verbose(VERB_ALGO, "negcache denial proven");
+ return nsec;
+}
+
int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
uint16_t qclass, struct rrset_cache* rrset_cache, time_t now)
{
Index: unbound-1.6.1~rc3/validator/val_neg.h
===================================================================
--- unbound-1.6.1~rc3.orig/validator/val_neg.h
+++ unbound-1.6.1~rc3/validator/val_neg.h
@@ -231,6 +231,8 @@ void val_neg_addreferral(struct val_neg_
*/
int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
uint16_t qclass, struct rrset_cache* rrset_cache, time_t now);
+struct packed_rrset_data* val_neg_lookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
+ uint16_t qtype, uint16_t qclass, struct rrset_cache* rrset_cache, time_t now);
/**
* For the given query, try to get a reply out of the negative cache.
Index: unbound-1.6.1~rc3/validator/validator.c
===================================================================
--- unbound-1.6.1~rc3.orig/validator/validator.c
+++ unbound-1.6.1~rc3/validator/validator.c
@@ -919,6 +919,9 @@ validate_nameerror_response(struct modul
/* Otherwise, we consider the message secure. */
verbose(VERB_ALGO, "successfully validated NAME ERROR response.");
chase_reply->security = sec_status_secure;
+
+ /* store NSECs into negative cache */
+ val_neg_addreply(ve->neg_cache, chase_reply);
}
/**
@@ -2271,6 +2274,8 @@ val_operate(struct module_qstate* qstate
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct val_qstate* vq = (struct val_qstate*)qstate->minfo[id];
+ struct packed_rrset_data* nsec;
+
verbose(VERB_QUERY, "validator[module %d] operate: extstate:%s "
"event:%s", id, strextstate(qstate->ext_state[id]),
strmodulevent(event));
@@ -2283,6 +2288,19 @@ val_operate(struct module_qstate* qstate
if(event == module_event_new ||
(event == module_event_pass && vq == NULL)) {
+ nsec = val_neg_lookup(ve->neg_cache, qstate->qinfo.qname,
+ qstate->qinfo.qname_len, qstate->qinfo.qtype,
+ qstate->qinfo.qclass,
+ qstate->env->rrset_cache, *qstate->env->now);
+
+ /* Aggressive NSEC caching */
+ if (nsec != NULL) {
+ qstate->return_rcode = LDNS_RCODE_NXDOMAIN;
+ qstate->return_msg = NULL;
+ qstate->ext_state[id] = module_finished;
+ return;
+ }
+
/* pass request to next module, to get it */
verbose(VERB_ALGO, "validator: pass to next module");
qstate->ext_state[id] = module_wait_module;