From: Florian Obser Date: Sat, 8 May 2021 14:56:32 +0000 (+0200) Subject: Make VAL_MAX_RESTART_COUNT configurable. X-Git-Tag: release-1.13.2rc1~152^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4314cad33142d6004a8cfdf3d20fdea60af655c;p=thirdparty%2Funbound.git Make VAL_MAX_RESTART_COUNT configurable. unbound tries very hard (up to 6 authoritative servers) to find a validating answer. This is not always desirable, for example on high latency links. --- diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 9aa12c65c..16de27941 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1131,6 +1131,10 @@ min and max very low disables the clock skew allowances. Setting both min and max very high makes the validator check the signature timestamps less strictly. .TP +.B val\-max\-restart: \fI +The maximum number the validator should restart validation with +another authority in case of failed validation. Default is 5. +.TP .B val\-bogus\-ttl: \fI The time to live for bogus data. This is data that has failed validation; due to invalid signatures or other checks. The TTL from that data cannot be diff --git a/util/config_file.c b/util/config_file.c index 1d6374156..d1bfa61c5 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -253,6 +253,7 @@ config_create(void) cfg->val_date_override = 0; cfg->val_sig_skew_min = 3600; /* at least daylight savings trouble */ cfg->val_sig_skew_max = 86400; /* at most timezone settings trouble */ + cfg->val_max_restart = 5; cfg->val_clean_additional = 1; cfg->val_log_level = 0; cfg->val_log_squelch = 0; @@ -764,12 +765,14 @@ int config_set_option(struct config_file* cfg, const char* opt, #endif else if(strcmp(opt, "define-tag:") ==0) { return config_add_tag(cfg, val); - /* val_sig_skew_min and max are copied into val_env during init, - * so this does not update val_env with set_option */ + /* val_sig_skew_min, max and val_max_restart are copied into val_env + * during init so this does not update val_env with set_option */ } else if(strcmp(opt, "val-sig-skew-min:") == 0) { IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); } else if(strcmp(opt, "val-sig-skew-max:") == 0) { IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); } + else if(strcmp(opt, "val-max-restart:") == 0) + { IS_NUMBER_OR_ZERO; cfg->val_max_restart = (int32_t)atoi(val); } else if (strcmp(opt, "outgoing-interface:") == 0) { char* d = strdup(val); char** oi = @@ -1190,6 +1193,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_DEC(opt, "fast-server-permil", fast_server_permil) else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min) else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max) + else O_DEC(opt, "val-max-restart", val_max_restart) else O_YNO(opt, "qname-minimisation", qname_minimisation) else O_YNO(opt, "qname-minimisation-strict", qname_minimisation_strict) else O_IFC(opt, "define-tag", num_tags, tagname) diff --git a/util/config_file.h b/util/config_file.h index 524e648fe..67abe55a8 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -373,6 +373,8 @@ struct config_file { int32_t val_sig_skew_min; /** the maximum for signature clock skew */ int32_t val_sig_skew_max; + /** max number of query restarts, number of IPs to probe */ + int32_t val_max_restart; /** this value sets the number of seconds before revalidating bogus */ int bogus_ttl; /** should validator clean additional section for secure msgs */ diff --git a/util/configlexer.lex b/util/configlexer.lex index e982463d1..732dd8310 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -385,6 +385,7 @@ root-key-sentinel{COLON} { YDVAR(1, VAR_ROOT_KEY_SENTINEL) } val-override-date{COLON} { YDVAR(1, VAR_VAL_OVERRIDE_DATE) } val-sig-skew-min{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) } val-sig-skew-max{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) } +val-max-restart{COLON} { YDVAR(1, VAR_VAL_MAX_RESTART) } val-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) } val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } diff --git a/util/configparser.y b/util/configparser.y index 6a8f83112..86febcf1d 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -104,13 +104,14 @@ extern struct config_parser_state* cfg_parser; %token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT %token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD VAR_LOG_TIME_ASCII %token VAR_DOMAIN_INSECURE VAR_PYTHON VAR_PYTHON_SCRIPT VAR_VAL_SIG_SKEW_MIN -%token VAR_VAL_SIG_SKEW_MAX VAR_CACHE_MIN_TTL VAR_VAL_LOG_LEVEL -%token VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING VAR_ADD_HOLDDOWN -%token VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE VAR_PREFETCH -%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT VAR_HARDEN_BELOW_NXDOMAIN -%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES VAR_LOG_LOCAL_ACTIONS -%token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM VAR_TCP_AUTH_QUERY_TIMEOUT -%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST +%token VAR_VAL_SIG_SKEW_MAX VAR_VAL_MAX_RESTART VAR_CACHE_MIN_TTL +%token VAR_VAL_LOG_LEVEL VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING +%token VAR_ADD_HOLDDOWN VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE +%token VAR_PREFETCH VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT +%token VAR_HARDEN_BELOW_NXDOMAIN VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES +%token VAR_LOG_REPLIES VAR_LOG_LOCAL_ACTIONS VAR_TCP_UPSTREAM +%token VAR_SSL_UPSTREAM VAR_TCP_AUTH_QUERY_TIMEOUT VAR_SSL_SERVICE_KEY +%token VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST %token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE %token VAR_HTTPS_PORT VAR_HTTP_ENDPOINT VAR_HTTP_MAX_STREAMS %token VAR_HTTP_QUERY_BUFFER_SIZE VAR_HTTP_RESPONSE_BUFFER_SIZE @@ -243,8 +244,9 @@ content_server: server_num_threads | server_verbosity | server_port | server_local_data_ptr | server_jostle_timeout | server_unwanted_reply_threshold | server_log_time_ascii | server_domain_insecure | server_val_sig_skew_min | - server_val_sig_skew_max | server_cache_min_ttl | server_val_log_level | - server_auto_trust_anchor_file | server_add_holddown | + server_val_sig_skew_max | server_val_max_restart | + server_cache_min_ttl | server_val_log_level | + server_auto_trust_anchor_file | server_add_holddown | server_del_holddown | server_keep_missing | server_so_rcvbuf | server_edns_buffer_size | server_prefetch | server_prefetch_key | server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag | @@ -1852,6 +1854,19 @@ server_val_sig_skew_max: VAR_VAL_SIG_SKEW_MAX STRING_ARG free($2); } ; +server_val_max_restart: VAR_VAL_MAX_RESTART STRING_ARG + { + OUTYY(("P(server_val_max_restart:%s)\n", $2)); + if(*$2 == '\0' || strcmp($2, "0") == 0) { + cfg_parser->cfg->val_max_restart = 0; + } else { + cfg_parser->cfg->val_max_restart = atoi($2); + if(!cfg_parser->cfg->val_max_restart) + yyerror("number expected"); + } + free($2); + } + ; server_cache_max_ttl: VAR_CACHE_MAX_TTL STRING_ARG { OUTYY(("P(server_cache_max_ttl:%s)\n", $2)); diff --git a/validator/validator.c b/validator/validator.c index e12180b4b..d4d48d956 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -137,6 +137,7 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env, val_env->date_override = cfg->val_date_override; val_env->skew_min = cfg->val_sig_skew_min; val_env->skew_max = cfg->val_sig_skew_max; + val_env->max_restart = cfg->val_max_restart; c = cfg_count_numbers(cfg->val_nsec3_key_iterations); if(c < 1 || (c&1)) { log_err("validator: unparseable or odd nsec3 key " @@ -1487,7 +1488,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq, enum val_classification subtype = val_classify_response( qstate->query_flags, &qstate->qinfo, &vq->qchase, vq->orig_msg->rep, vq->rrset_skip); - if(vq->restart_count > VAL_MAX_RESTART_COUNT) { + if(vq->restart_count > ve->max_restart) { verbose(VERB_ALGO, "restart count exceeded"); return val_error(qstate, id); } @@ -1640,7 +1641,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq, errinf(qstate, key_entry_get_reason(vq->key_entry)); } /* no retries, stop bothering the authority until timeout */ - vq->restart_count = VAL_MAX_RESTART_COUNT; + vq->restart_count = ve->max_restart; vq->chase_reply->security = sec_status_bogus; vq->state = VAL_FINISHED_STATE; return 1; @@ -1848,7 +1849,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq, LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class); vq->chase_reply->security = sec_status_bogus; errinf(qstate, "while building chain of trust"); - if(vq->restart_count >= VAL_MAX_RESTART_COUNT) + if(vq->restart_count >= ve->max_restart) key_cache_insert(ve->kcache, vq->key_entry, qstate); return 1; } @@ -2064,7 +2065,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, * endless bogus revalidation */ if(vq->orig_msg->rep->security == sec_status_bogus) { /* see if we can try again to fetch data */ - if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + if(vq->restart_count < ve->max_restart) { int restart_count = vq->restart_count+1; verbose(VERB_ALGO, "validation failed, " "blacklist and retry to fetch data"); @@ -2605,6 +2606,7 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, int id, int rcode, struct dns_msg* msg, struct query_info* qinfo, struct sock_list* origin) { + struct val_env* ve = (struct val_env*)qstate->env->modinfo[id]; struct key_entry_key* dske = NULL; uint8_t* olds = vq->empty_DS_name; vq->empty_DS_name = NULL; @@ -2638,7 +2640,7 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq, vq->chain_blacklist = NULL; /* fresh blacklist for next part*/ /* Keep the forState.state on FINDKEY. */ } else if(key_entry_isbad(dske) - && vq->restart_count < VAL_MAX_RESTART_COUNT) { + && vq->restart_count < ve->max_restart) { vq->empty_DS_name = olds; val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); qstate->errinf = NULL; @@ -2691,7 +2693,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, /* bad response */ verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to " "DNSKEY query."); - if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + if(vq->restart_count < ve->max_restart) { val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); qstate->errinf = NULL; @@ -2730,7 +2732,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq, * state. */ if(!key_entry_isgood(vq->key_entry)) { if(key_entry_isbad(vq->key_entry)) { - if(vq->restart_count < VAL_MAX_RESTART_COUNT) { + if(vq->restart_count < ve->max_restart) { val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); qstate->errinf = NULL; @@ -2807,7 +2809,7 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq, lock_basic_unlock(&ta->lock); if(vq->key_entry) { if(key_entry_isbad(vq->key_entry) - && vq->restart_count < VAL_MAX_RESTART_COUNT) { + && vq->restart_count < ve->max_restart) { val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1); qstate->errinf = NULL; diff --git a/validator/validator.h b/validator/validator.h index 35da1920a..a928e10a6 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -64,9 +64,6 @@ struct config_strlist; */ #define BOGUS_KEY_TTL 60 /* seconds */ -/** max number of query restarts, number of IPs to probe */ -#define VAL_MAX_RESTART_COUNT 5 - /** Root key sentinel is ta preamble */ #define SENTINEL_IS "root-key-sentinel-is-ta-" /** Root key sentinel is not ta preamble */ @@ -95,6 +92,9 @@ struct val_env { /** clock skew max for signatures */ int32_t skew_max; + /** max number of query restarts, number of IPs to probe */ + int32_t max_restart; + /** TTL for bogus data; used instead of untrusted TTL from data. * Bogus data will not be verified more often than this interval. * seconds. */