mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-24 00:29:58 -05:00
- Fix #1185: Source IP rate limiting, patch from Larissa Feng.
git-svn-id: file:///svn/unbound/trunk@3981 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
9b4b0de746
commit
3a1ffe4c69
20 changed files with 2818 additions and 2338 deletions
|
|
@ -762,6 +762,8 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||||
struct timeval avg;
|
struct timeval avg;
|
||||||
if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm,
|
if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm,
|
||||||
(unsigned long)s->svr.num_queries)) return 0;
|
(unsigned long)s->svr.num_queries)) return 0;
|
||||||
|
if(!ssl_printf(ssl, "%s.num.queries_ip_ratelimited"SQ"%lu\n", nm,
|
||||||
|
(unsigned long)s->svr.num_queries_ip_ratelimited)) return 0;
|
||||||
if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm,
|
if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm,
|
||||||
(unsigned long)(s->svr.num_queries
|
(unsigned long)(s->svr.num_queries
|
||||||
- s->svr.num_queries_missed_cache))) return 0;
|
- s->svr.num_queries_missed_cache))) return 0;
|
||||||
|
|
@ -2559,6 +2561,8 @@ struct ratelimit_list_arg {
|
||||||
time_t now;
|
time_t now;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ip_ratelimit_list_arg ratelimit_list_arg
|
||||||
|
|
||||||
/** list items in the ratelimit table */
|
/** list items in the ratelimit table */
|
||||||
static void
|
static void
|
||||||
rate_list(struct lruhash_entry* e, void* arg)
|
rate_list(struct lruhash_entry* e, void* arg)
|
||||||
|
|
@ -2577,6 +2581,24 @@ rate_list(struct lruhash_entry* e, void* arg)
|
||||||
ssl_printf(a->ssl, "%s %d limit %d\n", buf, max, lim);
|
ssl_printf(a->ssl, "%s %d limit %d\n", buf, max, lim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** list items in the ip_ratelimit table */
|
||||||
|
static void
|
||||||
|
ip_rate_list(struct lruhash_entry* e, void* arg)
|
||||||
|
{
|
||||||
|
char ip[128];
|
||||||
|
struct ip_ratelimit_list_arg* a = (struct ip_ratelimit_list_arg*)arg;
|
||||||
|
struct ip_rate_key* k = (struct ip_rate_key*)e->key;
|
||||||
|
struct ip_rate_data* d = (struct ip_rate_data*)e->data;
|
||||||
|
int lim = infra_ip_ratelimit;
|
||||||
|
int max = infra_rate_max(d, a->now);
|
||||||
|
if(a->all == 0) {
|
||||||
|
if(max < lim)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addr_to_str(&k->addr, k->addrlen, ip, sizeof(ip));
|
||||||
|
ssl_printf(a->ssl, "%s %d limit %d\n", ip, max, lim);
|
||||||
|
}
|
||||||
|
|
||||||
/** do the ratelimit_list command */
|
/** do the ratelimit_list command */
|
||||||
static void
|
static void
|
||||||
do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||||
|
|
@ -2595,6 +2617,24 @@ do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||||
slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a);
|
slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** do the ip_ratelimit_list command */
|
||||||
|
static void
|
||||||
|
do_ip_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||||
|
{
|
||||||
|
struct ip_ratelimit_list_arg a;
|
||||||
|
a.all = 0;
|
||||||
|
a.infra = worker->env.infra_cache;
|
||||||
|
a.now = *worker->env.now;
|
||||||
|
a.ssl = ssl;
|
||||||
|
arg = skipwhite(arg);
|
||||||
|
if(strcmp(arg, "+a") == 0)
|
||||||
|
a.all = 1;
|
||||||
|
if(a.infra->client_ip_rates==NULL ||
|
||||||
|
(a.all == 0 && infra_ip_ratelimit == 0))
|
||||||
|
return;
|
||||||
|
slabhash_traverse(a.infra->client_ip_rates, 0, ip_rate_list, &a);
|
||||||
|
}
|
||||||
|
|
||||||
/** tell other processes to execute the command */
|
/** tell other processes to execute the command */
|
||||||
static void
|
static void
|
||||||
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||||
|
|
@ -2673,6 +2713,9 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||||
} else if(cmdcmp(p, "ratelimit_list", 14)) {
|
} else if(cmdcmp(p, "ratelimit_list", 14)) {
|
||||||
do_ratelimit_list(ssl, worker, p+14);
|
do_ratelimit_list(ssl, worker, p+14);
|
||||||
return;
|
return;
|
||||||
|
} else if(cmdcmp(p, "ip_ratelimit_list", 17)) {
|
||||||
|
do_ip_ratelimit_list(ssl, worker, p+17);
|
||||||
|
return;
|
||||||
} else if(cmdcmp(p, "stub_add", 8)) {
|
} else if(cmdcmp(p, "stub_add", 8)) {
|
||||||
/* must always distribute this cmd */
|
/* must always distribute this cmd */
|
||||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||||
|
|
|
||||||
|
|
@ -102,12 +102,14 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||||
int threadnum)
|
int threadnum)
|
||||||
{
|
{
|
||||||
log_info("server stats for thread %d: %u queries, "
|
log_info("server stats for thread %d: %u queries, "
|
||||||
"%u answers from cache, %u recursions, %u prefetch",
|
"%u answers from cache, %u recursions, %u prefetch, %u rejected by "
|
||||||
|
"ip ratelimiting",
|
||||||
threadnum, (unsigned)stats->num_queries,
|
threadnum, (unsigned)stats->num_queries,
|
||||||
(unsigned)(stats->num_queries -
|
(unsigned)(stats->num_queries -
|
||||||
stats->num_queries_missed_cache),
|
stats->num_queries_missed_cache),
|
||||||
(unsigned)stats->num_queries_missed_cache,
|
(unsigned)stats->num_queries_missed_cache,
|
||||||
(unsigned)stats->num_queries_prefetch);
|
(unsigned)stats->num_queries_prefetch,
|
||||||
|
(unsigned)stats->num_queries_ip_ratelimited);
|
||||||
log_info("server stats for thread %d: requestlist max %u avg %g "
|
log_info("server stats for thread %d: requestlist max %u avg %g "
|
||||||
"exceeded %u jostled %u", threadnum,
|
"exceeded %u jostled %u", threadnum,
|
||||||
(unsigned)stats->max_query_list_size,
|
(unsigned)stats->max_query_list_size,
|
||||||
|
|
@ -226,6 +228,7 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||||
void server_stats_add(struct stats_info* total, struct stats_info* a)
|
void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||||
{
|
{
|
||||||
total->svr.num_queries += a->svr.num_queries;
|
total->svr.num_queries += a->svr.num_queries;
|
||||||
|
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
||||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ struct sldns_buffer;
|
||||||
struct server_stats {
|
struct server_stats {
|
||||||
/** number of queries from clients received. */
|
/** number of queries from clients received. */
|
||||||
size_t num_queries;
|
size_t num_queries;
|
||||||
|
/** number of queries that have been dropped/ratelimited by ip. */
|
||||||
|
size_t num_queries_ip_ratelimited;
|
||||||
/** number of queries that had a cache-miss. */
|
/** number of queries that had a cache-miss. */
|
||||||
size_t num_queries_missed_cache;
|
size_t num_queries_missed_cache;
|
||||||
/** number of prefetch queries - cachehits with prefetch */
|
/** number of prefetch queries - cachehits with prefetch */
|
||||||
|
|
|
||||||
|
|
@ -825,7 +825,29 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||||
comm_point_drop_reply(repinfo);
|
comm_point_drop_reply(repinfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
worker->stats.num_queries++;
|
worker->stats.num_queries++;
|
||||||
|
|
||||||
|
/* check if this query should be dropped based on source ip rate limiting */
|
||||||
|
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
|
||||||
|
*worker->env.now)) {
|
||||||
|
/* See if we are passed through with slip factor */
|
||||||
|
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
|
||||||
|
ub_random_max(worker->env.rnd,
|
||||||
|
worker->env.cfg->ip_ratelimit_factor) == 1) {
|
||||||
|
|
||||||
|
char addrbuf[128];
|
||||||
|
addr_to_str(&repinfo->addr, repinfo->addrlen,
|
||||||
|
addrbuf, sizeof(addrbuf));
|
||||||
|
verbose(VERB_OPS, "ip_ratelimit allowed through for ip address %s ",
|
||||||
|
addrbuf);
|
||||||
|
} else {
|
||||||
|
worker->stats.num_queries_ip_ratelimited++;
|
||||||
|
comm_point_drop_reply(repinfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* see if query is in the cache */
|
/* see if query is in the cache */
|
||||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||||
verbose(VERB_ALGO, "worker parse request: formerror.");
|
verbose(VERB_ALGO, "worker parse request: formerror.");
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
- Fix #1184: Log DNS replies. This includes the same logging
|
- Fix #1184: Log DNS replies. This includes the same logging
|
||||||
information that DNS queries and response code and response size,
|
information that DNS queries and response code and response size,
|
||||||
patch from Larissa Feng.
|
patch from Larissa Feng.
|
||||||
|
- Fix #1185: Source IP rate limiting, patch from Larissa Feng.
|
||||||
|
|
||||||
3 January 2017: Wouter
|
3 January 2017: Wouter
|
||||||
- configure --enable-systemd and lets unbound use systemd sockets if
|
- configure --enable-systemd and lets unbound use systemd sockets if
|
||||||
|
|
|
||||||
|
|
@ -674,6 +674,20 @@ server:
|
||||||
# can give this multiple times, the name closest to the zone is used.
|
# can give this multiple times, the name closest to the zone is used.
|
||||||
# ratelimit-below-domain: com 1000
|
# ratelimit-below-domain: com 1000
|
||||||
|
|
||||||
|
# global query ratelimit for all ip addresses.
|
||||||
|
# feature is experimental.
|
||||||
|
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||||
|
# ip-ratelimit: 0
|
||||||
|
|
||||||
|
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
||||||
|
# ip-ratelimit-size: 4m
|
||||||
|
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
||||||
|
# ip-ratelimit-slabs: 4
|
||||||
|
|
||||||
|
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||||
|
# ip-ratelimit-factor: 10
|
||||||
|
|
||||||
|
|
||||||
# Python config section. To enable:
|
# Python config section. To enable:
|
||||||
# o use --with-pythonmodule to configure before compiling.
|
# o use --with-pythonmodule to configure before compiling.
|
||||||
# o list python in the module-config string (above) to enable.
|
# o list python in the module-config string (above) to enable.
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||||||
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||||||
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||||||
keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size, ratelimit,
|
keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size, ratelimit,
|
||||||
cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
ip\-ratelimit, cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||||||
.TP
|
.TP
|
||||||
.B get_option \fIopt
|
.B get_option \fIopt
|
||||||
Get the value of the option. Give the option name without a trailing ':'.
|
Get the value of the option. Give the option name without a trailing ':'.
|
||||||
|
|
@ -280,6 +280,12 @@ just the ratelimited domains, with their estimated qps. The ratelimited
|
||||||
domains return an error for uncached (new) queries, but cached queries work
|
domains return an error for uncached (new) queries, but cached queries work
|
||||||
as normal.
|
as normal.
|
||||||
.TP
|
.TP
|
||||||
|
.B ip_ratelimit_list \fR[\fI+a\fR]
|
||||||
|
List the ip addresses that are ratelimited. Printed one per line with current
|
||||||
|
estimated qps and qps limit from config. With +a it prints all ips, not
|
||||||
|
just the ratelimited ips, with their estimated qps. The ratelimited
|
||||||
|
ips are dropped before checking the cache.
|
||||||
|
.TP
|
||||||
.B view_list_local_zones \fIview\fR
|
.B view_list_local_zones \fIview\fR
|
||||||
\fIlist_local_zones\fR for given view.
|
\fIlist_local_zones\fR for given view.
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -319,6 +325,9 @@ The \fIstats\fR command shows a number of statistic counters.
|
||||||
.I threadX.num.queries
|
.I threadX.num.queries
|
||||||
number of queries received by thread
|
number of queries received by thread
|
||||||
.TP
|
.TP
|
||||||
|
.I threadX.num.queries_ip_ratelimited
|
||||||
|
number of queries rate limited by thread
|
||||||
|
.TP
|
||||||
.I threadX.num.cachehits
|
.I threadX.num.cachehits
|
||||||
number of queries that were successfully answered using a cache lookup
|
number of queries that were successfully answered using a cache lookup
|
||||||
.TP
|
.TP
|
||||||
|
|
|
||||||
|
|
@ -1205,6 +1205,34 @@ in different parts of the namespace. The closest matching suffix is used
|
||||||
to determine the qps limit. The rate for the exact matching domain name
|
to determine the qps limit. The rate for the exact matching domain name
|
||||||
is not changed, use ratelimit\-for\-domain to set that, you might want
|
is not changed, use ratelimit\-for\-domain to set that, you might want
|
||||||
to use different settings for a top\-level\-domain and subdomains.
|
to use different settings for a top\-level\-domain and subdomains.
|
||||||
|
.TP 5
|
||||||
|
.B ip\-ratelimit: \fI<number or 0>
|
||||||
|
Enable global ratelimiting of queries accepted per ip address.
|
||||||
|
If 0, the default, it is disabled. This option is experimental at this time.
|
||||||
|
The ratelimit is in queries per second that are allowed. More queries are
|
||||||
|
completely dropped and will not receive a reply, SERVFAIL or otherwise.
|
||||||
|
IP ratelimiting happens before looking in the cache. This may be useful for
|
||||||
|
mitigating amplification attacks.
|
||||||
|
.TP 5
|
||||||
|
.B ip\-ratelimit\-size: \fI<memory size>
|
||||||
|
Give the size of the data structure in which the current ongoing rates are
|
||||||
|
kept track in. Default 4m. In bytes or use m(mega), k(kilo), g(giga).
|
||||||
|
The ip ratelimit structure is small, so this data structure likely does
|
||||||
|
not need to be large.
|
||||||
|
.TP 5
|
||||||
|
.B ip\-ratelimit\-slabs: \fI<number>
|
||||||
|
Give power of 2 number of slabs, this is used to reduce lock contention
|
||||||
|
in the ip ratelimit tracking data structure. Close to the number of cpus is
|
||||||
|
a fairly good setting.
|
||||||
|
.TP 5
|
||||||
|
.B ip\-ratelimit\-factor: \fI<number>
|
||||||
|
Set the amount of queries to rate limit when the limit is exceeded.
|
||||||
|
If set to 0, all queries are dropped for addresses where the limit is
|
||||||
|
exceeded. If set to another value, 1 in that number is allowed through
|
||||||
|
to complete. Default is 10, allowing 1/10 traffic to flow normally.
|
||||||
|
This can make ordinary queries complete (if repeatedly queried for),
|
||||||
|
and enter the cache, whilst also mitigating the traffic flow by the
|
||||||
|
factor given.
|
||||||
.SS "Remote Control Options"
|
.SS "Remote Control Options"
|
||||||
In the
|
In the
|
||||||
.B remote\-control:
|
.B remote\-control:
|
||||||
|
|
|
||||||
127
services/cache/infra.c
vendored
127
services/cache/infra.c
vendored
|
|
@ -61,6 +61,10 @@
|
||||||
/** ratelimit value for delegation point */
|
/** ratelimit value for delegation point */
|
||||||
int infra_dp_ratelimit = 0;
|
int infra_dp_ratelimit = 0;
|
||||||
|
|
||||||
|
/** ratelimit value for client ip addresses,
|
||||||
|
* in queries per second. */
|
||||||
|
int infra_ip_ratelimit = 0;
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||||
{
|
{
|
||||||
|
|
@ -244,6 +248,14 @@ infra_create(struct config_file* cfg)
|
||||||
}
|
}
|
||||||
name_tree_init_parents(&infra->domain_limits);
|
name_tree_init_parents(&infra->domain_limits);
|
||||||
}
|
}
|
||||||
|
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||||
|
infra->client_ip_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||||
|
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||||
|
&ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
|
||||||
|
if(!infra->client_ip_rates) {
|
||||||
|
infra_delete(infra);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return infra;
|
return infra;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,6 +276,7 @@ infra_delete(struct infra_cache* infra)
|
||||||
slabhash_delete(infra->hosts);
|
slabhash_delete(infra->hosts);
|
||||||
slabhash_delete(infra->domain_rates);
|
slabhash_delete(infra->domain_rates);
|
||||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||||
|
slabhash_delete(infra->client_ip_rates);
|
||||||
free(infra);
|
free(infra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,21 +297,28 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||||
return infra;
|
return infra;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** calculate the hash value for a host key */
|
/** calculate the hash value for a host key
|
||||||
|
* set use_port to a non-0 number to use the port in
|
||||||
|
* the hash calculation; 0 to ignore the port.*/
|
||||||
static hashvalue_t
|
static hashvalue_t
|
||||||
hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
hash_addr(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
|
int use_port)
|
||||||
{
|
{
|
||||||
hashvalue_t h = 0xab;
|
hashvalue_t h = 0xab;
|
||||||
/* select the pieces to hash, some OS have changing data inside */
|
/* select the pieces to hash, some OS have changing data inside */
|
||||||
if(addr_is_ip6(addr, addrlen)) {
|
if(addr_is_ip6(addr, addrlen)) {
|
||||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
|
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
|
||||||
h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
|
h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
|
||||||
h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
|
if(use_port){
|
||||||
|
h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
|
||||||
|
}
|
||||||
h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
|
h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
|
||||||
} else {
|
} else {
|
||||||
struct sockaddr_in* in = (struct sockaddr_in*)addr;
|
struct sockaddr_in* in = (struct sockaddr_in*)addr;
|
||||||
h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
|
h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
|
||||||
h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
|
if(use_port){
|
||||||
|
h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
|
||||||
|
}
|
||||||
h = hashlittle(&in->sin_addr, INET_SIZE, h);
|
h = hashlittle(&in->sin_addr, INET_SIZE, h);
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
|
|
@ -308,7 +328,7 @@ hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
||||||
static hashvalue_t
|
static hashvalue_t
|
||||||
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
|
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
|
||||||
{
|
{
|
||||||
return dname_query_hash(name, hash_addr(addr, addrlen));
|
return dname_query_hash(name, hash_addr(addr, addrlen, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** lookup version that does not check host ttl (you check it) */
|
/** lookup version that does not check host ttl (you check it) */
|
||||||
|
|
@ -726,6 +746,30 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||||
return infra_dp_ratelimit;
|
return infra_dp_ratelimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ip_rate_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||||
|
{
|
||||||
|
struct ip_rate_key* key = (struct ip_rate_key*)k;
|
||||||
|
return sizeof(*key) + sizeof(struct ip_rate_data)
|
||||||
|
+ lock_get_mem(&key->entry.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ip_rate_compfunc(void* key1, void* key2)
|
||||||
|
{
|
||||||
|
struct ip_rate_key* k1 = (struct ip_rate_key*)key1;
|
||||||
|
struct ip_rate_key* k2 = (struct ip_rate_key*)key2;
|
||||||
|
return sockaddr_cmp_addr(&k1->addr, k1->addrlen,
|
||||||
|
&k2->addr, k2->addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
struct ip_rate_key* key = (struct ip_rate_key*)k;
|
||||||
|
if(!key)
|
||||||
|
return;
|
||||||
|
lock_rw_destroy(&key->entry.lock);
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
/** find data item in array, for write access, caller unlocks */
|
/** find data item in array, for write access, caller unlocks */
|
||||||
static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||||
uint8_t* name, size_t namelen, int wr)
|
uint8_t* name, size_t namelen, int wr)
|
||||||
|
|
@ -739,6 +783,20 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||||
return slabhash_lookup(infra->domain_rates, h, &key, wr);
|
return slabhash_lookup(infra->domain_rates, h, &key, wr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** find data item in array for ip addresses */
|
||||||
|
struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
|
||||||
|
struct comm_reply* repinfo, int wr)
|
||||||
|
{
|
||||||
|
struct ip_rate_key key;
|
||||||
|
hashvalue_t h = hash_addr(&(repinfo->addr),
|
||||||
|
repinfo->addrlen, 0);
|
||||||
|
memset(&key, 0, sizeof(key));
|
||||||
|
key.addr = repinfo->addr;
|
||||||
|
key.addrlen = repinfo->addrlen;
|
||||||
|
key.entry.hash = h;
|
||||||
|
return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
|
||||||
|
}
|
||||||
|
|
||||||
/** create rate data item for name, number 1 in now */
|
/** create rate data item for name, number 1 in now */
|
||||||
static void infra_create_ratedata(struct infra_cache* infra,
|
static void infra_create_ratedata(struct infra_cache* infra,
|
||||||
uint8_t* name, size_t namelen, time_t timenow)
|
uint8_t* name, size_t namelen, time_t timenow)
|
||||||
|
|
@ -767,6 +825,30 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
||||||
slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
|
slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** create rate data item for ip address */
|
||||||
|
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||||
|
struct comm_reply* repinfo, time_t timenow)
|
||||||
|
{
|
||||||
|
hashvalue_t h = hash_addr(&(repinfo->addr),
|
||||||
|
repinfo->addrlen, 0);
|
||||||
|
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
||||||
|
struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
|
||||||
|
if(!k || !d) {
|
||||||
|
free(k);
|
||||||
|
free(d);
|
||||||
|
return; /* alloc failure */
|
||||||
|
}
|
||||||
|
k->addr = repinfo->addr;
|
||||||
|
k->addrlen = repinfo->addrlen;
|
||||||
|
lock_rw_init(&k->entry.lock);
|
||||||
|
k->entry.hash = h;
|
||||||
|
k->entry.key = k;
|
||||||
|
k->entry.data = d;
|
||||||
|
d->qps[0] = 1;
|
||||||
|
d->timestamp[0] = timenow;
|
||||||
|
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/** find the second and return its rate counter, if none, remove oldest */
|
/** find the second and return its rate counter, if none, remove oldest */
|
||||||
static int* infra_rate_find_second(void* data, time_t t)
|
static int* infra_rate_find_second(void* data, time_t t)
|
||||||
{
|
{
|
||||||
|
|
@ -875,6 +957,41 @@ infra_get_mem(struct infra_cache* infra)
|
||||||
{
|
{
|
||||||
size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
|
size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
|
||||||
if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
|
if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
|
||||||
|
if(infra->client_ip_rates) s += slabhash_get_mem(infra->client_ip_rates);
|
||||||
/* ignore domain_limits because walk through tree is big */
|
/* ignore domain_limits because walk through tree is big */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||||
|
struct comm_reply* repinfo, time_t timenow)
|
||||||
|
{
|
||||||
|
int max;
|
||||||
|
struct lruhash_entry* entry;
|
||||||
|
|
||||||
|
/* not enabled */
|
||||||
|
if(!infra_ip_ratelimit) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* find or insert ratedata */
|
||||||
|
entry = infra_find_ip_ratedata(infra, repinfo, 1);
|
||||||
|
if(entry) {
|
||||||
|
int premax = infra_rate_max(entry->data, timenow);
|
||||||
|
int* cur = infra_rate_find_second(entry->data, timenow);
|
||||||
|
(*cur)++;
|
||||||
|
max = infra_rate_max(entry->data, timenow);
|
||||||
|
lock_rw_unlock(&entry->lock);
|
||||||
|
|
||||||
|
if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
|
||||||
|
char client_ip[128];
|
||||||
|
addr_to_str((struct sockaddr_storage *)&repinfo->addr,
|
||||||
|
repinfo->addrlen, client_ip, sizeof(client_ip));
|
||||||
|
verbose(VERB_OPS, "ratelimit exceeded %s %d", client_ip,
|
||||||
|
infra_ip_ratelimit);
|
||||||
|
}
|
||||||
|
return (max <= infra_ip_ratelimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create */
|
||||||
|
infra_ip_create_ratedata(infra, repinfo, timenow);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
||||||
48
services/cache/infra.h
vendored
48
services/cache/infra.h
vendored
|
|
@ -36,7 +36,10 @@
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*
|
*
|
||||||
* This file contains the infrastructure cache.
|
* This file contains the infrastructure cache, as well as rate limiting.
|
||||||
|
* Note that there are two sorts of rate-limiting here:
|
||||||
|
* - Pre-cache, per-query rate limiting (query ratelimits)
|
||||||
|
* - Post-cache, per-domain name rate limiting (infra-ratelimits)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERVICES_CACHE_INFRA_H
|
#ifndef SERVICES_CACHE_INFRA_H
|
||||||
|
|
@ -44,6 +47,8 @@
|
||||||
#include "util/storage/lruhash.h"
|
#include "util/storage/lruhash.h"
|
||||||
#include "util/storage/dnstree.h"
|
#include "util/storage/dnstree.h"
|
||||||
#include "util/rtt.h"
|
#include "util/rtt.h"
|
||||||
|
#include "util/netevent.h"
|
||||||
|
#include "util/data/msgreply.h"
|
||||||
struct slabhash;
|
struct slabhash;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
|
|
||||||
|
|
@ -113,6 +118,8 @@ struct infra_cache {
|
||||||
struct slabhash* domain_rates;
|
struct slabhash* domain_rates;
|
||||||
/** ratelimit settings for domains, struct domain_limit_data */
|
/** ratelimit settings for domains, struct domain_limit_data */
|
||||||
rbtree_t domain_limits;
|
rbtree_t domain_limits;
|
||||||
|
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
||||||
|
struct slabhash* client_ip_rates;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** ratelimit, unless overridden by domain_limits, 0 is off */
|
/** ratelimit, unless overridden by domain_limits, 0 is off */
|
||||||
|
|
@ -142,6 +149,21 @@ struct rate_key {
|
||||||
size_t namelen;
|
size_t namelen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** ip ratelimit, 0 is off */
|
||||||
|
extern int infra_ip_ratelimit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key for ip_ratelimit lookups, a source IP.
|
||||||
|
*/
|
||||||
|
struct ip_rate_key {
|
||||||
|
/** lruhash key entry */
|
||||||
|
struct lruhash_entry entry;
|
||||||
|
/** client ip information */
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
/** length of address */
|
||||||
|
socklen_t addrlen;
|
||||||
|
};
|
||||||
|
|
||||||
/** number of seconds to track qps rate */
|
/** number of seconds to track qps rate */
|
||||||
#define RATE_WINDOW 2
|
#define RATE_WINDOW 2
|
||||||
|
|
||||||
|
|
@ -160,6 +182,8 @@ struct rate_data {
|
||||||
time_t timestamp[RATE_WINDOW];
|
time_t timestamp[RATE_WINDOW];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ip_rate_data rate_data
|
||||||
|
|
||||||
/** infra host cache default hash lookup size */
|
/** infra host cache default hash lookup size */
|
||||||
#define INFRA_HOST_STARTSIZE 32
|
#define INFRA_HOST_STARTSIZE 32
|
||||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||||
|
|
@ -381,6 +405,16 @@ int infra_rate_max(void* data, time_t now);
|
||||||
int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||||
size_t namelen);
|
size_t namelen);
|
||||||
|
|
||||||
|
/** Update query ratelimit hash and decide
|
||||||
|
* whether or not a query should be dropped.
|
||||||
|
* @param infra: infra cache
|
||||||
|
* @param repinfo: information about client
|
||||||
|
* @param timenow: what time it is now.
|
||||||
|
* @return 1 if it could be incremented. 0 if the increment overshot the
|
||||||
|
* ratelimit and the query should be dropped. */
|
||||||
|
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||||
|
struct comm_reply* repinfo, time_t timenow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get memory used by the infra cache.
|
* Get memory used by the infra cache.
|
||||||
* @param infra: infrastructure cache.
|
* @param infra: infrastructure cache.
|
||||||
|
|
@ -413,4 +447,16 @@ void rate_delkeyfunc(void* k, void* arg);
|
||||||
/** delete data */
|
/** delete data */
|
||||||
void rate_deldatafunc(void* d, void* arg);
|
void rate_deldatafunc(void* d, void* arg);
|
||||||
|
|
||||||
|
/* calculate size for the client ip hashtable */
|
||||||
|
size_t ip_rate_sizefunc(void* k, void* d);
|
||||||
|
|
||||||
|
/* compare two addresses */
|
||||||
|
int ip_rate_compfunc(void* key1, void* key2);
|
||||||
|
|
||||||
|
/* delete key, and destroy the lock */
|
||||||
|
void ip_rate_delkeyfunc(void* d, void* arg);
|
||||||
|
|
||||||
|
/* delete data */
|
||||||
|
#define ip_rate_deldatafunc rate_deldatafunc
|
||||||
|
|
||||||
#endif /* SERVICES_CACHE_INFRA_H */
|
#endif /* SERVICES_CACHE_INFRA_H */
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ usage(void)
|
||||||
printf(" or off to turn off root forwarding\n");
|
printf(" or off to turn off root forwarding\n");
|
||||||
printf(" or give list of ip addresses\n");
|
printf(" or give list of ip addresses\n");
|
||||||
printf(" ratelimit_list [+a] list ratelimited domains\n");
|
printf(" ratelimit_list [+a] list ratelimited domains\n");
|
||||||
|
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
|
||||||
printf(" +a list all, also not ratelimited\n");
|
printf(" +a list all, also not ratelimited\n");
|
||||||
printf("Version %s\n", PACKAGE_VERSION);
|
printf("Version %s\n", PACKAGE_VERSION);
|
||||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||||
|
|
|
||||||
|
|
@ -245,11 +245,15 @@ config_create(void)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
#endif
|
#endif
|
||||||
cfg->disable_dnssec_lame_check = 0;
|
cfg->disable_dnssec_lame_check = 0;
|
||||||
|
cfg->ip_ratelimit = 0;
|
||||||
cfg->ratelimit = 0;
|
cfg->ratelimit = 0;
|
||||||
|
cfg->ip_ratelimit_slabs = 4;
|
||||||
cfg->ratelimit_slabs = 4;
|
cfg->ratelimit_slabs = 4;
|
||||||
|
cfg->ip_ratelimit_size = 4*1024*1024;
|
||||||
cfg->ratelimit_size = 4*1024*1024;
|
cfg->ratelimit_size = 4*1024*1024;
|
||||||
cfg->ratelimit_for_domain = NULL;
|
cfg->ratelimit_for_domain = NULL;
|
||||||
cfg->ratelimit_below_domain = NULL;
|
cfg->ratelimit_below_domain = NULL;
|
||||||
|
cfg->ip_ratelimit_factor = 10;
|
||||||
cfg->ratelimit_factor = 10;
|
cfg->ratelimit_factor = 10;
|
||||||
cfg->qname_minimisation = 0;
|
cfg->qname_minimisation = 0;
|
||||||
cfg->qname_minimisation_strict = 0;
|
cfg->qname_minimisation_strict = 0;
|
||||||
|
|
@ -488,12 +492,19 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||||
else S_STR("module-config:", module_conf)
|
else S_STR("module-config:", module_conf)
|
||||||
else S_STR("python-script:", python_script)
|
else S_STR("python-script:", python_script)
|
||||||
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
|
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
|
||||||
|
else if(strcmp(opt, "ip-ratelimit:") == 0) {
|
||||||
|
IS_NUMBER_OR_ZERO; cfg->ip_ratelimit = atoi(val);
|
||||||
|
infra_ip_ratelimit=cfg->ip_ratelimit;
|
||||||
|
}
|
||||||
else if(strcmp(opt, "ratelimit:") == 0) {
|
else if(strcmp(opt, "ratelimit:") == 0) {
|
||||||
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
|
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
|
||||||
infra_dp_ratelimit=cfg->ratelimit;
|
infra_dp_ratelimit=cfg->ratelimit;
|
||||||
}
|
}
|
||||||
|
else S_MEMSIZE("ip-ratelimit-size:", ip_ratelimit_size)
|
||||||
else S_MEMSIZE("ratelimit-size:", ratelimit_size)
|
else S_MEMSIZE("ratelimit-size:", ratelimit_size)
|
||||||
|
else S_POW2("ip-ratelimit-slabs:", ip_ratelimit_slabs)
|
||||||
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
|
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
|
||||||
|
else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor)
|
||||||
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
|
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
|
||||||
else S_YNO("qname-minimisation:", qname_minimisation)
|
else S_YNO("qname-minimisation:", qname_minimisation)
|
||||||
else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
|
else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
|
||||||
|
|
@ -798,11 +809,15 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||||
else O_DEC(opt, "max-udp-size", max_udp_size)
|
else O_DEC(opt, "max-udp-size", max_udp_size)
|
||||||
else O_STR(opt, "python-script", python_script)
|
else O_STR(opt, "python-script", python_script)
|
||||||
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
|
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
|
||||||
|
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
|
||||||
else O_DEC(opt, "ratelimit", ratelimit)
|
else O_DEC(opt, "ratelimit", ratelimit)
|
||||||
|
else O_MEM(opt, "ip-ratelimit-size", ip_ratelimit_size)
|
||||||
else O_MEM(opt, "ratelimit-size", ratelimit_size)
|
else O_MEM(opt, "ratelimit-size", ratelimit_size)
|
||||||
|
else O_DEC(opt, "ip-ratelimit-slabs", ip_ratelimit_slabs)
|
||||||
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
|
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
|
||||||
else O_LS2(opt, "ratelimit-for-domain", ratelimit_for_domain)
|
else O_LS2(opt, "ratelimit-for-domain", ratelimit_for_domain)
|
||||||
else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
|
else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
|
||||||
|
else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor)
|
||||||
else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
|
else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
|
||||||
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
|
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
|
||||||
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
|
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,16 @@ struct config_file {
|
||||||
/** true to disable DNSSEC lameness check in iterator */
|
/** true to disable DNSSEC lameness check in iterator */
|
||||||
int disable_dnssec_lame_check;
|
int disable_dnssec_lame_check;
|
||||||
|
|
||||||
/** ratelimit 0 is off, otherwise qps (unless overridden) */
|
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
|
||||||
|
int ip_ratelimit;
|
||||||
|
/** number of slabs for ip_ratelimit cache */
|
||||||
|
size_t ip_ratelimit_slabs;
|
||||||
|
/** memory size in bytes for ip_ratelimit cache */
|
||||||
|
size_t ip_ratelimit_size;
|
||||||
|
/** ip_ratelimit factor, 0 blocks all, 10 allows 1/10 of traffic */
|
||||||
|
int ip_ratelimit_factor;
|
||||||
|
|
||||||
|
/** ratelimit for domains. 0 is off, otherwise qps (unless overridden) */
|
||||||
int ratelimit;
|
int ratelimit;
|
||||||
/** number of slabs for ratelimit cache */
|
/** number of slabs for ratelimit cache */
|
||||||
size_t ratelimit_slabs;
|
size_t ratelimit_slabs;
|
||||||
|
|
|
||||||
2724
util/configlexer.c
2724
util/configlexer.c
File diff suppressed because it is too large
Load diff
|
|
@ -387,11 +387,15 @@ dnstap-log-forwarder-query-messages{COLON} {
|
||||||
dnstap-log-forwarder-response-messages{COLON} {
|
dnstap-log-forwarder-response-messages{COLON} {
|
||||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
|
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
|
||||||
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
|
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
|
||||||
|
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
|
||||||
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
|
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
|
||||||
|
ip-ratelimit-slabs{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SLABS) }
|
||||||
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
|
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
|
||||||
|
ip-ratelimit-size{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SIZE) }
|
||||||
ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) }
|
ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) }
|
||||||
ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) }
|
ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) }
|
||||||
ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) }
|
ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) }
|
||||||
|
ip-ratelimit-factor{COLON} { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) }
|
||||||
ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) }
|
ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) }
|
||||||
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
|
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
|
||||||
|
|
||||||
|
|
|
||||||
1932
util/configparser.c
1932
util/configparser.c
File diff suppressed because it is too large
Load diff
|
|
@ -203,31 +203,35 @@ extern int yydebug;
|
||||||
VAR_HARDEN_ALGO_DOWNGRADE = 413,
|
VAR_HARDEN_ALGO_DOWNGRADE = 413,
|
||||||
VAR_IP_TRANSPARENT = 414,
|
VAR_IP_TRANSPARENT = 414,
|
||||||
VAR_DISABLE_DNSSEC_LAME_CHECK = 415,
|
VAR_DISABLE_DNSSEC_LAME_CHECK = 415,
|
||||||
VAR_RATELIMIT = 416,
|
VAR_IP_RATELIMIT = 416,
|
||||||
VAR_RATELIMIT_SLABS = 417,
|
VAR_IP_RATELIMIT_SLABS = 417,
|
||||||
VAR_RATELIMIT_SIZE = 418,
|
VAR_IP_RATELIMIT_SIZE = 418,
|
||||||
VAR_RATELIMIT_FOR_DOMAIN = 419,
|
VAR_RATELIMIT = 419,
|
||||||
VAR_RATELIMIT_BELOW_DOMAIN = 420,
|
VAR_RATELIMIT_SLABS = 420,
|
||||||
VAR_RATELIMIT_FACTOR = 421,
|
VAR_RATELIMIT_SIZE = 421,
|
||||||
VAR_CAPS_WHITELIST = 422,
|
VAR_RATELIMIT_FOR_DOMAIN = 422,
|
||||||
VAR_CACHE_MAX_NEGATIVE_TTL = 423,
|
VAR_RATELIMIT_BELOW_DOMAIN = 423,
|
||||||
VAR_PERMIT_SMALL_HOLDDOWN = 424,
|
VAR_IP_RATELIMIT_FACTOR = 424,
|
||||||
VAR_QNAME_MINIMISATION = 425,
|
VAR_RATELIMIT_FACTOR = 425,
|
||||||
VAR_QNAME_MINIMISATION_STRICT = 426,
|
VAR_CAPS_WHITELIST = 426,
|
||||||
VAR_IP_FREEBIND = 427,
|
VAR_CACHE_MAX_NEGATIVE_TTL = 427,
|
||||||
VAR_DEFINE_TAG = 428,
|
VAR_PERMIT_SMALL_HOLDDOWN = 428,
|
||||||
VAR_LOCAL_ZONE_TAG = 429,
|
VAR_QNAME_MINIMISATION = 429,
|
||||||
VAR_ACCESS_CONTROL_TAG = 430,
|
VAR_QNAME_MINIMISATION_STRICT = 430,
|
||||||
VAR_LOCAL_ZONE_OVERRIDE = 431,
|
VAR_IP_FREEBIND = 431,
|
||||||
VAR_ACCESS_CONTROL_TAG_ACTION = 432,
|
VAR_DEFINE_TAG = 432,
|
||||||
VAR_ACCESS_CONTROL_TAG_DATA = 433,
|
VAR_LOCAL_ZONE_TAG = 433,
|
||||||
VAR_VIEW = 434,
|
VAR_ACCESS_CONTROL_TAG = 434,
|
||||||
VAR_ACCESS_CONTROL_VIEW = 435,
|
VAR_LOCAL_ZONE_OVERRIDE = 435,
|
||||||
VAR_VIEW_FIRST = 436,
|
VAR_ACCESS_CONTROL_TAG_ACTION = 436,
|
||||||
VAR_SERVE_EXPIRED = 437,
|
VAR_ACCESS_CONTROL_TAG_DATA = 437,
|
||||||
VAR_FAKE_DSA = 438,
|
VAR_VIEW = 438,
|
||||||
VAR_LOG_IDENTITY = 439,
|
VAR_ACCESS_CONTROL_VIEW = 439,
|
||||||
VAR_USE_SYSTEMD = 440
|
VAR_VIEW_FIRST = 440,
|
||||||
|
VAR_SERVE_EXPIRED = 441,
|
||||||
|
VAR_FAKE_DSA = 442,
|
||||||
|
VAR_LOG_IDENTITY = 443,
|
||||||
|
VAR_USE_SYSTEMD = 444
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/* Tokens. */
|
/* Tokens. */
|
||||||
|
|
@ -389,31 +393,35 @@ extern int yydebug;
|
||||||
#define VAR_HARDEN_ALGO_DOWNGRADE 413
|
#define VAR_HARDEN_ALGO_DOWNGRADE 413
|
||||||
#define VAR_IP_TRANSPARENT 414
|
#define VAR_IP_TRANSPARENT 414
|
||||||
#define VAR_DISABLE_DNSSEC_LAME_CHECK 415
|
#define VAR_DISABLE_DNSSEC_LAME_CHECK 415
|
||||||
#define VAR_RATELIMIT 416
|
#define VAR_IP_RATELIMIT 416
|
||||||
#define VAR_RATELIMIT_SLABS 417
|
#define VAR_IP_RATELIMIT_SLABS 417
|
||||||
#define VAR_RATELIMIT_SIZE 418
|
#define VAR_IP_RATELIMIT_SIZE 418
|
||||||
#define VAR_RATELIMIT_FOR_DOMAIN 419
|
#define VAR_RATELIMIT 419
|
||||||
#define VAR_RATELIMIT_BELOW_DOMAIN 420
|
#define VAR_RATELIMIT_SLABS 420
|
||||||
#define VAR_RATELIMIT_FACTOR 421
|
#define VAR_RATELIMIT_SIZE 421
|
||||||
#define VAR_CAPS_WHITELIST 422
|
#define VAR_RATELIMIT_FOR_DOMAIN 422
|
||||||
#define VAR_CACHE_MAX_NEGATIVE_TTL 423
|
#define VAR_RATELIMIT_BELOW_DOMAIN 423
|
||||||
#define VAR_PERMIT_SMALL_HOLDDOWN 424
|
#define VAR_IP_RATELIMIT_FACTOR 424
|
||||||
#define VAR_QNAME_MINIMISATION 425
|
#define VAR_RATELIMIT_FACTOR 425
|
||||||
#define VAR_QNAME_MINIMISATION_STRICT 426
|
#define VAR_CAPS_WHITELIST 426
|
||||||
#define VAR_IP_FREEBIND 427
|
#define VAR_CACHE_MAX_NEGATIVE_TTL 427
|
||||||
#define VAR_DEFINE_TAG 428
|
#define VAR_PERMIT_SMALL_HOLDDOWN 428
|
||||||
#define VAR_LOCAL_ZONE_TAG 429
|
#define VAR_QNAME_MINIMISATION 429
|
||||||
#define VAR_ACCESS_CONTROL_TAG 430
|
#define VAR_QNAME_MINIMISATION_STRICT 430
|
||||||
#define VAR_LOCAL_ZONE_OVERRIDE 431
|
#define VAR_IP_FREEBIND 431
|
||||||
#define VAR_ACCESS_CONTROL_TAG_ACTION 432
|
#define VAR_DEFINE_TAG 432
|
||||||
#define VAR_ACCESS_CONTROL_TAG_DATA 433
|
#define VAR_LOCAL_ZONE_TAG 433
|
||||||
#define VAR_VIEW 434
|
#define VAR_ACCESS_CONTROL_TAG 434
|
||||||
#define VAR_ACCESS_CONTROL_VIEW 435
|
#define VAR_LOCAL_ZONE_OVERRIDE 435
|
||||||
#define VAR_VIEW_FIRST 436
|
#define VAR_ACCESS_CONTROL_TAG_ACTION 436
|
||||||
#define VAR_SERVE_EXPIRED 437
|
#define VAR_ACCESS_CONTROL_TAG_DATA 437
|
||||||
#define VAR_FAKE_DSA 438
|
#define VAR_VIEW 438
|
||||||
#define VAR_LOG_IDENTITY 439
|
#define VAR_ACCESS_CONTROL_VIEW 439
|
||||||
#define VAR_USE_SYSTEMD 440
|
#define VAR_VIEW_FIRST 440
|
||||||
|
#define VAR_SERVE_EXPIRED 441
|
||||||
|
#define VAR_FAKE_DSA 442
|
||||||
|
#define VAR_LOG_IDENTITY 443
|
||||||
|
#define VAR_USE_SYSTEMD 444
|
||||||
|
|
||||||
/* Value type. */
|
/* Value type. */
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||||
|
|
@ -424,7 +432,7 @@ union YYSTYPE
|
||||||
|
|
||||||
char* str;
|
char* str;
|
||||||
|
|
||||||
#line 428 "util/configparser.h" /* yacc.c:1909 */
|
#line 436 "util/configparser.h" /* yacc.c:1909 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union YYSTYPE YYSTYPE;
|
typedef union YYSTYPE YYSTYPE;
|
||||||
|
|
|
||||||
|
|
@ -124,8 +124,10 @@ extern struct config_parser_state* cfg_parser;
|
||||||
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
|
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
|
||||||
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
|
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
|
||||||
%token VAR_DISABLE_DNSSEC_LAME_CHECK
|
%token VAR_DISABLE_DNSSEC_LAME_CHECK
|
||||||
|
%token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE
|
||||||
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
|
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
|
||||||
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
|
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN
|
||||||
|
%token VAR_IP_RATELIMIT_FACTOR VAR_RATELIMIT_FACTOR
|
||||||
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
|
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
|
||||||
%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
|
%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
|
||||||
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
||||||
|
|
@ -198,9 +200,12 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||||
server_unblock_lan_zones | server_insecure_lan_zones |
|
server_unblock_lan_zones | server_insecure_lan_zones |
|
||||||
server_dns64_prefix | server_dns64_synthall |
|
server_dns64_prefix | server_dns64_synthall |
|
||||||
server_infra_cache_min_rtt | server_harden_algo_downgrade |
|
server_infra_cache_min_rtt | server_harden_algo_downgrade |
|
||||||
server_ip_transparent | server_ratelimit | server_ratelimit_slabs |
|
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
|
||||||
server_ratelimit_size | server_ratelimit_for_domain |
|
server_ip_ratelimit_slabs | server_ratelimit_slabs |
|
||||||
|
server_ip_ratelimit_size | server_ratelimit_size |
|
||||||
|
server_ratelimit_for_domain |
|
||||||
server_ratelimit_below_domain | server_ratelimit_factor |
|
server_ratelimit_below_domain | server_ratelimit_factor |
|
||||||
|
server_ip_ratelimit_factor |
|
||||||
server_caps_whitelist | server_cache_max_negative_ttl |
|
server_caps_whitelist | server_cache_max_negative_ttl |
|
||||||
server_permit_small_holddown | server_qname_minimisation |
|
server_permit_small_holddown | server_qname_minimisation |
|
||||||
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
||||||
|
|
@ -1504,6 +1509,16 @@ server_access_control_view: VAR_ACCESS_CONTROL_VIEW STRING_ARG STRING_ARG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(server_ip_ratelimit:%s)\n", $2));
|
||||||
|
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||||
|
yyerror("number expected");
|
||||||
|
else cfg_parser->cfg->ip_ratelimit = atoi($2);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
server_ratelimit: VAR_RATELIMIT STRING_ARG
|
server_ratelimit: VAR_RATELIMIT STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_ratelimit:%s)\n", $2));
|
OUTYY(("P(server_ratelimit:%s)\n", $2));
|
||||||
|
|
@ -1513,6 +1528,14 @@ server_ratelimit: VAR_RATELIMIT STRING_ARG
|
||||||
free($2);
|
free($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
server_ip_ratelimit_size: VAR_IP_RATELIMIT_SIZE STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(server_ip_ratelimit_size:%s)\n", $2));
|
||||||
|
if(!cfg_parse_memsize($2, &cfg_parser->cfg->ip_ratelimit_size))
|
||||||
|
yyerror("memory size expected");
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG
|
server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_ratelimit_size:%s)\n", $2));
|
OUTYY(("P(server_ratelimit_size:%s)\n", $2));
|
||||||
|
|
@ -1521,6 +1544,19 @@ server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG
|
||||||
free($2);
|
free($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
server_ip_ratelimit_slabs: VAR_IP_RATELIMIT_SLABS STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", $2));
|
||||||
|
if(atoi($2) == 0)
|
||||||
|
yyerror("number expected");
|
||||||
|
else {
|
||||||
|
cfg_parser->cfg->ip_ratelimit_slabs = atoi($2);
|
||||||
|
if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs))
|
||||||
|
yyerror("must be a power of 2");
|
||||||
|
}
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG
|
server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_ratelimit_slabs:%s)\n", $2));
|
OUTYY(("P(server_ratelimit_slabs:%s)\n", $2));
|
||||||
|
|
@ -1560,6 +1596,15 @@ server_ratelimit_below_domain: VAR_RATELIMIT_BELOW_DOMAIN STRING_ARG STRING_ARG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(server_ip_ratelimit_factor:%s)\n", $2));
|
||||||
|
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||||
|
yyerror("number expected");
|
||||||
|
else cfg_parser->cfg->ip_ratelimit_factor = atoi($2);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG
|
server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_ratelimit_factor:%s)\n", $2));
|
OUTYY(("P(server_ratelimit_factor:%s)\n", $2));
|
||||||
|
|
|
||||||
|
|
@ -456,7 +456,7 @@ void log_dns_msg(const char* str, struct query_info* qinfo,
|
||||||
* status code from, and size of a query response.
|
* status code from, and size of a query response.
|
||||||
*
|
*
|
||||||
* @param v: at what verbosity level to print this.
|
* @param v: at what verbosity level to print this.
|
||||||
* @param qinfo: query section.
|
* @param qinf: query section.
|
||||||
* @param addr: address of the client.
|
* @param addr: address of the client.
|
||||||
* @param addrlen: length of the client address.
|
* @param addrlen: length of the client address.
|
||||||
* @param dur: how long it took to complete the query.
|
* @param dur: how long it took to complete the query.
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,7 @@ fptr_whitelist_hash_sizefunc(lruhash_sizefunc_t fptr)
|
||||||
else if(fptr == &infra_sizefunc) return 1;
|
else if(fptr == &infra_sizefunc) return 1;
|
||||||
else if(fptr == &key_entry_sizefunc) return 1;
|
else if(fptr == &key_entry_sizefunc) return 1;
|
||||||
else if(fptr == &rate_sizefunc) return 1;
|
else if(fptr == &rate_sizefunc) return 1;
|
||||||
|
else if(fptr == &ip_rate_sizefunc) return 1;
|
||||||
else if(fptr == &test_slabhash_sizefunc) return 1;
|
else if(fptr == &test_slabhash_sizefunc) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -228,6 +229,7 @@ fptr_whitelist_hash_compfunc(lruhash_compfunc_t fptr)
|
||||||
else if(fptr == &infra_compfunc) return 1;
|
else if(fptr == &infra_compfunc) return 1;
|
||||||
else if(fptr == &key_entry_compfunc) return 1;
|
else if(fptr == &key_entry_compfunc) return 1;
|
||||||
else if(fptr == &rate_compfunc) return 1;
|
else if(fptr == &rate_compfunc) return 1;
|
||||||
|
else if(fptr == &ip_rate_compfunc) return 1;
|
||||||
else if(fptr == &test_slabhash_compfunc) return 1;
|
else if(fptr == &test_slabhash_compfunc) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -240,6 +242,7 @@ fptr_whitelist_hash_delkeyfunc(lruhash_delkeyfunc_t fptr)
|
||||||
else if(fptr == &infra_delkeyfunc) return 1;
|
else if(fptr == &infra_delkeyfunc) return 1;
|
||||||
else if(fptr == &key_entry_delkeyfunc) return 1;
|
else if(fptr == &key_entry_delkeyfunc) return 1;
|
||||||
else if(fptr == &rate_delkeyfunc) return 1;
|
else if(fptr == &rate_delkeyfunc) return 1;
|
||||||
|
else if(fptr == &ip_rate_delkeyfunc) return 1;
|
||||||
else if(fptr == &test_slabhash_delkey) return 1;
|
else if(fptr == &test_slabhash_delkey) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue