ntp: ignore poll in KoD RATE packets

The meaning of the poll value in KoD RATE packets is not currently
defined in the NTP specification (RFC 5905). In the reference NTP
implementation it signals the minimum acceptable polling interval to the
clients. In chrony the minimum poll is set to the KoD RATE poll if it's
larger, but not to a larger value than 10.

The problem is that ntpd as a server sets the KoD RATE poll to the
maximum of the client's poll and the configured rate limiting interval.
An attacker can send a burst of spoofed packets to the server to trigger
the client's request rate limit. When the client sends its next request
and the server responds with a KoD RATE packet, the client will set its
minimum poll to the current poll and it will no longer be able to switch
to a shorter poll when needed.

ntpd could be fixed to always set the KoD RATE poll to the rate limiting
interval. Unfortunately, ntpd as a client seems to depend on the current
behavior. It tries to follow the server poll and if the KoD RATE poll
was shorter than the current poll, the polling interval would be
reduced, defeating the purpose of KoD RATE. The server fix will probably
need to wait until clients are fixed and that could take a very long
time.

For now, ignore the poll value in KoD RATE packets. Just add an extra
delay based on the current poll to the next transmit timeout and stop an
ongoing burst.
This commit is contained in:
Miroslav Lichvar 2015-11-16 15:21:32 +01:00
parent a634fd3a2d
commit d28d644b04

View file

@ -1380,24 +1380,6 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
/* Reduce polling rate if KoD RATE was received */
if (kod_rate) {
if (message->poll > inst->minpoll) {
/* Set our minpoll to message poll, but use a reasonable maximum */
if (message->poll <= MAX_KOD_RATE_POLL)
inst->minpoll = message->poll;
else if (inst->minpoll < MAX_KOD_RATE_POLL)
inst->minpoll = MAX_KOD_RATE_POLL;
if (inst->minpoll > inst->maxpoll)
inst->maxpoll = inst->minpoll;
if (inst->minpoll > inst->local_poll)
inst->local_poll = inst->minpoll;
LOG(LOGS_WARN, LOGF_NtpCore,
"Received KoD RATE with poll %d from %s, minpoll set to %d",
message->poll, UTI_IPToString(&inst->remote_addr.ip_addr),
inst->minpoll);
}
/* Stop ongoing burst */
if (inst->opmode == MD_BURST_WAS_OFFLINE || inst->opmode == MD_BURST_WAS_ONLINE) {
inst->burst_good_samples_to_go = 0;