netfilter整体架构解析初步

转载 2012年03月31日 14:49:43

原文地址:http://blog.chinaunix.net/uid-22227409-id-2656909.html

1. 挂接点(hooknum)
 
netfilter是Linux2.4/2.6内核中自带的防火墙架构,定义了5个挂接点:
NF_IP_PRE_ROUTING-------->NF_IP_FORWARD--------->NF_IP_POST_ROUTING
                     |                    ^
                     |                    |
                     V                    |
                 NF_IP_LOCAL_IN       NF_IP_LOCAL_OUT
 
netfilter定义了一个二维的链表头数组struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]来表示所有协议族的各个挂接点,NPROTO值为32,可表示linux所支持所有32个协议族(include/linux/socket.h文件中定义),也就是使用socket(2)函数的第一个参数的值,如互联网的TCP/IP协议族PF_INET(2)。每个协议族有NF_MAX_HOOKS(8)个挂接点,但实际只用了如上所述的5个,数组中每个元素表示一个协议族在一个挂接点的处理链表头,。
 
以下分析使用2.4.26内核中的netfilter代码。
 
在IPv4(PF_INET协议族)下,各挂接点定义在:
NF_IP_PRE_ROUTING,在IP栈成功接收sk_buff包后处理,挂接点在在net/ipv4/ip_input.c的函数
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)中定义:
 return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
         ip_rcv_finish);
 
NF_IP_LOCAL_IN,在对接收的sk_buff包完成路由分类判断是到达自身的包后进行处理,挂接点在在net/ipv4/ip_input.c的函数int ip_local_deliver(struct sk_buff *skb)中定义:
 
 return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
         ip_local_deliver_finish);
 
NF_IP_FORWARD,在对接收的sk_buff包完成路由分类判断是需要进行转发的包进行处理,挂接点在在net/ipv4/ip_input.c的函数int ip_forward(struct sk_buff *skb)中定义:
 
 return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,
         ip_forward_finish);
 
NF_IP_LOCAL_OUT,在对自身发出的包进行处理,挂接点在在net/ipv4/ip_output.c的函数
int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
     u32 saddr, u32 daddr, struct ip_options *opt)
中定义:
 
 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
         output_maybe_reroute);

NF_IP_POST_ROUTING,在IP栈成功接收sk_buff包后处理,挂接点在在net/ipv4/ip_output.c的函数
__inline__ int ip_finish_output(struct sk_buff *skb)中定义:
 
 return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
         ip_finish_output2);
 
2. 挂接点操作
 
挂接点的操作由结构struct nf_hook_ops定义:
include/linux/netfilter.h
struct nf_hook_ops
{
 struct list_head list;
 /* User fills in from here down. */
 nf_hookfn *hook;
 int pf;
 int hooknum;
 /* Hooks are ordered in ascending priority. */
 int priority;
};
 
数组中的元素说明如下:
struct list_head list: 链表头,用于将此结构接入操作链表
nf_hookfn *hook:用户定义的挂接处理函数
int pf:协议族
hooknum:挂接点
priority:优先级
 
每个struct nf_hook_ops结构需要挂接到nf_hooks数组中的某个链表中才起作用,每个协议族的各种处理形成一个处理链表,链表上可以挂接多个节点,每个节点是一个数据处理结构(struct nf_hook_ops),用来描述对数据包进行如何处理,这些节点根据优先级顺序进行排序处理,优先级是有符号的32位数,值越小优先级越高,如果优先级相同,则按挂接的顺序依次处理,netfilter预定义了以下优先级:
 
 NF_IP_PRI_FIRST = INT_MIN,
 NF_IP_PRI_CONNTRACK = -200,
 NF_IP_PRI_MANGLE = -150,
 NF_IP_PRI_NAT_DST = -100,
 NF_IP_PRI_FILTER = 0,
 NF_IP_PRI_NAT_SRC = 100,
 NF_IP_PRI_LAST = INT_MAX,
 
由此可见,netfilter的处理顺序是先连接跟踪、然后是mangle处理,再目的NAT(PREROUTING),然后是过滤(FILTER),然后是源NAT(POSTROUTING),这就是为什么mangle链的规则会先执行。
 
在各个处理点处理数据包时,如果发现需要丢弃数据包,那么数据包就被立即释放而不再进入后面的处理点;如果该处理点的最终结论是接受,那该数据包还会继续进入下一处理点进行匹配检查,所以对于最终通过防火墙的数据包,是经过了所有处理点的匹配的。

3. 连接跟踪
 
