netfilter简介

1. netfilter简介

netfilter是在Linux内核中一组钩子,这些钩子允许在网络协议栈中使用内核模块来注册回调函数,可以处理协议栈中经过钩子的每一个报文。因此我们可以利用它来实现很多功能,如过滤报文,修改报文等。

和netfilter常常出现在一起的还有iptable,它是在netfilter基础上在Linux内核中内置的防火墙架构,它工作在用户空间,根据我们配置的规则集工作,每一个规则都由一些匹配(match)和动作(target)组成。

2. netfilter编程

2.1 netfilter钩子

如图1所示,netfiter提供的钩子分两部分,一部分是接收网络中的数据,另一部分是发送数据到网络中去。

 

图1

  • NF_IP_PRE_ROUTING (0)
    从网络中接收到的,进行完正确性检查的数据报文。经过这个钩子后,对报文进行路由检查,判断是进入本机还是转发。
  • NF_IP_LOCAL_IN (1)
    对目的地是本机的报文,会经过这个钩子。
  • NF_IP_FORWARD (2)
    而对需要转发的数据报文,则会经过这个钩子。(组播报文最终也会经过这个钩子?)
  • NF_IP_LOCAL_OUT (3)
    本地发出的报文做发送路由之前经过的钩子。
  • NF_IP_POST_ROUTING (4)
    所有将要发出的报文都会通过此钩子。

2.2 netfilter对数据包处理方式

netfilter的钩子函数返回值有5种,分别如下:

  • NF_ACCEPT:继续处理数据包;
  • NF_DROP:丢弃此包,不再继续处理;
  • NF_STOLEN:表示此包已经被处理过,不需继续处理;
  • NF_QUERE:队列化数据包(通常是为用户空间处理做准备);
  • NF_REPEAT:再一次调用这个钩子函数。

做屏蔽数据包处理时常常会使用NF_ACCEPT,NF_DROP,而拷贝数据包时常常会用到NF_STOLEN。

2.3 注册和注销钩子

2.3.1 NF_HOOK宏

netfilter在协议栈处理过程中在注册的钩子处调用NF_HOOK()宏来插入回调函数的。

在3.2.0-26内核中:

如果配置了netfilter则调用nf_hook_thresh,并在返回NF_ACCEPT的情况下,调用okfn。

static inline int
NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,
	struct net_device *in, struct net_device *out,
	int (*okfn)(struct sk_buff *))
{
	return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN);
}

否则,直接调用okfn,

#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)

okfn是一个函数指针,是从钩子函数返回协议栈时继续要执行的函数。在ip_rcv()函数中调用时设置的ip_rcv_finish。


2.3.2 nf_hook_ops

在内核中操作网络数据的模块的注册与注销。

nf_hook_ops结构体:

struct nf_hook_ops {
	/* 用户从这里开始向下填 */
	struct list_head list;

	/* 用户从这里开始向下填 */
	/* hook为钩子处理函数*/
	nf_hookfn *hook;
	/* 模块所有者 */
	struct module *owner;
	/* 协议簇 */
	u_int8_t pf;
	/* 2.1中5个挂载点之一 */
	unsigned int hooknum;
	/* 优先级,依据升序来排列钩子 */
	int priority;
};


 注册和注销函数:

int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);

例如:

/*Initialize the hook*/
static struct nf_hook_ops nf_out_modify =
{
	.hook = ip4_multi_modify,
	.hooknum = NF_IP_POST_ROUTING,
	.pf = PF_INET,
	.priority = NF_IP_PRI_FIRST,
};


// static
static int __init hello_init(void)
{
	nf_register_hook(&nf_out_modify);
	return 0;
}


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

/*module initial and exit*/
module_init(hello_init);
module_exit(hello_exit);

2.3.3 nf_sockopt_ops

socket选项控制的钩子函数的注册与注销。(TODO)
 

3. IPv4与IPv6的区别

1. nf_hook_ops里面的协议簇不同,IPv4的是PF_INET,而IPv6的是PF_INET6.

2. nf_hook_ops中的priority和hooknum针对IPv6的在netfilter_ipv6.h里也有定义。

3. 取得报文header处理不同。

IPv4:ip_hdr(skb)

IPv6:ipv6_hdr(skb)

 

参考:

[1] http://www.netfilter.org/

[2] 宋敬彬,孙海滨等,《Linux网络编程》

[3] http://blog.csdn.net/efan_linux/article/details/4605073

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值