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 <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4.h>
#include <linux/in.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/netfilter_bridge.h>
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;
在netfilter的hook中还隐藏了一个钩子点,如: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网桥时的数据;