LINUX 2.4.x 内核网络安全框架的示例分析

65次阅读
没有评论

共计 4388 个字符,预计需要花费 11 分钟才能阅读完成。

这篇文章将为大家详细讲解有关 LINUX 2.4.x 内核网络安全框架的示例分析,丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

1. 概述

在分析 LINUX2.4.x 网络安全的实现之前先简单介绍一下它里面包含的几个重要概念:netfilter、iptables、match、target、nf_sockopt_ops、网络安全功能点的实现。详细解释会在后面的分析中讲到。

首先是 netfilter,它定义了协议栈中的检查点和在检查点上引用的数据结构,以及在检查点上对这些结构引用的过程。iptables 定义了实现网络安全功能的规则的组织以及对规则的操作。一个规则中包含零个或多个 match 和一个 target,规则组织沿用了 LINUX2.2.x 中的 chain,rule 的概念,但是增加了 table 的概念,这三者的关系是:table 是实现某项功能所有规则的总和,chain 是在某个检查点上所引用规则的集合,rule 是一个单独的规则。match 在规则中用于匹配数据包中的各项参数,每个 match 匹配特定的参数,所以一个规则中可以有多个 match,这包括系统已定义的 match,也包括通过内核模块另外添加的 match。target 在规则中决定如何处理匹配到的数据包,因此在 target 中实现了具体的网络安全功能。nf_sockopt_ops 是在系统调用 get/setssockopt 中引用的数据结构,实现用户空间对规则的添加、删除、修改、查询等动作。以上的结构在使用之前必须先注册到系统中才能被引用。

LINUX2.4.x 网络安全实现了包过滤,地址转换 (包含了 LINUX2.2.x 中的地址伪装和透明代理功能并有其他扩展功能),连接跟踪(这是实现地址转换的基础,在它里面实现了对连接状态的记录和监控,与状态检测类似),Mangle(这是 LINUX2.4.x 新增的一个功能,它对数据包进行检查但不做禁止、丢弃或允许的判断)。实现这些功能点需要分别注册 netfilter,iptables,match,target,nf_sockopt_ops 的数据结构。如果实现其他新的功能,只需定义相应的结构并将它注册到系统中,并且通过用户空间的配置工具(这个配置工具也须支持新的结构) 把它加入到规则中就可以了。这些结构在规则中自动被引用。

2.netfilter

netfilter 定义了协议栈中的检查点和检查点上引用的数据结构以及对这些数据结构引用的过程。首先看看在检查点上引用的数据结构,如图所示:

图中 ns_hook_ops 就是在检查点上引用的结构。每个协议栈预先定义的 8 个链表数组用于保存这些结构,这些链表与协议栈中的检查点一一对应。在实际的应用中,这 8 个链表并不一定都被使用,比如在 IPV4 中,只定义了 5 个检查点,分别对应前 5 个链表。nf_hook_ops 结构如下:

struct nf_hook_ops

{

struct list_head list;

nf_hookfn hook; /* 函数指针 */

int pf; /* 结构对应的协议栈号 */

int hooknum; /* 结构对应的检查点号 */

int priority; /* 结构的优先值 */

};

nf_register_hook 函数将 ns_hook_ops 结构注册到这些链表上,链表的索引由结构中 hooknum 指定。同一链表上的结构按优先值由小到大排列。在检查点上引用这些结构时,以它们在链表上的先后顺序引用。

检查点由宏 NF_HOOK 定义。在检查点上,函数 nf_hook_slow 调用函数 nf_iterate 遍历对应链表并调用链表上的结构 ns_hook_ops 中定义的函数。如果结构中的函数返回 NF_ACCEPT,则继续调用下一个结构中的函数; 如果结构中的函数返回 NF_DROP 或 NF_STOLEN 或 NF_QUEUE,则将这个值返回给 nf_hook_slow; 如果结构中的函数返回 NF_REPEAT, 则重复调用此结构上的函数; 如果到了链表上的最后一个结构,则把这个结构中函数的返回值返回给 ns_hook_slow。在 ns_hook_slow 中判断 nf_iterate 的返回值,如果是 NF_ACCEPT,则允许数据包通过,并将数据包传递给协议栈中的下一个函数; 如果是 NF_DROP,则释放数据包,协议栈流程中断; 如果是 NF_STOLEN,同样中断协议栈的流程,但是没有释放这个数据包; 如果是 NF_QUEUE,则将这个包发送到用户空间处理,同时中断协议栈的流程。

检查点分布在协议栈的流程中,下图是 IPV4 中的检查点:

图中检查点的名称如下:

检查点编号 检查点名称 检查点所在文件名

1 NF_IP_PRE_ROUTING ip_input.c

2 NF_IP_LOCAL_IN ip_input.c

3 NF_IP_FORWARD ip_forward.c

4 NF_IP_POST_ROUTING ip_output.c

5 NF_IP_LOCAL_OUT ip_output.c

表 2.1 IPV4 中检查点的名称

