分享
 
 
 

Linux2.2.x地址伪装模块的实现(二)

王朝system·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

在上一篇文章中,以 ip_masq_ftp 为例分析了 ip_masq_app 的实现。在这篇文章里,将以 ip_masq_portfw 为例分析 ip_masq_mod 的实现。

1. 概述

Linux 2.2.x 中实现了地址伪装。它在发出包时修改包的源地址和源端口 (OUTBOUND 方向,由 ip_fw_masquerade 实现),并在收到应答包时修改其目的地址和目的端口 (INBOUND 方向,由 ip_fw_demasquerade 实现)。它还可以在正常的流程中加入一些检查点,并在这些检查点上调用特定的函数去实现一些扩展的功能。在上一篇文章中,以 ip_masq_ftp 为例分析了 ip_masq_app 的实现。在这篇文章里,将以 ip_masq_portfw 为例分析 ip_masq_mod 的实现。(ip_masq_app 与 ip_masq_mod 的主要区别在于 ip_masq_app 检查应用协议中的动态地址或端口,而 ip_masq_mod 检查 IP 和 TCP 头中的地址或端口)

先来看看检查点的位置,如图:

图中 ip_fw_masquerade 中的检查点 ip_masq_mod_out_rule 在内核代码中并没有使用,画在这里是为了让图看起来对称一点 :-);ip_masq_mod_in_rule 根据规则检查本机收到的包,这个包有可能是地址伪装的应答包,或是需要做目的转换的包,或者是发往本机上层的包,检查的结果决定是否要继续后面的动作;ip_masq_mod_out_create 和 ip_masq_mod_in_create 分别根据包所匹配的规则创建相应的地址伪装结构;ip_masq_mod_out_update 和 ip_masq_mod_in_update 则用新的参数更新已创建的地址伪装结构;ip_masq_app_pkt_out 和 ip_masq_app_pkt_in 是 ip_masq_app 模块的两个检查点,上一篇文章中讲到的 masq_ftp_out 和 masq_ftp_in 两个函数就分别在这两个检查点上被调用。(判断一个包是在 OUTBOUND 方向还是在 INBOUND 方向可以看这个包是转发的包还是发往本机的包。需要转发的包是在 OUTBOUND 方向上,本机收到的包是在 INBOUND 方向上) 实现一个 ip_masq_mod 的模块,先要定义一个 ip_masq_mod 的结构,以 ip_masq_portfw 为例,它定义了如下的结构:

static struct ip_masq_mod portfw_mod = { NULL,/* next */ NULL,/* next_reg */ "portfw",/* name */ ATOMIC_INIT(0),/* nent */ ATOMIC_INIT(0),/* refcnt */ proc_ent, portfw_ctl, NULL,/* masq_mod_init */ NULL,/* masq_mod_done */ portfw_in_rule, portfw_in_update, portfw_in_create, portfw_out_rule, portfw_out_update, portfw_out_create, };

(在这个结构中用粗体标记的函数没有实现)。可以看到,结构定义了在检查点上调用的函数和描述结构信息的一些参数。结构定义之后需要注册到一个全局的 ip_masq_mod_reg_base 链表之中(指针 next_reg 用于指向这个链表上的下一个结构),这个表上有所有注册的 ip_masq_mod 结构。同时还有一个链表 ip_masq_mod_lkp_base(指针 next 用于指向这个链表上的下一个结构),一般会在添加模块规则时将结构同时注册到这个链表中,如果没有模块规则,结构不会在这个链表上(在检查点上查找相应结构时就引用这个链表,这样做的目的是为了减少不必要的遍历)。结构中的 proc_ent 项代表 proc 文件系统中的一个文件,它实现了用户空间读模块规则的接口。

2. IP_MASQ_MOD

ip_masq_portfw 实现了目的地址转换。用下图所示的环境分析它在检查点上定义的函数:

图中 A、C 是内网主机,B 是外网主机。在 FW 配置规则如下:

ipmasqadm portfw -a -L 192.168.0.88

80

-R

10.0.0.1 80 -p 2

ipmasqadm portfw -a -L 192.168.0.88

80

-R

10.0.0.2 80 -p 1 ipchains -A forward -s 10.0.0.0/8 -j MASQ

前两条规则是 portfw 的规则,它把对 FW 外网地址的端口为 80(一般是 HTTP 服务)的访问映射到内网的监听端口为 80的服务器上。它们映射相同的服务,以轮询的方式去选择真正转换后的地址。第三条规则是地址伪装的规则,加这条规则的目的是为了使服务器返回的包可以走到 ip_fw_masquerade 函数中,进而恢复原来的目的地址。 下面从模块初始化,模块释放,portfw 的规则,和 portfw 定义的方法四个方面分析 ip_masq_portfw 的实现。

