[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