基于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转换的实现分析。本节将总的调用起点分析了一下,后面我们将针对每一个模块的实现进行分析。
这几年大多是昆明空运来的,