解析Linux下Netfilter & iptables:开发一个Hook函数

http://www.bairimeng.net/2012/11/28/netfilter_iptables_hook_1/

一、说明
Netfilter通过挂载在Hook链上的函数,来对经过链的数据包进行逐一处理,这一篇笔记记录了开发一个最简单的Hook函数的过程,这是一个内核模块,直接加载在内核,只要载入即可生效。
我的Linux内核版本为2.6.27.41。

二、模块描述
这个模块的作用很简单,每收到4个ICMP报文,就丢弃一个报文,也就是逢5就丢,这个笔记不记录任何对于Linux网络编程有直接提高的信息,那些需要系统的不断的学习。
OK,我们开始动手。

三、代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <linux/kernel.h>
 
#include <linux/module.h>
 
#include <asm/atomic.h>
 
#include <linux/ip.h>
 
#include <linux/version.h>
 
#include <linux/skbuff.h>
 
#include <linux/netfilter.h>
 
#include <linux/netfilter_ipv4.h>
 
#include <linux/moduleparam.h>
 
#include <linux/netfilter_ipv4/ip_tables.h>
 
 
 
MODULE_LICENSE( "GPL" );
 
MODULE_AUTHOR( "Sekai" );
 
MODULE_DESCRIPTION( "My hook" );
 
 
 
static atomic_t pktcnt =
 
{
 
     .counter = 0,
 
};
 
 
 
// 我们自己定义的hook回调函数,每隔4个丢弃1个icmp报文
 
static unsigned int myhook_func(unsigned int hooknum, struct sk_buff* skb,
 
     const struct net_device* in, const struct net_device* out,
 
     int (*okfn)( struct sk_buff*))
 
{
 
     const struct iphdr* iph = ip_hdr(skb);
 
     if (iph->protocol == 1)
 
     {
 
         atomic_inc(&pktcnt);
 
         if (atomic_read(&pktcnt) % 5 == 0)
 
         {
 
             printk(KERN_INFO "%d: drop an ICMP to %u.%u.%u.%u!\n" ,
 
                 atomic_read(&pktcnt), NIPQUAD(iph->daddr));
 
             return NF_DROP;
 
         }
 
     }
 
 
 
     return NF_ACCEPT;
 
}
 
 
 
// <linux/netfilter.h>
 
static struct nf_hook_ops nfho =
 
{
 
     .hook       = myhook_func,      // 回调函数
 
     .owner      = THIS_MODULE,
 
     .pf     = PF_INET,
 
     // <linux/netfilter_ipv4.h> NF_IP_LOCAL_OUT 不知道为什么识别不了
 
     .hooknum    = 3,            // 挂载在本地出口处
 
     .priority   = NF_IP_PRI_FIRST,  // 优先级最高
 
};
 
 
 
static int __init myhook_init( void )
 
{
 
     return nf_register_hook(&nfho);
 
}
 
 
 
static void __exit myhook_fini( void )
 
{
 
     nf_unregister_hook(&nfho);
 
}
 
 
 
module_init(myhook_init);
 
module_exit(myhook_fini);

四、代码详解

我们使用nf_hook_ops来实例化一个hook函数,这个结构体有一系列成员,具体定义在linux/netfilter.h中,可以注意到.hook成员就是我们自己编写的回调函数,.hooknum是挂载点,也就是Netfilter定义的5个挂载点,具体定义在linux/netfilter_ipv4.h中,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* IP Hooks */
 
/* After promisc drops, checksum checks. */
 
#define NF_IP_PRE_ROUTING   0
 
/* If the packet is destined for this box. */
 
#define NF_IP_LOCAL_IN      1
 
/* If the packet is destined for another interface. */
 
#define NF_IP_FORWARD       2
 
/* Packets coming from a local process. */
 
#define NF_IP_LOCAL_OUT     3
 
/* Packets about to hit the wire. */
 
#define NF_IP_POST_ROUTING  4
 
#define NF_IP_NUMHOOKS      5
 
#endif /* ! __KERNEL__ */

我们将这个函数挂载在NF_IP_LOCAL_OUT上,可以直接使用这个宏。
我们使用 nf_register_hook()来挂载我们这个Hook函数,然后定义了一个atomic_t来作为计数器,使用atomic的函数来对它进行原子操作,实现进程间同步。
值得注意的是在myhook_func()中使用的atomic_inc()在2.6.27.41使用atomic_t作为传入参数,而某个版本之前,传入参数还是简单的int。

五、挂载
我们稍微修改下之前一篇笔记写的那个Makefile,然后编译成为.ko内核库之后,使用insmod命令安装。
接着使用Ping www.baidu.com来测试。

我们发现每隔4个包就会被抛弃1个包,目标达成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值