• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

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

发布: 2007-7-04 12:06 | 作者: admin | 来源:  网友评论 | 查看: 10次 | 进入软件测试论坛讨论

领测软件测试网
  ip_masq_ftp 的实现
  
  作者:朱小平 (droplet@163.net ) 2003 年 3 月
  
  1. 概述
  
  Linux 2.2.x 中实现了地址伪装 (本文引用的代码版本是 2.2.19)。它在缺省的伪装流程中可以附加一些其他模块来扩展其功能,有两种类型的模块,ip_masq_mod 和 ip_masq_app。在这篇文章中,将分析 ip_masq_app 模块的实现,ip_masq_mod 的实现将在以后的文章中分析。
  
  2. IP_MASQ_FTP 模块
  
  2.1. 概述
  
  ip_masq_app 是对应用层协议数据进行处理的模块,以 ip_masq_ftp 的实现为例说明其实现要点。
  
   struct ip_masq_app ip_masq_ftp = {     NULL,/* next */  "ftp",      /* name */     0,           /* type */     0,           /* n_attach */     masq_ftp_init_1,    /* ip_masq_init_1 */     masq_ftp_done_1,    /* ip_masq_done_1 */     masq_ftp_out,      /* pkt_out */     masq_ftp_in,      /* pkt_in */ };
  
  首先定义一个 ip_masq_app 类型数据结构。结构成员中 next 用于在哈希表中指向相同哈希值单向链表中的下一个结构;name 是结构的名称;type 是一个由协议,端口和 INBOUND 或 OUTBOUND 或 fwmark 标记决定的值,有两种情况,如图:
   javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)">
  如果 flags 是 0x80000000,则低 24 位是 fwmark,这个值是 ipchains 在 skb 中做的标记;如果 flags 是 0x01000000 或0x02000000,则低 16 位是端口号,中间 8 位是协议号。
  
  n_attach 是结构的引用计数。 masq_ftp_init_1 和 masq_ftp_done_1 分别在结构绑定和去绑定时调用;masq_ftp_in,masq_ftp_out分别由 ip_masq_app_pkt_in 和 ip_masq_app_pkt_out 调用。 接下来要把这个数据结构注册到系统的 ip_masq_app_base 哈希表中,哈希值是由结构中的 type 定义的,所以注册时要指定 flags,协议,端口等参数。下面就详细分析一下 ip_masq_ftp 模块中的过程。
  
  2.2. 初始化
  
  初始化在模块注册时进行,如图:
  
   
  首先注册 OUTBOUND 方向的结构。register_ports 分配结构,并将它注册到系统中,同时将 masq_ftp_objs 或 masq_in_ftp_objs 数组中的指针指向这些结构(这是一个 12 元素的数组,其中最后一个元素用于 mark 和 in_mark 时的注册)。参数 ports 的默认值为 {21},这是一个端口的数组,ip_masq_ftp 可以指定多达 11 个端口,默认的端口为 21。注册后,这些结构会在 ip_masq_bind_app 中被引用。接下来注册 INBOUND 方向的结构。参数 in_ports 的默认值是 {0},所以在 INBOUND 方向上没有相应的结构。这使得 FTP 在目的转换中 PASV 模式不能使用,具体的分析将会在后面看到。
  
  后面对 mark和in_mark 的处理与前面的处理大同小异,区别在于这里用指定的 fwmark 去计算结构中的 type 值,而前面使用端口号和协议去计算结构中的 type 值。它们所引用的函数也不同,一个是 ip_masq_app_init_fwmark,一个是 ip_masq_app_init_proto_port。
  
  2.3. 释放
  
  释放在模块卸载时进行,如图:
  
   
  模块卸载时,将注册到系统的结构从哈希表中取下,然后释放结构,并将 masq_ftp_objs 或 masq_in_ftp_objs 数组中的相应元素置为 NULL。
  
  2.4. 发出和收到的处理
  
  对发出和收到处理的分析将以下图所示的环境为例分析:
  
   
  图中所示 A 是内网主机,FW 是防火墙 (有两个接口),B 是外网主机。
  
  2.4.1. 源转换时的处理
  
  在 FW 上配置源转换,规则为:ipchains -A forward -s 10.0.0.0/8 -j MASQ。在 B 上运行 FTP 的服务器,A 作为 FTP 的客户端。A 从服务器 B 上取文件,过程如下:
  
  [1] A (端口 1735) 发起到 B (端口 21) 的 TCP 连接,在 ip_fw_masquerade 中将会创建如下的地址伪装结构:
  
   
  同时这个伪装结构会与 ip_masq_ftp 绑定 (在 ip_masq_bind_app 中)。然后 FW 会将包中的源地址/源端口改为伪装结构中的伪装地址/伪装端口。
  
  B 返回的应答包在 ip_fw_demasquerade 中处理时会找到这个伪装结构,并将其中的目的地址/目的端口改为伪装结构中的源地址/源端口。
  
  [2] 如果 A 发出 PORT 命令,建立从 B 到 A 的主动的数据连接取文件。
  
  A 发出 PORT 命令的数据包中有A的地址和监听端口 (port 10,0,0,1,6,217)。这个包会在 ip_masq_app_pkt_out 中由 masq_ftp_out 处理,如图:
  
   
  处理时先检查伪装结构的 state,如果不是 IP_MASQ_S_ESTABLISHED 状态,则返回。接下来检查数据的长度是否正确。然后检查 ip_masq_app 结构中的 type。在上一步伪装结构与 ip_masq_app 绑定时得到的 ip_masq_app 结构的 type 是 IP_MASQ_APP_OUTBOUND,所以使用 OUTBOUND 的过程。
  
  它在数据包中匹配 "PORT" 或 "PASV" 字符串,如果含有 "PORT" 字符串,它在 "PORT" 之后的数据中找到A的地址和端口,地址是前四个逗号分隔的字符串,端口是第五个字符串的值乘 256 加第六个字符串的值的到。找到地址和端口后,查看它是否是系统允许的端口 (masq_ftp_unsafe 中会检查这个端口是否小于 1024 或在 noports 中包含的端口)。接下来检查包含此地址和端口的伪装结构是否已创建 (ip_masq_out_get),如果没有创建,创建一个新的伪装结构 (ip_masq_new),如图:
  
   
  ( 这个结构中目的端口为 0 是因为此时还不知道下一步 B 连接 A 的源端口 ) 然后将数据中包含的地址和端口用此伪装结构中的伪装地址和端口替换。
  
  [3] B (端口为 20) 发起到地址 192。168。0。88 端口 61012 的 TCP 连接,ip_fw_demasquerade 中的处理会将伪装结构中的目的地址更新为 20,然后将它的目的地址/目的端口替换为伪装结构中的源地址 (10。0。0。1) /源端口 (1753),这样数据连接就可以建立了。
  
  [4] 如果 A 发出 "PASV" 命令,这个包在 masq_ftp_out 中由 OUTBOUND 方向的过程检查,它将伪装结构的 app_data 置为 masq_ftp_pasv。然后 B 会应答 "Entering Passive Mode 192,168,0,88,221,30" 的包,这个包会在 masq_ftp_in 中由 OUTBOUND 方向的过程检查 (可以参考后面 masq_ftp_in 的流程,在这个流程中会检查 masq_ftp_pasv 标记),它会创建一个新的地址伪装结构,如图:
  
   
  ( 这个伪装结构的源端口为 0 的原因会在后面讲到 )
  
  [5] A (端口为 1753) 发起到 B (端口为 56606) 的 TCP 连接,在 ip_fw_masquerade 中会伪装结构中的源端口更新为 1753,然后将源地址/源端口替换为伪装结构中的伪装地址/伪装端口,这样数据连接就建立起来了。
  
  2.4.2. 目的转换时的处理
  
  在 FW 上配置目的转换和源转换,规则如下:
  
  ipmasqadm portfw -a -P tcp -L 192.168.0.88 21 -R 10.0.0.1 21
  ipchains -A forward -s 10.0.0.0/8 -j MASQ
  
  A 上运行 FTP 的服务器,B 上运行 FTP 的客户端,B 从服务器 A 上取文件,过程如下:
  
  [1] B (端口为 1735) 发起到 FW (端口为 21) 的 TCP 连接,在 ip_fw_demasquerade 中将会创建地址伪装结构:
  
   
  同时这个结构会与 ip_masq_app 绑定 ( ip_masq_bind_app 中会根据伪装结构中的目的端口和伪装端口去匹配在系统中注册的 ip_masq_app 结构。在 ip_masq_ftp 的实现中,默认只有 OUTBOUND 方向的端口为 21 的 ip_masq_app 结构,这里假设系统也注册了 INBOUND 方向的端口为 21 的 ip_masq_app 结构 )。然后 FW 会将包中的目的地址/目的端口改为伪装结构中的源地址/源端口。
  
  A 返回的应答包会在 ip_fw_masquerade 中匹配到这个伪装结构,并将其中的源地址/源端口改为伪装结构中的伪装地址/伪装端口。
  
  [2] 如果 B 发出 "PORT" 命令,建立从 A 到 B 的主动连接取文件。
  
  B 发出 PORT 命令,这个命令中有 B 的地址和监听端口 (port 192.168.0.1.6.217),这个包会在 ip_masq_app_pkt_in 中由 masq_ftp_in 处理,如图:
  
   
  处理时先检查伪装结构的 state,这与 masq_ftp_out 中的检查是一样的。然后检查 ip_masq_app的type,这里匹配到的是 IP_MASQ_IN_BOUND,所以使用 INBOUND 方向上的过程。它在数据包中匹配 "PORT" 字符串,如果找到,接下来在 "PORT" 后面的字符串中找到 B 的地址和端口。然后检查包含这个地址和端口的伪装结构是否已创建,如果没有,则创建一个新的伪装结构,如图:
  
   
  ( 这个结构中的源端口为 0 是因为此时还不知到下一步 A 到 B 的连接的源端口 )
  
  最后的操作是将 ms->app_data 置为 NULL。这一步操作对应第一种情况中A发出 "PASV" 命令时所置的标志。
  
  ( 在 masq_ftp_in 没有替换数据中的地址和端口是因为这个地址和端口都是外网的地址和端口,内网主机发起连接时可以找到这个地址和端口,这与 masq_ftp_out 中的处理不同 )
  
  [3] A (端口为 20) 发起到 B (端口为 1753) 的 TCP 连接,ip_fw_masquerade 中会将伪装结构种的源端口更新为 20,然后将源地址/源端口替换为伪装结构中的伪装地址/伪装端口,这样数据连接就建立起来了。
  
  [4] 如果 B 发出 "PASV" 命令,这个包在 masq_ftp_in 中由 INBOUND 方向的过程检查,这个过程并没有对 "PASV" 命令做特殊的处理。然后 A 会应答 "Entering Passive Mode 10.0.0.1.221.30" 的包,这个包会在 masq_ftp_out 中由 INBOUND 方向的过程处理 (可以参考 masq_ftp_out 的流程),它将创建一个新的伪装结构如图:
  
  (这个结构中的目的端口为0的原因在前面已提到)
  
   
  [5] A (端口为 1753) 发起到 FW (端口为 61015) 的 TCP 连接,在 ip_fw_demasquerade 中会更新伪装结构中的目的端口 (填为 1753),并且将包的目的地址/目的端口替换为伪装结构中的源地址/源端口。
  
  2.5. 其他
  
  ip_masq_ftp 以内核模块的方式实现,有 6 个模块参数,如下:
  
  
  [表2.1]
  
  3. 总结
  
  以上就对 ip_masq_ftp 实现的分析。可以看到实现一个 ip_masq_app 所需要做的工作。现在网络环境中使用了很多在协议数据中传递动态地址和端口的应用协议,如 irc,h.323 等。实现对这些协议的动态地址和端口的转换与上面 FTP 协议的转换的过程基本一致。不同之处是在于动态地址和端口的查找和协议交互方式的区别。
  
  作者简介:
  
  朱小平,现从事网络安全的开发,比较感兴趣的方向是操作系统和网络协议栈的实现。写文章,只是为整理思路,发现问题。邮件地址为 droplet@163.net ,如有相同兴趣,可以共同进步。
  
  
  

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网