АнтиDDoS для Prosody

Как известно, у xmpp сервера Prosody нет никаких защитных механизмов против злонамеренных атак. Одно время они доставляли мне определённые неудобства и я написал простенький скрипт, который чистит оффлайн сообщения от контактов вне ростера. Его можно прописать в cron с временем исполнения каждые 5 минут. В итоге никто из "спамеров" не прорвётся. Запускать желательно от пользователя prosody. Собственно сам скрипт на питоне:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------------- #
# #
# Оffline message cleaner for Prosody #
# Copyright (C) 2011 diSabler <dsy@dsy.name> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
# --------------------------------------------------------------------------- #
# ---------------------------------
import re,os,time
# ---------------------------------
DOMAIN = 'isida%2dbot%2ecom'
USERNAME = 'dissy'
ROSTER = '/var/lib/prosody/%s/roster/%s.dat' % (DOMAIN,USERNAME)
OFFLINE = '/var/lib/prosody/%s/offline/%s.list' % (DOMAIN,USERNAME)
slog_folder = 'log/'
# ---------------------------------
def readfile(filename):
fp = file(filename)
data = fp.read()
fp.close()
return data
def writefile(filename, data):
fp = file(filename, 'w')
fp.write(data)
fp.close()
def parser(t): return ''.join([['?',l][l<='~'] for l in unicode(t)])
def tZ(val): return ['%s','0%s'][val<10] % val
def onlytimeadd(lt): return '%s:%s:%s' % (tZ(lt[3]),tZ(lt[4]),tZ(lt[5]))
def pprint(text):
lt = tuple(time.localtime())
zz = parser('[%s] %s' % (onlytimeadd(lt),text))
print zz
fname = '%s%s%s%s.txt' % (slog_folder,tZ(lt[0]),tZ(lt[1]),tZ(lt[2]))
fbody = '%s|%s\n' % (onlytimeadd(lt),text)
fl = open(fname, 'a')
fl.write(fbody.encode('utf-8'))
fl.close()
pprint('-'*32)
pprint('Read roster file...')
R = readfile(ROSTER)
RR = re.findall('\t\["(.*?@.*?)"\] = {',R,re.U)
pprint('Roster size: %s' % len(RR))
pprint('Read offline events file...')
if os.path.isfile(OFFLINE):
SERVERS = []
O = readfile(OFFLINE)
OO = re.findall('item\(\{.*?\}\);',O,re.U+re.S+re.I)
pprint('Offline events count is: %s' % len(OO))
pprint('Cleaning...')
NEW_OFFLINE = ''
REMOVED = 0
for tmp in OO:
FROM = re.findall('\["from"\] = "(.*?@.*?)/',tmp,re.U)
if FROM and FROM[0] in RR: NEW_OFFLINE += '%s\n' % tmp
else:
server = FROM[0].split('@')[1]
if server not in SERVERS: SERVERS.append(server)
REMOVED += 1
pprint('Removed items: %s' % REMOVED)
if len(NEW_OFFLINE):
pprint('Save offline events file...')
writefile(OFFLINE,NEW_OFFLINE)
else:
pprint('Offline events file is empty!')
try: os.remove(OFFLINE)
except: pass
if len(SERVERS): pprint('Need ignore: %s' % ' '.join(SERVERS))
else: pprint('No offline events!')

В начале скрипта надо прописать пути к ростеру и оффлайновым сообщениям, имя сервера и юзернейм. Надеюсь этот скрипт Вам поможет в борьбе со спамерами и ддосерами. :)