[Mac_prise] Modification du wrapper, logging + mail dans analyzer, et mise en place de reperage

* Le wrapper n'envoie plus de mails
    * Analyzer envoie ses mails lui-même, avec en pièce jointe le contenu du logging.
    * Analyzer n'envoit rien si les tableaux sont vide, sauf si hargneux, et sur une demi heure
    * Création de mac_prise_reperage, dont le but est de lister les macs inconnues d'une chambre sur une plage de 24h (script exécuté par cron toutes les heures), et de compter le nombre de minutes pendant lesquelles elles ont été présentes. Si la somme des compteurs pour une chambre dépasse une quantité dans config, on envoie un mail. Pas de logging ici, tout est "limpide". Il faudra bien définir la variable de config sus-citée.
    * Modification de config, on rajoute les deux variables pour mac_prise_reperage.py
This commit is contained in:
Pierre-Elliott Bécue 2013-02-02 02:02:02 +01:00
parent b37a0137e2
commit 777ba5cd9c
4 changed files with 197 additions and 24 deletions

View file

@ -5,6 +5,7 @@ import psycopg2
import psycopg2.extras
import sys
import smtplib
import time
sys.path.append('/usr/scripts/gestion')
from config import mac_prise
@ -60,38 +61,46 @@ def genere_comptage(duree, groupe, associes):
pb_comptage_suspect = {}
pb_comptage_tres_suspect = {}
output = ""
requete = "SELECT array_to_string(array_agg(DISTINCT date), ',') AS dates , %(groupe)s, array_to_string(array_agg(DISTINCT %(associes)s), ',') AS %(associes)ss, COUNT(DISTINCT %(associes)s) AS nb_%(associes)ss_distinctes, COUNT(%(associes)s) AS nb_%(associes)ss, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT %(groupe)s) as nb_%(groupe)ss_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY %(groupe)s;" % { 'groupe': groupe, 'associes': associes, 'delay': mac_prise.delay[duree] }
requete = "SELECT array_to_string(array_agg(DISTINCT date), ', ') AS dates , %(groupe)s, array_to_string(array_agg(DISTINCT %(associes)s), ', ') AS %(associes)ss, COUNT(DISTINCT %(associes)s) AS nb_%(associes)ss_distinctes, COUNT(%(associes)s) AS nb_%(associes)ss, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT %(groupe)s) as nb_%(groupe)ss_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY %(groupe)s;" % { 'groupe': groupe, 'associes': associes, 'delay': mac_prise.delay[duree] }
cur.execute(requete)
fetched = cur.fetchall()
for entry in fetched:
# Si c'est la chambre d'un membre actif ou d'un club, on droppe.
if groupe == 'chambre':
if entry[groupe] in chambres_ma + chambres_clubs:
if entry[groupe] in chambres_ma:
Logs.append(u"Chambre dropée, car appartenant à un membre actif : %s\n\n" % entry[groupe])
continue
elif entry[groupe] in chambres_clubs:
Logs.append(u"Chambre dropée, car appartenant à un club : %s\n\n" % entry[groupe])
continue
# Sinon, on vérifie si le local est bien rempli.
if entry['nb_'+associes+'s_distinctes'] >= mac_prise.tres_suspect[duree][groupe]:
liste_associes = entry[associes+'s'].split(',')
Logs.append(u"Recherche par %s, entrée très suspecte : %s -> %s \n" % (groupe, entry[groupe], entry[associes+'s']))
liste_associes = entry[associes+'s'].split(', ')
# On retire les machines associées à l'adhérent possédant la chambre
if groupe == 'chambre':
for i in liste_associes:
try:
proprio_associe = ldap.search('macAddress=%s' % i)[0].proprio()
if str(proprio_associe['chbre']).lower() == entry[groupe]:
if str(proprio_associe['chbre'][0]).lower() == entry[groupe]:
liste_associes.remove(i)
except:
pass
if len(liste_associes) < mac_prise.tres_suspect[duree][groupe]:
Logs.append(u"Entrée rejetée : la plupart des %s appartiennent au propriétaire de la %s\n\n" % (associes, groupe))
continue
# Toujours un problème ? On ajoute au dico
Logs.append(u"Entrée ajoutée au tableau %s pour la recherche par %s.\n\n" % (duree, groupe))
pb_comptage_tres_suspect[entry[groupe]] = liste_associes
# Même chose avec un seuil plus faible
elif entry['nb_'+associes+'s_distinctes'] >= mac_prise.suspect[duree][groupe]:
liste_associes = entry[associes+'s'].split(',')
Logs.append(u"Recherche par %s, entrée suspecte : %s -> %s \n" % (groupe, entry[groupe], entry[associes+'s']))
liste_associes = entry[associes+'s'].split(', ')
if groupe == 'chambre':
for i in liste_associes:
@ -102,14 +111,16 @@ def genere_comptage(duree, groupe, associes):
except:
pass
if len(liste_associes) < mac_prise.suspect[duree][groupe]:
Logs.append(u"Entrée rejetée : la plupart des %s appartiennent au propriétaire de la %s\n\n" % (associes, groupe))
continue
# On calcul la "probabilité" qu'un truc ne soit pas clair concernant la chambre/mac
rapport = lin(entry['nb_'+associes+'s'], entry['nb_dates_distinctes'], float(entry['nb_'+associes+'s_distinctes']))
if rapport >= mac_prise.rapport_suspect[duree][groupe]:
Logs.append(u"Entrée ajoutée au tableau %s pour la recherche par %s, car rapport supérieur au seuil.\n\n" % (duree, groupe))
pb_comptage_suspect[entry[groupe]] = (liste_associes, rapport, mac_prise.rapport_suspect[duree][groupe])
else:
pass
Logs.append(u"Entrée rejetée du tableau %s pour la recherche par %s, car rapport inférieur au seuil.\n\n" % (duree, groupe))
else:
pass
@ -148,10 +159,14 @@ def genere_comptage(duree, groupe, associes):
return output
if __name__ == '__main__':
output = u"Détection de spoof potentiel\n\n\n"
coupure = len(output)
Logs = [u"Logs du script mac_prise_analyzer\n\n\n"]
output += genere_comptage('instant', 'mac', 'chambre')
output += genere_comptage('heuristique', 'mac', 'chambre')
output += genere_comptage('journalier', 'mac', 'chambre')
@ -159,7 +174,45 @@ if __name__ == '__main__':
output += genere_comptage('heuristique', 'chambre', 'mac')
output += genere_comptage('journalier', 'chambre', 'mac')
if len(output) == coupure:
if time.localtime().tm_min % 30 == 0 and mac_prise.hargneux:
hargneux = True
else:
hargneux = False
if len(output) == coupure and not hargneux:
sys.exit(0)
print output.encode('utf-8')
message = """From: %(from)s
To: %(to)s
Subject: %(subject)s
Content-Type: multipart/mixed; boundary="_424234545aaff-ffca234efff-556adceff5646_"
--_424234545aaff-ffca234efff-556adceff5646_
Content-Type: text/plain, charset="UTF-8"
%(contenu)s
--
Script d'analyse mac_prise (en test)
--_424234545aaff-ffca234efff-556adceff5646_
Content-Type: text/plain; charset="UTF-8"
Content-Disposition: attachment; filename="logs_analyse"
%(logs)s
--_424234545aaff-ffca234efff-556adceff5646_--
"""
corps = message % { 'from': 'Spoofing watcher <spoof-watcher@crans.org>',
'to': 'test@lists.crans.org',
'subject': 'Analyse du spoofing',
'contenu': output,
'logs': "".join(Logs),
}
mail = smtplib.SMTP('localhost')
mailfrom = 'spoof-watcher@crans.org'
mailto = 'test@lists.crans.org'
mail.sendmail(mailfrom, mailto, corps.encode('utf-8'))