[gl-como] Net Sniff

Pietro Bertera gl-como@lists.linux.it
Sat, 08 Mar 2003 16:07:42 +0100


This is a multi-part message in MIME format.
--------------030603020809010508000301
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit

Pietro Bertera wrote:

Ups.. mi sono accorto che *dopo un po'* chrashava tutto (kernel panic).
dopo essere diventato scemo tutta la notte, tutta la mattina e parte del 
pomeriggio mi sonoa ccorto che non sempre i pacchetti (in sk_buff) hanno 
tutti i campi inizializzati e ad esempio paccehtti icmp non hanno il 
numero di porta.
ho risolto il tutto con qualche if(pippo != NULL)

è interessante vedere come si degradano le prestazioni della cpu quando 
ci sono scambi di dati tra kernel space e user space:

per ogni pacchetto, ogni volta che viene letto dal kernel, viene 
stampato : source address, source port, destination address e 
destination port.
Ogni pacchetto ricevuto viene letto 2 volte nei 2 hook  facendo questo 
percorso:
PREROUTING -> INPUT  (se è per la macchina stessa)
PREROUTING -> FORWARD (se è per un altra macchina)

indem per i pacchetti inviati:
OUTPUT -> POSTROUTING  (se parte dalla macchina stessa)
FORWARD -> POSTROUTING (se parte da un altra macchina)

quindi nel caso non ci siano regole di iptables per l'interfaccia lo 
(127.0.0.1)
se si fa un nmap 127.0.0.1 ad ogni richiesta su ogni porta il kernel 
risponde (con un pacchetto per dire se è aperta o chiusa)

In definitiva con in modulo installato quando si fa un nmap 127.0.0.1
vengono stampati 4 dati per ogni pacchetto generato da nmap e altri 4 
per ogni pacchetto in risposta a quello di nmap, quindi in totale 8 dati 
per ogni richiesta di nmap.
Un portscan in queste condizioni ci mette 2 minuti !!! (un nmap 127.0.0.1)

se dal sorgente eliminate le printk ci mette 2 secondi: come se non 
fosse installato il modulo.

Questo fatto dovrebbe fare pensare sulla convenienza o meno di fare 
logging massiccio.

allego ancora il codice corretto.

ciao

--------------030603020809010508000301
Content-Type: text/x-csrc;
 name="NetSniff.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="NetSniff.c"

