Option for DOS protection on slower links.

git-svn-id: file:///svn/unbound/trunk@1282 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-10-06 09:28:50 +00:00
parent 620c85ee32
commit 351ef6e252
12 changed files with 1231 additions and 1152 deletions

View file

@ -1,3 +1,6 @@
6 October 2008: Wouter
- jostle-timeout option, so you can config for slow links.
2 October 2008: Wouter
- fixup unlink of pidfile.
- fixup SHA256 algorithm collation code.

View file

@ -89,6 +89,9 @@ server:
# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024
# if very busy, 50% queries run to completion, 50% get timeout in msec
# jostle-timeout: 200
# the amount of memory to use for the RRset cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# rrset-cache-size: 4m

View file

@ -182,10 +182,19 @@ reasonable guess.
.TP
.B num\-queries\-per\-thread: \fI<number>
The number of queries that every thread will service simultaneously.
If more queries arrive that need servicing, they are dropped. This forces
If more queries arrive that need servicing, and no queries can be jostled out
(see \fIjostle\-timeout\fR), then the queries are dropped. This forces
the client to resend after a timeout; allowing the server time to work on
the existing queries. Default 1024.
.TP
.B jostle\-timeout: \fI<msec>
Timeout used when the server is very busy. Set to a value that usually
results in one roundtrip to the authority servers. If too many queries
arrive, then 50% of the queries are allowed to run to completion, and
the other 50% are replaced with the new incoming query if they have already
spent more than their allowed time. This protects against denial of
service by slow queries or high query rates. Default 200 milliseconds.
.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes

View file

@ -104,6 +104,22 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
#endif
}
/** histogram compare of time values */
static int
timeval_smaller(const struct timeval* x, const struct timeval* y)
{
#ifndef S_SPLINT_S
if(x->tv_sec < y->tv_sec)
return 1;
else if(x->tv_sec == y->tv_sec) {
if(x->tv_usec <= y->tv_usec)
return 1;
else return 0;
}
else return 0;
#endif
}
int
mesh_state_compare(const void* ap, const void* bp)
{
@ -162,6 +178,9 @@ mesh_create(struct module_stack* stack, struct module_env* env)
mesh->stats_dropped = 0;
mesh->max_reply_states = env->cfg->num_queries_per_thread;
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
mesh->jostle_max.tv_sec = (time_t)(env->cfg->jostle_time / 1000);
mesh->jostle_max.tv_usec = (time_t)((env->cfg->jostle_time % 1000)
*1000);
return mesh;
}
@ -196,8 +215,7 @@ int mesh_make_new_space(struct mesh_area* mesh)
struct timeval age;
timeval_subtract(&age, mesh->env->now_tv,
&m->reply_list->start_time);
#ifndef S_SPLINT_S
if(age.tv_sec > 0 || age.tv_usec > MESH_JOSTLE_USEC) {
if(timeval_smaller(&mesh->jostle_max, &age)) {
/* its a goner */
log_nametypeclass(VERB_ALGO, "query jostled out to "
"make space for a new one",
@ -214,7 +232,6 @@ int mesh_make_new_space(struct mesh_area* mesh)
mesh_state_delete(&m->s);
return 1;
}
#endif
}
/* no space for new item */
return 0;

View file

@ -65,12 +65,6 @@ struct timehist;
*/
#define MESH_MAX_ACTIVATION 1000
/**
* Maximum time to live in the jostle list. usec.
* The entries older than this could be removed to make space for new ones.
*/
#define MESH_JOSTLE_USEC 200000 /* 0.200000 sec */
/**
* Mesh of query states
*/
@ -133,6 +127,8 @@ struct mesh_area {
struct mesh_state* jostle_first;
/** last entry in jostle list - this is the entry that is newest */
struct mesh_state* jostle_last;
/** timeout for jostling. if age is lower, it does not get jostled. */
struct timeval jostle_max;
};
/**

View file

@ -94,6 +94,7 @@ config_create()
cfg->msg_cache_size = 4 * 1024 * 1024;
cfg->msg_cache_slabs = 4;
cfg->num_queries_per_thread = 1024;
cfg->jostle_time = 200;
cfg->rrset_cache_size = 4 * 1024 * 1024;
cfg->rrset_cache_slabs = 4;
cfg->host_ttl = 900;
@ -268,6 +269,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
} else if(strcmp(opt, "num-queries-per-thread:") == 0) {
IS_NONZERO_NUMBER;
cfg->num_queries_per_thread = (size_t)atoi(val);
} else if(strcmp(opt, "jostle-timeout:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->jostle_time = (size_t)atoi(val);
} else if(strcmp(opt, "rrset-cache-size:") == 0) {
return cfg_parse_memsize(val, &cfg->rrset_cache_size);
} else if(strcmp(opt, "rrset-cache-slabs:") == 0) {

View file

@ -91,6 +91,8 @@ struct config_file {
size_t msg_cache_slabs;
/** number of queries every thread can service */
size_t num_queries_per_thread;
/** number of msec to wait before items can be jostled out */
size_t jostle_time;
/** size of the rrset cache */
size_t rrset_cache_size;
/** slabs in the rrset cache */

File diff suppressed because it is too large Load diff

View file

@ -142,6 +142,7 @@ infra-cache-slabs{COLON} { YDOUT; return VAR_INFRA_CACHE_SLABS;}
infra-cache-numhosts{COLON} { YDOUT; return VAR_INFRA_CACHE_NUMHOSTS;}
infra-cache-lame-size{COLON} { YDOUT; return VAR_INFRA_CACHE_LAME_SIZE;}
num-queries-per-thread{COLON} { YDOUT; return VAR_NUM_QUERIES_PER_THREAD;}
jostle-timeout{COLON} { YDOUT; return VAR_JOSTLE_TIMEOUT;}
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;}

File diff suppressed because it is too large Load diff

View file

@ -133,7 +133,8 @@
VAR_CONTROL_KEY_FILE = 349,
VAR_CONTROL_CERT_FILE = 350,
VAR_EXTENDED_STATISTICS = 351,
VAR_LOCAL_DATA_PTR = 352
VAR_LOCAL_DATA_PTR = 352,
VAR_JOSTLE_TIMEOUT = 353
};
#endif
/* Tokens. */
@ -232,6 +233,7 @@
#define VAR_CONTROL_CERT_FILE 350
#define VAR_EXTENDED_STATISTICS 351
#define VAR_LOCAL_DATA_PTR 352
#define VAR_JOSTLE_TIMEOUT 353
@ -243,7 +245,7 @@ typedef union YYSTYPE
char* str;
}
/* Line 1489 of yacc.c. */
#line 247 "util/configparser.h"
#line 249 "util/configparser.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1

View file

@ -95,7 +95,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
%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
%token VAR_EXTENDED_STATISTICS VAR_LOCAL_DATA_PTR VAR_JOSTLE_TIMEOUT
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -141,7 +141,7 @@ 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_local_data_ptr | server_jostle_timeout
;
stubstart: VAR_STUB_ZONE
{
@ -525,6 +525,15 @@ server_num_queries_per_thread: VAR_NUM_QUERIES_PER_THREAD STRING
free($2);
}
;
server_jostle_timeout: VAR_JOSTLE_TIMEOUT STRING
{
OUTYY(("P(server_jostle_timeout:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->jostle_time = atoi($2);
free($2);
}
;
server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING
{
OUTYY(("P(server_rrset_cache_size:%s)\n", $2));