mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
- Warn for unused 'nodefault' local-zone configuration in
unbound-checkconf (related to #1416).
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
6 March 2026: Yorgos
|
||||
- Document the suggestion for a higher value for 'outgoing-range';
|
||||
helps when the request list is full.
|
||||
- Warn for unused 'nodefault' local-zone configuration in
|
||||
unbound-checkconf (related to #1416).
|
||||
|
||||
5 March 2026: Wouter
|
||||
- Fix for DNS Rebinding Bypass via SVCB/HTTPS Records in Unbound.
|
||||
|
||||
+67
-59
@@ -56,6 +56,24 @@
|
||||
* with 16 bytes for an A record, a 64K packet has about 4000 max */
|
||||
#define LOCALZONE_RRSET_COUNT_MAX 4096
|
||||
|
||||
static const char* default_zones_reverse_array[] = {
|
||||
"127.in-addr.arpa.", /* reverse ip4 zone */
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", /* reverse ip6 zone */
|
||||
0
|
||||
};
|
||||
const char** local_zones_default_reverse = default_zones_reverse_array;
|
||||
|
||||
static const char* default_zones_special_array[] = {
|
||||
"test.", /* RFC 6761 */
|
||||
"invalid.", /* RFC 6761 */
|
||||
"onion.", /* RFC 7686 */
|
||||
"home.arpa.", /* RFC 8375 */
|
||||
"resolver.arpa.", /* RFC 9462 */
|
||||
"service.arpa.", /* RFC 9665 */
|
||||
0
|
||||
};
|
||||
const char** local_zones_default_special = default_zones_special_array;
|
||||
|
||||
/** print all RRsets in local zone */
|
||||
static void
|
||||
local_zone_out(struct local_zone* z)
|
||||
@@ -834,7 +852,7 @@ lz_nodefault(struct config_file* cfg, const char* name)
|
||||
|
||||
for(p = cfg->local_zones_nodefault; p; p = p->next) {
|
||||
/* compare zone name, lowercase, compare without ending . */
|
||||
if(strncasecmp(p->str, name, len) == 0 &&
|
||||
if(strncasecmp(p->str, name, len) == 0 &&
|
||||
(strlen(p->str) == len || (strlen(p->str)==len+1 &&
|
||||
p->str[len] == '.')))
|
||||
return 1;
|
||||
@@ -842,6 +860,45 @@ lz_nodefault(struct config_file* cfg, const char* name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** enter reverse default zone */
|
||||
static int
|
||||
add_reverse_default(struct local_zones* zones, struct config_file* cfg,
|
||||
const char* name)
|
||||
{
|
||||
struct local_zone* z;
|
||||
char str[1024]; /* known long enough */
|
||||
if(lz_exists(zones, name) || lz_nodefault(cfg, name))
|
||||
return 1; /* do not enter default content */
|
||||
if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN)))
|
||||
return 0;
|
||||
snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
if(strncasecmp("127.in-addr.arpa.", name, 17) == 0) {
|
||||
if(!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
} else if(strncasecmp("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", name, 73) == 0) {
|
||||
snprintf(str, sizeof(str), "%s 10800 IN PTR localhost.", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** enter (AS112) empty default zone */
|
||||
static int
|
||||
add_empty_default(struct local_zones* zones, struct config_file* cfg,
|
||||
@@ -902,72 +959,23 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* reverse ip4 zone */
|
||||
if(!lz_exists(zones, "127.in-addr.arpa.") &&
|
||||
!lz_nodefault(cfg, "127.in-addr.arpa.")) {
|
||||
if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static",
|
||||
LDNS_RR_CLASS_IN)) ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"127.in-addr.arpa. 10800 IN NS localhost.") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"127.in-addr.arpa. 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
|
||||
|
||||
/* ip4 and ip6 reverse */
|
||||
for(zstr = local_zones_default_reverse; *zstr; zstr++) {
|
||||
if(!add_reverse_default(zones, cfg, *zstr)) {
|
||||
log_err("out of memory adding default zone");
|
||||
if(z) { lock_rw_unlock(&z->lock); }
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* reverse ip6 zone */
|
||||
if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") &&
|
||||
!lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) {
|
||||
if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static",
|
||||
LDNS_RR_CLASS_IN)) ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) {
|
||||
|
||||
/* special-use zones */
|
||||
for(zstr = local_zones_default_special; *zstr; zstr++) {
|
||||
if(!add_empty_default(zones, cfg, *zstr)) {
|
||||
log_err("out of memory adding default zone");
|
||||
if(z) { lock_rw_unlock(&z->lock); }
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* home.arpa. zone (RFC 8375) */
|
||||
if(!add_empty_default(zones, cfg, "home.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* resolver.arpa. zone (RFC 9462) */
|
||||
if(!add_empty_default(zones, cfg, "resolver.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* service.arpa. zone (draft-ietf-dnssd-srp-25) */
|
||||
if(!add_empty_default(zones, cfg, "service.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* onion. zone (RFC 7686) */
|
||||
if(!add_empty_default(zones, cfg, "onion.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* test. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "test.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* invalid. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "invalid.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* block AS112 zones, unless asked not to */
|
||||
if(!cfg->unblock_lan_zones) {
|
||||
for(zstr = as112_zones; *zstr; zstr++) {
|
||||
|
||||
@@ -57,6 +57,9 @@ struct sldns_buffer;
|
||||
struct comm_reply;
|
||||
struct config_strlist;
|
||||
|
||||
extern const char** local_zones_default_special;
|
||||
extern const char** local_zones_default_reverse;
|
||||
|
||||
/**
|
||||
* Local zone type
|
||||
* This type determines processing for queries that did not match
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "util/as112.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/module.h"
|
||||
@@ -188,11 +189,55 @@ donotquerylocalhostcheck(struct config_file* cfg)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nodefaultzonescheck(struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* d;
|
||||
const char** zstr;
|
||||
size_t len;
|
||||
|
||||
#define COMPARE_ZONE_NAME(confname, builtname, len) \
|
||||
(strncasecmp(confname, builtname, (len)) == 0 && \
|
||||
(strlen(confname) == (len) || \
|
||||
(strlen(confname) == (len) + 1 \
|
||||
&& confname[(len)] == '.')))
|
||||
|
||||
for(d = cfg->local_zones_nodefault; d; d = d->next) {
|
||||
if(!cfg->unblock_lan_zones) {
|
||||
for(zstr = as112_zones; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
}
|
||||
for(zstr = local_zones_default_special; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
for(zstr = local_zones_default_reverse; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
if(COMPARE_ZONE_NAME(d->str, "localhost.", 10 - 1))
|
||||
goto default_continue;
|
||||
fprintf(stderr, "unbound-checkconf: warning: local-zone: '%s' "
|
||||
"is configured as 'nodefault' but there is no such "
|
||||
"default local-zone. Check the unbound.conf "
|
||||
"documentation for default configured local-zones.\n",
|
||||
d->str);
|
||||
default_continue:
|
||||
}
|
||||
#undef COMPARE_ZONE_NAME
|
||||
}
|
||||
|
||||
/** check localzones */
|
||||
static void
|
||||
localzonechecks(struct config_file* cfg)
|
||||
{
|
||||
struct local_zones* zs;
|
||||
nodefaultzonescheck(cfg);
|
||||
if(!(zs = local_zones_create()))
|
||||
fatal_exit("out of memory");
|
||||
if(!local_zones_apply_cfg(zs, cfg))
|
||||
|
||||
+1
-1
@@ -2399,7 +2399,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
||||
yyerror("local-zone type: expected static, deny, "
|
||||
"refuse, redirect, transparent, "
|
||||
"typetransparent, inform, inform_deny, "
|
||||
"inform_redirect, always_transparent, block_a,"
|
||||
"inform_redirect, always_transparent, block_a, "
|
||||
"always_refuse, always_nxdomain, "
|
||||
"always_nodata, always_deny, always_null, "
|
||||
"noview, nodefault or ipset");
|
||||
|
||||
Reference in New Issue
Block a user