mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-27 08:59:19 -05:00
unwanted reply threshold like in the draft.
git-svn-id: file:///svn/unbound/trunk@1321 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
60d8b26ba1
commit
6cebdd2baf
16 changed files with 1362 additions and 1240 deletions
|
|
@ -1042,7 +1042,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
|||
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
worker->daemon->env->infra_cache, worker->rndstate,
|
||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports);
|
||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
|
||||
cfg->unwanted_threshold, &worker_alloc_cleanup, worker);
|
||||
if(!worker->back) {
|
||||
log_err("could not create outgoing sockets");
|
||||
worker_delete(worker);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
- new stub-prime: yesno option. Default is off, so it does not prime.
|
||||
can be turned on to get same behaviour as previous unbound release.
|
||||
- made automated test that checks if builtin root hints are uptodate.
|
||||
- finished draft-wijngaards-dnsext-resolver-side-mitigation
|
||||
implementation. The unwanted-reply-threshold can be set.
|
||||
- fixup so fptr_whitelist test in alloc.c works.
|
||||
|
||||
21 October 2008: Wouter
|
||||
- fix update-anchors.sh, so it does not report different RR order
|
||||
|
|
|
|||
|
|
@ -261,6 +261,13 @@ server:
|
|||
# Allow the domain (and its subdomains) to contain private addresses.
|
||||
# local-data statements are allowed to contain private addresses too.
|
||||
# private-domain: "example.com"
|
||||
|
||||
# If nonzero, unwanted replies are not only reported in statistics,
|
||||
# but also a running total is kept per thread. If it reaches the
|
||||
# threshold, a warning is printed and a defensive action is taken,
|
||||
# the cache is cleared to flush potential poison out of it.
|
||||
# A suggested value is 10000000, the default is 0 (turned off).
|
||||
# unwanted-reply-threshold: 0
|
||||
|
||||
# Do not query the following addresses. No DNS queries are sent there.
|
||||
# List one address per entry. List classless netblocks with /size,
|
||||
|
|
|
|||
|
|
@ -446,6 +446,13 @@ Allow this domain, and all its subdomains to contain private addresses.
|
|||
Give multiple times to allow multiple domain names to contain private
|
||||
addresses. Default is none.
|
||||
.TP
|
||||
.B unwanted\-reply\-threshold: \fI<number>
|
||||
If set, a total number of unwanted replies is kept track of in every thread.
|
||||
When it reaches the threshold, a defensive action is taken and a warning
|
||||
is printed to the log. The defensive action is to clear the rrset and
|
||||
message caches, hopefully flushing away any poison. A value of 10 million
|
||||
is suggested. Default is 0 (turned off).
|
||||
.TP
|
||||
.B do\-not\-query\-address: \fI<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
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ libworker_setup(struct ub_ctx* ctx, int is_bg)
|
|||
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||
cfg->do_tcp?cfg->outgoing_num_tcp:0,
|
||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||
ports, numports);
|
||||
ports, numports, cfg->unwanted_threshold,
|
||||
&libworker_alloc_cleanup, w);
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,6 +330,17 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
|
|||
verbose(VERB_QUERY, "received unwanted or unsolicited udp reply dropped.");
|
||||
log_buf(VERB_ALGO, "dropped message", c->buffer);
|
||||
outnet->unwanted_replies++;
|
||||
if(outnet->unwanted_threshold && ++outnet->unwanted_total
|
||||
>= outnet->unwanted_threshold) {
|
||||
log_warn("unwanted reply total reached threshold (%u)"
|
||||
" you may be under attack."
|
||||
" defensive action: clearing the cache",
|
||||
(unsigned)outnet->unwanted_threshold);
|
||||
fptr_ok(fptr_whitelist_alloc_cleanup(
|
||||
outnet->unwanted_action));
|
||||
(*outnet->unwanted_action)(outnet->unwanted_param);
|
||||
outnet->unwanted_total = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -339,6 +350,17 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
|
|||
verbose(VERB_QUERY, "received reply id,addr on wrong port. "
|
||||
"dropped.");
|
||||
outnet->unwanted_replies++;
|
||||
if(outnet->unwanted_threshold && ++outnet->unwanted_total
|
||||
>= outnet->unwanted_threshold) {
|
||||
log_warn("unwanted reply total reached threshold (%u)"
|
||||
" you may be under attack."
|
||||
" defensive action: clearing the cache",
|
||||
(unsigned)outnet->unwanted_threshold);
|
||||
fptr_ok(fptr_whitelist_alloc_cleanup(
|
||||
outnet->unwanted_action));
|
||||
(*outnet->unwanted_action)(outnet->unwanted_param);
|
||||
outnet->unwanted_total = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
comm_timer_disable(p->timer);
|
||||
|
|
@ -444,7 +466,8 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
|
||||
int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports)
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param)
|
||||
{
|
||||
struct outside_network* outnet = (struct outside_network*)
|
||||
calloc(1, sizeof(struct outside_network));
|
||||
|
|
@ -459,6 +482,9 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||
outnet->infra = infra;
|
||||
outnet->rnd = rnd;
|
||||
outnet->svcd_overhead = 0;
|
||||
outnet->unwanted_threshold = unwanted_threshold;
|
||||
outnet->unwanted_action = unwanted_action;
|
||||
outnet->unwanted_param = unwanted_param;
|
||||
outnet->use_caps_for_id = use_caps_for_id;
|
||||
if(numavailports == 0) {
|
||||
log_err("no outgoing ports available");
|
||||
|
|
|
|||
|
|
@ -76,8 +76,17 @@ struct outside_network {
|
|||
size_t svcd_overhead;
|
||||
/** use x20 bits to encode additional ID random bits */
|
||||
int use_caps_for_id;
|
||||
/** number of unwanted replies received */
|
||||
|
||||
/** number of unwanted replies received (for statistics) */
|
||||
size_t unwanted_replies;
|
||||
/** cumulative total of unwanted replies (for defense) */
|
||||
size_t unwanted_total;
|
||||
/** threshold when to take defensive action. If 0 then never. */
|
||||
size_t unwanted_threshold;
|
||||
/** what action to take, called when defensive action is needed */
|
||||
void (*unwanted_action)(void*);
|
||||
/** user param for action */
|
||||
void* unwanted_param;
|
||||
|
||||
/** linked list of available commpoints, unused file descriptors,
|
||||
* for use as outgoing UDP ports. cp.fd=-1 in them. */
|
||||
|
|
@ -334,13 +343,17 @@ struct serviced_query {
|
|||
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
|
||||
* @param availports: array of available ports.
|
||||
* @param numavailports: number of available ports in array.
|
||||
* @param unwanted_threshold: when to take defensive action.
|
||||
* @param unwanted_action: the action to take.
|
||||
* @param unwanted_param: user parameter to action.
|
||||
* @return: the new structure (with no pending answers) or NULL on error.
|
||||
*/
|
||||
struct outside_network* outside_network_create(struct comm_base* base,
|
||||
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
|
||||
int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
|
||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
||||
int numavailports);
|
||||
int numavailports, size_t unwanted_threshold,
|
||||
void (*unwanted_action)(void*), void* unwanted_param);
|
||||
|
||||
/**
|
||||
* Delete outside_network structure.
|
||||
|
|
|
|||
|
|
@ -722,10 +722,12 @@ outside_network_create(struct comm_base* base, size_t bufsize,
|
|||
struct infra_cache* ATTR_UNUSED(infra),
|
||||
struct ub_randstate* ATTR_UNUSED(rnd),
|
||||
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
|
||||
int ATTR_UNUSED(numavailports))
|
||||
int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
|
||||
void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param))
|
||||
{
|
||||
struct outside_network* outnet = calloc(1,
|
||||
sizeof(struct outside_network));
|
||||
(void)unwanted_action;
|
||||
if(!outnet)
|
||||
return NULL;
|
||||
outnet->base = base;
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ alloc_get_id(struct alloc_cache* alloc)
|
|||
uint64_t id = alloc->next_id++;
|
||||
if(id == alloc->last_id) {
|
||||
log_warn("rrset alloc: out of 64bit ids. Clearing cache.");
|
||||
fptr_whitelist_alloc_cleanup(alloc->cleanup);
|
||||
fptr_ok(fptr_whitelist_alloc_cleanup(alloc->cleanup));
|
||||
(*alloc->cleanup)(alloc->cleanup_arg);
|
||||
|
||||
/* start back at first number */ /* like in alloc_init*/
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ config_create()
|
|||
cfg->use_caps_bits_for_id = 0;
|
||||
cfg->private_address = NULL;
|
||||
cfg->private_domain = NULL;
|
||||
cfg->unwanted_threshold = 0;
|
||||
cfg->hide_identity = 0;
|
||||
cfg->hide_version = 0;
|
||||
cfg->identity = NULL;
|
||||
|
|
@ -325,6 +326,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
return cfg_strlist_insert(&cfg->private_address, strdup(val));
|
||||
} else if(strcmp(opt, "private-domain:") == 0) {
|
||||
return cfg_strlist_insert(&cfg->private_domain, strdup(val));
|
||||
} else if(strcmp(opt, "unwanted-reply-threshold:") == 0) {
|
||||
IS_NUMBER_OR_ZERO;
|
||||
cfg->unwanted_threshold = (size_t)atoi(val);
|
||||
} else if(strcmp(opt, "do-not-query-localhost:") == 0) {
|
||||
IS_YES_OR_NO;
|
||||
cfg->donotquery_localhost = (strcmp(val, "yes") == 0);
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ struct config_file {
|
|||
struct config_strlist* private_address;
|
||||
/** allow domain (and subdomains) to use private address space */
|
||||
struct config_strlist* private_domain;
|
||||
/** what threshold for unwanted action. */
|
||||
size_t unwanted_threshold;
|
||||
|
||||
/** chrootdir, if not "" or chroot will be done */
|
||||
char* chrootdir;
|
||||
|
|
|
|||
1638
util/configlexer.c
1638
util/configlexer.c
File diff suppressed because it is too large
Load diff
|
|
@ -150,6 +150,7 @@ harden-glue{COLON} { YDOUT; return VAR_HARDEN_GLUE;}
|
|||
harden-dnssec-stripped{COLON} { YDOUT; return VAR_HARDEN_DNNSEC_STRIPPED;}
|
||||
harden-referral-path{COLON} { YDOUT; return VAR_HARDEN_REFERRAL_PATH;}
|
||||
use-caps-for-id{COLON} { YDOUT; return VAR_USE_CAPS_FOR_ID;}
|
||||
unwanted-reply-threshold{COLON} { YDOUT; return VAR_UNWANTED_REPLY_THRESHOLD;}
|
||||
private-address{COLON} { YDOUT; return VAR_PRIVATE_ADDRESS;}
|
||||
private-domain{COLON} { YDOUT; return VAR_PRIVATE_DOMAIN;}
|
||||
stub-zone{COLON} { YDOUT; return VAR_STUB_ZONE;}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -135,7 +135,8 @@
|
|||
VAR_EXTENDED_STATISTICS = 351,
|
||||
VAR_LOCAL_DATA_PTR = 352,
|
||||
VAR_JOSTLE_TIMEOUT = 353,
|
||||
VAR_STUB_PRIME = 354
|
||||
VAR_STUB_PRIME = 354,
|
||||
VAR_UNWANTED_REPLY_THRESHOLD = 355
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -236,6 +237,7 @@
|
|||
#define VAR_LOCAL_DATA_PTR 352
|
||||
#define VAR_JOSTLE_TIMEOUT 353
|
||||
#define VAR_STUB_PRIME 354
|
||||
#define VAR_UNWANTED_REPLY_THRESHOLD 355
|
||||
|
||||
|
||||
|
||||
|
|
@ -247,7 +249,7 @@ typedef union YYSTYPE
|
|||
char* str;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 251 "util/configparser.h"
|
||||
#line 253 "util/configparser.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
||||
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
||||
%token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT
|
||||
%token VAR_STUB_PRIME
|
||||
%token VAR_STUB_PRIME VAR_UNWANTED_REPLY_THRESHOLD
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
|
@ -142,7 +142,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||
server_harden_referral_path | server_private_address |
|
||||
server_private_domain | server_extended_statistics |
|
||||
server_local_data_ptr | server_jostle_timeout
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
|
|
@ -686,6 +687,15 @@ server_private_domain: VAR_PRIVATE_DOMAIN STRING
|
|||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
server_unwanted_reply_threshold: VAR_UNWANTED_REPLY_THRESHOLD STRING
|
||||
{
|
||||
OUTYY(("P(server_unwanted_reply_threshold:%s)\n", $2));
|
||||
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||
yyerror("number expected");
|
||||
else cfg_parser->cfg->unwanted_threshold = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_do_not_query_address: VAR_DO_NOT_QUERY_ADDRESS STRING
|
||||
{
|
||||
OUTYY(("P(server_do_not_query_address:%s)\n", $2));
|
||||
|
|
|
|||
Loading…
Reference in a new issue