nts: rework NTS-KE retry interval
Make the NTS-KE retry interval exponentially increasing, using a factor provided by the NKE session. Use shorter intervals when the server is refusing TCP connections or the connection is closed or timing out before the TLS handshake.
This commit is contained in:
parent
bcdbbbd694
commit
66dc2b6d6b
7 changed files with 68 additions and 8 deletions
4
nts_ke.h
4
nts_ke.h
|
@ -56,6 +56,10 @@
|
|||
#define NKE_MAX_COOKIES 8
|
||||
#define NKE_MAX_KEY_LENGTH SIV_MAX_KEY_LENGTH
|
||||
|
||||
#define NKE_RETRY_FACTOR2_CONNECT 4
|
||||
#define NKE_RETRY_FACTOR2_TLS 10
|
||||
#define NKE_MAX_RETRY_INTERVAL2 19
|
||||
|
||||
typedef struct {
|
||||
int length;
|
||||
unsigned char key[NKE_MAX_KEY_LENGTH];
|
||||
|
|
|
@ -393,3 +393,11 @@ NKC_GetNtsData(NKC_Instance inst,
|
|||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NKC_GetRetryFactor(NKC_Instance inst)
|
||||
{
|
||||
return NKSN_GetRetryFactor(inst->session);
|
||||
}
|
||||
|
|
|
@ -55,4 +55,7 @@ extern int NKC_GetNtsData(NKC_Instance inst,
|
|||
NKE_Cookie *cookies, int *num_cookies, int max_cookies,
|
||||
IPSockAddr *ntp_address);
|
||||
|
||||
/* Get a factor to calculate retry interval (in log2 seconds) */
|
||||
extern int NKC_GetRetryFactor(NKC_Instance inst);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -75,6 +75,7 @@ struct NKSN_Instance_Record {
|
|||
char *label;
|
||||
gnutls_session_t tls_session;
|
||||
SCH_TimeoutID timeout_id;
|
||||
int retry_factor;
|
||||
|
||||
struct Message message;
|
||||
int new_message;
|
||||
|
@ -382,6 +383,12 @@ handle_event(NKSN_Instance inst, int event)
|
|||
LOG(inst->server ? LOGS_DEBUG : LOGS_ERR,
|
||||
"TLS handshake with %s failed : %s", inst->label, gnutls_strerror(r));
|
||||
stop_session(inst);
|
||||
|
||||
/* Increase the retry interval if the handshake did not fail due
|
||||
to the other end closing the connection */
|
||||
if (r != GNUTLS_E_PULL_ERROR && r != GNUTLS_E_PREMATURE_TERMINATION)
|
||||
inst->retry_factor = NKE_RETRY_FACTOR2_TLS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -391,6 +398,8 @@ handle_event(NKSN_Instance inst, int event)
|
|||
return 0;
|
||||
}
|
||||
|
||||
inst->retry_factor = NKE_RETRY_FACTOR2_TLS;
|
||||
|
||||
if (DEBUG) {
|
||||
char *description = gnutls_session_get_desc(inst->tls_session);
|
||||
DEBUG_LOG("Handshake with %s completed %s",
|
||||
|
@ -644,6 +653,7 @@ NKSN_CreateInstance(int server_mode, const char *server_name,
|
|||
inst->label = NULL;
|
||||
inst->tls_session = NULL;
|
||||
inst->timeout_id = 0;
|
||||
inst->retry_factor = NKE_RETRY_FACTOR2_CONNECT;
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
@ -677,6 +687,7 @@ NKSN_StartSession(NKSN_Instance inst, int sock_fd, const char *label,
|
|||
|
||||
inst->label = Strdup(label);
|
||||
inst->timeout_id = SCH_AddTimeoutByDelay(timeout, session_timeout, inst);
|
||||
inst->retry_factor = NKE_RETRY_FACTOR2_CONNECT;
|
||||
|
||||
reset_message(&inst->message);
|
||||
inst->new_message = 0;
|
||||
|
@ -783,3 +794,11 @@ NKSN_StopSession(NKSN_Instance inst)
|
|||
{
|
||||
stop_session(inst);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NKSN_GetRetryFactor(NKSN_Instance inst)
|
||||
{
|
||||
return inst->retry_factor;
|
||||
}
|
||||
|
|
|
@ -80,4 +80,8 @@ extern int NKSN_IsStopped(NKSN_Instance inst);
|
|||
/* Stop the session */
|
||||
extern void NKSN_StopSession(NKSN_Instance inst);
|
||||
|
||||
/* Get a factor to calculate retry interval (in log2 seconds)
|
||||
based on the session state or how it was terminated */
|
||||
extern int NKSN_GetRetryFactor(NKSN_Instance inst);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -54,7 +54,8 @@ struct NNC_Instance_Record {
|
|||
SIV_Instance siv_s2c;
|
||||
NKC_Instance nke;
|
||||
|
||||
double last_nke_attempt;
|
||||
int nke_attempts;
|
||||
double next_nke_attempt;
|
||||
double last_nke_success;
|
||||
NKE_Cookie cookies[NTS_MAX_COOKIES];
|
||||
int num_cookies;
|
||||
|
@ -70,7 +71,8 @@ struct NNC_Instance_Record {
|
|||
static void
|
||||
reset_instance(NNC_Instance inst)
|
||||
{
|
||||
inst->last_nke_attempt = -MIN_NKE_RETRY_INTERVAL;
|
||||
inst->nke_attempts = 0;
|
||||
inst->next_nke_attempt = 0.0;
|
||||
inst->last_nke_success = 0.0;
|
||||
inst->num_cookies = 0;
|
||||
inst->cookie_index = 0;
|
||||
|
@ -167,6 +169,21 @@ set_ntp_address(NNC_Instance inst, NTP_Remote_Address *negotiated_address)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
update_next_nke_attempt(NNC_Instance inst, double now)
|
||||
{
|
||||
int factor, interval;
|
||||
|
||||
if (!inst->nke)
|
||||
return;
|
||||
|
||||
factor = NKC_GetRetryFactor(inst->nke);
|
||||
interval = MIN(factor + inst->nke_attempts - 1, NKE_MAX_RETRY_INTERVAL2);
|
||||
inst->next_nke_attempt = now + UTI_Log2ToDouble(interval);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
get_nke_data(NNC_Instance inst)
|
||||
{
|
||||
|
@ -181,8 +198,9 @@ get_nke_data(NNC_Instance inst)
|
|||
now = SCH_GetLastEventMonoTime();
|
||||
|
||||
if (!inst->nke) {
|
||||
if (now - inst->last_nke_attempt < MIN_NKE_RETRY_INTERVAL) {
|
||||
DEBUG_LOG("Limiting NTS-KE request rate");
|
||||
if (now < inst->next_nke_attempt) {
|
||||
DEBUG_LOG("Limiting NTS-KE request rate (%f seconds)",
|
||||
inst->next_nke_attempt - now);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -194,12 +212,15 @@ get_nke_data(NNC_Instance inst)
|
|||
|
||||
inst->nke = NKC_CreateInstance(&inst->nts_address, inst->name);
|
||||
|
||||
inst->nke_attempts++;
|
||||
update_next_nke_attempt(inst, now);
|
||||
|
||||
if (!NKC_Start(inst->nke))
|
||||
return 0;
|
||||
|
||||
inst->last_nke_attempt = now;
|
||||
}
|
||||
|
||||
update_next_nke_attempt(inst, now);
|
||||
|
||||
if (NKC_IsActive(inst->nke))
|
||||
return 0;
|
||||
|
||||
|
@ -418,7 +439,8 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
|
|||
|
||||
/* At this point we know the client interoperates with the server. Allow a
|
||||
new NTS-KE session to be started as soon as the cookies run out. */
|
||||
inst->last_nke_attempt = -MIN_NKE_RETRY_INTERVAL;
|
||||
inst->nke_attempts = 0;
|
||||
inst->next_nke_attempt = 0.0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ get_request(NNC_Instance inst)
|
|||
TEST_CHECK(!NNC_GenerateRequestAuth(inst, &packet, &info));
|
||||
|
||||
while (!NNC_PrepareForAuth(inst)) {
|
||||
inst->last_nke_attempt = random() % 100000 - 50000;
|
||||
inst->next_nke_attempt = SCH_GetLastEventMonoTime() + random() % 10 - 7;
|
||||
}
|
||||
|
||||
TEST_CHECK(inst->num_cookies > 0);
|
||||
|
|
Loading…
Reference in a new issue