简单学习netfilter

之后工作重心又会有点小调整, 提前先了解下netfilter相关的东西~ 网上相关的资料和文章还是非常丰富的, 这里推荐几个:

  1. 介绍如何写netfilter模块: linuxjournal
  2. netfilter的整体介绍: developerworks
  3. CU上的一系列的netfilter的剖析文章: CU

稍微了解了之后我们可以写一个简单的netfilter模块了. 网上很多代码都是基于2.x.x的内核版本, 为了在最近的内核上跑需要做一点小小的修改. 下面是一个简单的将lo上收到的数据包丢弃并打印相关信息的模块:

hello.c
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
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/skbuff.h>

static struct nf_hook_ops nf_ops;
const char *interface = "lo";

static unsigned int
my_nf_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in,
    const struct net_device *out, int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;

    if (skb->nohdr)
        return NF_ACCEPT;

    iph = ip_hdr(skb);

    if (strcmp(in->name, interface) == 0) {
        printk(KERN_WARNING "drop lo packet: %pI4 -> ip %pI4, type is %d\n", &iph->saddr, &iph->daddr, iph->protocol);
        return NF_DROP;
    }

    return NF_ACCEPT;
}

static int __init hello_init(void)
{
    nf_ops.hook     = my_nf_hook;
    nf_ops.pf       = PF_INET;
    nf_ops.hooknum  = NF_INET_PRE_ROUTING;
    nf_ops.priority = NF_IP_PRI_FIRST;
    nf_register_hook(&nf_ops);

    return 0;
}

static void __exit hello_exit(void)
{
    nf_unregister_hook(&nf_ops);
}

module_init(hello_init);
module_exit(hello_exit);

打印出来的日志情况:

log
1
drop lo: ip: 127.0.0.1 -> ip 127.0.0.1, type is 6

知道了具体的模块写法之后, 之后就是需要了解kernel网络编程和协议相关的东西了. 这个小模块用到了sk_buf(linux/skbuff.h)和net_device结构体.

最近一个多月感觉很忙, 但觉得不怎么充实, 继续调整一下….

Comments