From 41fa45c99e827012112fb4d3fc59cd54d3391687 Mon Sep 17 00:00:00 2001 From: Christian Allred Date: Mon, 5 Apr 2021 15:41:53 -0700 Subject: [PATCH 1/4] Add max-query-restarts config parameter --- util/config_file.c | 3 +++ util/config_file.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/util/config_file.c b/util/config_file.c index 171251f67..ce3fc543b 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -344,6 +344,7 @@ config_create(void) cfg->pad_responses_block_size = 468; /* from RFC8467 */ cfg->pad_queries = 1; cfg->pad_queries_block_size = 128; /* from RFC8467 */ + cfg->max_query_restarts = MAX_RESTART_COUNT; #ifdef USE_IPSECMOD cfg->ipsecmod_enabled = 1; cfg->ipsecmod_ignore_bogus = 0; @@ -749,6 +750,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_SIZET_NONZERO("pad-responses-block-size:", pad_responses_block_size) else S_YNO("pad-queries:", pad_queries) else S_SIZET_NONZERO("pad-queries-block-size:", pad_queries_block_size) + else S_SIZET_NONZERO("max-query-restarts:", max_query_restarts) #ifdef USE_IPSECMOD else S_YNO("ipsecmod-enabled:", ipsecmod_enabled) else S_YNO("ipsecmod-ignore-bogus:", ipsecmod_ignore_bogus) @@ -1196,6 +1198,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_YNO(opt, "pad-queries", pad_queries) else O_DEC(opt, "pad-queries-block-size", pad_queries_block_size) else O_LS2(opt, "edns-client-strings", edns_client_strings) + else O_DEC(opt, "max-query-restarts", max_query_restarts) #ifdef USE_IPSECMOD else O_YNO(opt, "ipsecmod-enabled", ipsecmod_enabled) else O_YNO(opt, "ipsecmod-ignore-bogus", ipsecmod_ignore_bogus) diff --git a/util/config_file.h b/util/config_file.h index f5eda738c..23837065a 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -615,6 +615,9 @@ struct config_file { /** block size with which to pad encrypted queries (default: 128) */ size_t pad_queries_block_size; + /** max number of query restarts. Determines max number of CNAME chain (default: 8) */ + size_t max_query_restarts; + /** IPsec module */ #ifdef USE_IPSECMOD /** false to bypass the IPsec module */ From 0e3068559c1e893fdf9de587cc3c7820ac4d554b Mon Sep 17 00:00:00 2001 From: Christian Allred Date: Mon, 5 Apr 2021 16:24:49 -0700 Subject: [PATCH 2/4] Add max-query-restarts to grammar and lexer --- util/configlexer.lex | 1 + util/configparser.y | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/util/configlexer.lex b/util/configlexer.lex index b52ddf81e..17d281faa 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -517,6 +517,7 @@ pad-responses{COLON} { YDVAR(1, VAR_PAD_RESPONSES) } pad-responses-block-size{COLON} { YDVAR(1, VAR_PAD_RESPONSES_BLOCK_SIZE) } pad-queries{COLON} { YDVAR(1, VAR_PAD_QUERIES) } pad-queries-block-size{COLON} { YDVAR(1, VAR_PAD_QUERIES_BLOCK_SIZE) } +max-query-restarts{COLON} { YDVAR(1, VAR_MAX_QUERY_RESTARTS) } ipsecmod-enabled{COLON} { YDVAR(1, VAR_IPSECMOD_ENABLED) } ipsecmod-ignore-bogus{COLON} { YDVAR(1, VAR_IPSECMOD_IGNORE_BOGUS) } ipsecmod-hook{COLON} { YDVAR(1, VAR_IPSECMOD_HOOK) } diff --git a/util/configparser.y b/util/configparser.y index 10f5ac1c4..95426dd9c 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -164,6 +164,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_DNSCRYPT_NONCE_CACHE_SLABS %token VAR_PAD_RESPONSES VAR_PAD_RESPONSES_BLOCK_SIZE %token VAR_PAD_QUERIES VAR_PAD_QUERIES_BLOCK_SIZE +%token VAR_MAX_QUERY_RESTARTS %token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS %token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT %token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED @@ -280,6 +281,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_qname_minimisation_strict | server_pad_responses | server_pad_responses_block_size | server_pad_queries | server_pad_queries_block_size | + server_max_query_restarts | server_serve_expired | server_serve_expired_ttl | server_serve_expired_ttl_reset | server_serve_expired_reply_ttl | server_serve_expired_client_timeout | @@ -2501,6 +2503,15 @@ server_pad_queries_block_size: VAR_PAD_QUERIES_BLOCK_SIZE STRING_ARG free($2); } ; +server_max_query_restarts: VAR_MAX_QUERY_RESTARTS STRING_ARG + { + OUTYY(("P(server_max_query_restarts:%s)\n", $2)); + if(atoi($2) == 0) + yyerror("number expected"); + else cfg_parser->cfg->max_query_restarts = atoi($2); + free($2); + } + ; server_ipsecmod_enabled: VAR_IPSECMOD_ENABLED STRING_ARG { #ifdef USE_IPSECMOD From 07c0d04a148a3da8a3d6fcd78ef3a2128ab5df95 Mon Sep 17 00:00:00 2001 From: Christian Allred Date: Mon, 5 Apr 2021 16:25:43 -0700 Subject: [PATCH 3/4] Use max-query-restarts in iterative resolver --- iterator/iter_utils.c | 3 +++ iterator/iterator.c | 2 +- iterator/iterator.h | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 94fa18f63..637acf736 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -176,6 +176,9 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) } iter_env->supports_ipv6 = cfg->do_ip6; iter_env->supports_ipv4 = cfg->do_ip4; + + iter_env->max_query_restarts = cfg->max_query_restarts; + return 1; } diff --git a/iterator/iterator.c b/iterator/iterator.c index 99d020117..5163857fa 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1237,7 +1237,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, /* We enforce a maximum number of query restarts. This is primarily a * cheap way to prevent CNAME loops. */ - if(iq->query_restart_count > MAX_RESTART_COUNT) { + if(iq->query_restart_count > ie->max_query_restarts) { verbose(VERB_QUERY, "request has exceeded the maximum number" " of query restarts with %d", iq->query_restart_count); errinf(qstate, "request has exceeded the maximum number " diff --git a/iterator/iterator.h b/iterator/iterator.h index 342ac207e..d3ca716fc 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -139,6 +139,9 @@ struct iter_env { lock_basic_type queries_ratelimit_lock; /** number of queries that have been ratelimited */ size_t num_queries_ratelimited; + + /** max number of query restarts to limit length of CNAME chain */ + size_t max_query_restarts; }; /** From 766244bd81f1d8c808d44ee42a443f43d7a902b8 Mon Sep 17 00:00:00 2001 From: Christian Allred Date: Mon, 5 Apr 2021 18:59:09 -0700 Subject: [PATCH 4/4] Document max-query-restarts option --- doc/unbound.conf.5.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 00c1191be..6fe9f6203 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1613,6 +1613,11 @@ option can be used multiple times. The most specific match will be used. EDNS0 option code for the \fIedns\-client\-string\fR option, from 0 to 65535. A value from the `Reserved for Local/Experimental` range (65001-65534) should be used. Default is 65001. +.TP 5 +.B max\-query\-restarts: \fI +Set the maximum number of times a query is allowed to restart upon encountering +a CNAME record. If a query encounters more than the specified number of CNAME +records before resolving, unbound will reply with SERVFAIL. Default is 8. .SS "Remote Control Options" In the .B remote\-control: