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:
parent
5059019535
commit
50022e9286
4 changed files with 53 additions and 65 deletions
34
clientlog.c
34
clientlog.c
|
@ -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
31
conf.c
|
@ -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
4
conf.h
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue