Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Fabio - Ottobre 25, 2011, 03:55:59 pm

Titolo: Sniffer conta traffico
Inserito da: Fabio - Ottobre 25, 2011, 03:55:59 pm
Hey xinyiman ma cos'è che quando cerco qualcosa capito in un thread che hai già  aperto tu in passato?   :D
http://www.lazarus.freepascal.org/index.php?topic=9744.0

Ho una situazione dove mi servirebbe fare uno sniffer che più che intercettare i dati mi faccia la conta del traffico, quindi più un monitor di rete che non uno sniffer di contenuti.

Sostanzialmente che abbia minimo i dati divisi per ip src/dst, porta src/dst, protocollo ( principalmente tcp e udp ) e che quindi poi possa giocarci e tirami fuori solo quello che mi serve, tipo dammi il traffico generato sulla porta 5000 diviso per ip sorgente, una roba di questo genere.

Il sistema sarebbe Windows, ma ne uscisse una cosa cross è più gradita.

Sapete innanzitutto se è possibile e darmi eventualmente qualche dritta verso cosa concentrare le ricerche per non perdere tempo su cose magari già viste e che non portano a niente ?
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 25, 2011, 04:12:00 pm
Nessuno mi aveva dato delle risposte. Bhe la prima cosa che mi viene in mente è: socket. Bisognerebbe dare un occhiata ai socket del free pascal e leggere tutto ciò che passa sulla scheda di rete scelta (mettendo la scheda di rete in quello stato chiamato: promiscuous mode). Io partirei da li...ora non ho tempo per fare delle prove. Se non risolvi appena posso vedo come fare. Io fossi in te partirei proprio dal promiscuous mode
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 25, 2011, 04:26:21 pm
Per i socket dai un occhiata a questo:

http://wiki.lazarus.freepascal.org/Sockets

Per capire la logica prova a guardare questo sorgente (c), dovresti replicare qualcosa di simile in pascal.

Codice: [Seleziona]
#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h> //For standard things
#include<netinet/ip_icmp.h> //Provides declarations for icmp header
#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

void ProcessPacket(unsigned char* , int);
void print_ip_header(unsigned char* , int);
void print_tcp_header(unsigned char* buffer , int size);
void print_udp_header(unsigned char* , int);

int sock_raw;
FILE *logfile;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;
struct sockaddr_in source,dest;

int main()
{
int saddr_size , data_size;
struct sockaddr_in saddr;
struct in_addr in;

unsigned char *buffer = (unsigned char *)malloc(65536); //Its Big!

logfile=fopen("log.txt","w");
if(logfile==NULL) printf("Unable to create file.");
printf("Starting...\n");
//Create a raw socket that shall sniff
sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
if(sock_raw < 0)
{
printf("Socket Error\n");
return 1;
}
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
//Now process the packet
ProcessPacket(buffer , data_size);
}
close(sock_raw);
printf("Finished");
return 0;
}

void ProcessPacket(unsigned char* buffer, int size)
{
//Get the IP Header part of this packet
struct iphdr *iph = (struct iphdr*)buffer;
++total;
switch (iph->protocol) //Check the Protocol and do accordingly...
{
case 1:  //ICMP Protocol
++icmp;
//PrintIcmpPacket(Buffer,Size);
break;

case 2:  //IGMP Protocol
++igmp;
break;

case 6:  //TCP Protocol
++tcp;
print_tcp_packet(buffer , size);
break;

case 17: //UDP Protocol
++udp;
print_udp_packet(buffer , size);
break;

default: //Some Other Protocol like ARP etc.
++others;
break;
}
printf("TCP : %d   UDP : %d   ICMP : %d   IGMP : %d   Others : %d   Total : %d\r",tcp,udp,icmp,igmp,others,total);
}

void print_ip_header(unsigned char* Buffer, int Size)
{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen =iph->ihl*4;

memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;

memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
fprintf(logfile,"   |-IP Version        : %d\n",(unsigned int)iph->version);
fprintf(logfile,"   |-IP Header Length  : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4);
fprintf(logfile,"   |-Type Of Service   : %d\n",(unsigned int)iph->tos);
fprintf(logfile,"   |-IP Total Length   : %d  Bytes(Size of Packet)\n",ntohs(iph->tot_len));
fprintf(logfile,"   |-Identification    : %d\n",ntohs(iph->id));
//fprintf(logfile,"   |-Reserved ZERO Field   : %d\n",(unsigned int)iphdr->ip_reserved_zero);
//fprintf(logfile,"   |-Dont Fragment Field   : %d\n",(unsigned int)iphdr->ip_dont_fragment);
//fprintf(logfile,"   |-More Fragment Field   : %d\n",(unsigned int)iphdr->ip_more_fragment);
fprintf(logfile,"   |-TTL      : %d\n",(unsigned int)iph->ttl);
fprintf(logfile,"   |-Protocol : %d\n",(unsigned int)iph->protocol);
fprintf(logfile,"   |-Checksum : %d\n",ntohs(iph->check));
fprintf(logfile,"   |-Source IP        : %s\n",inet_ntoa(source.sin_addr));
fprintf(logfile,"   |-Destination IP   : %s\n",inet_ntoa(dest.sin_addr));
}

void print_tcp_packet(unsigned char* Buffer, int Size)
{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;

struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen);

fprintf(logfile,"\n\n***********************TCP Packet*************************\n");

print_ip_header(Buffer,Size);

fprintf(logfile,"\n");
fprintf(logfile,"TCP Header\n");
fprintf(logfile,"   |-Source Port      : %u\n",ntohs(tcph->source));
fprintf(logfile,"   |-Destination Port : %u\n",ntohs(tcph->dest));
fprintf(logfile,"   |-Sequence Number    : %u\n",ntohl(tcph->seq));
fprintf(logfile,"   |-Acknowledge Number : %u\n",ntohl(tcph->ack_seq));
fprintf(logfile,"   |-Header Length      : %d DWORDS or %d BYTES\n" ,(unsigned int)tcph->doff,(unsigned int)tcph->doff*4);
//fprintf(logfile,"   |-CWR Flag : %d\n",(unsigned int)tcph->cwr);
//fprintf(logfile,"   |-ECN Flag : %d\n",(unsigned int)tcph->ece);
fprintf(logfile,"   |-Urgent Flag          : %d\n",(unsigned int)tcph->urg);
fprintf(logfile,"   |-Acknowledgement Flag : %d\n",(unsigned int)tcph->ack);
fprintf(logfile,"   |-Push Flag            : %d\n",(unsigned int)tcph->psh);
fprintf(logfile,"   |-Reset Flag           : %d\n",(unsigned int)tcph->rst);
fprintf(logfile,"   |-Synchronise Flag     : %d\n",(unsigned int)tcph->syn);
fprintf(logfile,"   |-Finish Flag          : %d\n",(unsigned int)tcph->fin);
fprintf(logfile,"   |-Window         : %d\n",ntohs(tcph->window));
fprintf(logfile,"   |-Checksum       : %d\n",ntohs(tcph->check));
fprintf(logfile,"   |-Urgent Pointer : %d\n",tcph->urg_ptr);
fprintf(logfile,"\n");
fprintf(logfile,"                        DATA Dump                         ");
fprintf(logfile,"\n");

fprintf(logfile,"IP Header\n");
PrintData(Buffer,iphdrlen);

fprintf(logfile,"TCP Header\n");
PrintData(Buffer+iphdrlen,tcph->doff*4);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + tcph->doff*4 , (Size - tcph->doff*4-iph->ihl*4) );

fprintf(logfile,"\n###########################################################");
}

void print_udp_packet(unsigned char *Buffer , int Size)
{

unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;

struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen);

fprintf(logfile,"\n\n***********************UDP Packet*************************\n");

print_ip_header(Buffer,Size);

fprintf(logfile,"\nUDP Header\n");
fprintf(logfile,"   |-Source Port      : %d\n" , ntohs(udph->source));
fprintf(logfile,"   |-Destination Port : %d\n" , ntohs(udph->dest));
fprintf(logfile,"   |-UDP Length       : %d\n" , ntohs(udph->len));
fprintf(logfile,"   |-UDP Checksum     : %d\n" , ntohs(udph->check));

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
PrintData(Buffer , iphdrlen);

fprintf(logfile,"UDP Header\n");
PrintData(Buffer+iphdrlen , sizeof udph);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + sizeof udph ,( Size - sizeof udph - iph->ihl * 4 ));

fprintf(logfile,"\n###########################################################");
}

void print_icmp_packet(unsigned char* Buffer , int Size)
{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;
iphdrlen = iph->ihl*4;

struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen);

fprintf(logfile,"\n\n***********************ICMP Packet*************************\n");

print_ip_header(Buffer , Size);

fprintf(logfile,"\n");

fprintf(logfile,"ICMP Header\n");
fprintf(logfile,"   |-Type : %d",(unsigned int)(icmph->type));

if((unsigned int)(icmph->type) == 11)
fprintf(logfile,"  (TTL Expired)\n");
else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY)
fprintf(logfile,"  (ICMP Echo Reply)\n");
fprintf(logfile,"   |-Code : %d\n",(unsigned int)(icmph->code));
fprintf(logfile,"   |-Checksum : %d\n",ntohs(icmph->checksum));
//fprintf(logfile,"   |-ID       : %d\n",ntohs(icmph->id));
//fprintf(logfile,"   |-Sequence : %d\n",ntohs(icmph->sequence));
fprintf(logfile,"\n");

fprintf(logfile,"IP Header\n");
PrintData(Buffer,iphdrlen);

fprintf(logfile,"UDP Header\n");
PrintData(Buffer + iphdrlen , sizeof icmph);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + sizeof icmph , (Size - sizeof icmph - iph->ihl * 4));

fprintf(logfile,"\n###########################################################");
}

void PrintData (unsigned char* data , int Size)
{

for(i=0 ; i < Size ; i++)
{
if( i!=0 && i%16==0)   //if one line of hex printing is complete...
{
fprintf(logfile,"         ");
for(j=i-16 ; j<i ; j++)
{
if(data[j]>=32 && data[j]<=128)
fprintf(logfile,"%c",(unsigned char)data[j]); //if its a number or alphabet

else fprintf(logfile,"."); //otherwise print a dot
}
fprintf(logfile,"\n");
}

if(i%16==0) fprintf(logfile,"   ");
fprintf(logfile," %02X",(unsigned int)data[i]);

if( i==Size-1)  //print the last spaces
{
for(j=0;j<15-i%16;j++) fprintf(logfile,"   "); //extra spaces

fprintf(logfile,"         ");

for(j=i-i%16 ; j<=i ; j++)
{
if(data[j]>=32 && data[j]<=128) fprintf(logfile,"%c",(unsigned char)data[j]);
else fprintf(logfile,".");
}
fprintf(logfile,"\n");
}
}
}
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 25, 2011, 04:34:02 pm
Non so se può dare una mano ma mi sono imbattuto in: http://www.magsys.co.uk/delphi/magmonsock.asp

Per delphi (vedi se riesci a riutilizzare le info)
Titolo: Re:Sniffer conta traffico
Inserito da: Fabio - Ottobre 26, 2011, 10:35:35 am
Grazie delle info, in settimana faccio qualche prova e parto studiando quello.
Ovviamente se ne cavo poi in qualcosa posto qui quello trovato.

ciao.
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 26, 2011, 11:35:39 am
Ok ci conto, io se trovo altro ti avverto!
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 26, 2011, 01:44:27 pm
Guarda http://www.dubaron.com/synapsecookbook/synapsecookbook-0.1.pdf

Leggi bene RawIP
Titolo: Re:Sniffer conta traffico
Inserito da: Fabio - Ottobre 26, 2011, 01:54:21 pm
Ustia  :D

Questo me lo devo studiare bene, spero solo non sia ancora troppo avanzato per le mie misere conoscenze del linguaggio  :-[

Grazie.
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Ottobre 26, 2011, 02:05:21 pm
Figurati, se trovo altro ti aggiorno :)
Titolo: Re:Sniffer conta traffico
Inserito da: Goblin - Ottobre 26, 2011, 02:18:11 pm
Credo di avere bisogno di una piccola spiegazione, non ho capito bene cosa sta cercando Fabio.
1) un programma che controlla (monitora) tutto il traffico di rete.
2) un programma che controlla (monitora) il traffico della propria applicazione.

cmq oltre tutti i link che ti sono stati dati fai una ricerca di Winpcap, e dai un occhio anche qui http://delphi.about.com/od/fullcodeprojects/l/aa112903a.htm
G.
Titolo: Re:Sniffer conta traffico
Inserito da: Fabio - Ottobre 26, 2011, 02:30:34 pm
Cerco di spiegarmi, un esempio molto schietto:

vorrei fare un tool che monitorizzi il traffico generato su un server ma solo su certe porte/protocolli, ad esempio come detto sopra tutto il traffico ( solo la quantità non i dati ) generato sulla porta TCP 5000 e suddiviso per IP sorgente ( ovviamente saranno poi parametri questi )

es. di risultato

192.168.1.10 ha generato 1000 KB
192.168.1.11 ha generato 10 KB
192.168.1.12 ha generato 5000 KB

Non mi interessa analizzare il contenuto dei pacchetti devo solo quantificare il traffico generato da un servizio che opera su una particolare porta.
Titolo: Re:Sniffer conta traffico
Inserito da: Fabio - Novembre 03, 2011, 07:42:53 pm
Giusto un paio di aggiornamenti per lasciare traccia delle ricerche.

Ho contattato il creatore di lNet per sapere se potevo usare la sua libreria per questa cosa ma mi ha detto di no e consigliato di usare libpcap invece.

Ho anche trovato questa unit che dovrò poi vedere se si riesce ad adattare a lazarus, lo appunto e allego solo per non perderlo:
http://read.pudn.com/downloads81/sourcecode/hack/sniffer/314333/delphi%20winpcap/Pcap.pas__.htm
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Novembre 03, 2011, 08:23:53 pm
Interessante...appena posso gli do un occhiata
Titolo: Re:Sniffer conta traffico
Inserito da: Fabio - Novembre 03, 2011, 08:34:23 pm
Appunto altra documentazione:
http://pasotech.altervista.org/delphi/articolo123.htm
Titolo: Re:Sniffer conta traffico
Inserito da: xinyiman - Novembre 03, 2011, 08:46:52 pm
Se riesci poi a mettere su un esempio di come appoggiarsi alle libpcap tramite lazarus fai cosa gradita.

Se riesci cross-platform  :D