mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-03-16 14:57:48 +08:00
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:
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
33
src/main.h
33
src/main.h
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user