Linux netfilter 学习笔记 之二 ip 层netfilter的hook 注册以及

基于linux2.6.21

上一节分析了hook机制,本节简单介绍下三层防火墙借助hook机制,实现的总体框架

1三层netfilterhook点的注册与注销

我们知道使用iptables,添加规则时需要指定表,在iptables中有filter、nat、mangle三张表,因为我们接下来几节分析的内容也是从这三个table表加上连接跟踪,此处我们也已这四个模块来将,而不是按HOOK点的分类来分析

1.1filter机制相关的hook注册注册

Filter表主要在以下几个hook点上其作用:

NF_IP_LOCAL_IN、NF_IP_FORWARD、NF_IP_LOCAL_OUT

即只在数据包的接收、数据包的发送及数据包的转发时进行过滤,filter表相关的hook点的注册是在iptablesfilter模块初始化时注册的,定义的hook_ops结构体变量如下:

staticstructnf_hook_opsipt_ops[]={

{

.hook=ipt_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_IN,

.priority=NF_IP_PRI_FILTER,

},

{

.hook=ipt_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_FORWARD,

.priority=NF_IP_PRI_FILTER,

},

{

.hook=ipt_local_out_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_OUT,

.priority=NF_IP_PRI_FILTER,

},

};

通过上面的定义我们知道,相应的hook函数分别为ipt_hook、ipt_local_out_hook(关于这两个函数的具体执行过程暂且不分析,后面分析)。

然后通过调用nf_register_hook进行注册,调用nf_unregister_hook进行注销

1.2nat机制相关的hook注册注册

nat表主要在以下几个hook点上其作用:

NF_IP_PRE_ROUTING、NF_IP_POST_ROUTING、NF_IP_LOCAL_OUT、NF_IP_LOCAL_IN

其中NF_IP_PRE_ROUTING、NF_IP_LOCAL_OUT为目的地址转发,而NF_IP_POST_ROUTING、NF_IP_LOCAL_IN为源地址转换。

/*Beforepacketfiltering,changedestination*/

staticstructnf_hook_opsip_nat_in_ops={

.hook=ip_nat_in,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_PRE_ROUTING,

.priority=NF_IP_PRI_NAT_DST,

};

/*Afterpacketfiltering,changesource*/

staticstructnf_hook_opsip_nat_out_ops={

.hook=ip_nat_out,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_POST_ROUTING,

.priority=NF_IP_PRI_NAT_SRC,

};

/*Afterconntrack,adjustsequencenumber*/

staticstructnf_hook_opsip_nat_adjust_out_ops={

.hook=ip_nat_adjust,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_POST_ROUTING,

.priority=NF_IP_PRI_NAT_SEQ_ADJUST,

};

/*Beforepacketfiltering,changedestination*/

staticstructnf_hook_opsip_nat_local_out_ops={

.hook=ip_nat_local_fn,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_OUT,

.priority=NF_IP_PRI_NAT_DST,

};

/*Afterpacketfiltering,changesourceforreplypacketsofLOCAL_OUTDNAT*/

staticstructnf_hook_opsip_nat_local_in_ops={

.hook=ip_nat_fn,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_IN,

.priority=NF_IP_PRI_NAT_SRC,

};

/*Afterconntrack,adjustsequencenumber*/

staticstructnf_hook_opsip_nat_adjust_in_ops={

.hook=ip_nat_adjust,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_IN,

.priority=NF_IP_PRI_NAT_SEQ_ADJUST,

};

1.3mangle机制相关的hook注册与注销

主要定义了以下个hook_ops变量,mangle表主要在NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、NF_IP_FORWARD、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING等hook点起作用

staticstructnf_hook_opsipt_ops[]={

{

.hook=ipt_route_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_PRE_ROUTING,

.priority=NF_IP_PRI_MANGLE,

},

{

.hook=ipt_route_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_IN,

.priority=NF_IP_PRI_MANGLE,

},

{

.hook=ipt_route_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_FORWARD,

.priority=NF_IP_PRI_MANGLE,

},

{

.hook=ipt_local_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_OUT,

.priority=NF_IP_PRI_MANGLE,

},

{

.hook=ipt_route_hook,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_POST_ROUTING,

.priority=NF_IP_PRI_MANGLE,

},

};

1.4连接跟踪模块相关的hook注册与注销

主要定义了以下个hook_ops变量,连接跟踪模块主要在NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING等hook点起作用,连接跟踪模块是实现nat的基础,也是实现ALG功能的基础。