/*             Sat Mar  8 00:05:40 2003
 *
 *					Bertera Pietro 
 *		e-mail: p.bertera@valtellinux.it dr.iggy@iol.it
 *
 *					compile with:
 * gcc -Wall -DMODULE -D__KERNEL__ -DDEBUG -c NetSniff.c -I/usr/src/linux/include
 *
 *					run with:
 * insmod NetSniff.o
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 


#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif

#include <asm/uaccess.h>

#include <linux/module.h>

#include <linux/sched.h>
#include <linux/kernel.h> 
#include <linux/slab.h>	   
#include <linux/errno.h>  
#include <linux/types.h>  
#include <linux/interrupt.h> 

#include <linux/netdevice.h>   
#include <linux/etherdevice.h> 
#include <linux/ip.h>          
#include <linux/tcp.h>         
#include <linux/udp.h>		   
#include <linux/skbuff.h>


#include <linux/netfilter.h> 
#include <linux/netfilter_ipv4.h>

#include <linux/config.h>
#include <linux/in.h>
#include <linux/socket.h>

MODULE_LICENSE("GPL");

unsigned int in_hook(unsigned int hooknum,
                             struct sk_buff **skb_p,
                             const struct net_device *in,
                             const struct net_device *out,
                             int (*okfn)(struct sk_buff *))
{   
    int retval = NF_ACCEPT;
	struct 	sk_buff *skb = (*skb_p); 				
	struct 	iphdr  *iph;  				
    struct 	tcphdr *tcph = NULL; 				
	struct 	udphdr *udph = NULL; 				

	__u32   saddr;						
	__u32 	daddr; 					
	__u8	protocol_type; 		
	__u16  	dport = 0;								
	__u16	sport = 0;		
	
	if(&(skb->nh.iph) != NULL){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(iph->saddr) != NULL){
		saddr = iph->saddr;
	}else{
		return retval;
	}
	
	if(&(iph->daddr) != NULL){
		daddr = iph->daddr;
	}else{
		return retval;
	}
	
	if(&(skb->h.th) != NULL){
		tcph = skb->h.th;
	}
	
	if(&(skb->h.uh) != NULL){
		udph = skb->h.uh;
	}
		
	if(iph->protocol){
		protocol_type=iph->protocol;
	}else{
		return retval;
	}
	
		
	if((protocol_type == IPPROTO_TCP) && (&(tcph->dest) != NULL) && (&(tcph->source) != NULL)){				
		dport = tcph->dest;
		sport = tcph->source;
	}
	
	if((protocol_type == IPPROTO_UDP) && (&(udph->dest) != NULL) && (&(udph->source) != NULL)){	 			
		dport = udph->dest;
		sport = udph->source;
	}
	
	printk("INPUT	--> S: %d.%d.%d.%d:%d  D: %d.%d.%d.%d:%d\n",NIPQUAD(saddr),sport,NIPQUAD(daddr),dport);
	//printk("INPUT	--> S: %d.%d.%d.%d D: %d.%d.%d.%d\n",NIPQUAD(saddr),NIPQUAD(daddr));
	
    return retval; 
}

unsigned int out_hook(unsigned int hooknum,
                             struct sk_buff **skb_p,
                             const struct net_device *in,
                             const struct net_device *out,
                             int (*okfn)(struct sk_buff *))
{  
    int retval = NF_ACCEPT;
	struct 	sk_buff *skb = (*skb_p); 				
	struct 	iphdr  *iph = NULL;  				
    struct 	tcphdr *tcph = NULL; 				
	struct 	udphdr *udph = NULL;				

	__u32   saddr;						
	__u32 	daddr; 					
	__u8	protocol_type; 		
	__u16  	dport = 0;								
	__u16	sport = 0;		
	
	if(&(skb->nh.iph) != NULL){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(iph->saddr) != NULL){
		saddr = iph->saddr;
	}else{
		return retval;
	}
	
	if(&(iph->daddr) != NULL){
		daddr = iph->daddr;
	}else{
		return retval;
	}
	
	if(&(skb->h.th) != NULL){
		tcph = skb->h.th;
	}
	
	if(&(skb->h.uh) != NULL){
		udph = skb->h.uh;
	}
		
	if(iph->protocol){
		protocol_type=iph->protocol;
	}else{
		return retval;
	}
	
		
	if((protocol_type == IPPROTO_TCP) && (&(tcph->dest) != NULL) && (&(tcph->source) != NULL)){				
		dport = tcph->dest;
		sport = tcph->source;
	}
	
	if((protocol_type == IPPROTO_UDP) && (&(udph->dest) != NULL) && (&(udph->source) != NULL)){	 			
		dport = udph->dest;
		sport = udph->source;
	}
	
	printk("OUT	--> S: %d.%d.%d.%d:%d  D: %d.%d.%d.%d:%d\n",NIPQUAD(saddr),sport,NIPQUAD(daddr),dport);
	//printk("OUT	--> S: %d.%d.%d.%d  D: %d.%d.%d.%d\n",NIPQUAD(saddr),NIPQUAD(daddr));
	
    return retval; 
}

unsigned int fw_hook(unsigned int hooknum,
                             struct sk_buff **skb_p,
                             const struct net_device *in,
                             const struct net_device *out,
                             int (*okfn)(struct sk_buff *))
{
    int retval = NF_ACCEPT;
	struct 	sk_buff *skb = (*skb_p); 				
	struct 	iphdr  *iph;  				
    struct 	tcphdr *tcph = NULL; 				
	struct 	udphdr *udph = NULL;				

	__u32   saddr;						
	__u32 	daddr; 					
	__u8	protocol_type; 		
	__u16  	dport = 0;								
	__u16	sport = 0;		
	
	if(&(skb->nh.iph) != NULL){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(iph->saddr) != NULL){
		saddr = iph->saddr;
	}else{
		return retval;
	}
	
	if(&(iph->daddr) != NULL){
		daddr = iph->daddr;
	}else{
		return retval;
	}
	
	if(&(skb->h.th) != NULL){
		tcph = skb->h.th;
	}
	
	if(&(skb->h.uh) != NULL){
		udph = skb->h.uh;
	}
		
	if(iph->protocol){
		protocol_type=iph->protocol;
	}else{
		return retval;
	}
	
		
	if((protocol_type == IPPROTO_TCP) && (&(tcph->dest) != NULL) && (&(tcph->source) != NULL)){				
		dport = tcph->dest;
		sport = tcph->source;
	}
	
	if((protocol_type == IPPROTO_UDP) && (&(udph->dest) != NULL) && (&(udph->source) != NULL)){	 			
		dport = udph->dest;
		sport = udph->source;
	}
	
	printk("FW	--> S: %d.%d.%d.%d:%d  D: %d.%d.%d.%d:%d\n",NIPQUAD(saddr),sport,NIPQUAD(daddr),dport);
	//printk("FW	--> S: %d.%d.%d.%d  D: %d.%d.%d.%d\n",NIPQUAD(saddr),NIPQUAD(daddr));
	
    return retval; 
}

unsigned int pre_hook(unsigned int hooknum,
                             struct sk_buff **skb_p,
                             const struct net_device *in,
                             const struct net_device *out,
                             int (*okfn)(struct sk_buff *))
{
    int retval = NF_ACCEPT;
	struct 	sk_buff *skb = (*skb_p); 				
	struct 	iphdr  *iph;  				
    struct 	tcphdr *tcph = NULL; 				
	struct 	udphdr *udph = NULL;				

	__u32   saddr;						
	__u32 	daddr; 					
	__u8	protocol_type; 		
	__u16  	dport = 0;								
	__u16	sport = 0;		
	
	if(skb->nh.iph){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(skb->nh.iph) != NULL){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(iph->saddr) != NULL){
		saddr = iph->saddr;
	}else{
		return retval;
	}
	
	if(&(iph->daddr) != NULL){
		daddr = iph->daddr;
	}else{
		return retval;
	}
	
	if(&(skb->h.th) != NULL){
		tcph = skb->h.th;
	}
	
	if(&(skb->h.uh) != NULL){
		udph = skb->h.uh;
	}
		
	if(iph->protocol){
		protocol_type=iph->protocol;
	}else{
		return retval;
	}
	
		
	if((protocol_type == IPPROTO_TCP) && (&(tcph->dest) != NULL) && (&(tcph->source) != NULL)){				
		dport = tcph->dest;
		sport = tcph->source;
	}
	
	if((protocol_type == IPPROTO_UDP) && (&(udph->dest) != NULL) && (&(udph->source) != NULL)){	 			
		dport = udph->dest;
		sport = udph->source;
	}
	
	printk("PRE	--> S: %d.%d.%d.%d:%d  D: %d.%d.%d.%d:%d\n",NIPQUAD(saddr),sport,NIPQUAD(daddr),dport);
	//printk("PRE	--> S: %d.%d.%d.%d D: %d.%d.%d.%d\n",NIPQUAD(saddr),NIPQUAD(daddr));
	
    return retval; 
}

unsigned int post_hook(unsigned int hooknum,
                             struct sk_buff **skb_p,
                             const struct net_device *in,
                             const struct net_device *out,
                             int (*okfn)(struct sk_buff *))
{
     int retval = NF_ACCEPT;
	struct 	sk_buff *skb = (*skb_p); 				
	struct 	iphdr  *iph;  				
    struct 	tcphdr *tcph = NULL; 				
	struct 	udphdr *udph = NULL;				

	__u32   saddr;						
	__u32 	daddr; 					
	__u8	protocol_type; 		
	__u16  	dport = 0;								
	__u16	sport = 0;		
	
	if(&(skb->nh.iph) != NULL){
		iph = skb->nh.iph; 
	}else{
		return retval;
	}
	
	if(&(iph->saddr) != NULL){
		saddr = iph->saddr;
	}else{
		return retval;
	}
	
	if(&(iph->daddr) != NULL){
		daddr = iph->daddr;
	}else{
		return retval;
	}
	
	if(&(skb->h.th) != NULL){
		tcph = skb->h.th;
	}
	
	if(&(skb->h.uh) != NULL){
		udph = skb->h.uh;
	}
		
	if(iph->protocol){
		protocol_type=iph->protocol;
	}else{
		return retval;
	}
	
		
	if((protocol_type == IPPROTO_TCP) && (&(tcph->dest) != NULL) && (&(tcph->source) != NULL)){				
		dport = tcph->dest;
		sport = tcph->source;
	}
	
	if((protocol_type == IPPROTO_UDP) && (&(udph->dest) != NULL) && (&(udph->source) != NULL)){	 			
		dport = udph->dest;
		sport = udph->source;
	}
	
	printk("POST	--> S: %d.%d.%d.%d:%d  D: %d.%d.%d.%d:%d\n",NIPQUAD(saddr),sport,NIPQUAD(daddr),dport);
	//printk("POST	--> S: %d.%d.%d.%d  D: %d.%d.%d.%d\n",NIPQUAD(saddr),NIPQUAD(daddr));
	
    return retval; 
}

struct nf_hook_ops in_hook_ops = {  
   hook :       in_hook,
   pf :         PF_INET,
   hooknum :    NF_IP_LOCAL_IN,
};

struct nf_hook_ops out_hook_ops = { 
   hook :       out_hook,   
   pf :         PF_INET,
   hooknum :    NF_IP_LOCAL_OUT,
};

struct nf_hook_ops fw_hook_ops = {   
   hook :       fw_hook,   
   pf :         PF_INET,
   hooknum :    NF_IP_FORWARD,
};

struct nf_hook_ops pre_hook_ops = {   
   hook :       pre_hook,   
   pf :         PF_INET,
   hooknum :    NF_IP_PRE_ROUTING,
};

struct nf_hook_ops post_hook_ops = {   
   hook :       post_hook,   
   pf :         PF_INET,
   hooknum :    NF_IP_POST_ROUTING,
};

static int init_status_flag;
#define IN_HOOK_REGISTERED		0x02
#define OUT_HOOK_REGISTERED		0x04
#define FW_HOOK_REGISTERED		0x06
#define PRE_HOOK_REGISTERED		0x08
#define POST_HOOK_REGISTERED	0x20

void cleanup_module(void)
{

    if (init_status_flag&IN_HOOK_REGISTERED)   
       nf_unregister_hook(&in_hook_ops);

    if (init_status_flag&OUT_HOOK_REGISTERED)   
       nf_unregister_hook(&out_hook_ops);

	if (init_status_flag&FW_HOOK_REGISTERED)  
       nf_unregister_hook(&fw_hook_ops);
	
	if (init_status_flag&PRE_HOOK_REGISTERED)  
       nf_unregister_hook(&pre_hook_ops);
	
	if (init_status_flag&POST_HOOK_REGISTERED)  
       nf_unregister_hook(&post_hook_ops);
}

int init_module(void)
{
   int result;

       result = nf_register_hook(&in_hook_ops);
       if (result < 0) {
           printk(KERN_ERR "can't register netfilter hook");
           cleanup_module();
           return result;
       }
       init_status_flag |= IN_HOOK_REGISTERED;

       result = nf_register_hook(&out_hook_ops);
       if (result < 0) {
           printk(KERN_ERR "can't register netfilter hook");
           cleanup_module();
           return result;
       }
       init_status_flag |= OUT_HOOK_REGISTERED;

       result = nf_register_hook(&fw_hook_ops);
       if (result < 0) {
           printk(KERN_ERR "can't register netfilter hook");
           cleanup_module();
           return result;
       }
       init_status_flag |= FW_HOOK_REGISTERED;
	   
	   result = nf_register_hook(&pre_hook_ops);
       if (result < 0) {
           printk(KERN_ERR "can't register netfilter hook");
           cleanup_module();
           return result;
       }
       init_status_flag |= PRE_HOOK_REGISTERED;
	   
	   result = nf_register_hook(&post_hook_ops);
       if (result < 0) {
           printk(KERN_ERR "can't register netfilter hook");
           cleanup_module();
           return result;
       }
       init_status_flag |= POST_HOOK_REGISTERED;
	   printk("Netfilter Sniff run! stop with: #rmmod NetSnif \n");
	   
    return 0; 
}
--------------030603020809010508000301--