src/plugin_blacklist.c doc/siproxd.conf.example
This commit is contained in:
@@ -344,6 +344,7 @@ load_plugin=plugin_logcall.la
|
||||
#load_plugin=plugin_siptrunk.la
|
||||
#load_plugin=plugin_fix_fbox_anoncall.la
|
||||
#load_plugin=plugin_stats.la
|
||||
#load_plugin=plugin_blacklist.la
|
||||
|
||||
|
||||
######################################################################
|
||||
@@ -535,17 +536,20 @@ plugin_fix_fbox_anoncall_networks = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/20
|
||||
# during the duration to recover (the UAC must remain silent during
|
||||
# this period)
|
||||
#
|
||||
# ..._dbpath: path where to locate the database
|
||||
# ..._mode: 0: no block, 1: IP based, 2: IP and SIP-user based
|
||||
# ..._simulate: 0: block UACs once the failure count limit has been reached
|
||||
# 1: simulate, only log but don't block
|
||||
# ..._duration: block duration in seconds, 0: forever
|
||||
# ..._hitcount: required failed REGISTER attempts until blocked.
|
||||
# ...dbpath: path where the database is located
|
||||
# ...mode: 0: no block, 1: IP based, 2: IP and SIP-user based
|
||||
# ...simulate: 0: block UACs once the failure count limit has been reached
|
||||
# 1: simulate, only log but don't block
|
||||
# ...duration: block duration in seconds, 0: forever
|
||||
# ...hitcount: required failed REGISTER attempts until blocked.
|
||||
# ...register_window: time window within which a response to a REGISTER must
|
||||
# be received, otherwise the REGISTER response will be
|
||||
# ignored for blacklisting
|
||||
#
|
||||
plugin_blacklist_dbpath = /var/lib/siproxd/blacklist.sqlite
|
||||
//plugin_blacklist_mode = 0
|
||||
plugin_blacklist_simulate = 0
|
||||
plugin_blacklist_duration = 3600
|
||||
plugin_blacklist_hitcount = 10
|
||||
|
||||
plugin_blacklist_register_window = 30
|
||||
|
||||
|
||||
+40
-20
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
@@ -57,6 +58,7 @@ static struct plugin_config {
|
||||
int simulate; /* 0: no, 1: don't block, just log */
|
||||
int duration; /* in seconds, 0: forever, dont' expire */
|
||||
int hitcount; /* required attempts until blocked */
|
||||
int register_window;/* time window for REGISTER reesponse to arrive */
|
||||
} plugin_cfg;
|
||||
|
||||
/* Instructions for config parser */
|
||||
@@ -66,6 +68,7 @@ static cfgopts_t plugin_cfg_opts[] = {
|
||||
{ "plugin_blacklist_simulate", TYP_INT4, &plugin_cfg.simulate, {0, NULL} },
|
||||
{ "plugin_blacklist_duration", TYP_INT4, &plugin_cfg.duration, {3600, NULL} },
|
||||
{ "plugin_blacklist_hitcount", TYP_INT4, &plugin_cfg.hitcount, {10, NULL} },
|
||||
{ "plugin_blacklist_register_window", TYP_INT4, &plugin_cfg.register_window, {30, NULL} },
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -83,27 +86,29 @@ static sql_statement_t sql_statement[] = {
|
||||
/* blacklist_check() */
|
||||
{ 0, NULL, "SELECT count(*) from blacklist WHERE ip=?001 and sipuri=?002 AND (type=1 or failcount>?003);" },
|
||||
{ 1, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
{ 2, NULL, "INSERT OR REPLACE INTO requests (timestamp, ip, sipuri, callid) VALUES (?001, ?002, ?003, ?004);" },
|
||||
{ 2, NULL, "UPDATE OR IGNORE requests SET timestamp=?001, callid=?004 WHERE ip=?002 AND sipuri=?003;" },
|
||||
{ 3, NULL, "INSERT OR IGNORE INTO requests (timestamp, ip, sipuri, callid) VALUES (?001, ?002, ?003, ?004);" },
|
||||
/* blacklist_update() */
|
||||
{ 3, NULL, "DELETE FROM requests WHERE timestamp<?001;" },
|
||||
{ 4, NULL, "SELECT count(*) from requests WHERE ip=?001 and sipuri=?002 AND callid=?003;" },
|
||||
{ 5, NULL, "INSERT OR IGNORE INTO blacklist (ip, sipuri) VALUES (?001, ?002);" },
|
||||
{ 6, NULL, "UPDATE OR IGNORE blacklist SET failcount=failcount+1, lastseen=?003, lastfail=?003 WHERE type=0 and ip=?001 and sipuri=?002;" },
|
||||
{ 7, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
{ 8, NULL, "UPDATE OR IGNORE blacklist SET failcount=0, lastseen=?003 WHERE type=0 and ip=?001 and sipuri=?002;" },
|
||||
{ 9, NULL, "UPDATE OR IGNORE blacklist SET failcount=0 WHERE type=0 and failcount<?001 and lastseen<?002;" },
|
||||
{ 4, NULL, "DELETE FROM requests WHERE timestamp<?001;" },
|
||||
{ 5, NULL, "SELECT count(*) from requests WHERE ip=?001 and sipuri=?002 AND callid=?003;" },
|
||||
{ 6, NULL, "INSERT OR IGNORE INTO blacklist (ip, sipuri) VALUES (?001, ?002);" },
|
||||
{ 7, NULL, "UPDATE OR IGNORE blacklist SET failcount=failcount+1, lastseen=?003, lastfail=?003 WHERE type=0 and ip=?001 and sipuri=?002;" },
|
||||
{ 8, NULL, "UPDATE OR IGNORE blacklist SET lastseen=?003 WHERE ip=?001 and sipuri=?002;" },
|
||||
{ 9, NULL, "UPDATE OR IGNORE blacklist SET failcount=0, lastseen=?003 WHERE type=0 and ip=?001 and sipuri=?002;" },
|
||||
{ 10, NULL, "UPDATE OR IGNORE blacklist SET failcount=0 WHERE type=0 and failcount<?001 and lastseen<?002;" },
|
||||
};
|
||||
#define SQL_CHECK_1 0
|
||||
#define SQL_CHECK_2 1
|
||||
#define SQL_CHECK_3 2
|
||||
#define SQL_CHECK_4 3
|
||||
|
||||
#define SQL_UPDATE_1 3 /* expire old request records */
|
||||
#define SQL_UPDATE_2 4 /* check is REGISTER response macthes a know record */
|
||||
#define SQL_UPDATE_3 5 /* insert new blacklist record to DB */
|
||||
#define SQL_UPDATE_4 6 /* increment failcount */
|
||||
#define SQL_UPDATE_5 7 /* just update lastseen */
|
||||
#define SQL_UPDATE_6 8 /* reset failcount upon successful registration */
|
||||
#define SQL_UPDATE_7 9 /* cleanup blacklist table */
|
||||
#define SQL_UPDATE_1 4 /* expire old request records */
|
||||
#define SQL_UPDATE_2 5 /* check if REGISTER response matches a know record */
|
||||
#define SQL_UPDATE_3 6 /* insert new blacklist record to DB */
|
||||
#define SQL_UPDATE_4 7 /* increment failcount */
|
||||
#define SQL_UPDATE_5 8 /* just update lastseen */
|
||||
#define SQL_UPDATE_6 9 /* reset failcount upon successful registration */
|
||||
#define SQL_UPDATE_7 10 /* cleanup blacklist table */
|
||||
|
||||
/* string magic in C preprocessor */
|
||||
#define xstr(s) str(s)
|
||||
@@ -152,7 +157,9 @@ blacklist
|
||||
/* local prototypes */
|
||||
static int blacklist_check(sip_ticket_t *ticket);
|
||||
static int blacklist_update(sip_ticket_t *ticket);
|
||||
#if 0
|
||||
static int blacklist_expire(sip_ticket_t *ticket);
|
||||
#endif
|
||||
/* helpers */
|
||||
static int sqlite_begin(void);
|
||||
static int sqlite_end(void);
|
||||
@@ -286,7 +293,7 @@ static int blacklist_check(sip_ticket_t *ticket) {
|
||||
sql_stmt = NULL;
|
||||
|
||||
if (MSG_IS_REGISTER(ticket->sipmsg)) {
|
||||
/* Query 3: INSERT OR IGNORE REGISTER request into requests DB */
|
||||
/* Query 3: UPDATE OR IGNORE REGISTER request into requests DB */
|
||||
/* bind */
|
||||
sql_stmt = &sql_statement[SQL_CHECK_3];
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp);
|
||||
@@ -295,15 +302,27 @@ static int blacklist_check(sip_ticket_t *ticket) {
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 004, call_id,-1, SQLITE_TRANSIENT);
|
||||
sts = sqlite_exec_stmt_none(sql_stmt);
|
||||
sql_stmt = NULL;
|
||||
/* Query 3: INSERT OR IGNORE REGISTER request into requests DB */
|
||||
/* bind */
|
||||
sql_stmt = &sql_statement[SQL_CHECK_4];
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 002, srcip, -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 003, from, -1, SQLITE_TRANSIENT);
|
||||
sts = sqlite3_bind_text(sql_stmt->stmt, 004, call_id,-1, SQLITE_TRANSIENT);
|
||||
sts = sqlite_exec_stmt_none(sql_stmt);
|
||||
sql_stmt = NULL;
|
||||
}
|
||||
|
||||
// not present in sqlite 3.3.6 sts = sqlite3_clear_bindings(stmt1);
|
||||
|
||||
if (retval > 0) {
|
||||
if ((retval > 0) && (plugin_cfg.simulate==0)) {
|
||||
DEBUGC(DBCLASS_BABBLE, "leaving blacklist_check, UAC is blocked");
|
||||
INFO ("UAC with IP %s [%s] is blocked", srcip, from);
|
||||
osip_free(from);
|
||||
return STS_FAILURE;
|
||||
} else if (retval > 0) {
|
||||
DEBUGC(DBCLASS_BABBLE, "leaving blacklist_check, UAC is blocked");
|
||||
INFO ("UAC with IP %s [%s] would be blocked (simulate=1)", srcip, from);
|
||||
}
|
||||
|
||||
/* free resources */
|
||||
@@ -325,10 +344,10 @@ static int blacklist_update(sip_ticket_t *ticket) {
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE, "entering blacklist_update");
|
||||
|
||||
/* Query 1: remove old records (> 30s) */
|
||||
/* Query 1: remove old records (> register_window seconds) */
|
||||
/* bind */
|
||||
sql_stmt = &sql_statement[SQL_UPDATE_1];
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp - 30);
|
||||
sts = sqlite3_bind_int(sql_stmt->stmt, 001, ticket->timestamp - plugin_cfg.register_window);
|
||||
sts = sqlite_exec_stmt_none(sql_stmt);
|
||||
sql_stmt = NULL;
|
||||
|
||||
@@ -417,6 +436,7 @@ static int blacklist_update(sip_ticket_t *ticket) {
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int blacklist_expire(sip_ticket_t *ticket) {
|
||||
// int sts;
|
||||
// char *zErrMsg = NULL;
|
||||
@@ -428,7 +448,7 @@ static int blacklist_expire(sip_ticket_t *ticket) {
|
||||
DEBUGC(DBCLASS_BABBLE, "leaving blacklist_expire");
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/* helper functions */
|
||||
|
||||
@@ -267,7 +267,7 @@ static int sdp_filter_codec(sdp_message_t *sdp) {
|
||||
//
|
||||
for (i=0; i<plugin_cfg.codec_blacklist.used; i++) {
|
||||
// do an *case-insensitive* *substring* match
|
||||
if (strcasestr(sdp_attr->a_att_value, plugin_cfg.codec_blacklist.string[i])) {
|
||||
/*&&&*/ if (strcasestr(sdp_attr->a_att_value, plugin_cfg.codec_blacklist.string[i])) {
|
||||
// match, need to remove this codec
|
||||
DEBUGC(DBCLASS_PLUGIN, "%s: blacklisted - removing media attr [%s] at attrpos=%i", name,
|
||||
sdp_attr->a_att_value, media_attr_no);
|
||||
@@ -289,7 +289,7 @@ static int sdp_filter_codec(sdp_message_t *sdp) {
|
||||
|
||||
if ((attr = osip_list_get(&med->a_attributes, media_attr_no)) != NULL) {
|
||||
osip_list_remove(&med->a_attributes, media_attr_no);
|
||||
sdp_attribute_free(attr);
|
||||
/*&&&*/ sdp_attribute_free(attr);
|
||||
attr=NULL;
|
||||
// as I have removed the current attribute, all other
|
||||
// attributes are shifted one down, so for the next iteration
|
||||
|
||||
Reference in New Issue
Block a user