Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1800640
  • 博文数量: 306
  • 博客积分: 3133
  • 博客等级: 中校
  • 技术积分: 3932
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-19 16:50
文章分类

全部博文(306)

文章存档

2018年(7)

2017年(18)

2016年(39)

2015年(35)

2014年(52)

2013年(39)

2012年(22)

2011年(29)

2010年(53)

2009年(12)

分类: LINUX

2009-05-27 22:15:28

Netfilter架构

1.       数据包捕获:netfilter通过在内核中所设不同位置的hook点捕获通过的IP数据包。

2.       数据包处理:根据每个hook点上hook链上的处理模块处理经过的skb

3.       hook注册:用户、SElinux或者iptable根据自己的需要,在hook点上注册自己的数据处理模块。

 

int nf_register_hook(struct nf_hook_ops *reg) //(linux kernel 2.6.28 /net/netfilter/core)

{

       struct nf_hook_ops *elem;

       int err;

 

       err = mutex_lock_interruptible(&nf_hook_mutex);

       if (err < 0)

              return err;

       list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {

              if (reg->priority < elem->priority)

                     break;

       }

       list_add_rcu(®->list, elem->list.prev);

       mutex_unlock(&nf_hook_mutex);

       return 0;

}

void nf_unregister_hook(struct nf_hook_ops *reg)

{

       mutex_lock(&nf_hook_mutex);

       list_del_rcu(®->list);

       mutex_unlock(&nf_hook_mutex);

 

       synchronize_net();

}

 

内核中5hook点的轮询:


1、轮询NF_INET_PRE_ROUTING:

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) // net/ipv4/ip_input.c

{

       ……      

       return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL,

                     ip_rcv_finish);

       ……

}

多数netfilter函数为do_something do_something_finish或者do_something2,前者一般作check工作或者其他,而真正完成任务的在后者,前者通过NF_HOOK(……)调用后者。

2,轮询NF_INET_LOCAL_IN:

*     Deliver IP Packets to the higher protocol layers.

int ip_local_deliver(struct sk_buff *skb) // net/ipv4/ip_input.c

{

       /*

        *    Reassemble IP fragments.

        */

       if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {

              if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))

                     return 0;

       }

       return NF_HOOK(PF_INET, NF_INET_LOCAL_IN, skb, skb->dev, NULL,

                     ip_local_deliver_finish);

}

 

3、轮询NF_INET_FORWARD:

int ip_forward(struct sk_buff *skb) // net/ipv4/ip_forward.c

{

       ……

       return NF_HOOK(PF_INET, NF_INET_FORWARD, skb, skb->dev, rt->u.dst.dev,

                     ip_forward_finish);

……

}

 

4、轮询NF_INET_LOCAL_OUT:

int __ip_local_out(struct sk_buff *skb) // net/ipv4/ip_ouput.c

{

       struct iphdr *iph = ip_hdr(skb);

 

       iph->tot_len = htons(skb->len);

       ip_send_check(iph);

       return nf_hook(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev,

                     dst_output);

}

 

int ip_local_out(struct sk_buff *skb)

{

       int err;

       err = __ip_local_out(skb);

       if (likely(err == 1))

              err = dst_output(skb);

       return err;

}

 

5、轮询NF_INET_POST_ROUTING:

int ip_output(struct sk_buff *skb)

{

       struct net_device *dev = skb->dst->dev;

       IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);

       skb->dev = dev;

       skb->protocol = htons(ETH_P_IP);

       return NF_HOOK_COND(PF_INET, NF_INET_POST_ROUTING, skb, NULL, dev,

                         ip_finish_output,

                         !(IPCB(skb)->flags & IPSKB_REROUTED));

}

 

int ip_mc_output(struct sk_buff *skb)

{

       ……

}

输出设备不是环回接口设备,则使用输出函数ip_mc_output,否则使用输出函数ip_output

http://hi.baidu.com/linux_kernel/blog/item/58eafaf2bc87c713b17ec55b.html

 

用户自定义netfilter模块:

#ifndef __KERNEL__

#define __KERNEL__

#endif

 

#ifndef __MODULE__

#define __MODULE__

#endif

 

#include

#include

#include

#include

#include

#include

 

#define NF_IP_PRE_ROUTING 0

 

static struct nf_hook_ops nfho;

static unsigned char *drop_ip = "\x7f\x00\x00\x01";

 

unsigned int hook_func(unsigned int hooknum,

                       struct sk_buff **skb,

                       const struct net_device *in,

                       const struct net_device *out,

                       int (*okfn)(struct sk_buff *))

{

      // struct sk_buff *sb = *skb;

       struct iphdr     *iph ;

       struct sk_buff *sb;

 

       sb = skb;

       iph = ip_hdr(sb);

       pr_info("Packet from %d.%d.%d.%d\n",NIPQUAD(iph->saddr));

       if ( iph->saddr == *(__be32 *) drop_ip)

       {

             pr_info("Dropped packet from ... %d.%d.%d.%d\n",*drop_ip, *(drop_ip+1), *(drop_ip+2), *(drop_ip+3) );

             return NF_DROP;

       }else {

         

             return NF_ACCEPT;

       }

}

 

int init_module()

{

       pr_info("i'm now in the kernel space!\n");

       nfho.hook      = hook_func;

       nfho.hooknum   = NF_IP_PRE_ROUTING;

       nfho.pf                = PF_INET;

       nfho.priority      = NF_IP_PRI_FIRST;

 

       nf_register_hook(&nfho);

 

       return 0;

}

 

void cleanup_module()

{

    nf_unregister_hook(&nfho);

    pr_info("module removed from kernel!\n");

}

 

Makefile

obj-m +=netfilter.o

 

all:

       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:

       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

       rm Module.symvers

install:

       /sbin/insmod simpFilter.ko

remove:

       /sbin/rmmod simpFilter

 

PS:以上模块在数据包到达后理论上全部丢弃来自本地的ip数据包

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