From 0aa2c86f08f646a6d93463d66388e357b0f7f417 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 25 Feb 2015 14:31:21 +0100 Subject: [PATCH] Added points in KKDCP connections to prevent DoS attacks. --- doc/sample.config | 4 ++-- src/ipc.proto | 13 ++++++++----- src/main-misc.c | 16 ++++++++++++++++ src/main-sec-mod-cmd.c | 6 +++--- src/ocserv-args.def | 4 ++-- src/sec-mod-auth.c | 6 +++--- src/vpn.h | 2 ++ src/worker-kkdcp.c | 30 ++++++++++++++++++++++++++++++ 8 files changed, 66 insertions(+), 15 deletions(-) diff --git a/doc/sample.config b/doc/sample.config index e00ee0d2..de5a59b0 100644 --- a/doc/sample.config +++ b/doc/sample.config @@ -55,7 +55,7 @@ auth = "plain[passwd=./sample.passwd]" # system calls allowed to a worker process, in order to reduce damage from a # bug in the worker process. It is available on Linux systems at a performance cost. # The performance cost is roughly 2% overhead at transfer time (tested on a Linux 3.17.8). -isolate-workers = true +#isolate-workers = true # A banner to be displayed on clients #banner = "Welcome" @@ -216,7 +216,7 @@ min-reauth-time = 300 # Banning clients in ocserv works with a point system. IP addresses # that get a score over that configured number are banned for # min-reauth-time seconds. A wrong password attempt is 10 points, -# a connection is 1 point. +# a KKDCP POST is 1 point, and a connection is 1 point. # # Set to zero to disable. max-ban-score = 50 diff --git a/src/ipc.proto b/src/ipc.proto index f6f16fee..129a6503 100644 --- a/src/ipc.proto +++ b/src/ipc.proto @@ -137,6 +137,13 @@ message session_info_msg optional string dtls_compr = 5; } +/* WORKER_BAN_IP: sent from worker to main */ +message ban_ip_msg +{ + required string ip = 1; + required uint32 score = 2; +} + /* Messages to and from the security module */ @@ -257,8 +264,4 @@ message sec_auth_session_reply_msg } /* SEC_BAN_IP: sent from sec-mod to main */ -message sec_auth_ban_ip -{ - required string ip = 1; - required uint32 score = 2; -} +/* same as: ban_ip_msg */ diff --git a/src/main-misc.c b/src/main-misc.c index 40592a58..49ed278c 100644 --- a/src/main-misc.c +++ b/src/main-misc.c @@ -55,6 +55,7 @@ #include #include #include +#include #include int set_tun_mtu(main_server_st * s, struct proc_st *proc, unsigned mtu) @@ -505,6 +506,21 @@ int handle_commands(main_server_st * s, struct proc_st *proc) } switch (cmd) { + case CMD_BAN_IP:{ + BanIpMsg *tmsg; + + tmsg = ban_ip_msg__unpack(&pa, raw_len, raw); + if (tmsg == NULL) { + mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data"); + ret = ERR_BAD_COMMAND; + goto cleanup; + } + add_ip_to_ban_list(s, tmsg->ip, tmsg->score); + + ban_ip_msg__free_unpacked(tmsg, &pa); + } + + break; case CMD_TUN_MTU:{ TunMtuMsg *tmsg; diff --git a/src/main-sec-mod-cmd.c b/src/main-sec-mod-cmd.c index 29cfa48e..d92f3283 100644 --- a/src/main-sec-mod-cmd.c +++ b/src/main-sec-mod-cmd.c @@ -112,9 +112,9 @@ int handle_sec_mod_commands(main_server_st * s) switch (cmd) { case SM_CMD_AUTH_BAN_IP:{ - SecAuthBanIp *tmsg; + BanIpMsg *tmsg; - tmsg = sec_auth_ban_ip__unpack(&pa, raw_len, raw); + tmsg = ban_ip_msg__unpack(&pa, raw_len, raw); if (tmsg == NULL) { mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data"); ret = ERR_BAD_COMMAND; @@ -122,7 +122,7 @@ int handle_sec_mod_commands(main_server_st * s) } add_ip_to_ban_list(s, tmsg->ip, tmsg->score); - sec_auth_ban_ip__free_unpacked(tmsg, &pa); + ban_ip_msg__free_unpacked(tmsg, &pa); } break; diff --git a/src/ocserv-args.def b/src/ocserv-args.def index 7611b475..cced1566 100644 --- a/src/ocserv-args.def +++ b/src/ocserv-args.def @@ -130,7 +130,7 @@ An example configuration file follows. # system calls allowed to a worker process, in order to reduce damage from a # bug in the worker process. It is available on Linux systems at a performance cost. # The performance cost is roughly 2% overhead at transfer time (tested on a Linux 3.17.8). -#isolate-workers = true +isolate-workers = true # A banner to be displayed on clients #banner = "Welcome" @@ -291,7 +291,7 @@ min-reauth-time = 120 # Banning clients in ocserv works with a point system. IP addresses # that get a score over that configured number are banned for # min-reauth-time seconds. A wrong password attempt is 10 points, -# a connection is 1 point. +# a KKDCP POST is 1 point, and a connection is 1 point. # # Set to zero to disable. max-ban-score = 50 diff --git a/src/sec-mod-auth.c b/src/sec-mod-auth.c index 078071ba..21f14262 100644 --- a/src/sec-mod-auth.c +++ b/src/sec-mod-auth.c @@ -77,7 +77,7 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, void *pool, const char *ip, unsign { void *lpool; int ret, e; - SecAuthBanIp msg = SEC_AUTH_BAN_IP__INIT; + BanIpMsg msg = BAN_IP_MSG__INIT; msg.ip = (char*)ip; msg.score = points; @@ -88,8 +88,8 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, void *pool, const char *ip, unsign } ret = send_msg(lpool, sec->cmd_fd, SM_CMD_AUTH_BAN_IP, &msg, - (pack_size_func) sec_auth_ban_ip__get_packed_size, - (pack_func) sec_auth_ban_ip__pack); + (pack_size_func) ban_ip_msg__get_packed_size, + (pack_func) ban_ip_msg__pack); if (ret < 0) { e = errno; seclog(sec, LOG_WARNING, "error in sending BAN IP message: %s", strerror(e)); diff --git a/src/vpn.h b/src/vpn.h index 474e6f6b..c3ea3bb2 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -63,6 +63,7 @@ typedef enum { */ #define PASSWORD_POINTS 10 #define CONNECT_POINTS 1 +#define KKDCP_POINTS 1 #define DEFAULT_MAX_BAN_SCORE (MAX_PASSWORD_TRIES*PASSWORD_POINTS) #define DEFAULT_BAN_RESET_TIME 300 @@ -143,6 +144,7 @@ typedef enum { CMD_TERMINATE = 12, CMD_SESSION_INFO = 13, CMD_CLI_STATS = 15, + CMD_BAN_IP = 16, /* from worker to sec-mod */ SM_CMD_AUTH_INIT = 120, diff --git a/src/worker-kkdcp.c b/src/worker-kkdcp.c index 16bc4d97..8d30a0b7 100644 --- a/src/worker-kkdcp.c +++ b/src/worker-kkdcp.c @@ -30,6 +30,33 @@ #ifdef HAVE_GSSAPI +static +void worker_add_score_to_ip(worker_st *ws, const char *ip, unsigned points) +{ + void *lpool; + int ret, e; + BanIpMsg msg = BAN_IP_MSG__INIT; + + msg.ip = (char*)ip; + msg.score = points; + + lpool = talloc_new(ws); + if (lpool == NULL) { + return; + } + + ret = send_msg(lpool, ws->cmd_fd, CMD_BAN_IP, &msg, + (pack_size_func) ban_ip_msg__get_packed_size, + (pack_func) ban_ip_msg__pack); + if (ret < 0) { + e = errno; + oclog(ws, LOG_WARNING, "error in sending BAN IP message: %s", strerror(e)); + } + talloc_free(lpool); + + return; +} + int der_decode(const uint8_t *der, unsigned der_size, uint8_t *out, unsigned *out_size, char *realm, unsigned realm_size, int *error) { @@ -140,6 +167,9 @@ int post_kkdcp_handler(worker_st *ws, unsigned http_ver) return -1; } + if (human_addr2((void*)&ws->remote_addr, ws->remote_addr_len, realm, sizeof(realm), 0) != NULL) + worker_add_score_to_ip(ws, realm, KKDCP_POINTS); + oclog(ws, LOG_HTTP_DEBUG, "HTTP processing kkdcp framed request: %u bytes", (unsigned)req->body_length);