Scripts obsolètes.

This commit is contained in:
Pierre-Elliott Bécue 2015-02-25 22:07:02 +01:00
parent 05f9c4580d
commit 8a4d7dfd78
3 changed files with 0 additions and 0 deletions

383
archive/surveillance/analyse.py Executable file
View file

@ -0,0 +1,383 @@
#! /usr/bin/env python
# -*- encoding: utf-8 -*-
import socket
import sys, re
import psycopg2
sys.path.append('/usr/scripts/gestion/')
from affich_tools import tableau
def stats(ip_crans=[], ip_ext=[],
show=['ip_crans', 'ip_ext', 'port_crans', 'port_ext'],
upload_mini=0, show_limit=10, begin_time=24, end_time=0,
show_download=False,resolve_dns=True):
"""
Retourne une chaine de caratères formatée avec le tableau de statistiques
d'upload de l'ip fourni
ip_crans : ips des machines Cr@ns
chaine de caratère si il a qu'une machine
liste si il y a plusieurs machines
ip_ext : ips des machines extérieures
chaine de caratère si il a qu'une machine
liste si il y a plusieurs machines
show : liste des champs à afficher parmi :
ip_crans, ip_ext, port_crans, port_ext
upload_mini : n'affiche que les lignes avec plus d'upload que la valeur donnée
show_limit : nombre max de lignes à afficher
begin_time : date de départ d'analyse (en heure avant maintenant)
end_time : date de fin d'analyse (en heure avant maintenant)
show_download: trie par rapport au download plutôt que l'upload
"""
if type(ip_crans) == str:
ip_crans = [ip_crans]
if type(ip_ext) == str:
ip_ext = [ip_ext]
# variables pour la requete et l'affichage
##########################################
select = []
largeur = []
titre = []
format = []
alignement = []
if 'ip_crans' in show and len(ip_crans)!=1:
select.append('ip_crans')
largeur.append(13)
titre.append('machine crans')
format.append('s')
alignement.append('c')
if 'ip_ext' in show :
select.append('ip_ext')
largeur.append('*')
titre.append('machine ext')
format.append('s')
alignement.append('c')
if 'port_ext' in show :
select.append('port_ext')
largeur.append(10)
titre.append('port ext')
format.append('s')
alignement.append('d')
if 'port_crans' in show :
select.append('port_crans')
largeur.append(10)
titre.append('port crans')
format.append('s')
alignement.append('d')
select += ['sum(download) as download','sum(upload) as upload']
largeur += [10,10]
format += ['o','o']
alignement += ['d','d']
if show_download:
sort_by = 'download'
titre += ['*download*','upload']
else:
sort_by = 'upload'
titre += ['download','*upload*']
# requete dans la base
######################
ip_crans = ' OR '.join([ "ip_crans='%s'"%x for x in ip_crans ])
if not ip_crans: ip_crans='true'
ip_ext = ' OR '.join([ "ip_ext='%s'"%x for x in ip_ext ])
if not ip_ext: ip_ext='true'
requete = """
SELECT * FROM (
(
SELECT %(select)s FROM upload WHERE (%(ip_crans)s) AND (%(ip_ext)s)
AND (date > timestamp 'now' - interval '%(begin_time)d hours')
AND (date < timestamp 'now' - interval '%(end_time)d hours')
GROUP BY %(show)s
)
) AS resultat_intemediaire
WHERE %(sort_by)s >= '%(sort_mini)d'
ORDER BY %(sort_by)s DESC
LIMIT %(show_limit)d;""" % {
'select': ','.join(select),
'ip_crans': ip_crans,
'ip_ext': ip_ext,
'begin_time': begin_time,
'end_time': end_time,
'show': ','.join(show),
'sort_by': sort_by,
'sort_mini': upload_mini*1024*1024,
'show_limit': show_limit }
pgsql = psycopg2.connect(database="filtrage", user="crans")
curseur = pgsql.cursor()
curseur.execute(requete)
results = curseur.fetchall()
# on transforme tout en chaine
results = [ [ str(x).decode("utf-8") for x in line ] for line in results ]
headers = u""
try:
upload = 0
download = 0
for line in results:
upload += int(line[4])
download += int(line[3])
headers += u" upload: %sMo\n" % (upload/1024/1024)
headers += u" download: %sMo\n" % (download/1024/1024)
except IndexError:
pass
# on modifie les ip en noms de machine et les ports en noms
def nom_de_machine(ip):
if not resolve_dns: return ip
try:
return socket.gethostbyaddr(ip)[0]
except:
return ip
port_to_service = {}
for service,port in [re.split('[ \t]+',
x.strip().replace('/tcp','').replace('/udp',''))[:2]
for x in open('/etc/services').readlines()
if x[0] not in ['\n','#']]:
port_to_service[port] = service
for champ in select:
if champ == 'ip_ext':
col = select.index(champ)
results = [x[:col] + [nom_de_machine(x[col])] + x[col+1:]
for x in results]
elif champ == 'ip_crans':
col = select.index(champ)
results = [x[:col] + [nom_de_machine(x[col]).split('.')[0]] + x[col+1:]
for x in results]
elif 'port' in champ:
col = select.index(champ)
results = [x[:col] + [port_to_service.get(x[col],x[col])] + x[col+1:]
for x in results]
return headers + tableau(results, titre=titre, largeur=largeur,
alignement=alignement, format=format)
def stats_fork(stub='', ip_crans=[],
upload_mini=0, show_limit=10, begin_time=24, end_time=0,
show_download=False,resolve_dns=False):
if '/' in stub:
return
import subprocess
args=[]
if show_download:
args.append('--show-download')
args.extend(['--show-limit','%s' % show_limit])
args.extend(['--begin-time', '%s' % begin_time])
args.extend(['--end-time', '%s' % end_time])
if not resolve_dns:
args.append('-n')
for ip in ip_crans:
subprocess.Popen(
["/usr/scripts/surveillance/analyse.py",
"--file","/usr/scripts/var/analyse/%s%s.txt" % (ip,stub),
"--ip-crans", "%s" % ip
] + args)
if __name__ == '__main__' :
help = """Statistiques d'upload d'une machine du crans
usage: analyse.py [option]...
Option fait partie des options suivantes :
-d ou --show-download
trier par download plutôt que par upload
--ip-crans [ip]
ip de la machine crans
--ip-ext [ip]
ip de la machine extérieure
--show [champ]
champs à afficher (parmi ip_crans, ip_ext, port_crans, port_ext)
--upload-mini [n Mo]
upload mini des lignes à afficher
--show-limit [n]
nombre maximum de lignes à afficher
--begin-time [n heures]
heure de départ de l'analyse (en heures depuis maintenant)
--end-time [n heures]
heure de fin de l'analyse (en heures depuis maintenant)
-n
Ne pas résoudre les adresses ip
Exemple :
sudo /usr/scripts/surveillance/analyse.py bilou.crans.org"""
headers=""
# import des modules
import getopt
# aide
######
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv)==1:
print help
sys.exit(0)
# parsage des arguments
#######################
try :
opts, args = getopt.getopt(sys.argv[1:], 'dn', ['show-download',
'ip-crans=', 'ip-ext=', 'show=', 'upload-mini=',
'begin-time=', 'end-time=', 'show-limit=', 'file='])
except getopt.GetoptError,message :
print help
sys.exit(4)
# affichage des stats de download
#################################
show_download = False
for key,value in opts:
if key == '-d' or key == '--show-download':
show_download = True
if show_download:
headers += u"Statistiques de download\n"
else:
headers += u"Statistiques d'upload\n"
# recherche de la machine crans
###############################
ip_crans = []
ip_crans_nom = []
for key,value in opts :
if key == '--ip-crans' :
try :
ip_crans.append(socket.gethostbyaddr(value)[2][0])
ip_crans_nom.append(socket.gethostbyaddr(value)[0])
except socket.gaierror :
print "Hôte %s inconnu" % value
sys.exit(5)
except socket.herror:
print "Hôte %s inconnu" % value
ip_crans.append(value)
if len(ip_crans_nom)==1:
headers += u' depuis la machine %s\n' % ip_crans_nom[0]
elif ip_crans_nom:
headers += u' depuis les machines %s\n' % ', '.join(ip_crans_nom)
# recherche de la machine ext
#############################
ip_ext = []
ip_ext_nom = []
for key,value in opts :
if key == '--ip-ext' :
# recherche de l'ip de la machine extérieur
try:
ip_ext.append(socket.gethostbyaddr(value)[2][0])
except socket.herror:
ip_ext.append(value)
except socket.gaierror :
print "Hôte %s inconnu" % value
sys.exit(5)
# recherche du nom d'hote
try :
ip_ext_nom.append(socket.gethostbyaddr(value)[0])
except socket.herror:
ip_ext_nom.append(ip_ext[-1])
except socket.gaierror :
ip_ext_nom.append(ip_ext[-1])
if len(ip_ext_nom)==1:
headers += u' vers la machine extérieure %s\n' % ip_ext_nom[0]
elif ip_ext_nom:
headers += u' vers les machines extérieures %s\n' % ', '.join(ip_ext_nom)
# limite d'affichage
####################
show = [x[1] for x in opts
if x[0] == '--show'
and x[1] in ['ip_crans', 'ip_ext', 'port_crans', 'port_ext']]
if not show :
show = ['ip_crans', 'ip_ext', 'port_crans', 'port_ext']
else :
headers += u' affichage de %s\n' % ', '.join(show)
# upload mini à afficher
########################
upload_mini = 0
for key,value in opts :
if key == '--upload-mini' :
try :
upload_mini = int(value)
except :
print 'L\'upload mini doit être un entier (en MO)'
sys.exit(4)
break
if upload_mini:
headers += u' pour les traffics supérieurs à %d Mo\n' % upload_mini
# nombre limite d'enregristrements
##################################
limit = 10
for key,value in opts :
if key == '--show-limit' :
try :
limit = int(value)
headers += u' affichage des %d premiers résultats\n' % limit
except :
print 'Le nombre limite n\'est pas un entier'
sys.exit(3)
break
# Résolution dns
################
resolve_dns = '-n' not in [key for (key,value) in opts]
# début de l'analyse
####################
begin_time = 24
for key,value in opts :
if key == '--begin-time' :
try :
begin_time = int(value)
except :
print 'Le nombre d\'heures doit être un entier'
sys.exit(4)
break
# fin de l'analyse
##################
end_time = 0
for key,value in opts :
if key == '--end-time' :
try :
end_time = int(value)
except :
print 'Le nombre d\'heures doit être un entier'
sys.exit(4)
break
if begin_time != 24 or end_time:
headers += u' entre il y a %d heure(s) et il y a %d heure(s)\n' % (begin_time,end_time)
# fichier de sortie
###################
file = None
for key,value in opts :
if key == '--file' :
file = value
# affichage du résultat
#######################
out = stats(ip_crans, ip_ext, show, upload_mini, limit, begin_time,
end_time, show_download,resolve_dns)
out = headers + out
if not file:
print out.encode("utf-8")
else:
with open(file, 'w') as f:
f.write(out.encode('utf-8'))