staticstructnf_hook_opsip_conntrack_defrag_ops={

.hook=ip_conntrack_defrag,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_PRE_ROUTING,

.priority=NF_IP_PRI_CONNTRACK_DEFRAG,

};

staticstructnf_hook_opsip_conntrack_in_ops={

.hook=ip_conntrack_in,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_PRE_ROUTING,

.priority=NF_IP_PRI_CONNTRACK,

};

staticstructnf_hook_opsip_conntrack_defrag_local_out_ops={

.hook=ip_conntrack_defrag,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_OUT,

.priority=NF_IP_PRI_CONNTRACK_DEFRAG,

};

staticstructnf_hook_opsip_conntrack_local_out_ops={

.hook=ip_conntrack_local,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_OUT,

.priority=NF_IP_PRI_CONNTRACK,

};

/*helpers*/

staticstructnf_hook_opsip_conntrack_helper_out_ops={

.hook=ip_conntrack_help,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_POST_ROUTING,

.priority=NF_IP_PRI_CONNTRACK_HELPER,

};

staticstructnf_hook_opsip_conntrack_helper_in_ops={

.hook=ip_conntrack_help,

.owner=THIS_MODULE,

.pf=PF_INET,

.hooknum=NF_IP_LOCAL_IN,

.priority=NF_IP_PRI_CONNTRACK_HELPER,

};

2三层netfilterhook点的调用

上面是三层netfilter相关的hook点的注册,下面我们需要知道三层netfilter的hook回调函数是在哪些函数里调用的。我们主要分析ip协议在五个hook点的调用

上图便是五个hook点调用的地方,对应于代码,我们来分析一下。

2.1PRE_ROUTING

看这个名字,我们知道在这里执行hook回调函数时,数据包还没有经过路由,对于ip报文来说,在ip_rcv函数里,只是对数据包进行了合理性检查,还没有对数据包进行查找路由操作,所以PRE_ROUTINGhook点的回调函数的调用,即是在该函数的末尾通过调用函数NF_HOOK实现

returnNF_HOOK(PF_INET,NF_IP_PRE_ROUTING,skb,dev,NULL,

ip_rcv_finish);

2.2LOCAL_IN

当进入该hook点之前,数据包已经进行了路由操作,通过对协议栈的流程分析我们知道,在ip_rcv_finish进行了路由选择后,对于属于本地接收的报文会调用函数ip_local_deliver,那很显然,LOCAL_INHOOK点的回调函数的调用执行,肯定是在这个函数的末尾执行的了。函数片断如下:

returnNF_HOOK(PF_INET,NF_IP_LOCAL_IN,skb,skb->dev,NULL,

ip_local_deliver_finish);

2.3FORWARD

在进行了路由后,对于需要转发的数据,通过调用函数dst_input(skb),间接调用函数ip_forward进行数据转发操作(关于为何会调用到ip_forward及ip_local_deliver,这是通过建立路由缓存时填充dst_entry指针实现的)。所以该HOOK点的hook回调函数的执行也是在该函数的末尾通过调用NF_HOOK实现的。

returnNF_HOOK(PF_INET,NF_IP_FORWARD,skb,skb->dev,rt->u.dst.dev,

ip_forward_finish);

2.4LOCAL_OUT

对于该hook点,是本地发送数据的hook调用,由于本地发送的数据既可以是UDP数据也可以是TCP数据,亦可以是组播数据。所以OUThook点的调用函数不止一处。其代码书写如下:

returnNF_HOOK(PF_INET,NF_IP_LOCAL_OUT,skb,NULL,rt->u.dst.dev,

dst_output);

一般是本地数据找到路由之后,且没有调用skb->dst.out准备将数据包发送出去之前调用NF_HOOK

2.5POST_ROUTING

在函数经过了FORWARD或者OUT节点后,就会通过skb->dst.out,执行到函数ip_output,所以函数

returnNF_HOOK_COND(PF_INET,NF_IP_POST_ROUTING,skb,NULL,dev,

ip_finish_output,

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

以上就是ip层netfilter涉及的hook_ops的注册以及调用,后面我们分析的xt_table表中的规则匹配、连接跟踪、nat操作、mangle操作,均是由上面五个hook点的NF_HOOK函数的调用而触发的。以下章节则侧重于表匹配、连接跟踪、nat转换的实现分析。本节将总的调用起点分析了一下,后面我们将针对每一个模块的实现进行分析。

这几年大多是昆明空运来的,

Linux netfilter 学习笔记 之二 ip 层netfilter的hook 注册以及

相关文章:

你感兴趣的文章:

标签云: