main: store additional statistics globally

That is, store:
 * number of timed out sessions
 * number of timed out due being idle sessions
 * number of errored sessions
 * total number of session handled (closed)
 * total number of kbytes sent
 * total number of kbytes received
 * minimum MTU seen
 * maximum MTU seen
 * total authentication failures
 * average/max authentication time (in secs)
 * average/max session time (in minutes)

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
This commit is contained in:
Nikos Mavrogiannopoulos
2017-03-11 22:03:35 +01:00
parent 81d2a86eff
commit e9cf88f8c2
8 changed files with 150 additions and 21 deletions

View File

@@ -137,6 +137,9 @@ message cli_stats_msg
optional uint32 discon_reason = 8;
optional uint32 secmod_client_entries = 9; /* from sec-mod to main only */
optional uint32 secmod_tlsdb_entries = 10; /* from sec-mod to main only */
optional uint64 secmod_auth_failures = 11; /* failures since last update - sec-mod to main only */
optional uint32 secmod_avg_auth_time = 12; /* average auth time in seconds - sec-mod to main only */
optional uint32 secmod_max_auth_time = 13; /* max auth time in seconds - sec-mod to main only */
}
/* UDP_FD */

View File

@@ -179,11 +179,11 @@ static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
rep.status = 1;
rep.pid = getpid();
rep.start_time = ctx->s->start_time;
rep.start_time = ctx->s->stats.start_time;
rep.sec_mod_pid = ctx->s->sec_mod_pid;
rep.active_clients = ctx->s->active_clients;
rep.secmod_client_entries = ctx->s->secmod_client_entries;
rep.stored_tls_sessions = ctx->s->tlsdb_entries;
rep.active_clients = ctx->s->stats.active_clients;
rep.secmod_client_entries = ctx->s->stats.secmod_client_entries;
rep.stored_tls_sessions = ctx->s->stats.tlsdb_entries;
rep.banned_ips = main_ban_db_elems(ctx->s);
ret = send_msg(ctx->pool, cfd, CTL_CMD_STATUS_REP, &rep,

View File

@@ -85,7 +85,7 @@ struct proc_st *ctmp;
list_add(&s->proc_list.head, &(ctmp->list));
put_into_cgroup(s, s->config->cgroup, pid);
s->active_clients++;
s->stats.active_clients++;
return ctmp;
}
@@ -100,7 +100,7 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
ev_child_stop(EV_A_ &proc->ev_child);
list_del(&proc->list);
s->active_clients--;
s->stats.active_clients--;
if ((flags&RPROC_KILL) && proc->pid != -1 && proc->pid != 0)
kill(proc->pid, SIGTERM);

View File