连接跟踪的struct nf_hook_ops结构在net/ipv4/netfilter/ip_conntrack_standalone.c中定义,
这是对用户隐藏的,也就是用户不能通过iptables规则对此操作点进行配置,是有系统自动完成的。
 
定义如下:
static struct nf_hook_ops ip_conntrack_in_ops
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
 NF_IP_PRI_CONNTRACK };
static struct nf_hook_ops ip_conntrack_local_out_ops
= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
 NF_IP_PRI_CONNTRACK };
 
分别挂接在外部数据包进入(NF_IP_PRE_ROUTING)和自身数据发出(NF_IP_LOCAL_OUT)时进行处理,其功能就是判断该数据包是什么状态,填充该数据包struct sk_buff结构中struct nf_ct_info *nfct项的值,维护连接状态表,从而实现状态检测,具体处理过程分析可见另一篇文章:Linux下如何实现状态检测。
 
4. 规则表(table)
 
为了定义每个处理点上要执行哪些规则,netfilter定义了表(table)的概念,每个表由一个struct ipt_table来描述,如缺省的filter/nat/mangle表,每个表可单独分成几个规则链,分别在几个挂接点起作用,如filter表是在只在NF_IP_LOCAL_IN/NF_IP_LOCAL_OUT/NF_IP_FORWARD上起作用,然后通过函数ipt_do_table()来实现对某个表中某个hooknum的规则集进行匹配处理。而由结构struct nf_hook_ops所定义的各个处理点的处理函数都是直接或间接的调用了ipt_do_table()函数来实现对规则集的调用。
 
下面是系统缺省的三个表的定义情况:
-------+---------------------------------+-------------------------------------
 table |  table definition               | file name
-------+---------------------------------+-------------------------------------
filter | struct ipt_table packet_filter  | net/ipv4/netfilter/iptable_filter.c
       |
hook   | NF_IP_LOCAL_IN、NF_IP_LOCAL_OUT、NF_IP_FORWARD
       |
ops    | struct nf_hook_ops ipt_ops[]
       | net/ipv4/netfilter/iptable_filter.c
       |
       |NF_IP_LOCAL_IN: ipt_hook()
       |    调用ipt_do_table()函数与filter表的INPUT链挂钩
       |
       |NF_IP_LOCAL_FORWARD: ipt_hook()
       |    调用ipt_do_table()函数与filter表的FORWARD链挂钩
       |
       |NF_IP_LOCAL_OUT: ipt_local_out_hook()
       |    调用ipt_do_table()函数与filter表的OUTPUT链挂钩
       |
-------+---------------------------------+-------------------------------------
nat    | struct ipt_table nat_table      | net/ipv4/netfilter/ip_nat_rule.c
       |                                
hook   | NF_IP_PRE_ROUTING_IN、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING
       |
ops    | net/ipv4/netfilter/ip_nat_standalone.c
       |
       |NF_IP_PRE_ROUTING:
       |    struct nf_hook_ops ip_nat_in_ops, ip_nat_fn()
       |      调用ip_nat_rule_find()函数
       |        调用ipt_do_table()函数与nat表的PREROUTING链挂钩
       |
       |NF_IP_POST_ROUTING:
       |    struct nf_hook_ops ip_nat_out_ops,ip_nat_out()
       |      调用ip_nat_fn()
       |        调用ip_nat_rule_find()函数
       |          调用ipt_do_table()函数与nat表的POSTROUTING链挂钩
       |
-------+---------------------------------+-------------------------------------
mangle | struct ipt_table packet_mangler | net/ipv4/netfilter/iptable_mangle.c
       |                                 |
hook   | 全部五个都有
       |
ops    | struct nf_hook_ops ipt_ops[]
       | net/ipv4/netfilter/iptable_mangle.c
       |
       |NF_IP_PRE_ROUTING: ip_route_hook()
       |    调用ipt_do_table()函数与mangle表的PREROUTING链挂钩
       |
       |NF_IP_LOCAL_IN: ip_route_hook()
       |    调用ipt_do_table()函数与mangle表的INPUT链挂钩
       |
       |NF_IP_FORWARD: ipt_hook()
       |    调用ipt_do_table()函数与mangle表的FORWARD链挂钩
       |
       |NF_IP_LOCAL_OUT: ipt_local_hook()
       |    调用ipt_do_table()函数与mangle表的OUTPUT链挂钩
       |
       |NF_IP_POST_ROUTING: ip_route_hook()
       |    调用ipt_do_table()函数与mangle表的POSTROUTING链挂钩
       |
-------+---------------------------------+-------------------------------------
 
