From d1977c679b75336386aade3a9ac9cf136aead99f Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 13 Sep 2023 13:11:53 +0200 Subject: [PATCH 1/9] - disable-edns-do, doc and add option disable-edns-do: no. --- doc/example.conf.in | 5 +++++ doc/unbound.conf.5.in | 7 +++++++ util/config_file.c | 3 +++ util/config_file.h | 2 ++ util/configlexer.lex | 1 + util/configparser.y | 13 +++++++++++-- 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/example.conf.in b/doc/example.conf.in index 0980212e1..44a19fc72 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -683,6 +683,11 @@ server: # that set CD but cannot validate themselves. # ignore-cd-flag: no + # Disable the DO flag in outgoing requests. It is helpful for upstream + # devices that cannot handle DNSSEC information. But do not enable it + # otherwise, because it would stop DNSSEC validation. + # disable-edns-do: no + # Serve expired responses from cache, with serve-expired-reply-ttl in # the response, and then attempt to fetch the data afresh. # serve-expired: no diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 84b903f49..bbc6ddae5 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1302,6 +1302,13 @@ servers that set the CD flag but cannot validate DNSSEC themselves are the clients, and then Unbound provides them with DNSSEC protection. The default value is "no". .TP +.B disable\-edns\-do: \fI +Disable the EDNS DO flag in upstream requests. This can be helpful for +devices that cannot handle DNSSEC information. But it should not be enabled +otherwise, because that would stop DNSSEC validation. The DNSSEC validation +would not work for Unbound itself, and also not for downstream users. +Default is no. +.TP .B serve\-expired: \fI If enabled, Unbound attempts to serve old responses from cache with a TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the diff --git a/util/config_file.c b/util/config_file.c index 454096342..8f7de905e 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -271,6 +271,7 @@ config_create(void) cfg->val_permissive_mode = 0; cfg->aggressive_nsec = 1; cfg->ignore_cd = 0; + cfg->disable_edns_do = 0; cfg->serve_expired = 0; cfg->serve_expired_ttl = 0; cfg->serve_expired_ttl_reset = 0; @@ -690,6 +691,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_YNO("val-permissive-mode:", val_permissive_mode) else S_YNO("aggressive-nsec:", aggressive_nsec) else S_YNO("ignore-cd-flag:", ignore_cd) + else S_YNO("disable-edns-do:", disable_edns_do) else if(strcmp(opt, "serve-expired:") == 0) { IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0); SERVE_EXPIRED = cfg->serve_expired; } @@ -1149,6 +1151,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_YNO(opt, "val-permissive-mode", val_permissive_mode) else O_YNO(opt, "aggressive-nsec", aggressive_nsec) else O_YNO(opt, "ignore-cd-flag", ignore_cd) + else O_YNO(opt, "disable-edns-do", disable_edns_do) else O_YNO(opt, "serve-expired", serve_expired) else O_DEC(opt, "serve-expired-ttl", serve_expired_ttl) else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset) diff --git a/util/config_file.h b/util/config_file.h index 452f3c6a7..d71d7ace5 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -409,6 +409,8 @@ struct config_file { int aggressive_nsec; /** ignore the CD flag in incoming queries and refuse them bogus data */ int ignore_cd; + /** disable EDNS DO flag in outgoing requests */ + int disable_edns_do; /** serve expired entries and prefetch them */ int serve_expired; /** serve expired entries until TTL after expiration */ diff --git a/util/configlexer.lex b/util/configlexer.lex index 3fcdfa62e..2b3141a42 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -403,6 +403,7 @@ val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } aggressive-nsec{COLON} { YDVAR(1, VAR_AGGRESSIVE_NSEC) } ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) } +disable-edns-do{COLON} { YDVAR(1, VAR_DISABLE_EDNS_DO) } serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) } serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) } serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) } diff --git a/util/configparser.y b/util/configparser.y index d8f25a67e..cbea62b58 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -198,7 +198,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG %token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA %token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO -%token VAR_HARDEN_UNKNOWN_ADDITIONAL +%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -332,7 +332,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_tcp_reuse_timeout | server_tcp_auth_query_timeout | server_interface_automatic_ports | server_ede | server_proxy_protocol_port | server_statistics_inhibit_zero | - server_harden_unknown_additional + server_harden_unknown_additional | server_disable_edns_do ; stubstart: VAR_STUB_ZONE { @@ -2060,6 +2060,15 @@ server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG free($2); } ; +server_disable_edns_do: VAR_DISABLE_EDNS_DO STRING_ARG + { + OUTYY(("P(server_disable_edns_do:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->disable_edns_do = (strcmp($2, "yes")==0); + free($2); + } + ; server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG { OUTYY(("P(server_serve_expired:%s)\n", $2)); From 9aaafddf04ddec500230a18e471376bc4f401c1a Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 20 Sep 2023 13:28:06 +0200 Subject: [PATCH 2/9] - disable-edns-do, the option turns of the EDNS DO flag when a message is sent from the iterator. --- iterator/iterator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/iterator/iterator.c b/iterator/iterator.c index 9f78aa17d..edb954cb5 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -2875,7 +2875,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* unset CD if to forwarder(RD set) and not dnssec retry * (blacklist nonempty) and no trust-anchors are configured * above the qname or on the first attempt when dnssec is on */ - EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& + (qstate->env->cfg->disable_edns_do?0:EDNS_DO)| + ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env, &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( From 4e5b0b7eec224c0fd369dfd760d07361874f238c Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Fri, 22 Sep 2023 11:39:39 +0200 Subject: [PATCH 3/9] - disable-edns-do, unit test checks lookup without EDNS DO flag. --- testcode/fake_event.c | 2 +- testdata/disable_edns_do.rpl | 164 +++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 testdata/disable_edns_do.rpl diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 2140b212a..13970c377 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1249,7 +1249,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits = 0; - if(dnssec) + if((dnssec & EDNS_DO)) edns.bits = EDNS_DO; edns.padding_block_size = 0; edns.cookie_present = 0; diff --git a/testdata/disable_edns_do.rpl b/testdata/disable_edns_do.rpl new file mode 100644 index 000000000..86b0c32a9 --- /dev/null +++ b/testdata/disable_edns_do.rpl @@ -0,0 +1,164 @@ +; config options +; The island of trust is at example.com +server: + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: "no" + trust-anchor-signaling: no + minimal-responses: no + disable-edns-do: yes + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test lookup with disable-edns-do + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 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. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest, when sent with EDNS DO +ENTRY_BEGIN +MATCH opcode qtype qname DO +ADJUST copy_id +REPLY QR AA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END + +; response to query of interest, when sent without DO +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD DO +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA DO NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END From 39df4f09234448219c10870180376a0f88ae0e69 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 4 Oct 2023 13:54:05 +0200 Subject: [PATCH 4/9] - disable-edns-do, queriers receive no EDNS in response if the disable-edns-do option is enabled and they set the DO flag. And unit test for that. --- daemon/worker.c | 6 ++++++ doc/unbound.conf.5.in | 2 ++ services/mesh.c | 4 ++++ testdata/disable_edns_do.rpl | 2 +- util/data/msgencode.c | 4 +++- 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/daemon/worker.c b/daemon/worker.c index 2433f97dd..8ae05eb67 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -543,6 +543,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep, (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad, worker->env.now_tv)) @@ -703,6 +705,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) @@ -743,6 +747,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) && !partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep, diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index bbc6ddae5..b56fe20bb 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1307,6 +1307,8 @@ Disable the EDNS DO flag in upstream requests. This can be helpful for devices that cannot handle DNSSEC information. But it should not be enabled otherwise, because that would stop DNSSEC validation. The DNSSEC validation would not work for Unbound itself, and also not for downstream users. +When the option is enabled, queriers that set the DO flag receive no EDNS +record in the response to indicate the lack of support to them. Default is no. .TP .B serve\-expired: \fI diff --git a/services/mesh.c b/services/mesh.c index be968e422..509bee36a 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -1197,6 +1197,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) + r->edns.edns_present = 0; if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) || @@ -1372,6 +1374,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) + r->edns.edns_present = 0; m->s.qinfo.qname = r->qname; m->s.qinfo.local_alias = r->local_alias; diff --git a/testdata/disable_edns_do.rpl b/testdata/disable_edns_do.rpl index 86b0c32a9..82a16da06 100644 --- a/testdata/disable_edns_do.rpl +++ b/testdata/disable_edns_do.rpl @@ -150,7 +150,7 @@ ENTRY_END STEP 10 CHECK_ANSWER ENTRY_BEGIN MATCH all -REPLY QR RD RA DO NOERROR +REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER diff --git a/util/data/msgencode.c b/util/data/msgencode.c index a170eb7b8..80ae33a38 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c @@ -1012,8 +1012,10 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, ede_size = calc_ede_option_size(edns, &ede_txt_size); if(sldns_buffer_capacity(pkt) < udpsize) udpsize = sldns_buffer_capacity(pkt); + if(!edns || !edns->edns_present) { + attach_edns = 0; /* EDEs are optional, try to fit anything else before them */ - if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { + } else if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { /* packet too small to contain edns, omit it. */ attach_edns = 0; } else { From 2e7714e80cdbf8491cc325ba2901abd7a4700d68 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 4 Oct 2023 15:28:52 +0200 Subject: [PATCH 5/9] - disable-edns-do, unbound-checkconf warns about disable-edns-do and DNSSEC validation that is enabled, and suggests to turn one off. --- smallapp/unbound-checkconf.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index ff8043711..8b45578fa 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -707,6 +707,23 @@ morechecks(struct config_file* cfg) cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg); check_chroot_filelist_wild("trusted-keys-file", cfg->trusted_keys_file_list, cfg->chrootdir, cfg); + if(cfg->disable_edns_do && strstr(cfg->module_conf, "validator") + && (cfg->trust_anchor_file_list + || cfg->trust_anchor_list + || cfg->auto_trust_anchor_file_list + || cfg->trusted_keys_file_list)) { + char* key = NULL; + if(cfg->auto_trust_anchor_file_list) + key = cfg->auto_trust_anchor_file_list->str; + if(!key && cfg->trust_anchor_file_list) + key = cfg->trust_anchor_file_list->str; + if(!key && cfg->trust_anchor_list) + key = cfg->trust_anchor_list->str; + if(!key && cfg->trusted_keys_file_list) + key = cfg->trusted_keys_file_list->str; + if(!key) key = ""; + fatal_exit("disable-edns-do does not allow DNSSEC to work, but the validator module uses a trust anchor %s, turn off disable-edns-do or disable validation", key); + } #ifdef USE_IPSECMOD if(cfg->ipsecmod_enabled && strstr(cfg->module_conf, "ipsecmod")) { /* only check hook if enabled */ From b624ed505064098a1002b23578f4862d1542f2ce Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 5 Oct 2023 14:33:22 +0200 Subject: [PATCH 6/9] - disable-edns-do, validator init prints warning when disable-edns-do is turned on, but there are trust anchors, and then turns off disable-edns-do. --- validator/val_anchor.c | 21 +++++++++++++++++++++ validator/val_anchor.h | 8 ++++++++ validator/validator.c | 11 +++++++++++ 3 files changed, 40 insertions(+) diff --git a/validator/val_anchor.c b/validator/val_anchor.c index b1a54e1f0..8466a8923 100644 --- a/validator/val_anchor.c +++ b/validator/val_anchor.c @@ -1322,3 +1322,24 @@ anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, free(taglist); return 0; } + +struct trust_anchor* +anchors_find_any_noninsecure(struct val_anchors* anchors) +{ + struct trust_anchor* ta, *next; + lock_basic_lock(&anchors->lock); + ta=(struct trust_anchor*)rbtree_first(anchors->tree); + while((rbnode_type*)ta != RBTREE_NULL) { + next = (struct trust_anchor*)rbtree_next(&ta->node); + lock_basic_lock(&ta->lock); + if(ta->numDS != 0 || ta->numDNSKEY != 0) { + /* not an insecurepoint */ + lock_basic_unlock(&anchors->lock); + return ta; + } + lock_basic_unlock(&ta->lock); + ta = next; + } + lock_basic_unlock(&anchors->lock); + return NULL; +} diff --git a/validator/val_anchor.h b/validator/val_anchor.h index 1597a7d62..02e7e17b5 100644 --- a/validator/val_anchor.h +++ b/validator/val_anchor.h @@ -240,4 +240,12 @@ size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num); int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, size_t namelen, uint16_t dclass, uint16_t keytag); +/** + * Find an anchor that is not an insecure point, if any, or there are no + * DNSSEC verification anchors if none. + * @param anchors: anchor storage + * @return trust anchor or NULL. It is locked. + */ +struct trust_anchor* anchors_find_any_noninsecure(struct val_anchors* anchors); + #endif /* VALIDATOR_VAL_ANCHOR_H */ diff --git a/validator/validator.c b/validator/validator.c index 9de9d54db..e83948492 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -200,6 +200,17 @@ val_init(struct module_env* env, int id) log_err("validator: could not apply configuration settings."); return 0; } + if(env->cfg->disable_edns_do) { + struct trust_anchor* anchor = anchors_find_any_noninsecure( + env->anchors); + if(anchor) { + char b[257]; + dname_str(anchor->name, b); + log_warn("validator: disable-edns-do is enabled, but there is a trust anchor for '%s'. Since DNSSEC could not work, the disable-edns-do setting is turned off. Continuing without it.", b); + lock_basic_unlock(&anchor->lock); + env->cfg->disable_edns_do = 0; + } + } return 1; } From c8ae3de61009f5b4ebbd894e9b5d5942a895c477 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Fri, 6 Oct 2023 16:39:33 +0200 Subject: [PATCH 7/9] Update validator/validator.c Co-authored-by: Yorgos Thessalonikefs --- validator/validator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator/validator.c b/validator/validator.c index e83948492..6cd15cfc1 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -204,7 +204,7 @@ val_init(struct module_env* env, int id) struct trust_anchor* anchor = anchors_find_any_noninsecure( env->anchors); if(anchor) { - char b[257]; + char b[LDNS_MAX_DOMAINLEN+2]; dname_str(anchor->name, b); log_warn("validator: disable-edns-do is enabled, but there is a trust anchor for '%s'. Since DNSSEC could not work, the disable-edns-do setting is turned off. Continuing without it.", b); lock_basic_unlock(&anchor->lock); From b05154218cdbe59f36e81f5a510a9d0547b5fb05 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Fri, 6 Oct 2023 16:40:34 +0200 Subject: [PATCH 8/9] Update doc/unbound.conf.5.in Co-authored-by: Yorgos Thessalonikefs --- doc/unbound.conf.5.in | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index b56fe20bb..e709725b1 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1303,12 +1303,17 @@ the clients, and then Unbound provides them with DNSSEC protection. The default value is "no". .TP .B disable\-edns\-do: \fI -Disable the EDNS DO flag in upstream requests. This can be helpful for -devices that cannot handle DNSSEC information. But it should not be enabled -otherwise, because that would stop DNSSEC validation. The DNSSEC validation -would not work for Unbound itself, and also not for downstream users. -When the option is enabled, queriers that set the DO flag receive no EDNS +Disable the EDNS DO flag in upstream requests. +It breaks DNSSEC validation for Unbound's clients. +This results in the upstream name servers to not include DNSSEC records in +their replies and could be helpful for devices that cannot handle DNSSEC +information. +When the option is enabled, clients that set the DO flag receive no EDNS record in the response to indicate the lack of support to them. +If this option is enabled but Unbound is already configured for DNSSEC +validation (i.e., the validator module is enabled; default) this option is +implicitly turned off with a warning as to not break DNSSEC validation in +Unbound. Default is no. .TP .B serve\-expired: \fI From 908e1cb11a8e0362eb32d2de4aebdc42fa46593a Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Thu, 12 Oct 2023 14:05:31 +0200 Subject: [PATCH 9/9] Changelog note for #944. - Merge #944: Disable EDNS DO. Disable the EDNS DO flag in upstream requests. This can be helpful for devices that cannot handle DNSSEC information. But it should not be enabled otherwise, because that would stop DNSSEC validation. The DNSSEC validation would not work for Unbound itself, and also not for downstream users. Default is no. The option is disable-edns-do: no --- doc/Changelog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/Changelog b/doc/Changelog index 07bf0c703..14fe19acd 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,12 @@ +12 October 2023: Wouter + - Merge #944: Disable EDNS DO. + Disable the EDNS DO flag in upstream requests. This can be helpful + for devices that cannot handle DNSSEC information. But it should not + be enabled otherwise, because that would stop DNSSEC validation. The + DNSSEC validation would not work for Unbound itself, and also not + for downstream users. Default is no. The option + is disable-edns-do: no + 11 October 2023: George - Fix #850: [FR] Ability to use specific database in Redis, with new redis-logical-db configuration option.