Chinaunix首页 | 论坛 | 博客
  • 博客访问: 32935
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 22
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-25 14:08
文章分类
文章存档

2018年(21)

我的朋友

分类: LINUX

2018-09-19 15:48:22

Netfilter 中对报文的过滤默认是放在filter表中的。根据以上讲解的内容,要使用filter表来实现对报文的过滤,需要做如下两步:

1、建立filter表并注册表

2、实现hook函数并注册hook函数

 

代码文件路径:net/ipv4/netfilter/iptable_filter.c

 

Filter表在INPUT,OUTPUT,FORWARD三个点来设置hook函数,对到本机,转发,本机发送的三个方向上的报文进行过滤。

 

/*有效hook点*/

#define FILTER_VALID_HOOKS ((1 << NF_INET_LOCAL_IN) | \

                         (1 << NF_INET_FORWARD) | \

                         (1 << NF_INET_LOCAL_OUT))

1、filter表的初始化和注册

/*初始化filter表用的rule项,每个chain里有一个默认rule,rule target ACCEPT*/

static struct

{

       struct ipt_replace repl;

       struct ipt_standard entries[3];

       struct ipt_error term;

} initial_table __net_initdata = {

       .repl = {

              .name = "filter",

              .valid_hooks = FILTER_VALID_HOOKS,

              .num_entries = 4,

              .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),

              .hook_entry = {

                     [NF_INET_LOCAL_IN] = 0,

                     [NF_INET_FORWARD] = sizeof(struct ipt_standard),

                     [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,

              },

              .underflow = {

                     [NF_INET_LOCAL_IN] = 0,

                     [NF_INET_FORWARD] = sizeof(struct ipt_standard),

                     [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,

              },

       },

       .entries = {

              IPT_STANDARD_INIT(NF_ACCEPT),      /* LOCAL_IN */

              IPT_STANDARD_INIT(NF_ACCEPT),      /* FORWARD */

              IPT_STANDARD_INIT(NF_ACCEPT),      /* LOCAL_OUT */

       },

       .term = IPT_ERROR_INIT,                 /* ERROR */

};

 /*filter*/

static const struct xt_table packet_filter = {

       .name             = "filter",

       .valid_hooks   = FILTER_VALID_HOOKS,

       .me         = THIS_MODULE,

       .af          = NFPROTO_IPV4,

};

 

注册filter

static int __net_init iptable_filter_net_init(struct net *net)

{

       /* Register table */

       net->ipv4.iptable_filter =

              ipt_register_table(net, &packet_filter, &initial_table.repl);

       if (IS_ERR(net->ipv4.iptable_filter))

              return PTR_ERR(net->ipv4.iptable_filter);

       return 0;

}

2HOOK函数的实现和注册

初始化hook_ops结构体

static struct nf_hook_ops ipt_ops[] __read_mostly = {

       {

              .hook             = ipt_local_in_hook,

              .owner           = THIS_MODULE,

              .pf          = NFPROTO_IPV4,

              .hooknum       = NF_INET_LOCAL_IN,

              .priority  = NF_IP_PRI_FILTER,

       },

       {

              .hook             = ipt_hook,

              .owner           = THIS_MODULE,

              .pf          = NFPROTO_IPV4,

              .hooknum       = NF_INET_FORWARD,

              .priority  = NF_IP_PRI_FILTER,

       },

       {

              .hook             = ipt_local_out_hook,

              .owner           = THIS_MODULE,

              .pf          = NFPROTO_IPV4,

              .hooknum       = NF_INET_LOCAL_OUT,

              .priority  = NF_IP_PRI_FILTER,

       },

};

 

注册hook函数

static int __init iptable_filter_init(void)

{

       int ret;

       /* Register hooks */

       ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));

       return ret;

}

 

现在来看看具体的hook函数实现

INPUT

static unsigned int ipt_local_in_hook(unsigned int hook,

                struct sk_buff *skb,

                const struct net_device *in,

                const struct net_device *out,

                int (*okfn)(struct sk_buff *))

{

       return ipt_do_table(skb, hook, in, out,

                         dev_net(in)->ipv4.iptable_filter);

}

 

FORWARD

static unsigned int

ipt_hook(unsigned int hook,

        struct sk_buff *skb,

        const struct net_device *in,

        const struct net_device *out,

        int (*okfn)(struct sk_buff *))

{

       return ipt_do_table(skb, hook, in, out,

                         dev_net(in)->ipv4.iptable_filter);

}

 

OUTPUT

static unsigned int

ipt_local_out_hook(unsigned int hook,

                 struct sk_buff *skb,

                 const struct net_device *in,

                 const struct net_device *out,

                 int (*okfn)(struct sk_buff *))

{

/*对本机产生的一些小报文不进行过滤*/

       /* root is playing with raw sockets. */

       if (skb->len < sizeof(struct iphdr) ||

           ip_hdrlen(skb) < sizeof(struct iphdr))

              return NF_ACCEPT;

       return ipt_do_table(skb, hook, in, out,

                         dev_net(out)->ipv4.iptable_filter);

}

 

 

从上面看出,三个hook函数最后都是调用 ipt_do_table函数来进行处理报文的。

 

raw表和mangle表的实现都和filter表一样,也都是调用ipt_do_table来进行表的遍历。这里就不进行详细分析了。

(未完待续)

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