2.1. 初始化

模块初始化的流程从 init_module 开始(如果将 ip_masq_portfw 编译成内核模块)。它调用 ip_portfw_init,在这个函数里初始化了两个规则链表,一个保存 TCP 协议的规则,一个保存 UDP 协议的规则。然后在这个函数里将前面定义的结构 portfw_mod 注册到系统的链表中。

2.2. 释放

模块释放的流程从 cleanup_module 开始。它调用 ip_portfw_done,在这个函数里将结构 portfw_mod 从系统链表中取下(取下时要判断结构的引用计数是否等于 0,等于 0 才可取下)。

2.3. 规则

规则分两部分讨论,一是添加、删除规则的接口,二是读规则的接口。 规则匹配收到包的协议,目的地址,目的端口,其结构如下:

struct ip_portfw { struct list_head list; __u32

laddr, raddr; __u16

lport, rport; atomic_tpref_cnt;/* pref "counter" down to 0 */ int pref;/* user set pref */ };

在这个结构中,list 用于双向链表的前后指针;laddr, lport 是 FW 的地址和端口(结构中没有定义协议是因为不同协议的规则保存在不同的链表中);pref_cnt 是一个优先值的计数,它的初值是 pref(在添加规则时指定),以后每次匹配到这个规则,都将这个值减 1,如果减为 0,将这条规则移到链表的末尾,并重置这个值为 pref,用这样的方法,实现了一个简单的轮询算法(代码在 portfw_in_create 中)。

2.3.1. 添加、删除规则

规则的添加和删除是通过用户空间的配置工具完成,它调用系统调用去作用于规则表,调用过程如下:

从图中可以看到,作用于规则表的函数是由 setsockopt 函数以 level 为 SOL_IP 调用的(level 想当于协议栈中的层,地址伪装在 IP 层上实现,所以用户接口也是以 SOL_IP 作为 level)。portfw_ctl 是一个分派函数,根据用户空间传来的不同的命令调用不同的函数如 ip_portfw_add 用于添加规则(地址、端口相同的规则,只更新其优先值),ip_portfw_del 用于删除规则。读写规则链表都需要得到锁 portfw_lock,然后才能进行读写动作。

2.3.2. 读规则

读规则是通过 proc 文件系统的接口完成的。用户空间的程序通过读文件 /proc/net/ip_masq/portfw 的内容得到当前系统中配置的 portfw 的规则。在 portfw_mod 结构中有指向 proc_dir_entry 数据结构的指针 proc_ent,在这个结构中定义了读 proc 文件的接口 portfw_procinfo。proc_dir_entry 的注册是在注册 portfw_mode 结构时完成的。一般在 ip_masq_mo 的实现中都会定义这个函数。

2.4. 方法

ip_masq_portfw 只实现了两个在检查点上调用的函数。

2.4.1. portfw_in_rule

portfw_in_rule 对 FW 收到的包(其目的地址是 FW 的地址)进行匹配。如果这个包需要做目的地址转换(匹配到了 portfw 规则表中的规则;或者其目的端口是在地址伪装端口的范围之内 [61000-65096];或是目的端口是指定的伪装端口(mport_count 不为 0)),则继续执行后面的过程;如果不需要做目的地址转换,则直接返回。这一步的检查避免对每个收到的包都去查伪装结构的表。

2.4.2. portfw_in_create

在这个函数里创建对应目的转换的伪装结构。首先,根据收到包的协议引用不同的规则表。然后用收到包的目的地址和目的端口匹配 portfw 规则。如果找到,创建地址伪装结构(这个结构将会在服务器应答包的源转换时被引用,同一连接的后续包也将引用这个结构,直到这个结构因连接超时被删除)。接下来,它减小规则的 pref_cnt, 并且如果 pref_cnt 为零,将规则移至链表末尾,并冲置 pref_cnt 的值。

3. 总结

实现一个 ip_masq_mod 的要点是定义 ip_masq_mod 的结构,并实现它在检查点上调用的函数。其中区别在于规则的组织以及创建地址伪装结构的条件,这可以根据应用的不同选择不同的实现方式。

关于作者

朱小平,现从事网络安全的开发,比较感兴趣的方向是操作系统和网络协议栈的实现。写文章,只是为整理思路,发现问题。邮件地址为 droplet@163.net ,如有相同兴趣,可以共同进步。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有