@@ -402,6 +402,16 @@ void apply_default_config(main_server_st *s, proc_st *proc, GroupCfgSt *gc)
(*proc->config_usage_count)++;
}
static void update_auth_failures(main_server_st * s, uint64_t auth_failures)
{
if (s->stats.auth_failures + auth_failures < s->stats.auth_failures) {
mslog(s, NULL, LOG_INFO, "overflow on updating authentication failures; resetting");
s->stats.auth_failures = 0;
return;
}
s->stats.auth_failures += auth_failures;
}
int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie, unsigned cookie_size)
{
int ret, e;
@@ -449,7 +459,8 @@ int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie
}
if (msg->reply != AUTH__REP__OK) {
mslog(s, proc, LOG_DEBUG, "could not initiate session");
mslog(s, proc, LOG_DEBUG, "session initiation was rejected");
update_auth_failures(s, 1);
return -1;
}
@@ -495,6 +506,64 @@ int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie
return 0;
}
static void update_main_stats(main_server_st * s, struct proc_st *proc, uint64_t auth_failures, uint32_t avg_auth_time, uint32_t max_auth_time)
{
uint64_t kb_in, kb_out;
time_t now = time(0), stime;
if (proc->discon_reason == REASON_IDLE_TIMEOUT)
s->stats.session_idle_timeouts++;
else if (proc->discon_reason == REASON_SESSION_TIMEOUT)
s->stats.session_timeouts++;
else if (proc->discon_reason == REASON_ERROR)
s->stats.session_errors++;
s->stats.sessions_closed++;
if (s->stats.sessions_closed == 0) { /* overflow */
goto reset;
}
kb_in = proc->bytes_in/1000;
kb_out = proc->bytes_out/1000;
if (s->stats.kbytes_in + kb_in < s->stats.kbytes_in)
goto reset;
if (s->stats.kbytes_out + kb_out < s->stats.kbytes_out)
goto reset;
update_auth_failures(s, auth_failures);
s->stats.kbytes_in += kb_in;
s->stats.kbytes_out += kb_out;
if (s->stats.min_mtu == 0 || proc->mtu < s->stats.min_mtu)
s->stats.min_mtu = proc->mtu;
if (s->stats.max_mtu == 0 || proc->mtu > s->stats.min_mtu)
s->stats.max_mtu = proc->mtu;
/* connection time in minutes */
stime = (now - proc->conn_time)/60;
if (stime > 0) {
s->stats.avg_session_mins = ((s->stats.sessions_closed-1) * s->stats.avg_session_mins + stime) / s->stats.sessions_closed;
if (stime > s->stats.max_session_mins)
s->stats.max_session_mins = stime;
}
s->stats.avg_auth_time = avg_auth_time;
s->stats.max_auth_time = max_auth_time;
return;
reset:
mslog(s, NULL, LOG_INFO, "overflow on updating server statistics, resetting stats");
s->stats.session_idle_timeouts = 0;
s->stats.session_timeouts = 0;
s->stats.session_errors = 0;
s->stats.last_reset = now;
s->stats.kbytes_in = 0;
s->stats.kbytes_out = 0;
}
int session_close(main_server_st * s, struct proc_st *proc)
{
int ret, e;
@@ -533,11 +602,14 @@ int session_close(main_server_st * s, struct proc_st *proc)
proc->bytes_in = msg->bytes_in;
proc->bytes_out = msg->bytes_out;
if (msg->has_secmod_client_entries)
s->secmod_client_entries = msg->secmod_client_entries;
s->stats.secmod_client_entries = msg->secmod_client_entries;
if (msg->has_secmod_tlsdb_entries)
s->tlsdb_entries = msg->secmod_tlsdb_entries;
if (msg->has_discon_reason)
s->stats.tlsdb_entries = msg->secmod_tlsdb_entries;
if (msg->has_discon_reason) {
proc->discon_reason = msg->discon_reason;
}
update_main_stats(s, proc, msg->secmod_auth_failures, msg->secmod_avg_auth_time, msg->secmod_max_auth_time);
cli_stats_msg__free_unpacked(msg, &pa);

View File

@@ -1080,9 +1080,9 @@ static void listen_watcher_cb (EV_P_ ev_io *w, int revents)
set_block(fd);
#endif
if (s->config->max_clients > 0 && s->active_clients >= s->config->max_clients) {
if (s->config->max_clients > 0 && s->stats.active_clients >= s->config->max_clients) {
close(fd);
mslog(s, NULL, LOG_INFO, "reached maximum client limit (active: %u)", s->active_clients);
mslog(s, NULL, LOG_INFO, "reached maximum client limit (active: %u)", s->stats.active_clients);
return;
}
@@ -1262,7 +1262,7 @@ int main(int argc, char** argv)
}
s->main_pool = main_pool;
s->creds = &creds;
s->start_time = time(0);
s->stats.start_time = s->stats.last_reset = time(0);
s->top_fd = -1;
s->ctl_fd = -1;

View File

@@ -171,6 +171,32 @@ struct proc_hash_db_st {
unsigned total;
};
struct main_stats_st {
uint64_t session_timeouts; /* sessions with timeout */
uint64_t session_idle_timeouts; /* sessions with idle timeout */
uint64_t session_errors; /* sessions closed with error */
uint64_t sessions_closed; /* sessions closed */
uint64_t kbytes_in;
uint64_t kbytes_out;
unsigned min_mtu;
unsigned max_mtu;
unsigned active_clients;
/* updated on the cli_stats_msg from sec-mod.
* Holds the number of entries in secmod list of users */
unsigned secmod_client_entries;
unsigned tlsdb_entries;
time_t start_time;
time_t last_reset;
uint64_t auth_failures; /* authentication failures */
uint32_t avg_auth_time; /* in seconds */
uint32_t max_auth_time; /* in seconds */
uint32_t avg_session_mins; /* in minutes */
uint32_t max_session_mins;
};
typedef struct main_server_st {
struct cfg_st *config; /* pointer inside perm_config */
struct perm_cfg_st *perm_config;
@@ -194,12 +220,7 @@ typedef struct main_server_st {
struct sockaddr_un secmod_addr;
unsigned secmod_addr_len;
unsigned active_clients;
/* updated on the cli_stats_msg from sec-mod.
* Holds the number of entries in secmod list of users */
unsigned secmod_client_entries;
unsigned tlsdb_entries;
time_t start_time;
struct main_stats_st stats;
void * auth_extra;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013-2016 Nikos Mavrogiannopoulos
* Copyright (C) 2013-2017 Nikos Mavrogiannopoulos
* Copyright (C) 2014-2016 Red Hat
*
* This program is free software; you can redistribute it and/or modify
@@ -109,6 +109,22 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e, const char *ip
return;
}
static void update_auth_time_stats(sec_mod_st * sec, time_t secs)
{
if (secs < 0)
return;
sec->total_authentications++;
if (sec->total_authentications == 0) { /* reset stats */
sec->avg_auth_time = 0;
return;
}
if (secs > sec->max_auth_time)
sec->max_auth_time = secs;
sec->avg_auth_time = (sec->avg_auth_time*(sec->total_authentications-1)+secs) / sec->total_authentications;
}
static
int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
{
@@ -125,6 +141,9 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
msg.msg = entry->msg_str;
}
/* calculate time in auth for this client */
update_auth_time_stats(sec, time(0) - entry->time);
msg.has_sid = 1;
msg.sid.data = entry->sid;
msg.sid.len = sizeof(entry->sid);
@@ -139,6 +158,8 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
sec_auth_reply_msg__get_packed_size,
(pack_func) sec_auth_reply_msg__pack);
} else {
sec->auth_failures++;
msg.reply = AUTH__REP__FAILED;
ret = send_msg(entry, cfd, CMD_SEC_AUTH_REPLY,
@@ -554,6 +575,14 @@ int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionClos
rep.secmod_tlsdb_entries = sec->tls_db.entries;
rep.has_secmod_tlsdb_entries = 1;
rep.secmod_auth_failures = sec->auth_failures;
rep.has_secmod_auth_failures = 1;
sec->auth_failures = 0;
rep.secmod_avg_auth_time = sec->avg_auth_time;
rep.secmod_max_auth_time = sec->max_auth_time;
rep.has_secmod_avg_auth_time = 1;
rep.has_secmod_max_auth_time = 1;
ret = send_msg(e, fd, CMD_SECM_CLI_STATS, &rep,
(pack_size_func) cli_stats_msg__get_packed_size,
(pack_func) cli_stats_msg__pack);

View File

@@ -40,6 +40,10 @@ typedef struct sec_mod_st {
int cmd_fd_sync;
tls_sess_db_st tls_db;
uint64_t auth_failures; /* auth failures since the last update (SECM_CLI_STATS) we sent to main */
uint32_t max_auth_time; /* the maximum time spent in (sucessful) authentication */
uint32_t avg_auth_time; /* the average time spent in (sucessful) authentication */
uint32_t total_authentications; /* successful authentications: to calculate the average above */
struct config_mod_st *config_module;
} sec_mod_st;