scripts/surveillance/statistiques.py
Pierre-Elliott Bécue bff0c9f555 Dans la série pgsql => thot, on transfère les bases de données, pour cela, on s'assure que tout est prêt niveau scripts.
Ignore-this: 1310db9d47caaf448d3727daafb43b77
Et on fait des patchs dégueux parce que psycopg est dans une trop vieille version...

darcs-hash:20130126222239-afe24-302736b502be967e4295205a6b865a9f55fb8e63.gz
2013-01-26 23:22:39 +01:00

313 lines
9.9 KiB
Python

#! /usr/bin/env python
# -*- encoding: iso-8859-15 -*-
"""
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
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
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('iso-8859-15')
# 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
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('iso-8859-15')
# 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('iso-8859-15')
# 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('iso-8859-15')
############################
# 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"""
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('iso-8859-15')
# 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('iso-8859-15')
# 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('iso-8859-15')
# 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('iso-8859-15')
# Machines ayant utilisé des protocoles P2P dans la journée :
#############################################################
requete = """SELECT ip_src, nom, compteur, max(date) FROM
(SELECT ip_src,nom,count(ip_src) as compteur
FROM p2p INNER JOIN protocole_p2p ON p2p.id_p2p=protocole_p2p.id_p2p
WHERE p2p.date > timestamp 'now' - interval '1 day'
GROUP BY ip_src,nom)
AS tous
LEFT JOIN
(SELECT * FROM avertis_p2p
WHERE date > timestamp 'now' - interval '1 day')
AS avertis
ON ip_src=ip_crans
WHERE tous.compteur>5
GROUP BY ip_src, nom, compteur
ORDER BY 3 DESC"""
curseur.execute(requete)
liste_p2p = []
for IP, protocole, compteur, blackliste in curseur.fetchall():
hostname = socket.getfqdn(IP)
# Le champ blackliste contient la date du blacklistage si il a eu lieu
if blackliste :
liste_p2p.append(['*%s*' % hostname,
'*%s*' % protocole,
'*%d*' % compteur,
'*%d*' % config.p2p.limite[protocole]])
else:
liste_p2p.append([hostname, protocole,
compteur, config.p2p.limite[protocole]])
liste_p2p = tableau(data = liste_p2p,
titre = ['machine', 'protocole', 'nombre', 'limite'],
largeur = [32, 14, 10, 8],
alignement = ['c', 'c', 'd', 'd']).encode('iso-8859-15')
#############
# Message : #
#############
expediteur = "disconnect@crans.org"
destinataire = "disconnect@crans.org"
message = """From: %(From)s
To: %(To)s
Subject: Statistiques des =?iso-8859-1?Q?derni=E8res?= 24h
Message-Id: <%(uuid)s1@crans.org>
Content-Type: text/plain; charset="iso-8859-15"
*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
*Machines ayant utilisé des protocoles P2P durant la journée*
%(liste_p2p)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_p2p': liste_p2p,
'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)