mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 09:20:01 -04:00
Limit the number of addresses returned per ADB find
Add a hard limit on the number of addresses that ADB returns from a single NS lookup (dns_adbfind_t). This mitigates a flood attack where an attacker controls a zone with many addresses for a nameserver, each returning an invalid response. The global max-query count (default 50) also limits this, but significant harm can be done before that limit is reached. The default limit is now 6 (v4 and/or v6) addresses for an ADB find (so, ADB looking up for A/AAAA addresses of a name server name). It can be overridden for testing via 'named -T adbaddrslimit=N'. (cherry picked from commit 3ec37fc69356ee682bee7f67940613ac31d93d7b)
This commit is contained in:
parent
1c390aacae
commit
1bedd7f244
2 changed files with 32 additions and 0 deletions
|
|
@ -123,6 +123,7 @@ extern unsigned int dns_zone_mkey_month;
|
|||
extern unsigned int dns_adb_entrywindow;
|
||||
extern unsigned int dns_adb_cachemin;
|
||||
extern size_t dns_dispatch_tcppipelining;
|
||||
extern size_t dns_adb_addrslimit;
|
||||
|
||||
static bool want_stats = false;
|
||||
static char program_name[NAME_MAX] = "named";
|
||||
|
|
@ -817,6 +818,13 @@ parse_T_opt(char *option) {
|
|||
"least 1");
|
||||
}
|
||||
dns_dispatch_tcppipelining = pipelining;
|
||||
} else if (!strncmp(option, "adbaddrslimit=", 14)) {
|
||||
size_t adb_addrslimit = atoi(option + 14);
|
||||
if (adb_addrslimit < 1) {
|
||||
named_main_earlyfatal("adbaddrslimit must be at "
|
||||
"least 1");
|
||||
}
|
||||
dns_adb_addrslimit = adb_addrslimit;
|
||||
} else {
|
||||
fprintf(stderr, "unknown -T flag '%s'\n", option);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,15 @@
|
|||
|
||||
#define DNS_ADB_MINADBSIZE (1024U * 1024U) /*%< 1 Megabyte */
|
||||
|
||||
/*
|
||||
* Default and override for the per-find address limit, the sum of the number of
|
||||
* A and AAAA RR from an ADB NS name resolution. When non-zero, this value is
|
||||
* used instead of the default. Can be set via 'named -T adbaddrslimit=N' for
|
||||
* testing.
|
||||
*/
|
||||
#define DEFAULT_ADDRSLIMIT 6
|
||||
size_t dns_adb_addrslimit = 0;
|
||||
|
||||
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
|
||||
typedef struct dns_adbnamehook dns_adbnamehook_t;
|
||||
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
|
||||
|
|
@ -1473,6 +1482,9 @@ static void
|
|||
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
||||
dns_adbnamehook_t *namehook = NULL;
|
||||
dns_adbentry_t *entry = NULL;
|
||||
size_t count = 0;
|
||||
size_t limit = dns_adb_addrslimit != 0 ? dns_adb_addrslimit
|
||||
: DEFAULT_ADDRSLIMIT;
|
||||
|
||||
if ((find->options & DNS_ADBFIND_INET) != 0) {
|
||||
namehook = ISC_LIST_HEAD(name->v4);
|
||||
|
|
@ -1493,6 +1505,12 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
|||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
|
||||
if (++count >= limit) {
|
||||
DP(ISC_LOG_DEBUG(3), "skipping addresses");
|
||||
return;
|
||||
}
|
||||
|
||||
nextv4:
|
||||
namehook = ISC_LIST_NEXT(namehook, name_link);
|
||||
}
|
||||
|
|
@ -1517,6 +1535,12 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name) {
|
|||
* Found a valid entry. Add it to the find's list.
|
||||
*/
|
||||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
|
||||
if (++count >= limit) {
|
||||
DP(ISC_LOG_DEBUG(3), "skipping addresses");
|
||||
return;
|
||||
}
|
||||
|
||||
nextv6:
|
||||
namehook = ISC_LIST_NEXT(namehook, name_link);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue