clientlog: enable NTP response rate limiting by default

Change the default interval of both NTP and command rate limiting to -10
(1024 packets per second) and the burst to 16. The default NTP leak is 2
(rate limiting is enabled by default) and the default command leak is 0
(rate limiting is disabled by default).
This commit is contained in:
Miroslav Lichvar 2016-12-15 11:11:05 +01:00
parent 5059019535
commit 50022e9286
4 changed files with 53 additions and 65 deletions

View file

@ -119,7 +119,7 @@ static int cmd_token_shift;
prevent an attacker sending requests with spoofed source address prevent an attacker sending requests with spoofed source address
from blocking responses to the address completely. */ from blocking responses to the address completely. */
#define MIN_LEAK_RATE 1 #define MIN_LEAK_RATE 0
#define MAX_LEAK_RATE 4 #define MAX_LEAK_RATE 4
static int ntp_leak_rate; static int ntp_leak_rate;
@ -305,29 +305,19 @@ CLG_Initialise(void)
{ {
int interval, burst, leak_rate; int interval, burst, leak_rate;
max_ntp_tokens = max_cmd_tokens = 0; CNF_GetNTPRateLimit(&interval, &burst, &leak_rate);
ntp_tokens_per_packet = cmd_tokens_per_packet = 0; set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet,
ntp_token_shift = cmd_token_shift = 0; &ntp_token_shift);
ntp_leak_rate = cmd_leak_rate = 0; ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
if (CNF_GetNTPRateLimit(&interval, &burst, &leak_rate)) { CNF_GetCommandRateLimit(&interval, &burst, &leak_rate);
set_bucket_params(interval, burst, &max_ntp_tokens, &ntp_tokens_per_packet, set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet,
&ntp_token_shift); &cmd_token_shift);
ntp_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE); cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
}
if (CNF_GetCommandRateLimit(&interval, &burst, &leak_rate)) {
set_bucket_params(interval, burst, &max_cmd_tokens, &cmd_tokens_per_packet,
&cmd_token_shift);
cmd_leak_rate = CLAMP(MIN_LEAK_RATE, leak_rate, MAX_LEAK_RATE);
}
active = !CNF_GetNoClientLog(); active = !CNF_GetNoClientLog();
if (!active) { if (!active)
if (ntp_leak_rate || cmd_leak_rate)
LOG_FATAL(LOGF_ClientLog, "ratelimit cannot be used with noclientlog");
return; return;
}
/* Calculate the maximum number of slots that can be allocated in the /* Calculate the maximum number of slots that can be allocated in the
configured memory limit. Take into account expanding of the hash configured memory limit. Take into account expanding of the hash
@ -530,7 +520,7 @@ CLG_LimitNTPResponseRate(int index)
Record *record; Record *record;
int drop; int drop;
if (!ntp_tokens_per_packet) if (!ntp_leak_rate)
return 0; return 0;
record = ARR_GetElement(records, index); record = ARR_GetElement(records, index);
@ -571,7 +561,7 @@ CLG_LimitCommandResponseRate(int index)
{ {
Record *record; Record *record;
if (!cmd_tokens_per_packet) if (!cmd_leak_rate)
return 0; return 0;
record = ARR_GetElement(records, index); record = ARR_GetElement(records, index);

31
conf.c
View file

@ -66,8 +66,7 @@ static void parse_log(char *);
static void parse_mailonchange(char *); static void parse_mailonchange(char *);
static void parse_makestep(char *); static void parse_makestep(char *);
static void parse_maxchange(char *); static void parse_maxchange(char *);
static void parse_ratelimit(char *line, int *enabled, int *interval, static void parse_ratelimit(char *line, int *interval, int *burst, int *leak);
int *burst, int *leak);
static void parse_refclock(char *); static void parse_refclock(char *);
static void parse_smoothtime(char *); static void parse_smoothtime(char *);
static void parse_source(char *line, NTP_Source_Type type, int pool); static void parse_source(char *line, NTP_Source_Type type, int pool);
@ -191,14 +190,12 @@ static char *ntp_signd_socket = NULL;
static char *pidfile; static char *pidfile;
/* Rate limiting parameters */ /* Rate limiting parameters */
static int ntp_ratelimit_enabled = 0; static int ntp_ratelimit_interval = -10;
static int ntp_ratelimit_interval = 3; static int ntp_ratelimit_burst = 16;
static int ntp_ratelimit_burst = 8; static int ntp_ratelimit_leak = 2;
static int ntp_ratelimit_leak = 3; static int cmd_ratelimit_interval = -10;
static int cmd_ratelimit_enabled = 0;
static int cmd_ratelimit_interval = 1;
static int cmd_ratelimit_burst = 16; static int cmd_ratelimit_burst = 16;
static int cmd_ratelimit_leak = 2; static int cmd_ratelimit_leak = 0;
/* Smoothing constants */ /* Smoothing constants */
static double smooth_max_freq = 0.0; /* in ppm */ static double smooth_max_freq = 0.0; /* in ppm */
@ -455,8 +452,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
} else if (!strcasecmp(command, "cmdport")) { } else if (!strcasecmp(command, "cmdport")) {
parse_int(p, &cmd_port); parse_int(p, &cmd_port);
} else if (!strcasecmp(command, "cmdratelimit")) { } else if (!strcasecmp(command, "cmdratelimit")) {
parse_ratelimit(p, &cmd_ratelimit_enabled, &cmd_ratelimit_interval, parse_ratelimit(p, &cmd_ratelimit_interval, &cmd_ratelimit_burst, &cmd_ratelimit_leak);
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
} else if (!strcasecmp(command, "combinelimit")) { } else if (!strcasecmp(command, "combinelimit")) {
parse_double(p, &combine_limit); parse_double(p, &combine_limit);
} else if (!strcasecmp(command, "corrtimeratio")) { } else if (!strcasecmp(command, "corrtimeratio")) {
@ -536,8 +532,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
} else if (!strcasecmp(command, "port")) { } else if (!strcasecmp(command, "port")) {
parse_int(p, &ntp_port); parse_int(p, &ntp_port);
} else if (!strcasecmp(command, "ratelimit")) { } else if (!strcasecmp(command, "ratelimit")) {
parse_ratelimit(p, &ntp_ratelimit_enabled, &ntp_ratelimit_interval, parse_ratelimit(p, &ntp_ratelimit_interval, &ntp_ratelimit_burst, &ntp_ratelimit_leak);
&ntp_ratelimit_burst, &ntp_ratelimit_leak);
} else if (!strcasecmp(command, "refclock")) { } else if (!strcasecmp(command, "refclock")) {
parse_refclock(p); parse_refclock(p);
} else if (!strcasecmp(command, "reselectdist")) { } else if (!strcasecmp(command, "reselectdist")) {
@ -642,13 +637,11 @@ parse_source(char *line, NTP_Source_Type type, int pool)
/* ================================================== */ /* ================================================== */
static void static void
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak) parse_ratelimit(char *line, int *interval, int *burst, int *leak)
{ {
int n, val; int n, val;
char *opt; char *opt;
*enabled = 1;
while (*line) { while (*line) {
opt = line; opt = line;
line = CPS_SplitWord(line); line = CPS_SplitWord(line);
@ -1830,22 +1823,20 @@ CNF_GetLockMemory(void)
/* ================================================== */ /* ================================================== */
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak) void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
{ {
*interval = ntp_ratelimit_interval; *interval = ntp_ratelimit_interval;
*burst = ntp_ratelimit_burst; *burst = ntp_ratelimit_burst;
*leak = ntp_ratelimit_leak; *leak = ntp_ratelimit_leak;
return ntp_ratelimit_enabled;
} }
/* ================================================== */ /* ================================================== */
int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak) void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak)
{ {
*interval = cmd_ratelimit_interval; *interval = cmd_ratelimit_interval;
*burst = cmd_ratelimit_burst; *burst = cmd_ratelimit_burst;
*leak = cmd_ratelimit_leak; *leak = cmd_ratelimit_leak;
return cmd_ratelimit_enabled;
} }
/* ================================================== */ /* ================================================== */

4
conf.h
View file

@ -102,8 +102,8 @@ extern void CNF_SetupAccessRestrictions(void);
extern int CNF_GetSchedPriority(void); extern int CNF_GetSchedPriority(void);
extern int CNF_GetLockMemory(void); extern int CNF_GetLockMemory(void);
extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak); extern void CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
extern int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak); extern void CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only); extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2); extern void CNF_GetTempComp(char **file, double *interval, char **point_file, double *T0, double *k0, double *k1, double *k2);

