#! /usr/bin/env python # -*- encoding: utf-8 -*- """ Script d'envoi des statistiques des déconnections et du trafic de la journée à disconnect@ Copyright (C) Xavier Pessoles - Étienne Chové - Michel Blockelet Licence : GPLv2 """ ########################### # Import des commmandes : # ########################### import commands import sys, os import psycopg2 sys.path.append('/usr/scripts/gestion') sys.path.append('/usr/scripts/surveillance') import config.virus import smtplib import socket import time, random, hashlib import netaddr from analyse import stats from affich_tools import tableau from iptools import AddrInNet from ldap_crans import AssociationCrans, crans_ldap CL = crans_ldap() def ipv4or6(addr): if ':' in addr: return "IPv6" else: return "IPv4" # Liste des IP des serveurs ips_serveurs = [] ips_proxys = [] for m in AssociationCrans().machines(): if m.nom() in [u'charybde.crans.org', u'sable.crans.org']: ips_proxys.extend([m.ip(), str(m.ipv6())]) else: ips_serveurs.extend([m.ip(), str(m.ipv6())]) ############################## # Ouverture des connexions : # ############################## pgsql = psycopg2.connect(database="filtrage", user="crans") curseur = pgsql.cursor() ########################### # Statistiques d'upload : # ########################### # Liste des uploads : ##################### requete = """(SELECT ip_crans, sum(upload) AS somme, sum(download) FROM upload WHERE date > timestamp 'now' - interval '1 day' AND NOT EXISTS ( SELECT 1 FROM exemptes WHERE upload.ip_crans <<= exemptes.ip_crans AND upload.ip_ext <<= exemptes.ip_dest ) GROUP BY ip_crans ) UNION (SELECT ip_crans, sum(upload) AS somme, sum(download) FROM ( SELECT DISTINCT * FROM ( SELECT upload6.date, mac_ip.mac AS ip_crans, upload6.ip_ext, upload6.id, upload6.port_crans, upload6.port_ext, upload6.download, upload6.upload FROM mac_ip,upload6 WHERE upload6.ip_crans = mac_ip.ip AND upload6.date > mac_ip.date AND upload6.date - interval '1 day' < mac_ip.date AND upload6.date > timestamp 'now' - interval '1 day' AND upload6.date < 'now' AND NOT EXISTS ( SELECT 1 FROM exemptes WHERE upload6.ip_crans <<= exemptes.ip_crans AND upload6.ip_ext <<= exemptes.ip_dest ) ) AS upload ) AS upload GROUP BY ip_crans ) ORDER BY somme DESC""" curseur.execute(requete) data_upload = curseur.fetchall() liste_upload = tableau(data = [ (l[1], l[2], ipv4or6(str(l[0])), socket.getfqdn(str(l[0]))) for l in data_upload if int(l[1]) > 100*1024*1024 and l[0] not in (ips_serveurs + ips_proxys)], titre = ['upload', 'download', 'proto', 'machine'], largeur = [10, 10, 10, 40], format = ['o', 'o', 's', 's'], alignement = ['d', 'd', 'c', 'c']).encode('utf-8') # Trafic exempté : ################## requete = """(SELECT ip_crans, sum(upload) AS somme, sum(download) FROM upload WHERE date > timestamp 'now' - interval '1 day' AND EXISTS ( SELECT 1 FROM exemptes WHERE upload.ip_crans = exemptes.ip_crans -- AND upload.ip_ext <<= exemptes.ip_dest ) GROUP BY ip_crans ) UNION (SELECT ip_crans, sum(upload) AS somme, sum(download) FROM upload6 WHERE date > timestamp 'now' - interval '1 day' AND EXISTS ( SELECT 1 FROM exemptes WHERE upload6.ip_crans = exemptes.ip_crans -- AND upload6.ip_ext <<= exemptes.ip_dest ) GROUP BY ip_crans ) ORDER BY somme DESC""" curseur.execute(requete) liste_exemptes = tableau(data = [[l[1], l[2], ipv4or6(str(l[0])), socket.getfqdn(str(l[0]))] for l in curseur.fetchall()], titre = ['upload', 'download', 'proto', 'machine'], largeur = [10, 10, 10, 30], format = ['o', 'o', 's', 's'], alignement = ['d', 'd', 'c', 'c']).encode('utf-8') # Upload des serveurs : ####################### liste_serveurs = [] for l in data_upload: if l[0] in (ips_serveurs + ips_proxys) and l[1] + l[2] > 10*1024*1024: liste_serveurs.append([l[1], l[2], ipv4or6(str(l[0])), socket.getfqdn(l[0])]) # requete = """SELECT sum(upload), sum(download) # FROM upload # WHERE # ip_crans='%s' # AND date > timestamp 'now' - interval '1 day' """ % IP # curseur.execute(requete) # traffic = curseur.fetchone() # On ne compte pas le serveur si le trafic est petit liste_serveurs = tableau(data = liste_serveurs, titre = ['upload', 'download', 'proto', 'serveur'], largeur = [10, 10, 10, 30], format = ['o', 'o', 's', 's'], alignement = ['d', 'd', 'c', 'c']).encode('utf-8') # statistiques des gros uploads depuis les serveurs ################################################### # Liste des IP des serveurs gros_uploads_des_serveurs = stats(ip_crans=ips_serveurs, show=['ip_crans', 'ip_ext'], upload_mini=50, show_limit=100).encode('utf-8') ############################ # Statistiques virus/p2p : # ############################ # IPs envoyant des paquets de protocole Ethernet inconnu : ######################################################### requete = """(SELECT COUNT(*), ip_ext FROM upload WHERE id=-1 GROUP BY ip_ext) UNION (SELECT COUNT(*), ip_ext FROM upload6 WHERE id=-1 GROUP BY ip_ext )""" curseur.execute(requete) liste_etherunk = tableau(data = [[l[0], socket.getfqdn(str(l[1]))] for l in curseur.fetchall()], titre = ['nombre','ip'], largeur = [10, 30], alignement = ['d','c']).encode('utf-8') # Machines actuellement déconnectées : ###################################### requete = "SELECT DISTINCT ip_crans FROM avertis_virus" curseur.execute(requete) infections = [ x[0] for x in curseur.fetchall() ] liste_virus = [] for IP in infections: hostname = socket.getfqdn(IP) liste_virus.append(["%s" % (str(hostname))]) liste_virus = tableau(liste_virus, titre=['machine'], largeur=[30]).encode('utf-8') # Machines ayant fait des attaques virus dans la journée : ########################################################## requete = """SELECT * FROM (SELECT ip_src,count(ip_src) as compteur FROM virus WHERE date > timestamp 'now' - interval '1 day' GROUP BY ip_src ORDER BY compteur DESC) AS tous WHERE tous.compteur>'%s' LIMIT 30""" % config.virus.virus curseur.execute(requete) liste_virus2 = [] for IP, compteur in curseur.fetchall(): hostname = socket.getfqdn(IP) liste_virus2.append([hostname, compteur]) liste_virus2 = tableau(data = liste_virus2, titre = ['machine', 'nombre'], largeur = [30, 12], alignement = ['c', 'd']).encode('utf-8') # Machines ayant fait de attaques flood dans la journée : ######################################################### requete = """SELECT * FROM (SELECT ip_src,count(ip_src) as compteur FROM flood WHERE date > timestamp 'now' - interval '1 day' GROUP BY ip_src ORDER BY compteur DESC) AS tous WHERE tous.compteur>'%s' LIMIT 30""" % config.virus.flood curseur.execute(requete) liste_virus3 = [] for IP, compteur in curseur.fetchall(): hostname = socket.getfqdn(IP) liste_virus3.append([hostname, compteur]) liste_virus3 = tableau(data = liste_virus3, titre = ['machine', 'nombre'], largeur = [30, 12], alignement = ['c', 'd']).encode('utf-8') ############# # Message : # ############# expediteur = "disconnect@crans.org" destinataire = "disconnect@crans.org" message = """From: %(From)s To: %(To)s Subject: Statistiques des =?utf-8?q?derni=C3=A8res?= 24h Message-Id: <%(uuid)s1@crans.org> Content-Type: text/plain; charset="utf-8" *Gros uploads des serveurs* (charybde et sable sont exemptés totalement) %(gros_uploads_des_serveurs)s *Statistiques de trafic des serveurs* %(liste_serveurs)s *IPs envoyant des paquets de protocole Ethernet inconnu* %(liste_etherunk)s *Machines actuellement déconnectées pour virus* %(liste_virus)s *Machines ayant commis des attaques virales dans la journée* %(liste_virus2)s *Machines ayant commis des attaques virales de type flood dans la journée* %(liste_virus3)s *Statistiques de trafic des adhérents* (tout le trafic) %(liste_upload)s *Statistiques de trafic des adhérents exemptés* (juste le trafic exempté) %(liste_exemptes)s -- statistiques.py """ uuid = hashlib.md5(str(long(time.time() * 1000)) + str(long(random.random()*100000000000000000L))).hexdigest() corps = message % { 'From': expediteur, 'To': destinataire, 'uuid': uuid, 'gros_uploads_des_serveurs': gros_uploads_des_serveurs, 'liste_etherunk': liste_etherunk, 'liste_serveurs': liste_serveurs, 'liste_upload': liste_upload, 'liste_virus': liste_virus, 'liste_virus2': liste_virus2, 'liste_virus3': liste_virus3, 'liste_exemptes': liste_exemptes } mail = smtplib.SMTP('localhost') mailaddr = os.getenv('CRANS_EMAIL', 'disconnect@crans.org') mail.sendmail(mailaddr, mailaddr, corps)