From: George Thessalonikefs Date: Tue, 22 Nov 2022 16:44:55 +0000 (+0100) Subject: - Ignore expired error responses. X-Git-Tag: release-1.17.1rc1~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=896f7a8306f7b5bfc05eb2b1f97b406f0deee206;p=thirdparty%2Funbound.git - Ignore expired error responses. --- diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index 6f987fc03..245daa986 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -551,10 +551,16 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf) verbose(VERB_ALGO, "cachedb msg expired"); /* If serve-expired is enabled, we still use an expired message * setting the TTL to 0. */ - if(qstate->env->cfg->serve_expired) - adjust = -1; - else + if(!qstate->env->cfg->serve_expired || + (FLAGS_GET_RCODE(qstate->return_msg->rep->flags) + != LDNS_RCODE_NOERROR && + FLAGS_GET_RCODE(qstate->return_msg->rep->flags) + != LDNS_RCODE_NXDOMAIN && + FLAGS_GET_RCODE(qstate->return_msg->rep->flags) + != LDNS_RCODE_YXDOMAIN)) return 0; /* message expired */ + else + adjust = -1; } verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust); adjust_msg_ttl(qstate->return_msg, adjust); diff --git a/daemon/worker.c b/daemon/worker.c index caefad621..2180b4f96 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -623,6 +623,14 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, if(worker->env.cfg->serve_expired_ttl && rep->serve_expired_ttl < timenow) return 0; + /* Ignore expired failure answers */ + if(FLAGS_GET_RCODE(rep->flags) != + LDNS_RCODE_NOERROR && + FLAGS_GET_RCODE(rep->flags) != + LDNS_RCODE_NXDOMAIN && + FLAGS_GET_RCODE(rep->flags) != + LDNS_RCODE_YXDOMAIN) + return 0; if(!rrset_array_lock(rep->ref, rep->rrset_count, 0)) return 0; *is_expired_answer = 1; @@ -730,8 +738,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, goto bail_out; } } else { - /* We don't check the global ede as this is a warning, not - * an error */ if (*is_expired_answer == 1 && worker->env.cfg->ede_serve_expired && worker->env.cfg->ede) { EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out, diff --git a/doc/Changelog b/doc/Changelog index 66cc6161d..0375b0716 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +22 November 2022: George + - Ignore expired error responses. + 11 November 2022: Wouter - Fix #779: [doc] Missing documention in ub_resolve_event() for callback parameter was_ratelimited. diff --git a/services/cache/dns.c b/services/cache/dns.c index b6e569734..6fc9919ef 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -636,6 +636,14 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, r->serve_expired_ttl < now) { return NULL; } + /* Ignore expired failure answers */ + if(FLAGS_GET_RCODE(r->flags) != + LDNS_RCODE_NOERROR && + FLAGS_GET_RCODE(r->flags) != + LDNS_RCODE_NXDOMAIN && + FLAGS_GET_RCODE(r->flags) != + LDNS_RCODE_YXDOMAIN) + return 0; } else { return NULL; } diff --git a/testdata/fwd_0ttlservfail.rpl b/testdata/fwd_0ttlservfail.rpl index f1a6dc629..ed912c73b 100644 --- a/testdata/fwd_0ttlservfail.rpl +++ b/testdata/fwd_0ttlservfail.rpl @@ -2,6 +2,7 @@ ; config options go here. server: serve-expired: yes + prefetch: yes forward-zone: name: "." forward-addr: 216.0.0.1 CONFIG_END @@ -45,7 +46,7 @@ SECTION ANSWER ENTRY_END ; enough to pass by the TTL of the servfail answer in cache -STEP 50 TIME_PASSES ELAPSE 40 +STEP 50 TIME_PASSES ELAPSE 5 ; this query triggers a prefetch STEP 210 QUERY diff --git a/testdata/serve_expired_cached_servfail.rpl b/testdata/serve_expired_cached_servfail.rpl new file mode 100644 index 000000000..286de708b --- /dev/null +++ b/testdata/serve_expired_cached_servfail.rpl @@ -0,0 +1,130 @@ +; config options +server: + module-config: "validator iterator" + qname-minimisation: "no" + minimal-responses: no + serve-expired: yes + serve-expired-reply-ttl: 123 + log-servfail: yes + ede: yes + ede-serve-expired: yes + + +stub-zone: + name: "example.com" + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test serve-expired with client-timeout and a SERVFAIL upstream reply +; Scenario overview: +; - query for example.com. IN A +; - answer from upstream is SERVFAIL; will be cached for NORR_TTL(5) +; - check that the client gets the SERVFAIL; also cached +; - query again right after the TTL expired +; - cached SERVFAIL should be ignored and upstream queried +; - check that we get the correct answer + +; ns.example.com. +RANGE_BEGIN 0 20 + ADDRESS 1.2.3.4 + ; response to A query + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR AA SERVFAIL + SECTION QUESTION + example.com. IN A + ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 30 100 + ADDRESS 1.2.3.4 + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. 10 IN NS + SECTION ANSWER + example.com. 10 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. 10 IN A 1.2.3.4 + ENTRY_END + + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. IN A + SECTION ANSWER + example.com. 10 IN A 5.6.7.8 + SECTION AUTHORITY + example.com. 10 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. 10 IN A 1.2.3.4 + ENTRY_END +RANGE_END + +; Query with RD flag +STEP 0 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + example.com. IN A +ENTRY_END + +; Check that we get the SERVFAIL (will be cached) +STEP 10 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA SERVFAIL + SECTION QUESTION + example.com. IN A +ENTRY_END + +; Query again +STEP 20 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + example.com. IN A +ENTRY_END + +; Check that we get the cached SERVFAIL +STEP 30 CHECK_ANSWER +ENTRY_BEGIN + MATCH all + REPLY QR RD RA SERVFAIL + SECTION QUESTION + example.com. IN A +ENTRY_END + +; Wait for the SERVFAIL to expire +STEP 31 TIME_PASSES ELAPSE 6 + +; Query again +STEP 40 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + example.com. IN A +ENTRY_END + +; Check that we got the correct answer +STEP 50 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl + REPLY QR RD RA NOERROR + SECTION QUESTION + example.com. IN A + SECTION ANSWER + example.com. 10 IN A 5.6.7.8 + SECTION AUTHORITY + example.com. 10 IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/testdata/serve_expired_servfail.rpl b/testdata/serve_expired_client_timeout_servfail.rpl similarity index 86% rename from testdata/serve_expired_servfail.rpl rename to testdata/serve_expired_client_timeout_servfail.rpl index 6e3192ef0..1cae3fd82 100644 --- a/testdata/serve_expired_servfail.rpl +++ b/testdata/serve_expired_client_timeout_servfail.rpl @@ -4,7 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes - serve-expired-client-timeout: 1800 + serve-expired-client-timeout: 1 serve-expired-reply-ttl: 123 log-servfail: yes ede: yes @@ -32,11 +32,11 @@ RANGE_BEGIN 0 20 ADJUST copy_id REPLY QR NOERROR SECTION QUESTION - example.com. IN NS + example.com. 10 IN NS SECTION ANSWER - example.com. IN NS ns.example.com. + example.com. 10 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ns.example.com. 10 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -48,14 +48,14 @@ RANGE_BEGIN 0 20 SECTION ANSWER example.com. 10 IN A 5.6.7.8 SECTION AUTHORITY - example.com. IN NS ns.example.com. + example.com. 10 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ns.example.com. 10 IN A 1.2.3.4 ENTRY_END RANGE_END ; ns.example.com. -RANGE_BEGIN 30 100 +RANGE_BEGIN 30 70 ADDRESS 1.2.3.4 ; response to A query ENTRY_BEGIN @@ -85,13 +85,13 @@ ENTRY_BEGIN SECTION ANSWER example.com. 10 IN A 5.6.7.8 SECTION AUTHORITY - example.com. IN NS ns.example.com. + example.com. 10 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ns.example.com. 10 IN A 1.2.3.4 ENTRY_END ; Wait for the TTL to expire -STEP 11 TIME_PASSES ELAPSE 3601 +STEP 11 TIME_PASSES ELAPSE 11 ; Query again STEP 30 QUERY diff --git a/testdata/subnet_cached_servfail.crpl b/testdata/subnet_cached_servfail.crpl new file mode 100644 index 000000000..9c746d579 --- /dev/null +++ b/testdata/subnet_cached_servfail.crpl @@ -0,0 +1,167 @@ +; Check if an expired SERVFAIL answer stored in the global cache does not block +; ECS queries to reach the ECS cache. + +server: + trust-anchor-signaling: no + target-fetch-policy: "0 0 0 0 0" + send-client-subnet: 1.2.3.4 + max-client-subnet-ipv4: 21 + module-config: "subnetcache iterator" + verbosity: 3 + access-control: 127.0.0.1 allow_snoop + qname-minimisation: no + minimal-responses: no + serve-expired: yes + prefetch: yes + +stub-zone: + name: "example.com." + stub-addr: 1.2.3.4 +CONFIG_END + +SCENARIO_BEGIN Test that expired SERVFAIL in global cache does not block clients to reach the ECS cache + +; ns.example.com. +RANGE_BEGIN 0 10 + ADDRESS 1.2.3.4 + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. IN NS + SECTION ANSWER + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 1.2.3.4 + ENTRY_END + + ; response to query of interest + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR SERVFAIL + SECTION QUESTION + www.example.com. IN A + ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 11 100 + ADDRESS 1.2.3.4 + ENTRY_BEGIN + MATCH opcode qtype qname + ADJUST copy_id + REPLY QR NOERROR + SECTION QUESTION + example.com. IN NS + SECTION ANSWER + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 1.2.3.4 + ENTRY_END + + ; response to query of interest + ENTRY_BEGIN + MATCH opcode qtype qname ednsdata + ADJUST copy_id copy_ednsdata_assume_clientsubnet + REPLY QR NOERROR + SECTION QUESTION + www.example.com. IN A + SECTION ANSWER + www.example.com. 10 IN A 10.20.30.40 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + HEX_EDNSDATA_BEGIN + ; client is 127.0.0.1 + 00 08 ; OPC + 00 05 ; option length + 00 01 ; Family + 08 00 ; source mask, scopemask + 7f ; address + HEX_EDNSDATA_END + ns.example.com. IN A 1.2.3.4 + ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; This answer should be in the global cache +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; Bring the cached SERVFAIL to prefetch time +STEP 10 TIME_PASSES ELAPSE 5 + +STEP 11 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 05 ; OPC, optlen + 00 01 08 00 ; ip4, source 8, scope 0 + 7f ; 127.0.0.0/8 +HEX_EDNSDATA_END +ENTRY_END + +; This answer was cached but a prefetch was triggerred +STEP 12 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; Wait for the SERVFAIL to expire +STEP 13 TIME_PASSES ELAPSE 2 + +; Query again to verify that the record was prefetched and stored in the ECS +; cache (because the server replied with ECS this time) +STEP 14 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 05 ; OPC, optlen + 00 01 08 00 ; ip4, source 8, scope 0 + 7f ; 127.0.0.0/8 +HEX_EDNSDATA_END +ENTRY_END + +; This record came from the ECS cache +STEP 15 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 8 IN A 10.20.30.40 +SECTION AUTHORITY +example.com. 3598 IN NS ns.example.com. +SECTION ADDITIONAL +HEX_EDNSDATA_BEGIN + 00 08 00 05 ; OPC, optlen + 00 01 08 08 ; ip4, source 8, scope 0 + 7f ; 127.0.0.0/8 +HEX_EDNSDATA_END +ns.example.com. 3598 IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END