]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Make VAL_MAX_RESTART_COUNT configurable. 486/head
authorFlorian Obser <florian@narrans.de>
Sat, 8 May 2021 14:56:32 +0000 (16:56 +0200)
committerFlorian Obser <florian@narrans.de>
Sat, 8 May 2021 14:56:32 +0000 (16:56 +0200)
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.

doc/unbound.conf.5.in
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y
validator/validator.c
validator/validator.h

index 9aa12c65c80391afb72fd35d56efa4800231c7ad..16de279412d3b8bf137461853e6c34f88996fe73 100644 (file)
@@ -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<number>
+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<number>
 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
index 1d63741566600407e4c052322cab5e9f4b51650e..d1bfa61c52ee537cb4033ace40af5b5ca3742011 100644 (file)
@@ -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)
index 524e648fe4c398f53124886b64bab143ef74955e..67abe55a8c800fee21b69f4d28ec112bdb9a83f5 100644 (file)
@@ -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 */
index e982463d101c06561d02692b8f1ac6be503bc64c..732dd83102c48c6c93a5de7e2568fea0b8798cf4 100644 (file)
@@ -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) }
index 6a8f831129d725b6aef44390cc1847f20b3d83b4..86febcf1da2afbd6fbc21f704bf3685895208356 100644 (file)
@@ -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));
index e12180b4bbdae472e7fd79b6c81dac4924562f47..d4d48d956895550d70108ca8bab2da87972d56e7 100644 (file)
@@ -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;
index 35da1920aa394459fbbcfe6ad91b16580db238af..a928e10a65d8104aceeca4bbd57bb25717baf7a3 100644 (file)
@@ -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. */