每个数据处理表(table)中就是定义各自的规则集,是用动态长度的数组的形式保存,每个数组节点是一个规则,规则用struct ipt_entry结构进行描述,每条规则除了基本项外,其他附加匹配条件项还形成一个动态长度的匹配数组,struct ipt_entry中保存数组头的地址,每个匹配用结构struct ipt_match描述。规则的动作如果是扩展动作的话,用struct ipt_target描述。
 
用户可以自己定义自己的新的表,可以以缺省表为蓝本,然后定义新的struct nf_hook_ops操作节点,在该操作节点中调用ipt_do_table()函数将该ops和新表联系起来,这样就可以用iptables定义新的规则集。如果不定义新表,用户也可以在ops处理函数中对包直接进行判断处理,适合需要对包进行固定方式处理的场合。
 
5. 总结
 
netfilter架构以nf_hooks数组为基点,挂接在内核的协议处理的几个基本点上,通过链表方式链接struct nf_hook_ops处理结构,这些处理结构可以是在内核内部自动固定处理,如状态检测;也可以通过和struct ipt_table联系,通过iptables来动态配置处理规则,实现了一个扩展性很高的防火墙处理架构,不过实现细节部分仍然很复杂,各种细节功能将在后续文章里分析。


整体二分初步

/* 整体二分是个很神的东西,它可以把许多复杂的数据结构题化简。它的精髓在于巧妙地利用了离线的特点,把所有的修改、询问操作整体把握。  先说说第k大数吧,这种问题是整体二分的标志性题目,什么...
  • cnyali
  • cnyali
  • 2016年06月16日 15:38
  • 326

Netfilter源码分析

一、基本介绍   1.1、常用名词解释 1、target//规则匹配后的处理方法 一般将target分为两类,一类为标准的target,即下面的宏定义 NF_DROP            ...
  • lanmolei814
  • lanmolei814
  • 2015年05月19日 23:06
  • 1105

深入浅出Netfilter/iptables防火墙框架(基础篇)

Netfilter/iptables可以对流入和流出的信息进行细化控制,且可以在一台低配置机器上很好地运行,被认为是Linux中实现包过滤功能的第四代应用程序。在接下来的这个《深入浅出Netfilte...
  • shuilaner_
  • shuilaner_
  • 2016年05月28日 15:45
  • 920

Tomcat整体架构浅析

整体结构 1各组件解释 组件包含关系 其它组件 2组件的生命线Lifecycle 启动流程 pipeline valve机制 1名词解释 2总体分析 3接口及默认实现 pipeline Valve V...
  • cx520forever
  • cx520forever
  • 2016年10月07日 10:30
  • 3324

整体二分小结

整体二分小结Ⅰ. 整体二分认知 摘抄部分2013许昊然论文−《浅谈数据结构题的几个非经典解法》摘抄部分2013许昊然论文-《浅谈数据结构题的几个非经典解法》 特么的论文用了啥j8加密编码,还...
  • lwt36
  • lwt36
  • 2016年02月15日 19:27
  • 2553

2.6内核基于NetFilter处理框架修改TCP数据包实现访问控制

http://blog.sina.com.cn/s/blog_6f0c85fb0100xi1x.html 征战论文的途中,以前公司的人来找我说要给之前我设计的网络内容过滤产品添加一个功能...
  • qiushanjushi
  • qiushanjushi
  • 2015年01月21日 21:50
  • 1125

Solr学习总结(七)Solr搜索引擎的整体架构

经过前面一段时间的努力,终于把我所知道的关于solr 的内容都总结完了。前面讲到了solr 的安装配置,web管理后台 的使用,solr 的查询参数和查询语法,还说到了solr的客户端 solrne...
  • gangzhucoll
  • gangzhucoll
  • 2016年08月10日 16:31
  • 533

向架构师进军--->如何编写软件架构文档

有文档的架构有助于不同利益相关者之间进行有效的沟通。 有文档的架构可以提供追溯其他工作产品的上下文。 有文档的架构可以传达可供选择的架构解决方案。 有文档的架构有助于从一个现有架构转换到一...
  • wyxhd2008
  • wyxhd2008
  • 2014年05月13日 22:05
  • 752

Unity3D研究:Unity3D引擎架构设计

组件(Component)这个概念最早是在2005年《Game Programming Gems 5》的《Component Based Object Management》中接触到的,当时感觉在设计...
  • jonahzheng
  • jonahzheng
  • 2015年01月22日 02:01
  • 8381

Spring整体架构

Spring框架是一个分层架构,它包含一系列的功能要素,并被分为20个模块如下图所示:...
  • u011225629
  • u011225629
  • 2016年05月17日 20:39
  • 1556
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:netfilter整体架构解析初步
举报原因:
原因补充:

(最多只允许输入30个字)