ntp: add server support for KoD RATE
Add "kod" option to the ratelimit directive to respond with the KoD RATE code to randomly selected requests exceeding the configured limit. This complements the client support of KoD RATE. It's disabled by default. There can be only one KoD code in one response. If both NTS NAK and RATE codes are triggered, drop the response. The KoD RATE code can be set in an NTS-authenticated response.
This commit is contained in:
parent
aac898343e
commit
24d28cd679
6 changed files with 41 additions and 11 deletions
|
@ -374,7 +374,7 @@ CLG_Initialise(void)
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case CLG_NTP:
|
case CLG_NTP:
|
||||||
if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate))
|
if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate, &krate))
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case CLG_NTSKE:
|
case CLG_NTSKE:
|
||||||
|
|
16
conf.c
16
conf.c
|
@ -79,7 +79,7 @@ static void parse_maxchange(char *);
|
||||||
static void parse_ntsserver(char *, ARR_Instance files);
|
static void parse_ntsserver(char *, ARR_Instance files);
|
||||||
static void parse_ntstrustedcerts(char *);
|
static void parse_ntstrustedcerts(char *);
|
||||||
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
static void parse_ratelimit(char *line, int *enabled, int *interval,
|
||||||
int *burst, int *leak);
|
int *burst, int *leak, int *kod);
|
||||||
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, char *type, int fatal);
|
static void parse_source(char *line, char *type, int fatal);
|
||||||
|
@ -220,6 +220,7 @@ static int ntp_ratelimit_enabled = 0;
|
||||||
static int ntp_ratelimit_interval = 3;
|
static int ntp_ratelimit_interval = 3;
|
||||||
static int ntp_ratelimit_burst = 8;
|
static int ntp_ratelimit_burst = 8;
|
||||||
static int ntp_ratelimit_leak = 2;
|
static int ntp_ratelimit_leak = 2;
|
||||||
|
static int ntp_ratelimit_kod = 0;
|
||||||
static int nts_ratelimit_enabled = 0;
|
static int nts_ratelimit_enabled = 0;
|
||||||
static int nts_ratelimit_interval = 6;
|
static int nts_ratelimit_interval = 6;
|
||||||
static int nts_ratelimit_burst = 8;
|
static int nts_ratelimit_burst = 8;
|
||||||
|
@ -591,7 +592,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||||
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_enabled, &cmd_ratelimit_interval,
|
||||||
&cmd_ratelimit_burst, &cmd_ratelimit_leak);
|
&cmd_ratelimit_burst, &cmd_ratelimit_leak, NULL);
|
||||||
} else if (!strcasecmp(command, "combinelimit")) {
|
} else if (!strcasecmp(command, "combinelimit")) {
|
||||||
parse_double(p, &combine_limit);
|
parse_double(p, &combine_limit);
|
||||||
} else if (!strcasecmp(command, "confdir")) {
|
} else if (!strcasecmp(command, "confdir")) {
|
||||||
|
@ -678,7 +679,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||||
parse_string(p, &ntp_signd_socket);
|
parse_string(p, &ntp_signd_socket);
|
||||||
} else if (!strcasecmp(command, "ntsratelimit")) {
|
} else if (!strcasecmp(command, "ntsratelimit")) {
|
||||||
parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
|
parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
|
||||||
&nts_ratelimit_burst, &nts_ratelimit_leak);
|
&nts_ratelimit_burst, &nts_ratelimit_leak, NULL);
|
||||||
} else if (!strcasecmp(command, "ntscachedir") ||
|
} else if (!strcasecmp(command, "ntscachedir") ||
|
||||||
!strcasecmp(command, "ntsdumpdir")) {
|
!strcasecmp(command, "ntsdumpdir")) {
|
||||||
parse_string(p, &nts_dump_dir);
|
parse_string(p, &nts_dump_dir);
|
||||||
|
@ -710,7 +711,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
||||||
parse_int(p, &ptp_port);
|
parse_int(p, &ptp_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_enabled, &ntp_ratelimit_interval,
|
||||||
&ntp_ratelimit_burst, &ntp_ratelimit_leak);
|
&ntp_ratelimit_burst, &ntp_ratelimit_leak, &ntp_ratelimit_kod);
|
||||||
} else if (!strcasecmp(command, "refclock")) {
|
} else if (!strcasecmp(command, "refclock")) {
|
||||||
parse_refclock(p);
|
parse_refclock(p);
|
||||||
} else if (!strcasecmp(command, "refresh")) {
|
} else if (!strcasecmp(command, "refresh")) {
|
||||||
|
@ -848,7 +849,7 @@ parse_sourcedir(char *line)
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
|
parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak, int *kod)
|
||||||
{
|
{
|
||||||
int n, val;
|
int n, val;
|
||||||
char *opt;
|
char *opt;
|
||||||
|
@ -869,6 +870,8 @@ parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
|
||||||
*burst = val;
|
*burst = val;
|
||||||
else if (!strcasecmp(opt, "leak"))
|
else if (!strcasecmp(opt, "leak"))
|
||||||
*leak = val;
|
*leak = val;
|
||||||
|
else if (!strcasecmp(opt, "kod") && kod)
|
||||||
|
*kod = val;
|
||||||
else
|
else
|
||||||
command_parse_error();
|
command_parse_error();
|
||||||
}
|
}
|
||||||
|
@ -2428,11 +2431,12 @@ CNF_GetLockMemory(void)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
|
int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod)
|
||||||
{
|
{
|
||||||
*interval = ntp_ratelimit_interval;
|
*interval = ntp_ratelimit_interval;
|
||||||
*burst = ntp_ratelimit_burst;
|
*burst = ntp_ratelimit_burst;
|
||||||
*leak = ntp_ratelimit_leak;
|
*leak = ntp_ratelimit_leak;
|
||||||
|
*kod = ntp_ratelimit_kod;
|
||||||
return ntp_ratelimit_enabled;
|
return ntp_ratelimit_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
conf.h
2
conf.h
|
@ -115,7 +115,7 @@ 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 int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod);
|
||||||
extern int CNF_GetNtsRateLimit(int *interval, int *burst, int *leak);
|
extern int CNF_GetNtsRateLimit(int *interval, int *burst, int *leak);
|
||||||
extern int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
|
extern int 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);
|
||||||
|
|
|
@ -1861,6 +1861,14 @@ source address from completely blocking responses to that address. The leak
|
||||||
rate is defined as a power of 1/2 and it is 2 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 fourth request has a response. The minimum value is 1 and the
|
least every fourth request has a response. The minimum value is 1 and the
|
||||||
maximum value is 4.
|
maximum value is 4.
|
||||||
|
*kod* _rate_:::
|
||||||
|
This option sets the rate at which Kiss-o'-Death (KoD) RATE responses are
|
||||||
|
randomly sent when the limits specified by the *interval* and *burst* options
|
||||||
|
are exceeded. It is an additional stream of responses to the *leak* option. A
|
||||||
|
KoD RATE response is a request for the client to reduce its polling rate. Few
|
||||||
|
implementations actually support it. The rate is defined as a power of 1/2. The
|
||||||
|
default value is 0, which means disabled. The minimum value is 0 and the maximu
|
||||||
|
value is 4.
|
||||||
{blank}::
|
{blank}::
|
||||||
+
|
+
|
||||||
An example use of the directive is:
|
An example use of the directive is:
|
||||||
|
@ -1876,7 +1884,7 @@ packets, by up to 75% (with default *leak* of 2).
|
||||||
[[ntsratelimit]]*ntsratelimit* [_option_]...::
|
[[ntsratelimit]]*ntsratelimit* [_option_]...::
|
||||||
This directive enables rate limiting of NTS-KE requests. It is similar to the
|
This directive enables rate limiting of NTS-KE requests. It is similar to the
|
||||||
<<ratelimit,*ratelimit*>> directive, except the default interval is 6
|
<<ratelimit,*ratelimit*>> directive, except the default interval is 6
|
||||||
(1 connection per 64 seconds).
|
(1 connection per 64 seconds) and the *kod* option is not supported.
|
||||||
+
|
+
|
||||||
An example of the use of the directive is:
|
An example of the use of the directive is:
|
||||||
+
|
+
|
||||||
|
@ -2024,8 +2032,8 @@ need to be run with the *-p 257* option to inter-operate correctly.)
|
||||||
[[cmdratelimit]]*cmdratelimit* [_option_]...::
|
[[cmdratelimit]]*cmdratelimit* [_option_]...::
|
||||||
This directive enables response rate limiting for command packets. It is
|
This directive enables response rate limiting for command packets. It is
|
||||||
similar to the <<ratelimit,*ratelimit*>> directive, except responses to
|
similar to the <<ratelimit,*ratelimit*>> directive, except responses to
|
||||||
localhost are never limited and the default interval is -4 (16 packets per
|
localhost are never limited, the default interval is -4 (16 packets per
|
||||||
second).
|
second), and the *kod* option is not supported.
|
||||||
+
|
+
|
||||||
An example of the use of the directive is:
|
An example of the use of the directive is:
|
||||||
+
|
+
|
||||||
|
|
|
@ -2717,6 +2717,13 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (limit == CLG_KOD) {
|
||||||
|
/* Don't respond if there is a conflict with the NTS NAK */
|
||||||
|
if (kod != 0)
|
||||||
|
return;
|
||||||
|
kod = KOD_RATE;
|
||||||
|
}
|
||||||
|
|
||||||
local_ntp_rx = NULL;
|
local_ntp_rx = NULL;
|
||||||
tx_ts = NULL;
|
tx_ts = NULL;
|
||||||
interleaved = 0;
|
interleaved = 0;
|
||||||
|
|
|
@ -15,4 +15,15 @@ check_sync || test_fail
|
||||||
check_file_messages " 2 1 " 1200 1300 log.packets || test_fail
|
check_file_messages " 2 1 " 1200 1300 log.packets || test_fail
|
||||||
check_file_messages " 1 2 " 180 220 log.packets || test_fail
|
check_file_messages " 1 2 " 180 220 log.packets || test_fail
|
||||||
|
|
||||||
|
server_conf="ratelimit interval 6 burst 2 leak 4 kod 2"
|
||||||
|
|
||||||
|
run_test || test_fail
|
||||||
|
check_chronyd_exit || test_fail
|
||||||
|
check_packet_interval || test_fail
|
||||||
|
check_sync || test_fail
|
||||||
|
|
||||||
|
check_file_messages " 2 1 " 700 850 log.packets || test_fail
|
||||||
|
check_file_messages " 1 2 " 350 450 log.packets || test_fail
|
||||||
|
check_log_messages "Received KoD RATE.*\.123.1" 100 140 || test_fail
|
||||||
|
|
||||||
test_pass
|
test_pass
|
||||||
|
|
Loading…
Reference in a new issue