Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1727744
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类: LINUX

2013-11-19 11:55:39

原文地址:netfilter钩子获取数据包 作者:zzappled

Netfilter中的5个钩子点:

1]:NF_IP_PRE_ROUTING:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验和等检测), 源地址转换在此点进行;
[2]:NF_IP_LOCAL_IN
:经路由查找后,送往本机的通过此检查点,INPUT包过滤在此点进行;
[3]:NF_IP_FORWARD
:要转发的包通过此检测点,FORWORD包过滤在此点进行;
[4]:NF_IP_POST_ROUTING
:所有马上便要通过网络设备出去的包通过此检测点,内置的目的地址转换功能(包括地址伪装)在此点进行;
[5]:NF_IP_LOCAL_OUT
:本机进程发出的包通过此检测点,OUTPUT包过滤在此点进行。

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static unsigned int PacketMonitor(unsigned int hook,
                      
struct sk_buff *skb,
                      
const struct net_device *in,
                      
const struct net_device *out,
                      
int (*okfn)(struct sk_buff *)
                      
)
{
    
struct iphdr *iph=ip_hdr(skb);
    
struct ethhdr *eth=eth_hdr(skb);
    
if(!skb || !iph || !eth)
        
return NF_ACCEPT;
    
if(skb->pkt_type==PACKET_BROADCAST)
            
return NF_ACCEPT;
    
if(skb->protocol==htons(ETH_P_IP))&&skb->len>=sizeof(struct ethhdr))
    
{
        
if(iph->version!=4)
            
return NF_ACCEPT;
        
switch(iph->protocol) {
            
case IPPROTO_ESP:
            
case IPPROTO_AH:
                
printk(“protocol is ESP AND AH\n”);
                
break;
            
case IPPROTO_GRE:
                
printk(“protocol is GRE\n”);
                
break;
            
case IPPROTO_ICMP:
                
printk(“protocol is ICMP\n”);
                
break;
            
case IPPROTO_IGMP:
                
printk(“protocol is IGMP\n”);
                
break;
            
default:
                
break;
        
}
    
}
    
return NF_ACCEPT;
}
static struct nf_hook_ops icmpsrv_ops[] __read_mostly ={
    
{
      
.hook = PacketMonitor,
      
.pf = PF_BRIDGE,
      
.hooknum = NF_BR_PRE_ROUTING,
      
.priority = NF_BR_PRI_FIRST,
    
},
    
{
      
.hook = PacketMonitor,
      
.pf = PF_INET,
      
.hooknum = NF_INET_FORWARD,
      
.priority = NF_IP_PRI_FIRST,
    
},
};
static int init_hook_icmp(void)
{
    
nf_register_hooks(icmpsrv_ops,
ARRAY_SIZE(icmpsrv_ops));
    return 0;
}
 
static void fini_hook_icmp(void)
{
    
nf_unregister_hooks(icmpsrv_ops,
ARRAY_SIZE(icmpsrv_ops));
}

MODULE_LICENSE("GPL");
module_init(init_hook_icmp);
module_exit(fini_hook_icmp);

在程序中用到了nf_register_hooks函数,同时注册多个hook函数,通过nf_unregister_hooks来卸载hook

也可以用nf_register_hook函数来单个注册hook点,如:

static struct nf_hook_ops icmpsrv_ops={
      
.hook = PacketMonitor,
      
.pf = PF_BRIDGE,
      
.hooknum = NF_BR_PRE_ROUTING,
      
.priority = NF_BR_PRI_FIRST,
};

然后调用nf_register_hook(&icmpsrv_ops);

通过nf_unregister_hook(&icmpsrv_ops)来写在hook;

 

netfilterhook中还隐藏了一个钩子点,如:NF_BR_PRE_ROUTING;此点是在网桥下用的,如果不做网桥,程序中用到这个钩子也不会发现数据包,这个钩子的定义如下:

static struct nf_hook_ops icmpsrv_ops ={
      
.hook = PacketMonitor,
      
.pf = PF_BRIDGE,
      
.hooknum = NF_BR_PRE_ROUTING,
      
.priority = NF_BR_PRI_FIRST,
    
};

这个点使用于vlan网桥环境,其他的点在这上面获取不到vlan网桥时的数据;

阅读(2768) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~