View file

@ -1221,8 +1221,8 @@ source port used in NTP client requests can be set by the
<<acquisitionport,*acquisitionport*>> directive. <<acquisitionport,*acquisitionport*>> directive.
[[ratelimit]]*ratelimit* [_option_]...:: [[ratelimit]]*ratelimit* [_option_]...::
This directive enables response rate limiting for NTP packets. Its purpose is This directive configures response rate limiting for NTP packets. Its purpose
to reduce network traffic with misconfigured or broken NTP clients that are is to reduce network traffic with misconfigured or broken NTP clients that are
polling the server too frequently. The limits are applied to individual IP polling the server too frequently. The limits are applied to individual IP
addresses. If multiple clients share one IP address (e.g. multiple hosts behind addresses. If multiple clients share one IP address (e.g. multiple hosts behind
NAT), the sum of their traffic will be limited. If a client that increases its NAT), the sum of their traffic will be limited. If a client that increases its
@ -1237,35 +1237,40 @@ in any order):
+ +
*interval*::: *interval*:::
This option sets the minimum interval between responses. It is defined as a This option sets the minimum interval between responses. It is defined as a
power of 2 in seconds. The default value is 3 (8 seconds). The minimum value power of 2 in seconds. The default value is -10 (1/1024 of a second, or 1024
is -19 and the maximum value is 12. Note that with values below -4 the rate packets per second). The minimum value is -19 (524288 packets per second) and
limiting is coarse (responses are allowed in bursts, even if the interval the maximum value is 12 (one packet per 4096 seconds). Note that with values
between them is shorter than the specified interval). below -4 the rate limiting is coarse (responses are allowed in bursts, even if
the interval between them is shorter than the specified interval).
*burst*::: *burst*:::
This option sets the maximum number of responses that can be sent in a burst, This option sets the maximum number of responses that can be sent in a burst,
temporarily exceeding the limit specified by the *interval* option. This is temporarily exceeding the limit specified by the *interval* option. This is
useful for clients that make rapid measurements on start (e.g. *chronyd* with useful for clients that make rapid measurements on start (e.g. *chronyd* with
the *iburst* option). The default value is 8. The minimum value is 1 and the the *iburst* option). The default value is 16. The minimum value is 1 and the
maximum value is 255. maximum value is 255.
*leak*::: *leak*:::
This option sets the rate at which responses are randomly allowed even if the This option sets the rate at which responses are randomly allowed even if the
limits specified by the *interval* and *burst* options are exceeded. This is limits specified by the *interval* and *burst* options are exceeded. This is
necessary to prevent an attacker who is sending requests with a spoofed necessary to prevent an attacker who is sending requests with a spoofed
source address from completely blocking responses to that address. The leak source address from completely blocking responses to that address. The leak
rate is defined as a power of 1/2 and it is 3 by default, i.e. on average at rate is defined as a power of 1/2 and it is 2 by default, i.e. on average at
least every eighth request has a response. The minimum value is 1 and the least every fourth request has a response. The minimum value is 0, which
maximum value is 4. disables the rate limiting, and the maximum value is 4 (one response per 16
requests).
:: ::
+ +
An example use of the directive is: An example use of the directive is:
+ +
---- ----
ratelimit interval 4 burst 4 ratelimit interval 1 burst 8
---- ----
+ +
This would reduce the response rate for IP addresses that send packets on This would reduce the response rate for IP addresses sending packets on average
average more frequently than once per 16 seconds or send packets in bursts more than once per 2 seconds, or sending packets in bursts of more than 8
of more than 4 packets. packets, by up to 75% (with default *leak* of 2).
+
Rate limiting can be disabled by setting the *leak* option to 0, or by the
<<noclientlog,*noclientlog*>> directive.
[[smoothtime]]*smoothtime* _max-freq_ _max-wander_ [*leaponly*]:: [[smoothtime]]*smoothtime* _max-freq_ _max-wander_ [*leaponly*]::
The *smoothtime* directive can be used to enable smoothing of the time that The *smoothtime* directive can be used to enable smoothing of the time that
@ -1392,16 +1397,18 @@ This would make *chronyd* use UDP 257 as its command port. (*chronyc* would
need to be run with the *-p 257* switch to inter-operate correctly.) need to be run with the *-p 257* switch to inter-operate correctly.)
[[cmdratelimit]]*cmdratelimit* [_option_]...:: [[cmdratelimit]]*cmdratelimit* [_option_]...::
This directive enables response rate limiting for command packets. It is This directive is identical to the <<ratelimit,*ratelimit*>> directive, except
similar to the <<ratelimit,*ratelimit*>> directive, except responses to it configures rate limiting for command packets and responses to localhost are
localhost are never limited and the default interval is 1 (2 seconds), the default never limited. It is disabled by default (the default *leak* is 0).
burst is 16, and the default leak rate is 2.
+ +
An example of the use of the directive is: An example of the use of the directive is:
+ +
---- ----
cmdratelimit interval 2 cmdratelimit interval -2 burst 128 leak 2
---- ----
+
This would reduce response rate for addresses that send more than 4 requests
per second, or bursts of more than 128 packets, by up to 75%.
=== Real-time clock (RTC) === Real-time clock (RTC)
@ -2220,7 +2227,7 @@ http://www.pool.ntp.org/en/join.html[pool.ntp.org] project. The configuration
is similar to the NTP client with permanent connection, except it needs to is similar to the NTP client with permanent connection, except it needs to
allow client access from all addresses. It is recommended to handpick at least allow client access from all addresses. It is recommended to handpick at least
few good servers, and possibly combine them with a random selection of other few good servers, and possibly combine them with a random selection of other
servers in the pool. Rate limiting can be enabled to not waste too much servers in the pool. The rate limiting interval can be increased to save more
bandwidth on misconfigured and broken NTP clients. The *-r* option with the bandwidth on misconfigured and broken NTP clients. The *-r* option with the
*dumpdir* directive shortens the time for which *chronyd* will not serve time *dumpdir* directive shortens the time for which *chronyd* will not serve time
to its clients when it needs to be restarted for any reason. to its clients when it needs to be restarted for any reason.
@ -2235,7 +2242,7 @@ pool pool.ntp.org iburst
makestep 1.0 3 makestep 1.0 3
rtcsync rtcsync
allow allow
ratelimit interval 2 burst 10 ratelimit interval 1
driftfile @CHRONYVARDIR@/drift driftfile @CHRONYVARDIR@/drift
dumpdir @CHRONYRUNDIR@ dumpdir @CHRONYRUNDIR@
dumponexit dumponexit