mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-28 02:29:51 -05:00
Harden dnssec stripped zones.
git-svn-id: file:///svn/unbound/trunk@730 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
d2892aa5ab
commit
a06131872d
13 changed files with 932 additions and 736 deletions
|
|
@ -7,6 +7,8 @@
|
|||
- VERB_DETAIL prints out what chdir, username, chroot is being done.
|
||||
- when id numbers run out, caches are cleared, as in design notes.
|
||||
Tested with a mock setup with very few bits in id, it worked.
|
||||
- harden-dnssec-stripped: yes is now default. It insists on dnssec
|
||||
data for trust anchors. Included tests for the feature.
|
||||
|
||||
31 October 2007: Wouter
|
||||
- cache-max-ttl config option.
|
||||
|
|
|
|||
|
|
@ -171,6 +171,12 @@ server:
|
|||
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
||||
# harden-glue: yes
|
||||
|
||||
# Harden against receiving dnssec-stripped data. If you turn it
|
||||
# off, receiving no dnssec dnskey data (at all) for a trustanchor will
|
||||
# trigger insecure mode for that zone (like without a trustanchor).
|
||||
# Default on, which insists on dnssec data for trust-anchored zones.
|
||||
# harden-dnssec-stripped: yes
|
||||
|
||||
# Do not query the following addresses. No DNS queries are sent there.
|
||||
# List one address per entry. List classless netblocks with /size,
|
||||
# do-not-query-address: 127.0.0.1/8
|
||||
|
|
|
|||
|
|
@ -231,6 +231,15 @@ wise to send these, and could be necessary for operation if TSIG or EDNS
|
|||
payload is very large.
|
||||
.It \fBharden-glue:\fR <yes or no>
|
||||
Will trust glue only if it is within the servers authority. Default is on.
|
||||
.It \fBharden-dnssec-stripped:\fR <yes or no>
|
||||
Require DNSSEC data for trust-anchored zones, if such data is absent,
|
||||
the zone becomes bogus. If turned off, and no DNSSEC data is received
|
||||
(no DNSKEY data to be precise), then the zone is made insecure, this behaves
|
||||
like there is no trust anchor. You could turn this off if you are sometimes
|
||||
behind an intrusive firewall (of some sort) that removes DNSSEC data from
|
||||
packets, or a zone changes from signed to unsigned often. If turned off you
|
||||
run the risk of a downgrade attack that disables security for a zone.
|
||||
Default is on.
|
||||
.It \fBdo-not-query-address:\fR <IP address>
|
||||
Do not query the given IP address. Can be IP4 or IP6. Append /num to
|
||||
indicate a classless delegation netblock, for example like
|
||||
|
|
|
|||
11
testdata/val_faildnskey.rpl
vendored
11
testdata/val_faildnskey.rpl
vendored
|
|
@ -3,6 +3,7 @@
|
|||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
# test that default value of harden-dnssec-stripped is still yes.
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
|
|
@ -108,18 +109,10 @@ ENTRY_END
|
|||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
REPLY QR RD RA SERVFAIL
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{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 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
|
|
|||
126
testdata/val_faildnskey_ok.rpl
vendored
Normal file
126
testdata/val_faildnskey_ok.rpl
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
; config options
|
||||
; The island of trust is at example.com
|
||||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
harden-dnssec-stripped: no
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test validator with failed DNSKEY request, but not hardened.
|
||||
|
||||
; 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
|
||||
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
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
;REPLY QR AA NOERROR
|
||||
REPLY QR AA SERVFAIL
|
||||
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
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR 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
|
||||
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 NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{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 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
|
@ -113,6 +113,7 @@ config_create()
|
|||
cfg->harden_short_bufsize = 0;
|
||||
cfg->harden_large_queries = 0;
|
||||
cfg->harden_glue = 1;
|
||||
cfg->harden_dnssec_stripped = 1;
|
||||
cfg->hide_identity = 0;
|
||||
cfg->hide_version = 0;
|
||||
cfg->identity = NULL;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ struct config_file {
|
|||
int harden_large_queries;
|
||||
/** harden against spoofed glue (out of zone data) */
|
||||
int harden_glue;
|
||||
/** harden against receiving no DNSSEC data for trust anchor */
|
||||
int harden_dnssec_stripped;
|
||||
|
||||
/** chrootdir, if not "" or chroot will be done */
|
||||
char* chrootdir;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -134,6 +134,7 @@ target-fetch-policy{COLON} { YDOUT; return VAR_TARGET_FETCH_POLICY;}
|
|||
harden-short-bufsize{COLON} { YDOUT; return VAR_HARDEN_SHORT_BUFSIZE;}
|
||||
harden-large-queries{COLON} { YDOUT; return VAR_HARDEN_LARGE_QUERIES;}
|
||||
harden-glue{COLON} { YDOUT; return VAR_HARDEN_GLUE;}
|
||||
harden-dnssec-stripped{COLON} { YDOUT; return VAR_HARDEN_DNNSEC_STRIPPED;}
|
||||
stub-zone{COLON} { YDOUT; return VAR_STUB_ZONE;}
|
||||
name{COLON} { YDOUT; return VAR_NAME;}
|
||||
stub-addr{COLON} { YDOUT; return VAR_STUB_ADDR;}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -107,7 +107,8 @@
|
|||
VAR_OUTGOING_INTERFACE = 323,
|
||||
VAR_ROOT_HINTS = 324,
|
||||
VAR_DO_NOT_QUERY_LOCALHOST = 325,
|
||||
VAR_CACHE_MAX_TTL = 326
|
||||
VAR_CACHE_MAX_TTL = 326,
|
||||
VAR_HARDEN_DNNSEC_STRIPPED = 327
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -180,6 +181,7 @@
|
|||
#define VAR_ROOT_HINTS 324
|
||||
#define VAR_DO_NOT_QUERY_LOCALHOST 325
|
||||
#define VAR_CACHE_MAX_TTL 326
|
||||
#define VAR_HARDEN_DNNSEC_STRIPPED 327
|
||||
|
||||
|
||||
|
||||
|
|
@ -191,7 +193,7 @@ typedef union YYSTYPE
|
|||
char* str;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 195 "util/configparser.h"
|
||||
#line 197 "util/configparser.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE
|
||||
%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG
|
||||
%token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST
|
||||
%token VAR_CACHE_MAX_TTL
|
||||
%token VAR_CACHE_MAX_TTL VAR_HARDEN_DNNSEC_STRIPPED
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
|
@ -123,7 +123,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_key_cache_size | server_key_cache_slabs |
|
||||
server_trusted_keys_file | server_val_nsec3_keysize_iterations |
|
||||
server_use_syslog | server_outgoing_interface | server_root_hints |
|
||||
server_do_not_query_localhost | server_cache_max_ttl
|
||||
server_do_not_query_localhost | server_cache_max_ttl |
|
||||
server_harden_dnssec_stripped
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
|
|
@ -546,6 +547,16 @@ server_harden_glue: VAR_HARDEN_GLUE STRING
|
|||
free($2);
|
||||
}
|
||||
;
|
||||
server_harden_dnssec_stripped: VAR_HARDEN_DNNSEC_STRIPPED STRING
|
||||
{
|
||||
OUTYY(("P(server_harden_dnssec_stripped:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->harden_dnssec_stripped =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING
|
||||
{
|
||||
OUTYY(("P(server_do_not_query_address:%s)\n", $2));
|
||||
|
|
|
|||
|
|
@ -1665,10 +1665,13 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
|||
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
|
||||
"could not fetch DNSKEY rrset",
|
||||
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
|
||||
kkey = key_entry_create_null(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||
if(qstate->env->cfg->harden_dnssec_stripped)
|
||||
kkey = key_entry_create_bad(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass);
|
||||
else kkey = key_entry_create_null(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||
if(!kkey) {
|
||||
log_err("out of memory: allocate null prime key");
|
||||
log_err("out of memory: allocate fail prime key");
|
||||
return NULL;
|
||||
}
|
||||
key_cache_insert(ve->kcache, kkey);
|
||||
|
|
@ -1709,8 +1712,11 @@ primeResponseToKE(int rcode, struct dns_msg* msg, struct trust_anchor* ta,
|
|||
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
|
||||
/* NOTE: in this case, we should probably reject the trust
|
||||
* anchor for longer, perhaps forever. */
|
||||
kkey = key_entry_create_null(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||
if(qstate->env->cfg->harden_dnssec_stripped)
|
||||
kkey = key_entry_create_bad(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass);
|
||||
else kkey = key_entry_create_null(qstate->region, ta->name,
|
||||
ta->namelen, ta->dclass, NULL_KEY_TTL);
|
||||
if(!kkey) {
|
||||
log_err("out of memory: allocate null prime key");
|
||||
return NULL;
|
||||
|
|
@ -2022,7 +2028,8 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
qstate, id);
|
||||
|
||||
/* If the result of the prime is a null key, skip the FINDKEY state.*/
|
||||
if(!vq->key_entry || key_entry_isnull(vq->key_entry)) {
|
||||
if(!vq->key_entry || key_entry_isnull(vq->key_entry) ||
|
||||
key_entry_isbad(vq->key_entry)) {
|
||||
vq->state = VAL_VALIDATE_STATE;
|
||||
}
|
||||
/* the qstate will be reactivated after inform_super is done */
|
||||
|
|
|
|||
Loading…
Reference in a new issue