[mac_prises] On envoie plus qu'un email par jour, qui contient un résumé qualitatif, et des détails en pièce jointe.
This commit is contained in:
parent
46bf7e47d6
commit
0e84b5e02d
6 changed files with 199 additions and 231 deletions
|
@ -8,45 +8,32 @@ hargneux = True
|
||||||
|
|
||||||
#: Si pour une chambre donnée, il y a plus de 300 entrées filaires
|
#: Si pour une chambre donnée, il y a plus de 300 entrées filaires
|
||||||
#: n'appartenant pas à l'adhérent propriétaire de la mac, on prévient.
|
#: n'appartenant pas à l'adhérent propriétaire de la mac, on prévient.
|
||||||
max_inconnues_par_jour = 300
|
max_inconnues_par_jour = 480
|
||||||
|
|
||||||
#: Titre utilisé dans le corps du message
|
#: Titre utilisé dans le corps du message
|
||||||
titre_mac_inconnue = u"Repérage de macs potentiellement non désirées dans les chambres suivantes."
|
titre_mac_inconnue = u"Repérage de macs potentiellement non désirées dans les chambres suivantes."
|
||||||
|
|
||||||
#: Pour la recherche dans postgres
|
#: Pour la recherche dans postgres
|
||||||
delay = { 'instant': '2 min',
|
delay = { 'instantanne': '2 min',
|
||||||
'heuristique': '30 min',
|
'moyen': '30 min',
|
||||||
'journalier': '1 day',
|
'journalier': '1 day',
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit suspect"
|
#: Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit suspect"
|
||||||
#: Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit suspect"
|
#: Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit suspect"
|
||||||
suspect = { 'instant':{'mac': 2, 'chambre': 2},
|
suspect = { 'instantanne':2,
|
||||||
'heuristique':{'mac': 2, 'chambre': 2},
|
'moyen':2,
|
||||||
'journalier':{'mac': 2, 'chambre': 2},
|
'journalier':2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit très suspect"
|
|
||||||
#: Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit très suspect"
|
|
||||||
tres_suspect = { 'instant':{'mac': 3, 'chambre': 3},
|
|
||||||
'heuristique':{'mac': 3, 'chambre': 3},
|
|
||||||
'journalier':{'mac': 3, 'chambre': 3},
|
|
||||||
}
|
|
||||||
|
|
||||||
#: Le point central des analyses.
|
#: Le point central des analyses.
|
||||||
rapport_suspect = { 'instant':{'mac': 0.51, 'chambre': 0.51},
|
rapport_suspect = { 'instantanne':0.51,
|
||||||
'heuristique':{'mac': 0.4, 'chambre': 0.55},
|
'moyen':0.4,
|
||||||
'journalier':{'mac': 0.2, 'chambre': 0.58},
|
'journalier':0.2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Titre des paragraphes suspects
|
#: Titre des paragraphes suspects
|
||||||
titre_suspect = { 'instant':{'mac': u"Macs se baladant un peu trop entre les chambres (instantanné)", 'chambre': u"Chambres avec un peu trop de macs (instantanné)"},
|
titre_suspect = { 'instantanne':u"Macs se baladant un peu trop entre les chambres (instantanneanné)",
|
||||||
'heuristique':{'mac': u"Macs se baladant un peu trop entre les chambres (délai moyen)", 'chambre': u"Chambres avec un peu trop de macs (délai moyen)"},
|
'moyen':u"Macs se baladant un peu trop entre les chambres (délai moyen)",
|
||||||
'journalier':{'mac': u"Macs s'étant peut-être un peu trop baladées aujourd'hui", 'chambre': u"Chambres avec un peu trop de macs sur un jour"},
|
'journalier':u"Macs s'étant peut-être un peu trop baladées aujourd'hui",
|
||||||
}
|
}
|
||||||
|
|
||||||
#: Titre des paragraphes très suspects
|
|
||||||
titre_tres_suspect = { 'instant':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (instantanné)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (instantanné)"},
|
|
||||||
'heuristique':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (délai moyen)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (délai moyen)"},
|
|
||||||
'journalier':{'mac': u"/!\ Spoof probable des macs suivantes dans les chambres ci-après aujourd'hui !!", 'chambre': u"/!\ Les chambres suivantes contiennent trop de macs inconnues (sur un jour)"},
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# PEB - 01/04/2012
|
# PEB - 01/04/2012 -> now()
|
||||||
#
|
#
|
||||||
|
|
||||||
import os, sys, re
|
import os, sys
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
from commands import getstatusoutput
|
from commands import getstatusoutput
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
# nécessite apparemment que l'objet conn soit bien créé lors de l'exec
|
# nécessite apparemment que l'objet conn soit bien créé lors de l'exec
|
||||||
# de annuaires_pg, il faut être root (ou dans je ne sais quel groupe)
|
# de annuaires_pg, il faut être root (ou dans je ne sais quel groupe)
|
||||||
|
@ -103,14 +103,7 @@ def __exec(cmd):
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
switchs = sys.argv[1:]
|
switchs = sys.argv[1:]
|
||||||
date = time.strftime('%F %T')
|
|
||||||
for switch in switchs:
|
for switch in switchs:
|
||||||
macs = liste_chambres_macs(switch)
|
macs = liste_chambres_macs(switch)
|
||||||
|
|
||||||
print macs
|
print macs
|
||||||
|
|
||||||
# fichier =
|
|
||||||
# for chambre in macs.keys():
|
|
||||||
# for mac in macs[chambre]:
|
|
||||||
#
|
|
||||||
# curseur.execute(requete, (date, chambre, mac))
|
|
||||||
|
|
|
@ -12,9 +12,14 @@ from config import mac_prise
|
||||||
from affich_tools import tableau
|
from affich_tools import tableau
|
||||||
sys.path.append('/usr/scripts/lc_ldap')
|
sys.path.append('/usr/scripts/lc_ldap')
|
||||||
import lc_ldap
|
import lc_ldap
|
||||||
|
import collections
|
||||||
|
|
||||||
ldap = lc_ldap.lc_ldap_local()
|
ldap = lc_ldap.lc_ldap_local()
|
||||||
|
|
||||||
|
conn = psycopg2.connect(user='crans', database='mac_prises')
|
||||||
|
conn.set_session(autocommit = True)
|
||||||
|
cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
|
||||||
|
|
||||||
membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))')
|
membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))')
|
||||||
chambres_ma = []
|
chambres_ma = []
|
||||||
for membre_actif in membres_actifs:
|
for membre_actif in membres_actifs:
|
||||||
|
@ -31,20 +36,12 @@ for club in clubs:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
conn = psycopg2.connect(user='crans', database='mac_prises')
|
|
||||||
conn.set_session(autocommit = True)
|
|
||||||
cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
|
|
||||||
|
|
||||||
requete = "SELECT * FROM signales WHERE date >= timestamp 'now' - interval '1 day';"
|
requete = "SELECT * FROM signales WHERE date >= timestamp 'now' - interval '1 day';"
|
||||||
cur.execute(requete)
|
cur.execute(requete)
|
||||||
signales = cur.fetchall()
|
signales = cur.fetchall()
|
||||||
|
|
||||||
longueur = { 'mac': (24, 3),
|
longueur = (24, 7)
|
||||||
'chambre': (10, 7),
|
titres = (u'mac', u'chambres')
|
||||||
}
|
|
||||||
titres = { 'mac':(u'mac', u'chambres'),
|
|
||||||
'chambre': (u'chambre', u'macs'),
|
|
||||||
}
|
|
||||||
alignements = ('c', 'c')
|
alignements = ('c', 'c')
|
||||||
|
|
||||||
def lin(x, y, z):
|
def lin(x, y, z):
|
||||||
|
@ -53,87 +50,168 @@ def lin(x, y, z):
|
||||||
"""
|
"""
|
||||||
return (float(x)/float(y)-1.0)/(float(z)-1.0)
|
return (float(x)/float(y)-1.0)/(float(z)-1.0)
|
||||||
|
|
||||||
def genere_comptage(duree, groupe, associes):
|
def genere_comptage(duree):
|
||||||
"""
|
"""
|
||||||
Grosse fonction de hack pour ne pas écrire six fois le même formatage de sortie bidon.
|
Grosse fonction de hack pour ne pas écrire six fois le même formatage de sortie bidon.
|
||||||
Prend en argument :
|
Prend en argument :
|
||||||
|
|
||||||
* duree, qui peut valoir 'instant', 'heuristique', ou 'journalier', permet d'importer
|
* duree, qui peut valoir 'instant', 'heuristique', ou 'journalier', permet d'importer
|
||||||
les variables de config qui vont bien
|
les variables de config qui vont bien
|
||||||
* groupe, qui précise selon quoi on groupe (mac ou chambre)
|
|
||||||
* associes, qui contient l'autre champ
|
|
||||||
"""
|
"""
|
||||||
|
global date
|
||||||
|
global Logs
|
||||||
pb_comptage_suspect = {}
|
pb_comptage_suspect = {}
|
||||||
output = ""
|
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 , mac, array_to_string(array_agg(DISTINCT chambre), ', ') AS chambres, COUNT(DISTINCT chambre) AS nb_chambres_distinctes, COUNT(chambre) AS nb_chambres, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT mac) as nb_macs_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY mac;" % {'delay': mac_prise.delay[duree]}
|
||||||
cur.execute(requete)
|
cur.execute(requete)
|
||||||
fetched = cur.fetchall()
|
fetched = cur.fetchall()
|
||||||
|
|
||||||
for entry in fetched:
|
for entry in fetched:
|
||||||
|
machines = ldap.search('(macAddress=%s)' % entry['mac'])
|
||||||
if groupe == "mac":
|
if len(machines) > 0:
|
||||||
machines = ldap.search('(macAddress=%s)' % entry[groupe])
|
if isinstance(machines[0], lc_ldap.machineWifi):
|
||||||
if len(machines) > 0:
|
|
||||||
if isinstance(machines[0], lc_ldap.machineWifi):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
if entry['nb_'+associes+'s_distinctes'] >= mac_prise.suspect[duree][groupe]:
|
if entry['nb_chambres_distinctes'] >= mac_prise.suspect[duree]:
|
||||||
Logs.append(u"Recherche par %s, entrée suspecte : %s -> %s : %s distinctes sur %s dates distinctes\n" % (groupe, entry[groupe], entry[associes+'s'], entry['nb_'+associes+'s'], entry['nb_dates_distinctes']))
|
Logs.append(u"Recherche par %s, entrée suspecte : %s -> %s : %s distinctes sur %s dates distinctes\n" % ('mac', entry['mac'], entry['chambres'], entry['nb_chambres'], entry['nb_dates_distinctes']))
|
||||||
liste_associes = entry[associes+'s'].split(', ')
|
liste_chambres = entry['chambres'].split(', ')
|
||||||
|
|
||||||
# On calcule la "probabilité" qu'un truc ne soit pas clair concernant la chambre/mac
|
# On calcule 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']))
|
rapport = lin(entry['nb_chambres'], entry['nb_dates_distinctes'], float(entry['nb_chambres_distinctes']))
|
||||||
if rapport >= mac_prise.rapport_suspect[duree][groupe]:
|
if rapport >= mac_prise.rapport_suspect[duree]:
|
||||||
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))
|
Logs.append(u"Entrée ajoutée au tableau %s, car rapport supérieur au seuil.\n\n" % (duree))
|
||||||
pb_comptage_suspect[entry[groupe]] = (liste_associes, rapport, mac_prise.rapport_suspect[duree][groupe])
|
pb_comptage_suspect[entry['mac']] = (liste_chambres, rapport, mac_prise.rapport_suspect[duree])
|
||||||
else:
|
else:
|
||||||
Logs.append(u"Entrée rejetée du tableau %s pour la recherche par %s, car rapport inférieur au seuil : (%s).\n\n" % (duree, groupe, rapport))
|
Logs.append(u"Entrée rejetée du tableau %s, car rapport inférieur au seuil : (%s).\n\n" % (duree, rapport))
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if len(pb_comptage_suspect) > 0:
|
if len(pb_comptage_suspect) > 0:
|
||||||
output += mac_prise.titre_suspect[duree][groupe] + "\n"
|
for clef, valeur in pb_comptage_suspect.items():
|
||||||
|
requete = "INSERT INTO spotted (mac, type, chambre, date, rapport, seuil) VALUES(%s, %s, %s, %s, %s, %s);"
|
||||||
|
cur.execute(requete, (clef, duree, ", ".join(valeur[0]), date, valeur[1], valeur[2]))
|
||||||
|
return None
|
||||||
|
|
||||||
# On prend la longueur de la plus longue valeur, on s'assure que cette longueur fait celle de la légende, plus un entier de marge
|
def summary():
|
||||||
longueur_max = max([len(", ".join(a[0])) for a in pb_comptage_suspect.values()] + [longueur[associes][1]]) + 4
|
"""
|
||||||
largeurs = (longueur[groupe][0], longueur_max, 11, 9)
|
Fonction résumant les entrées "spotted" des dernières 24h
|
||||||
titre = (titres[groupe][0], titres[groupe][1], "rapport", "seuil")
|
"""
|
||||||
alignement = (alignements[0], alignements[1], 'c', 'c')
|
|
||||||
|
output = u""
|
||||||
|
Logs = u""
|
||||||
|
|
||||||
|
requete = "SELECT * FROM spotted WHERE date >= timestamp 'now' - interval '1 day' ORDER BY date ASC;"
|
||||||
|
cur.execute(requete)
|
||||||
|
fetched = cur.fetchall()
|
||||||
|
liste_triee = collections.defaultdict(dict)
|
||||||
|
|
||||||
|
for entry in fetched:
|
||||||
|
chbres = entry['chambre'].split(', ')
|
||||||
|
chbres.sort()
|
||||||
|
chbres = tuple(chbres)
|
||||||
|
if liste_triee[entry['mac']].has_key(entry['type']):
|
||||||
|
if liste_triee[entry['mac']][entry['type']].has_key(chbres):
|
||||||
|
liste_triee[entry['mac']][entry['type']][chbres].append((entry['date'], entry['rapport'], entry['seuil']))
|
||||||
|
else:
|
||||||
|
liste_triee[entry['mac']][entry['type']][chbres] = []
|
||||||
|
else:
|
||||||
|
liste_triee[entry['mac']][entry['type']] = {}
|
||||||
|
|
||||||
|
for mac, ltype in liste_triee.items():
|
||||||
|
data = []
|
||||||
|
output += u"Il y a eu une activité suspecte concernant la mac %s :\n\n" % mac
|
||||||
|
Logs += u"Activité pour %s :\n" % mac
|
||||||
|
for dtype, dataset in ltype.items():
|
||||||
|
number = 0
|
||||||
|
chambres = set()
|
||||||
|
for chbres, dataframe in dataset.items():
|
||||||
|
chambres.update(chbres)
|
||||||
|
number += len(dataframe)
|
||||||
|
data += [[dtype, ", ".join(list(chbres)), donnee[0], donnee[1], donnee[2]] for donnee in dataframe]
|
||||||
|
output += u'Sur le relevé %s, la mac est apparue %s fois. Elle est apparue dans les chambres suivantes : %s.\n' % (dtype, number, ", ".join(list(chambres)))
|
||||||
|
output += u'Consulter les logs (en PJ) pour plus d\'informations.\n\n'
|
||||||
|
maxlen = max([len(a[1]) for a in data]) + 4
|
||||||
|
titres = (u'relevé', u'chambres', u'date', u'rapport', u'seuil')
|
||||||
|
alignements = ('c', 'c', 'c', 'c', 'c')
|
||||||
|
largeurs = (12, maxlen, 20, 10, 10)
|
||||||
|
Logs += tableau(data, titres, largeurs, alignements)
|
||||||
|
Logs += u"\n\n"
|
||||||
|
|
||||||
|
return output, Logs
|
||||||
|
|
||||||
|
def reperage_mac_inconnue():
|
||||||
|
"""
|
||||||
|
Fonction de repérage d'une mac qui ne devrait pas être
|
||||||
|
dans telle chambre, sur une plage de 24h, suivant un
|
||||||
|
paramètre de config pour le nombre d'occurrences.
|
||||||
|
"""
|
||||||
|
|
||||||
|
output = u""
|
||||||
|
probleme = {}
|
||||||
|
requete = "SELECT chambre, mac, COUNT(mac) as nb_min FROM correspondance WHERE date >= timestamp 'now' - interval '24 hours' GROUP BY chambre, mac ORDER BY chambre ASC;"
|
||||||
|
cur.execute(requete)
|
||||||
|
fetched = cur.fetchall()
|
||||||
|
liste_parsee = collections.defaultdict(dict)
|
||||||
|
|
||||||
|
for entry in fetched:
|
||||||
|
liste_parsee[entry['chambre']][entry['mac']] = int(entry['nb_min'])
|
||||||
|
|
||||||
|
for chambre in liste_parsee.keys():
|
||||||
|
if chambre in chambres_ma + chambres_clubs:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for mac in liste_parsee[chambre].keys():
|
||||||
|
try:
|
||||||
|
proprio_associe = ldap.search('macAddress=%s' % mac)[0].proprio()
|
||||||
|
if str(proprio_associe['chbre'][0]).lower() == chambre.lower():
|
||||||
|
garbage = liste_parsee[chambre].pop(mac)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
number = sum(liste_parsee[chambre].values())
|
||||||
|
|
||||||
|
if number >= mac_prise.max_inconnues_par_jour:
|
||||||
|
probleme[chambre] = (liste_parsee[chambre].keys(), number)
|
||||||
|
|
||||||
|
if len(probleme) > 0:
|
||||||
|
output += mac_prise.titre_mac_inconnue+"\n"
|
||||||
|
|
||||||
|
longueur_max = max([len(", ".join(a[0])) for a in probleme.values()] + [len("macs")]) + 2
|
||||||
|
largeurs = (len('chambre') + 2, longueur_max, len('compteur') + 2, len('seuil') + 2)
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
clefs = pb_comptage_suspect.keys()
|
clefs = probleme.keys()
|
||||||
clefs.sort()
|
clefs.sort()
|
||||||
for clef in clefs:
|
for clef in clefs:
|
||||||
data.append([clef, ", ".join(pb_comptage_suspect[clef][0]), pb_comptage_suspect[clef][1], pb_comptage_suspect[clef][2]])
|
data.append([clef, ", ".join(probleme[clef][0]), probleme[clef][1], mac_prise.max_inconnues_par_jour])
|
||||||
|
|
||||||
output += tableau(data, titre, largeurs, alignement)
|
output += tableau(data, ('chambre', 'macs', 'compteur', 'seuil'), largeurs, ('c', 'c', 'c', 'c'))
|
||||||
output += u"\n\n\n"
|
output += u"\n\n\n"
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
output = u"Détection de spoof potentiel\n\n\n"
|
date = time.strftime('%F %T')
|
||||||
coupure = len(output)
|
if len(sys.argv) >= 2:
|
||||||
|
output = u''
|
||||||
|
Logs = u''
|
||||||
|
if '--summary' in sys.argv or 'summary' in sys.argv:
|
||||||
|
# On envoie le résumé
|
||||||
|
output += u' *Résumé des apparitions de mac dans plusieurs chambres*\n\n'
|
||||||
|
texte, Logs = summary()
|
||||||
|
output += texte
|
||||||
|
output += u"\n\n"
|
||||||
|
if '--reperage' in sys.argv or 'reperage' in sys.argv:
|
||||||
|
# On envoie le repérage
|
||||||
|
output += u' *Repérage de spoof potentiel par comptage*\n\n'
|
||||||
|
output += reperage_mac_inconnue()
|
||||||
|
|
||||||
Logs = [u"Logs du script mac_prise_analyzer\n\n\n"]
|
Logs = Logs.encode('UTF-8')
|
||||||
|
output = output.encode('UTF-8')
|
||||||
output += genere_comptage('instant', 'mac', 'chambre')
|
message = """From: %(from)s
|
||||||
output += genere_comptage('heuristique', 'mac', 'chambre')
|
|
||||||
output += genere_comptage('journalier', 'mac', 'chambre')
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
message = """From: %(from)s
|
|
||||||
To: %(to)s
|
To: %(to)s
|
||||||
Subject: %(subject)s
|
Subject: Résumé quotidien : mac_prises.
|
||||||
Content-Type: multipart/mixed; boundary="_424234545aaff-ffca234efff-556adceff5646_"
|
Content-Type: multipart/mixed; boundary="_424234545aaff-ffca234efff-556adceff5646_"
|
||||||
|
|
||||||
--_424234545aaff-ffca234efff-556adceff5646_
|
--_424234545aaff-ffca234efff-556adceff5646_
|
||||||
|
@ -141,9 +219,6 @@ Content-Type: text/plain; charset="UTF-8"
|
||||||
|
|
||||||
%(contenu)s
|
%(contenu)s
|
||||||
|
|
||||||
--
|
|
||||||
Script d'analyse mac_prise (en test)
|
|
||||||
|
|
||||||
--_424234545aaff-ffca234efff-556adceff5646_
|
--_424234545aaff-ffca234efff-556adceff5646_
|
||||||
Content-Type: text/plain; charset="UTF-8"
|
Content-Type: text/plain; charset="UTF-8"
|
||||||
Content-Disposition: attachment; filename="logs_analyse"
|
Content-Disposition: attachment; filename="logs_analyse"
|
||||||
|
@ -151,17 +226,46 @@ Content-Disposition: attachment; filename="logs_analyse"
|
||||||
%(logs)s
|
%(logs)s
|
||||||
|
|
||||||
--_424234545aaff-ffca234efff-556adceff5646_--
|
--_424234545aaff-ffca234efff-556adceff5646_--
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
corps = message % { 'from': 'Spoofing watcher <spoof-watcher@crans.org>',
|
corps = message % { 'from': 'Spoofing watcher <spoof-watcher@crans.org>',
|
||||||
'to': 'test@lists.crans.org',
|
'to': 'test@lists.crans.org',
|
||||||
'subject': 'Analyse du spoofing',
|
'subject': 'Résumé journalier ',
|
||||||
'contenu': output,
|
'contenu': output,
|
||||||
'logs': "".join(Logs),
|
'logs': Logs,
|
||||||
}
|
}
|
||||||
|
|
||||||
mail = smtplib.SMTP('localhost')
|
mail = smtplib.SMTP('localhost')
|
||||||
mailfrom = 'spoof-watcher@crans.org'
|
mailfrom = 'spoof-watcher@crans.org'
|
||||||
mailto = 'test@lists.crans.org'
|
mailto = 'test@lists.crans.org'
|
||||||
mail.sendmail(mailfrom, mailto, corps.encode('utf-8'))
|
mail.sendmail(mailfrom, mailto, corps)
|
||||||
|
else:
|
||||||
|
Logs = [u"Logs du script mac_prise_analyzer\n\n\n"]
|
||||||
|
genere_comptage('instantanne')
|
||||||
|
genere_comptage('moyen')
|
||||||
|
genere_comptage('journalier')
|
||||||
|
|
||||||
|
if time.localtime().tm_min % 30 == 0 and mac_prise.hargneux:
|
||||||
|
hargneux = True
|
||||||
|
else:
|
||||||
|
hargneux = False
|
||||||
|
|
||||||
|
if hargneux:
|
||||||
|
message = """From: %(from)s
|
||||||
|
To: %(to)s
|
||||||
|
Subject: %(subject)s
|
||||||
|
Content-Type: text/plain; charset="UTF-8"
|
||||||
|
|
||||||
|
%(logs)s
|
||||||
|
"""
|
||||||
|
|
||||||
|
corps = message % { 'from': 'Spoofing watcher <spoof-watcher@crans.org>',
|
||||||
|
'to': 'test@lists.crans.org',
|
||||||
|
'subject': 'Logs de mac_prises_analyzer',
|
||||||
|
'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'))
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
psql -U crans mac_prises -c "DELETE FROM correspondance WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null
|
|
6
surveillance/mac_prises/mac_prise_daily.sh
Executable file
6
surveillance/mac_prises/mac_prise_daily.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
SUMMARY='/usr/scripts/surveillance/mac_prises/mac_prises_analyzer.py --summary --reperage'
|
||||||
|
|
||||||
|
psql -U crans mac_prises -c "DELETE FROM correspondance WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null
|
||||||
|
psql -U crans mac_prises -c "DELETE FROM spotted WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null
|
|
@ -1,119 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf8 -*-
|
|
||||||
|
|
||||||
import psycopg2
|
|
||||||
import psycopg2.extras
|
|
||||||
import sys
|
|
||||||
import smtplib
|
|
||||||
|
|
||||||
sys.path.append('/usr/scripts/gestion')
|
|
||||||
from config import mac_prise
|
|
||||||
from affich_tools import tableau
|
|
||||||
sys.path.append('/usr/scripts/lc_ldap')
|
|
||||||
import lc_ldap
|
|
||||||
import collections
|
|
||||||
|
|
||||||
ldap = lc_ldap.lc_ldap_local()
|
|
||||||
|
|
||||||
membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))')
|
|
||||||
chambres_ma = []
|
|
||||||
for membre_actif in membres_actifs:
|
|
||||||
try:
|
|
||||||
chambres_ma.append(str(membre_actif['chbre'][0]).lower())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
clubs = ldap.search('cid=*')
|
|
||||||
chambres_clubs = []
|
|
||||||
for club in clubs:
|
|
||||||
try:
|
|
||||||
chambres_clubs.append(str(club['chbre'][0]).lower())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
conn = psycopg2.connect(user='crans', database='mac_prises')
|
|
||||||
cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
|
|
||||||
|
|
||||||
def reperage_mac_inconnue():
|
|
||||||
"""
|
|
||||||
Fonction de repérage d'une mac qui ne devrait pas être
|
|
||||||
dans telle chambre, sur une plage de 24h, suivant un
|
|
||||||
paramètre de config pour le nombre d'occurrences.
|
|
||||||
|
|
||||||
Sans doute le truc le plus important, sera en tête du mail
|
|
||||||
"""
|
|
||||||
|
|
||||||
output = u""
|
|
||||||
probleme = {}
|
|
||||||
requete = "SELECT chambre, mac, COUNT(mac) as nb_min FROM correspondance WHERE date >= timestamp 'now' - interval '24 hours' GROUP BY chambre, mac ORDER BY chambre ASC;"
|
|
||||||
cur.execute(requete)
|
|
||||||
fetched = cur.fetchall()
|
|
||||||
liste_parsee = collections.defaultdict(dict)
|
|
||||||
|
|
||||||
for entry in fetched:
|
|
||||||
liste_parsee[entry['chambre']][entry['mac']] = int(entry['nb_min'])
|
|
||||||
|
|
||||||
for chambre in liste_parsee.keys():
|
|
||||||
if chambre in chambres_ma + chambres_clubs:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for mac in liste_parsee[chambre].keys():
|
|
||||||
try:
|
|
||||||
proprio_associe = ldap.search('macAddress=%s' % mac)[0].proprio()
|
|
||||||
if str(proprio_associe['chbre'][0]).lower() == chambre.lower():
|
|
||||||
garbage = liste_parsee[chambre].pop(mac)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
number = sum(liste_parsee[chambre].values())
|
|
||||||
|
|
||||||
if number >= mac_prise.max_inconnues_par_jour:
|
|
||||||
probleme[chambre] = (liste_parsee[chambre].keys(), number)
|
|
||||||
|
|
||||||
if len(probleme) > 0:
|
|
||||||
output += mac_prise.titre_mac_inconnue+"\n"
|
|
||||||
|
|
||||||
longueur_max = max([len(", ".join(a[0])) for a in probleme.values()] + [len("macs")]) + 2
|
|
||||||
largeurs = (len('chambre') + 2, longueur_max, len('compteur') + 2, len('seuil') + 2)
|
|
||||||
|
|
||||||
data = []
|
|
||||||
clefs = probleme.keys()
|
|
||||||
clefs.sort()
|
|
||||||
for clef in clefs:
|
|
||||||
data.append([clef, ", ".join(probleme[clef][0]), probleme[clef][1], mac_prise.max_inconnues_par_jour])
|
|
||||||
|
|
||||||
output += tableau(data, ('chambre', 'macs', 'compteur', 'seuil'), largeurs, ('c', 'c', 'c', 'c'))
|
|
||||||
output += u"\n\n\n"
|
|
||||||
|
|
||||||
return output
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
output = u'Repérage de spoof potentiel par comptage'
|
|
||||||
coupure = len(output)
|
|
||||||
|
|
||||||
output += reperage_mac_inconnue()
|
|
||||||
|
|
||||||
if len(output) == coupure and not mac_prise.hargneux:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
message = """From: %(from)s
|
|
||||||
To: %(to)s
|
|
||||||
Subject: %(subject)s
|
|
||||||
Content-Type: text/plain; charset="UTF-8"
|
|
||||||
|
|
||||||
%(contenu)s
|
|
||||||
|
|
||||||
--
|
|
||||||
Script d'analyse mac_prise (en test)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
corps = message % { 'from': 'Spoofing watcher <spoof-watcher@crans.org>',
|
|
||||||
'to': 'test@lists.crans.org',
|
|
||||||
'subject': 'Analyse horaire du spoofing',
|
|
||||||
'contenu': output,
|
|
||||||
}
|
|
||||||
|
|
||||||
mail = smtplib.SMTP('localhost')
|
|
||||||
mailfrom = 'spoof-watcher@crans.org'
|
|
||||||
mailto = 'test@lists.crans.org'
|
|
||||||
mail.sendmail(mailfrom, mailto, corps.encode('utf-8'))
|
|
Loading…
Add table
Add a link
Reference in a new issue