Harden dnssec stripped zones.

git-svn-id: file:///svn/unbound/trunk@730 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-11-01 15:32:27 +00:00
parent d2892aa5ab
commit a06131872d
13 changed files with 932 additions and 736 deletions

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -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 */