summaryrefslogtreecommitdiff
path: root/misc/freeswitch/scripts/event/perimeter.lua
diff options
context:
space:
mode:
Diffstat (limited to 'misc/freeswitch/scripts/event/perimeter.lua')
-rw-r--r--misc/freeswitch/scripts/event/perimeter.lua106
1 files changed, 106 insertions, 0 deletions
diff --git a/misc/freeswitch/scripts/event/perimeter.lua b/misc/freeswitch/scripts/event/perimeter.lua
new file mode 100644
index 0000000..3babba6
--- /dev/null
+++ b/misc/freeswitch/scripts/event/perimeter.lua
@@ -0,0 +1,106 @@
+-- Gemeinschaft 5 module: cdr event handler class
+-- (c) AMOOMA GmbH 2012
+--
+
+module(...,package.seeall)
+
+
+function handler_class()
+ return Perimeter
+end
+
+
+
+Perimeter = {}
+
+MALICIOUS_CONTACT_COUNT = 20;
+MALICIOUS_CONTACT_TIME_SPAN = 2;
+BAN_FUTILE = 2;
+
+function Perimeter.new(self, arg)
+ arg = arg or {}
+ object = arg.object or {}
+ setmetatable(object, self);
+ self.__index = self;
+ self.log = arg.log;
+ self.class = 'cdrsave'
+ self.database = arg.database;
+ self.domain = arg.domain;
+
+ self.ip_address_table = {}
+ self:init();
+
+ return object;
+end
+
+
+function Perimeter.event_handlers(self)
+ return { CUSTOM = { ['sofia::pre_register'] = self.sofia_pre_register } }
+end
+
+
+function Perimeter.init(self)
+ local config = common.configuration_file.get('/opt/freeswitch/scripts/ini/perimeter.ini');
+ if config and config.general then
+ self.malicious_contact_count = tonumber(config.general.malicious_contact_count) or MALICIOUS_CONTACT_COUNT;
+ self.malicious_contact_time_span = tonumber(config.general.malicious_contact_time_span) or MALICIOUS_CONTACT_TIME_SPAN;
+ self.ban_futile = tonumber(config.general.ban_futile) or BAN_FUTILE;
+ self.execute = config.general.execute;
+ end
+
+ self.log:info('[perimeter] PERIMETER - setup perimeter defense - config: ', self.malicious_contact_count, '/', self.malicious_contact_time_span, ', execute: ', self.execute);
+end
+
+
+function Perimeter.sofia_pre_register(self, event)
+ local ip_address = event:getHeader('network-ip');
+ self:check_ip(ip_address);
+end
+
+
+function Perimeter.check_ip(self, ip_address)
+ local event_time = os.time();
+
+ if not self.ip_address_table[ip_address] then
+ self.ip_address_table[ip_address] = { last_contact = event_time, contact_count = 0, start_stamp = event_time, banned = 0 }
+ end
+
+ local ip_record = self.ip_address_table[ip_address];
+ ip_record.last_contact = event_time;
+ ip_record.contact_count = ip_record.contact_count + 1;
+
+ if ip_record.contact_count > MALICIOUS_CONTACT_COUNT then
+ if (event_time - ip_record.start_stamp) <= MALICIOUS_CONTACT_TIME_SPAN then
+ self.log:warning('[', ip_address, '] PERIMETER - too many registration attempts');
+ ip_record.start_stamp = event_time;
+ ip_record.contact_count = 0;
+ if ip_record.banned < BAN_FUTILE then
+ ip_record.banned = ip_record.banned + 1;
+ self:ban_ip(ip_address);
+ else
+ self.log:error('[', ip_address, '] PERIMETER - ban futile');
+ end
+ end
+ end
+end
+
+
+function Perimeter.ban_ip(self, ip_address)
+ self.ip_address = ip_address;
+
+ if self.execute then
+ local command = self:expand_variables(self.execute);
+ self.log:debug('[', ip_address, '] PERIMETER - execute: ', command);
+ local result = os.execute(command);
+ if tostring(result) == '0' then
+ self.log:warning('[', ip_address, '] PERIMETER - IP banned');
+ end
+ end
+end
+
+
+function Perimeter.expand_variables(self, line)
+ return (line:gsub('{([%a%d_-]+)}', function(captured)
+ return self[captured];
+ end))
+end