[bcn-pm] Propuesta de charla futura
José Luis Pérez Diez
jluis at escomposlinux.org
Tue Jun 15 06:19:18 CDT 2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Estoy realizando un proyecto para monitorizar la red de forma pasiva Basado en
ARP request y para familiarizarme con algunos modulos como :
Net::PcapUtils
Net::Pcap
NetPacket::Ethernet
NetPacket::ARP
threads
threads::shared
Thread::Queue
DBI
y varios para realizar SNMP consultas netbios y nmap (monitorizar para
consulta del estado de la red en condiciones de alertas de virus ).
De momento estoy con el modulo que captura las peticiones de arp y gestiono
los datos directamente desde pgsql pero la intencion es generar un grupo de
paginas web (via XML) que faciliten la explotacion de los datos capturados.
Si os parece interesante mantendre al dia las incidencias y cosas curiosas que
vea para una poxima charla
=================================capture.pl ======================
#!/usr/bin/perl -w
=head1 Capture
=item Descripcion
captura paquetes ARP y almacena el origen (mac e ip) esta pensado para
ejecutar como root
=item Dependecias
Net::PcapUtils Net::Pcap NetPacket::Ethernet NetPacket::ARP threads
threads::shared Thread::Queue
Actualmente su funcinamiento se controla desde la entrada estandard
=cut
use Net::PcapUtils;
use Net::Pcap;
use NetPacket::Ethernet qw(:types);
use NetPacket::ARP;
use threads;
use threads::shared;
use Thread::Queue;
use DBI;
my %lista =();
my $cola = Thread::Queue->new;
my $stoped = 0;
my $captured =0;
my $processed =0;
share($stoped);
share($captured);
share($processed);
##no se puede sharear la lista
=head2 showhw(HexString)
retorna la conversion string de 12bytes que representan una MacAdress en
exadecimal a la notacion estandard para macs
=cut
sub showhw($){
my ($hw ) = @_;
$hw =~ s/([0-9A-Fa-f][0-9A-Fa-f])(?=[0-9A-Fa-f])/$1:/g;
return $hw;
}
=head2 showip(HexString)
retorna la conversion de un string de 8 bytes que representan una IP en
exadecimal a la notacion estandard para macs
=cut
sub showip($){
my ($ip) = @_;
return
hex(substr($ip,0,2)).".".hex(substr($ip,2,2)).".".hex(substr($ip,4,2)).".".hex(substr($ip,6,2));
}
=head2 showtipe(Numero)
retorna el nombre del tipo de paquete arp
=cut
sub showtype($) {
my @nombre = ("", arp_ask, arp_resp,rarp_ask,rarp_resp);
return $nombre[shift];
}
=head2 monta_lista
Actiualiza un hash de hash de array
con clave IP y MAC con la siguete informacion
=over 4
=item 1
timestamp del paquete
=item 2
cuenta de paquetes recibidos
=item 3
dirty flag
=back
=cut
sub monta_lista {
while ($cola->pending) {
my $ip = $cola->dequeue;
my $hw = $cola->dequeue;
my $cuando = $cola->dequeue;
$processed ++;
if ($lista{$ip}{$hw}[0]) {
$lista{$ip}{$hw}[0] = $cuando;
$lista{$ip}{$hw}[1] ++;
$lista{$ip}{$hw}[2] = 1;
}else{
$lista{$ip}{$hw}[0] = $cuando;
$lista{$ip}{$hw}[1] = 1;
$lista{$ip}{$hw}[2] = 1;
}
}
}
=head2 process_pkt
Rutina llamada por la thead del bucle de captura de paquetes
=cut
sub process_pkt {
my ($arg, $hdr, $pkt) = @_;
my $eth_obj = NetPacket::Ethernet->decode($pkt);
my $arp_obj = NetPacket::ARP->decode($eth_obj->{data}, $eth_obj);
$cola->enqueue($arp_obj->{spa},$arp_obj->{sha},$$hdr{tv_sec});
$captured ++;
# print
showtype($arp_obj->{opcode})."=s(".showhw($arp_obj->{sha}).",".showip($arp_obj->{spa})
# .")t(".showhw($arp_obj->{tha}).",".showip($arp_obj->{tpa}).")\n";
}
=head2 capture
tread de captura de paquetes ARP
=cut
sub capture {
Net::PcapUtils::loop(\&process_pkt, (FILTER => 'arp',PROMISC =>0,NUMPACKETS
=> -1,DEV => 'eth0'));
sleep(1);
$stoped = 1
}
my $Base = DBI->connect('dbi:Pg:dbname=redges;host=localhost','test','test');
=head2 readfrom_db
lee las macs desde la base de datos y llena el hash
=cut
sub readfrom_db{
my $consulta = $Base->prepare('SELECT ip,hwaddr,contador FROM ipmac ');
print $consulta->execute ."\n\n";
my @tira;
while (@tira = $consulta->fetchrow_array) {
my $ip = $tira[0];
$ip =~ s{/.*}{};
my $hw = $tira[1];
$hw =~ s{:}{}g;
my $cuantos = $tira[2];
$lista{$ip}{$hw}[0] = 0;
$lista{$ip}{$hw}[1] = $cuantos;
$lista{$ip}{$hw}[2] = 0;
}
}
=head2 imprime
Inserta los paquetes del hash de hases lista a la base de datos y limpia el
dirty flag
=cut
sub imprime {
foreach $clave (sort keys (%lista)){
my $macs = $lista{$clave};
foreach $mac (sort keys (%$macs)){
if ($$macs{$mac}[2]){
$$macs{$mac}[2]=0;
my $update = 'UPDATE ipmac SET ultimo=\''.
localtime($$macs{$mac}[0]).
'\',contador='.
$$macs{$mac}[1].
' WHERE ip= \''.
showip($clave).
'\' and hwaddr =\''.showhw($mac).'\';';
# print "$update\n";
# print " " x 44;print "^\n";
my $result = $Base->do($update);
# print "$result\n";
unless ($result !=0 ) {
my $insert ='INSERT INTO ipmac VALUES(\''.showip($clave).'\',\''.
$mac.'\',\''
.localtime($$macs{$mac}[0])."',".$$macs{$mac}[1].");";
# print $insert;
$result =$Base->do($insert);
# print $result;
}
}
#print showip($clave)."\t".showhw($mac)."\t".$$macs{$mac}[0]."\t".
$$macs{$mac}[1]."\n";
}
}
}
=head2 bucle
tread de control actualmente recive informacion desde el teclado
=cut
sub bucle {
while (<>){
my $entrada = $_;
chomp($entrada);
print "$entrada\n";
if ($entrada eq "X") {
$stoped = 1;
return;
}elsif ($entrada eq "L"){
$stoped = 2;
}
}
}
my $bucle = threads->new(\&bucle);
$bucle->detach;
my $scaning = threads->new(\&capture);
$scaning->detach();
while ($stoped != 1 ){
monta_lista;
if ($stoped == 2){
imprime;
$stoped= 0;
}
sleep(1);
}
print "Capturados $captured procesados $processed IPes ".keys(%lista)."\n";
imprime;
$Base->disconnect();
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iD8DBQFAzttJhcSSw1jZilwRAl3FAJsEvtllqCk3hW37EPkYo9h2l76eUwCgog6u
hK4jjuAfu6mvteBhzvt9V38=
=k5+5
-----END PGP SIGNATURE-----
More information about the Barcelona-pm
mailing list