- Fix #397: [Feature request] add new type always_null to local-zone

similar to always_nxdomain.
This commit is contained in:
W.C.A. Wijngaards 2021-01-12 13:35:05 +01:00
parent 64f508fa00
commit 3322f631e5
8 changed files with 375 additions and 282 deletions

View file

@ -1,3 +1,7 @@
12 January 2021: Wouter
- Fix #397: [Feature request] add new type always_null to local-zone
similar to always_nxdomain.
8 January 2021: Wouter
- Merge PR #391 from fhriley: Add start_time to reply callbacks so
modules can compute the response time.

View file

@ -706,6 +706,7 @@ server:
# o inform_redirect redirects queries and logs client IP address
# o always_transparent, always_refuse, always_nxdomain, resolve in
# that way but ignore local data for that name
# o always_null returns 0.0.0.0 or ::0 for any name in the zone.
# o noview breaks out of that view towards global local-zones.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1

View file

@ -1231,7 +1231,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
inform_redirect, always_transparent, always_refuse, always_nxdomain, noview,
inform_redirect, always_transparent, always_refuse, always_nxdomain, always_null, noview,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@ -1305,6 +1305,11 @@ Like refuse, but ignores local data and refuses the query.
\h'5'\fIalways_nxdomain\fR
Like static, but ignores local data and returns nxdomain for the query.
.TP 10
\h'5'\fIalways_null\fR
Always returns 0.0.0.0 or ::0 for every name in the zone. Like redirect
with zero data for A and AAAA. Ignores local data in the zone. Used for
some block lists.
.TP 10
\h'5'\fInoview\fR
Breaks out of that view and moves towards the global local zones for answer
to the query. If the view first is no, it'll resolve normally. If view first

View file

@ -1558,6 +1558,46 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|| lz_type == local_zone_always_transparent) {
/* no NODATA or NXDOMAINS for this zone type */
return 0;
} else if(lz_type == local_zone_always_null) {
/* 0.0.0.0 or ::0 or noerror/nodata for this zone type,
* used for blocklists. */
if(qinfo->qtype == LDNS_RR_TYPE_A ||
qinfo->qtype == LDNS_RR_TYPE_AAAA) {
struct ub_packed_rrset_key lrr;
struct packed_rrset_data d;
time_t rr_ttl = 3600;
size_t rr_len = 0;
uint8_t rr_data[2+16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t* rr_datas = rr_data;
memset(&lrr, 0, sizeof(lrr));
memset(&d, 0, sizeof(d));
lrr.entry.data = &d;
lrr.rk.dname = qinfo->qname;
lrr.rk.dname_len = qinfo->qname_len;
lrr.rk.type = htons(qinfo->qtype);
lrr.rk.rrset_class = htons(qinfo->qclass);
if(qinfo->qtype == LDNS_RR_TYPE_A) {
rr_len = 4;
sldns_write_uint16(rr_data, rr_len);
rr_len += 2;
} else {
rr_len = 16;
sldns_write_uint16(rr_data, rr_len);
rr_len += 2;
}
d.ttl = rr_ttl;
d.count = 1;
d.rr_len = &rr_len;
d.rr_data = &rr_datas;
d.rr_ttl = &rr_ttl;
return local_encode(qinfo, env, edns, repinfo, buf, temp,
&lrr, 1, LDNS_RCODE_NOERROR);
} else {
local_error_encode(qinfo, env, edns, repinfo, buf,
temp, LDNS_RCODE_NOERROR,
(LDNS_RCODE_NOERROR|BIT_AA));
}
return 1;
}
/* else lz_type == local_zone_transparent */
@ -1762,6 +1802,7 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_always_nxdomain: return "always_nxdomain";
case local_zone_always_nodata: return "always_nodata";
case local_zone_always_deny: return "always_deny";
case local_zone_always_null: return "always_null";
case local_zone_noview: return "noview";
case local_zone_invalid: return "invalid";
}
@ -1798,6 +1839,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_always_nodata;
else if(strcmp(type, "always_deny") == 0)
*t = local_zone_always_deny;
else if(strcmp(type, "always_null") == 0)
*t = local_zone_always_null;
else if(strcmp(type, "noview") == 0)
*t = local_zone_noview;
else if(strcmp(type, "nodefault") == 0)

View file

@ -96,6 +96,9 @@ enum localzone_type {
local_zone_always_nodata,
/** drop query, even when there is local data */
local_zone_always_deny,
/** answer with 0.0.0.0 or ::0 or noerror/nodata, even when there is
* local data */
local_zone_always_null,
/** answer not from the view, but global or no-answer */
local_zone_noview,
/** Invalid type, cannot be used to generate answer */

View file

@ -35,6 +35,9 @@ server:
local-zone: "redirect.top." redirect
local-data: "redirect.top. A 20.30.40.54"
; null zone
local-zone: "null.top." always_null
; create implicit data in the IN domain as well
local-data: "a.a.implicit. A 20.30.41.50"
local-data: "b.a.implicit. A 20.30.42.50"
@ -355,4 +358,36 @@ SECTION ANSWER
www.redirect.top. IN A 20.30.40.54
ENTRY_END
; always_null zone
STEP 60 QUERY
ENTRY_BEGIN
SECTION QUESTION
null.top. IN A
ENTRY_END
STEP 61 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA AA NOERROR
SECTION QUESTION
null.top. IN A
SECTION ANSWER
null.top. IN A 0.0.0.0
ENTRY_END
; always_null zone AAAA
STEP 62 QUERY
ENTRY_BEGIN
SECTION QUESTION
foo.null.top. IN AAAA
ENTRY_END
STEP 63 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RA AA NOERROR
SECTION QUESTION
foo.null.top. IN AAAA
SECTION ANSWER
foo.null.top. IN AAAA ::0
ENTRY_END
SCENARIO_END

File diff suppressed because it is too large Load diff

View file

@ -2030,6 +2030,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
&& strcmp($3, "always_transparent")!=0
&& strcmp($3, "always_refuse")!=0
&& strcmp($3, "always_nxdomain")!=0
&& strcmp($3, "always_null")!=0
&& strcmp($3, "noview")!=0
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0
&& strcmp($3, "inform_redirect") != 0
@ -2038,8 +2039,8 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
"refuse, redirect, transparent, "
"typetransparent, inform, inform_deny, "
"inform_redirect, always_transparent, "
"always_refuse, always_nxdomain, noview "
", nodefault or ipset");
"always_refuse, always_nxdomain, always_null, "
"noview, nodefault or ipset");
free($2);
free($3);
} else if(strcmp($3, "nodefault")==0) {