From d506309346b8beb402cc5a5bd64b84977a4e336f Mon Sep 17 00:00:00 2001 From: Jarrod Baumann Date: Wed, 8 Apr 2015 16:19:25 -0500 Subject: [PATCH 1/3] Added pike mi command for unblocking IP addresses --- modules/pike/pike.c | 2 ++ modules/pike/pike_mi.c | 78 +++++++++++++++++++++++++++++++++++++++++- modules/pike/pike_mi.h | 2 ++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/modules/pike/pike.c b/modules/pike/pike.c index 878c7182427..ff37df0ffd8 100644 --- a/modules/pike/pike.c +++ b/modules/pike/pike.c @@ -93,6 +93,8 @@ static param_export_t params[]={ static mi_export_t mi_cmds [] = { {MI_PIKE_LIST, "lists the nodes in the pike tree", mi_pike_list, MI_NO_INPUT_FLAG, 0, 0 }, + {MI_PIKE_RM, "remove a node from the tree", + mi_pike_rm, 0, 0, 0 }, {0,0,0,0,0,0} }; diff --git a/modules/pike/pike_mi.c b/modules/pike/pike_mi.c index 1f7bee7dafc..526b0df71bf 100644 --- a/modules/pike/pike_mi.c +++ b/modules/pike/pike_mi.c @@ -24,6 +24,11 @@ * 2006-12-05 created (bogdan) */ +#include + +#include "../../resolve.h" +#include "../../timer.h" + #include "ip_tree.h" #include "pike_mi.h" @@ -32,7 +37,11 @@ #define MAX_IP_LEN IPv6_LEN -static struct ip_node *ip_stack[MAX_IP_LEN]; +static struct ip_node *ip_stack[MAX_IP_LEN]; +extern int pike_log_level; +extern int timeout; +extern struct list_link* timer; +extern gen_lock_t* timer_lock; static inline void print_ip_stack( int level, struct mi_node *node) @@ -86,6 +95,73 @@ static void print_red_ips( struct ip_node *ip, int level, struct mi_node *node) } +struct mi_root* mi_pike_rm(struct mi_root *cmd, void *param) +{ + struct mi_node *mn; + struct ip_node *node; + struct ip_node *dad; + struct ip_node *kid; + struct ip_addr *ip; + int byte_pos; + + mn = cmd->node.kids; + if (mn==NULL) + return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); + + ip = str2ip(&mn->value); + if (ip==0) + return init_mi_tree( 500, "Bad IP", 6); + + node = 0; + byte_pos = 0; + + kid = get_tree_branch((unsigned char)ip->u.addr[byte_pos]); + + /* pilfered from ip_tree.c:mark_node(..) */ + while (kid && byte_pos < ip->len) { + while (kid && kid->byte!=(unsigned char)ip->u.addr[byte_pos]) { + kid = kid->next; + } + if (kid) { + node = kid; + kid = kid->kids; + byte_pos++; + } + } + + /* If all octets weren't matched, 404 */ + if (byte_pos!=ip->len) { + return init_mi_tree( 404, "Match not found", 15); + } + + /* If the node exists, check to see if it's really blocked */ + if (!(node->flags&NODE_ISRED_FLAG)) { + return init_mi_tree( 400, "IP not blocked", 14); + } + + /* pilfered from pike_funcs.c:clean_routine(..) */ + if (node->prev!=0) { + if (node->prev->kids==node && node->next==0) { + dad = node->prev; + if ( !(dad->flags&NODE_IPLEAF_FLAG) ) { + lock_get(timer_lock); + dad->expires = get_ticks() + timeout; + assert( !has_timer_set(&(dad->timer_ll)) ); + append_to_timer( timer, &(dad->timer_ll)); + dad->flags |= NODE_INTIMER_FLAG; + lock_release(timer_lock); + } else { + assert( has_timer_set(&(dad->timer_ll)) ); + } + } + } + remove_node(node); + + LM_GEN1(pike_log_level, + "PIKE - UNBLOCKing ip %s, node=%p\n",ip_addr2a(ip),node); + + return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); +} /* diff --git a/modules/pike/pike_mi.h b/modules/pike/pike_mi.h index 56fe849d64a..1650c9ef8d1 100644 --- a/modules/pike/pike_mi.h +++ b/modules/pike/pike_mi.h @@ -31,8 +31,10 @@ #include "../../mi/mi.h" #define MI_PIKE_LIST "pike_list" +#define MI_PIKE_RM "pike_rm" struct mi_root* mi_pike_list(struct mi_root* cmd_tree, void* param); +struct mi_root* mi_pike_rm(struct mi_root *cmd, void *param); #endif From 996c98967efc20611242884a064e521183cefe3b Mon Sep 17 00:00:00 2001 From: Jarrod Baumann Date: Wed, 8 Apr 2015 16:32:40 -0500 Subject: [PATCH 2/3] Added simple section to the pike_admin.xml docs detailing the command --- modules/pike/doc/pike_admin.xml | 64 ++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/modules/pike/doc/pike_admin.xml b/modules/pike/doc/pike_admin.xml index e992b91b6fd..6a9837eedf0 100644 --- a/modules/pike/doc/pike_admin.xml +++ b/modules/pike/doc/pike_admin.xml @@ -1,15 +1,15 @@ - + &adminguide; - +
Overview The module provides a simple mechanism for DOS protection - DOS based - on floods at network level. The module keeps trace of all (or selected - ones) IPs of incoming SIP traffic (as source IP) and blocks the ones + on floods at network level. The module keeps trace of all (or selected + ones) IPs of incoming SIP traffic (as source IP) and blocks the ones that exceeded some limit. Works simultaneous for IPv4 and IPv6 addresses. @@ -38,13 +38,13 @@ - automatic - the module will install + automatic - the module will install internal hooks to catch all incoming requests and replies (even if not well formed from SIP point of view) - more or less the module will monitor all incoming packages (from the network) on - the SIP sockets. Each time the source IP of a package needs to + the SIP sockets. Each time the source IP of a package needs to be analyse (to see if trusted or not), the module will run a - script route - see "check_route" module parameter -, where, + script route - see "check_route" module parameter -, where, based on custom logic, you can decide if that IP needs to be monitored for flooding or not. As action, when flood is detected, the module will automatically drop the packages. @@ -72,7 +72,7 @@
External Libraries or Applications - The following libraries or applications must be installed before + The following libraries or applications must be installed before running &osips; with this module loaded: @@ -89,14 +89,14 @@
<varname>sampling_time_unit</varname> (integer) - Time period used for sampling (or the sampling accuracy ;-) ). The - smaller the better, but slower. If you want to detect peaks, use a - small one. To limit the access (like total number of requests on a - long period of time) to a proxy resource (a gateway for ex), use + Time period used for sampling (or the sampling accuracy ;-) ). The + smaller the better, but slower. If you want to detect peaks, use a + small one. To limit the access (like total number of requests on a + long period of time) to a proxy resource (a gateway for ex), use a bigger value of this parameter. - IMPORTANT: a too small value may lead to performance penalties due + IMPORTANT: a too small value may lead to performance penalties due timer process overloading. @@ -116,9 +116,9 @@ modparam("pike", "sampling_time_unit", 10)
<varname>reqs_density_per_unit</varname> (integer) - How many requests should be allowed per sampling_time_unit before - blocking all the incoming request from that IP. Practically, the - blocking limit is between ( let's have x=reqs_density_per_unit) x + How many requests should be allowed per sampling_time_unit before + blocking all the incoming request from that IP. Practically, the + blocking limit is between ( let's have x=reqs_density_per_unit) x and 3*x for IPv4 addresses and between x and 8*x for ipv6 addresses. @@ -138,7 +138,7 @@ modparam("pike", "reqs_density_per_unit", 30)
<varname>remove_latency</varname> (integer) - For how long the IP address will be kept in memory after the last + For how long the IP address will be kept in memory after the last request from that IP address. It's a sort of timeout value. @@ -219,7 +219,7 @@ modparam("pike", "pike_log_level", -1) pike_check_req() - Process the source IP of the current request and returns false if + Process the source IP of the current request and returns false if the IP was exceeding the blocking limit. @@ -227,7 +227,7 @@ modparam("pike", "pike_log_level", -1) - 1 (true) - IP is not to be blocked or + 1 (true) - IP is not to be blocked or internal error occured. @@ -243,7 +243,7 @@ modparam("pike", "pike_log_level", -1) - -2 (false) - IP is detected as a new + -2 (false) - IP is detected as a new source of flooding - first time detection @@ -275,6 +275,30 @@ if (!pike_check_req()) { exit; }; Name: pike_list + Parameters: + + + IP - IP address currently blocked. + + + + MI FIFO Command Format: + + + :pike_list:_reply_fifo_file_ + _empty_line_ + +
+
+ + <function moreinfo="none">pike_rm</function> + + + Remove a node from the pike tree by IP address. + + + Name: pike_rm + Parameters: none MI FIFO Command Format: From 3a37fa4b89a04530cf3125a713688603aaf5c81b Mon Sep 17 00:00:00 2001 From: Jarrod Baumann Date: Thu, 9 Apr 2015 10:04:56 -0500 Subject: [PATCH 3/3] updated logic to reset the block flags and counters instead of actually removing the node from the tree --- modules/pike/pike_mi.c | 29 +++++++---------------------- modules/pike/pike_mi.h | 2 +- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/modules/pike/pike_mi.c b/modules/pike/pike_mi.c index 526b0df71bf..b56245eccca 100644 --- a/modules/pike/pike_mi.c +++ b/modules/pike/pike_mi.c @@ -27,7 +27,6 @@ #include #include "../../resolve.h" -#include "../../timer.h" #include "ip_tree.h" #include "pike_mi.h" @@ -39,9 +38,6 @@ static struct ip_node *ip_stack[MAX_IP_LEN]; extern int pike_log_level; -extern int timeout; -extern struct list_link* timer; -extern gen_lock_t* timer_lock; static inline void print_ip_stack( int level, struct mi_node *node) @@ -99,7 +95,6 @@ struct mi_root* mi_pike_rm(struct mi_root *cmd, void *param) { struct mi_node *mn; struct ip_node *node; - struct ip_node *dad; struct ip_node *kid; struct ip_addr *ip; int byte_pos; @@ -139,23 +134,13 @@ struct mi_root* mi_pike_rm(struct mi_root *cmd, void *param) return init_mi_tree( 400, "IP not blocked", 14); } - /* pilfered from pike_funcs.c:clean_routine(..) */ - if (node->prev!=0) { - if (node->prev->kids==node && node->next==0) { - dad = node->prev; - if ( !(dad->flags&NODE_IPLEAF_FLAG) ) { - lock_get(timer_lock); - dad->expires = get_ticks() + timeout; - assert( !has_timer_set(&(dad->timer_ll)) ); - append_to_timer( timer, &(dad->timer_ll)); - dad->flags |= NODE_INTIMER_FLAG; - lock_release(timer_lock); - } else { - assert( has_timer_set(&(dad->timer_ll)) ); - } - } - } - remove_node(node); + /* reset the node block flag and counters */ + node->flags &= ~(NODE_ISRED_FLAG); + + node->hits[PREV_POS] = 0; + node->hits[CURR_POS] = 0; + node->leaf_hits[PREV_POS] = 0; + node->leaf_hits[CURR_POS] = 0; LM_GEN1(pike_log_level, "PIKE - UNBLOCKing ip %s, node=%p\n",ip_addr2a(ip),node); diff --git a/modules/pike/pike_mi.h b/modules/pike/pike_mi.h index 1650c9ef8d1..e1f11faf9b2 100644 --- a/modules/pike/pike_mi.h +++ b/modules/pike/pike_mi.h @@ -31,7 +31,7 @@ #include "../../mi/mi.h" #define MI_PIKE_LIST "pike_list" -#define MI_PIKE_RM "pike_rm" +#define MI_PIKE_RM "pike_rm" struct mi_root* mi_pike_list(struct mi_root* cmd_tree, void* param); struct mi_root* mi_pike_rm(struct mi_root *cmd, void *param);