图中,ROUTE(1)处对收到的包做路由查找并判断这个包是需要转发的包还是发往本机上层的包,ROUTE(2)处查找发出包的路由。NF_IP_PRE_ROUTING 处对所有传入 IP 层的数据包进行检查,在这之前,有关数据包的版本、长度、校验和等正确性检查已经完成。NF_IP_LOCAL_IN 对发往本机上层的数据包进行检查。请注意这两个检查点与 LINUX2.2.x 中检查点的区别,在 LINUX2.2.x 没有区分发往本机上层包和需要转发的包,所以在做完地址解伪装之后又调用了一次路由查找函数,为解伪装之后的包查找路由。NF_IP_FORWARD 处检查需要转发的数据包。NF_IP_POST_ROUTING 处对所有向链路层传递的数据包进行检查,注意在此处数据包的路由已经确定。NF_IP_LOCAL_OUT 对本机发出的包进行检查,此处的路由还没有确定,所以可以做目的地址转换。实现某个网络安全功能可能需要在多个检查点上注册相应的结构,在后面的分析中我们可以看到具体的例子。

3. iptables

iptables 实现对规则的管理和访问。它里面有几个重要的数据结构 ipt_entry,ipt_match,ipt_target,ipt_table,用于构造规则表。还有一个重要的函数 ipt_do_table,用于遍历规则表并处理规则表上的结构。

ipt_entry 是规则的数据结构,如下:

struct ipt_entry

{

struct ipt_ip ip;

unsigned int nfcache;

u_int16_t target_offset;/* target 在规则中的偏移 */

u_int16_t next_offset; /* 下一条规则的偏移 */

unsigned int comefrom;

struct ipt_counters counters;/* 匹配规则的数据包的统计计数 */

unsigned char elems[0];

};

在 ipt_entry 中 ipt_ip 是一个基本的 match,它是固定的,用于匹配数据包的源地址 / 源端口、目的地址 / 目的端口、协议等。其他的 match 按需要添加,个数并不固定,所以在 ipt_entry 有一个变长的字符数组保存规则中 match 的指针,这些指针指向系统中注册的 match。每个规则有一个 target,决定数据包完全匹配规则后怎样处理这个数据包,它也是一个指向系统注册的 target 的指针,并且也放在前面提到的变长字符数组中。ipt_entry 中的 target_offset 是 target 在规则中的偏移,偏移是从规则的起始地址到 target 所在位置的长度,还有一个变量 next_offset 指示下一条规则偏移,它其实就是本条规则的长度。

前面提到在 iptables 中沿用了 LINUX2.2.x 中的 chain 和 rule 的概念,那么在 ipt_entry 中如何区分 chain 和 rule 的哪?

我们知道 chain 是某个检查点上检查的规则的集合。除了默认的 chain 外,还可以创建新的 chain。在 iptables 中,同一个 chain 里的规则是连续存放的。默认的 chain 的最后一条规则的 target 是 chain 的 policy。用户创建的 chain 的最后一条规则的 target 的调用返回值是 NF_RETURN,遍历过程将返回原来的 chain。规则中的 target 也可以指定跳转到某个用户创建的 chain 上,这时它的 target 是 ipt_stardard_target,并且这个 target 的 verdict 值大于 0。如果在用户创建的 chain 上没有找到匹配的规则,遍历过程将返回到原来 chain 的下一条规则上。

ipt_match 用于匹配数据包的参数,如 TCP 数据包中的标志位,ICMP 协议中的类型等,每个 match 所感兴趣的参数都不一样,所以一条规则可能有多个 match。ipt_target 决定在数据包完全匹配规则后应做什么样的处理。这两个在使用之间都必须先注册到系统的链表中才能被规则引用。对这两个数据结构不做过多分析,读者可以自行参考源代码。

ipt_table 是规则表的数据结构,如下:

struct ipt_table

{

struct list_head list;

char name[IPT_TABLE_MAXNAMELEN];

struct ipt_replace table;/* 用户空间传递的规则表 */

unsigned int valid_hooks; /* 有效的检查点置位 */

rwlock_t lock;

struct ipt_table_info private; /* 规则表在内核中的存储结构 */

struct module *me;

};

在 ipt_table 中,ipt_replace 是用户空间配置程序传递给内核的规则表,这个规则表不能直接使用,必须先根据它里面包含的 match 和 target 的名称将 match 和 target 转换成在内核注册的 match 和 target 的指针,还有一项重要的工作是检查规则表中是否有循环,如果有循环,要给用户空间的配置程序报告错误。转换之后的规则表存储在 ipt_table_info 中。valid_hooks 指示与这个表相关的检查点,并把相应的位置为 1。一个 table 中可以有多个 chain,chain 分为系统默认的 chain(与 table 注册的检查点对应)和用户创建的 chain。所有的 table 都注册放在一个链表中,而 chain 和 rule 则用偏移值 next_offset 连接成一个单向链表。

关于“LINUX 2.4.x 内核网络安全框架的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4388字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)