View file

@ -0,0 +1,46 @@
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
""" Pour détecter et signaler les collisions d'adresses IPv6 """
import psycopg2
import sys
import netaddr
import itertools
import gestion.ipt as ipt
from gestion.config import prefix as crans_prefixes
## Construit un filtre sql succint des réseaux à vérifier
# (crans_prefixes est un dictionnaire de listes de networks, mais on se fout des
# clés, donc on concatène méchamment)
prefixes = itertools.chain(['fe80::/64'], *crans_prefixes.values())
# Et on ne garde que le plus utile (histoire de faire moins de tests plus tard)
prefixes = netaddr.cidr_merge(prefixes)
prefixes = " OR \n".join( "a.ip <<= inet '%s'" % str(cidr) for cidr in prefixes)
# Connection à la base sql via pgsql
pgsql = psycopg2.connect(database='filtrage', user='crans')
# Il faudra remplacer la ligne ci-dessous par pgsql.set_session(autocommit = True) sous wheezy
pgsql.set_isolation_level(0)
curseur = pgsql.cursor()
# On regarde s'il y a deux ipv6 identiques avec des mac non identiques
collision_mac_ip_request = """SELECT DISTINCT
a.date as date1, a.mac as mac1, a.ip as ip1,
b.date as date2, b.mac as mac2, b.ip as ip2
FROM mac_ip as a, mac_ip as b
WHERE a.ip = b.ip AND
(%s) AND
a.mac != b.mac AND
a.date >= b.date AND
a.date - b.date < interval '3 day'
ORDER BY a.date;""" % prefixes
curseur.execute(collision_mac_ip_request)
collision_mac_ip = curseur.fetchall()
if collision_mac_ip != []:
print "Collision d'addresses ipv6 : "
for (date1, mac1, ip1, date2, mac2, ip2) in collision_mac_ip:
print "%s %s %s" % (date1, ipt.mac_addr(mac1), ip1)
print "%s %s %s" % (date2, ipt.mac_addr(mac2), ip2)

View file

@ -0,0 +1,327 @@
#! /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
X-Mailer: /usr/scripts/surveillance/statistiques.py
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)