IP 伪装代码后续
一年多以前,本杂志慷慨地允许我为他们撰写了几篇文章。其中一篇涉及 Linux 内核支持的 IP 伪装主题(1996 年 7 月,第 27 期)。自那时以来,在 Linux 的持续开发过程中发生了一些变化。我想向 Linux Journal 的读者介绍一下已经发生的变化,解释一些技术细节,并对未来的发展方向进行一些猜测。许多功能的具体技术细节将不再赘述,因为总体功能没有改变。之前的文章仍然适用于这方面。
IP 伪装是一种执行地址隐藏的方法。可能是某公司没有足够的已注册 IP 地址来连接其所有计算机到互联网,或者如果您像我一样,您通过本地拨号帐户只有一个地址,但有三台计算机。通过使用伪装来允许“内部”计算机通过一个外部连接点访问,可以解决这些情况。外部连接点将使用伪装来隐藏地址。图 1 是我设置的本地网络图。
使用伪装仍然像以往一样容易。我有一个网络,我希望我的所有主机都能访问互联网。由于它们位于 192.168.1.0(网络)上,我可以伪装整个 C 类地址空间。您会注意到,作为一名优秀的管理员,我正在使用 RFC 1918 定义的私有地址。
为了启动伪装,我在我的 /etc/rc.d/ 目录中定义了一个 rc.masq 文件,并将其添加到 /etc/rc.d/rc.local 中执行。rc.masq 文件的内容如下所示
#!/bin/sh # PATH=/usr/local/bin; export PATH
# # setup system forwarding policy ipfwadm -F -p deny # # masquerading rules ipfwadm -F a m -S 192.168.1.0/24 -D 0.0.0.0/0 # # list out the current ruleset ipfwadm -F -l -n,
首先,您会注意到设置伪装的命令是 ipfwadm(版本 2.3.0)命令。这与之前的文章明显不同,之前的文章只能使用 ipfw 命令。自内核 1.3.66 起,ipfwadm 是唯一用于操作伪装规则的命令,可从 http://www.xos.nl/linux/ipfwadm/ 获取。
实际上只给出了两个语句。第一个语句
ipfwadm -F -p deny
定义了这台机器(图 1 中的 deathstar)的转发策略 (-F)。它将策略设置为拒绝所有由 deathstar 转发的数据包。转发是指数据包的源地址和目标地址与 deathstar 的任何接口都不同,并且要通过路由的情况。
第二个语句
ipfwadm -F -a m -S 192.168.1.0/24 -D 0.0.0.0/0
为源 (-S) 网络 192.168.1.0 添加了一个伪装规则。我们可以通过与其关联的 24 位网络掩码来判断它是针对整个网络的。24 位等同于 255.255.255.0,用于指示网络与 IP 地址的主机部分。目标 (-D) 地址是无所不包的 0.0.0.0 网络,用于标识任何网络。就是这样。
最后一个命令允许我查看为 deathstar 设置的规则。输出如下所示
IP firewall forward rules, default policy: deny type prot source destination ports acc/m all 192.168.1.0/24 0.0.0.0/0 n/a
简而言之,输出表明它将伪装从源 192.168.1.* 到任何地方的所有协议,以及所有源端口和目标端口。
ipfwadm 程序主要用于设置 Linux 2.x 内核中防火墙代码的规则。
伪装需要少量的工作才能完成配置。在内核 2.0.30 之前,伪装代码仍然被认为是实验性的。因此,许多代码片段未包含在完整发行版中,而仅作为补丁包含。如果您正在运行 2.0.x 内核,其中 x 为 29 或更低,请参阅“代码成熟度级别”侧边栏,了解如何修补内核以包含伪装。我的内核已设置为运行 2.0.30 版本,其中包含伪装。与伪装相关的配置选项如 列表 1 所示。
您会注意到,伪装代码的某些部分只能作为内核模块包含。这些模块是针对特定协议或应用程序的;例如,包括 FTP、VDOLive 和 Real Audio。
目前,IP 伪装支持 TCP 和 UDP、FTP、Real Audio、IRC、ICMP(配置选项)、VDOLive、CUSeeMe 和 Quake。正常的 TCP 和 UDP 应用程序(如 TELNET 或 DNS)直接在内核伪装代码中支持。异常(即病态)协议(如 FTP 和 IRC(其消息流中包含 IP 地址))和 Real Audio(因为控制协议需要知道您在哪里)通过内核模块支持。VDOLive、CUSeeME 和 Quake 也是内核模块。
如前所述,ipfwadm 命令用于设置伪装的转发规则。它也用于创建防火墙和记帐规则,这些规则也受 Linux 内核支持。虽然我们在这里不担心这方面,但应该注意的是,防火墙管理和 IP 伪装可以紧密耦合,这取决于您尝试执行的任务。
除了设置规则外,ipfwadm 还允许您查看任何伪装连接的当前状态。例如,命令
# ipfwadm -M -l -n
给出以下输出
IP masquerading entries prot expire source destination ports udp 03:31.50 192.168.1.5 164.109.1.3 1110 (61009) -53 udp 03:36.67 192.168.1.5 164.109.1.3 1112 (61011) -53 tcp 14:06.91 192.168.1.5 207.79.74.21 1304 (61016) -80 tcp 14:07.17 192.168.1.5 207.79.74.21 1303 (61015) -80 tcp 14:05.62 192.168.1.5 207.79.74.21 1302 (61014) -80 tcp 01:44.79 192.168.1.5 204.192.48.81 1301 (61013) -23-M 选项用于伪装管理,仅与 -l 或 -s 选项一起使用。-l 选项提供选定的(在本例中为伪装)列表。如您所见,输出列表显示了源端口号和伪装端口号(在括号中),以及到目标端口的连接。我们的流量显示了三个 DNS 查询、三个 HTTP 连接和一个当前建立的 TELNET 连接。
expire 列与伪装相关的计时器有关。如果未看到进一步的流量,伪装数据包将具有过期时间。TCP 连接有两个计时器。第一个用于伪装连接,第二个用于接收到 FIN 段时。可以使用 ipfwadm 的 -s 选项设置这些计时器中的每一个。TCP 连接的默认超时值为 15 分钟,UDP 的超时值为 5 分钟。您可以通过给出如下命令来更改这些值
# ipfwadm -M -s 1200 60 120
此命令表示 TCP 连接在不活动 20 分钟后过期,接收到 FIN 段后 1 分钟过期,UDP 条目 2 分钟过期。在大多数情况下,默认值都能很好地工作。
当我添加规则以伪装 192.168.1.0 网络时,我可以指示伪装流量将发送和接收的接口。我可以扩展命令如下
ipfwadm -F -a m -S 192.168.1.0/24 \ -D 0.0.0.0/0 -W ppp0
ppp0 是 204.192.48.109 地址的接口名称。虽然此名称在我们的示例中是可选的,但如果伪装机器具有多个内部网络连接,则必须给出此名称。例如,假设 deathstar 有两个以太网连接,分别用于网络 192.168.1.0 和 192.168.2.0。如果没有 -W 选项,则两个内部网络之间的流量也会被伪装,从而导致极大的混乱。
我选择使用命令将所有要转发的数据包的默认策略设置为 deny
ipfwadm -F -p deny
您可以将默认策略设置为 masquerade
# ipfwadm -F -p masquerade此命令伪装所有外发和传入的连接。换句话说,如果伪装机器外部网络上的主机设置了到内部网络的路由,他们可以发送数据包并建立到内部机器的连接(甚至 ping)。危险显而易见——您的网络不再隐藏。
2.0.30 内核和 ipfwadm 确实出现了一个问题。IP 伪装代码在 /proc/net/ip_masquerade 文件中包含 ICMP 的条目,如 列表 2 所示。ipfwadm 对此存在问题,并将给出以下错误
# ipfwadm -M -l -n IP masquerading entries ipfwadm: unexpected input data Try ipfwadm -h for more information.
这个问题将在不久的将来得到解决。
我发现 ipfwadm 的最后一个有用的选项是 -o 选项,它为与 ipfwadm 设置的规则匹配的数据包启用内核级调试。但请注意,此选项仅在选择内核选项 CONFIG_IP_FIREWALL_VERBOSE 时有效。
正如我们已经注意到的,某些协议与伪装的基本概念根本不兼容。对于一些更流行的协议,如 FTP、CUSeeMe、VDOLive、IRC 和 Quake,存在支持。仍然存在一些应用程序/协议,2.0.30 发行版不支持这些协议。这些协议包括 talk、“R”程序,如 rsh 或 rlogin、Mplayer 和其他游戏。
ssh(安全外壳)是“R”程序的绝佳替代品。它可以直接替代 rsh、rlogin 和 rcp,并支持 X11 会话。它的主要功能是安全通信和强大的身份验证;但是,由于它是基于 TCP 的,因此它可以与伪装主机很好地配合使用。强烈建议在一般远程通信中使用此程序。
IP 伪装在隐藏内部网络方面做得非常好。如果它被隐藏了,就没人能访问你,对吧?也许这不是一个特别理想的情况。对于 Web 服务器、匿名 FTP 服务器或电子邮件等资源,传入连接可能是有意义的。您的 Linux 主机可以用于所有这些服务,并且很可能您无论如何都希望代理传入邮件。如果您需要内部 Web 服务器,可以使用几个程序来转发或重定向从外部主机绑定到内部主机的流量。最简单的是 Nigel Metheringham 更新的 redir 程序,可从 sunsite.unc.edu:/pub/Linux/system/Network/daemons/redir-0.7.tar.gz 获取。redir 是一个 TCP 端口重定向器,它驻留在您的伪装主机上,等待端口上的连接,然后重定向到内部服务器。一个重定向 HTTP 并记录所有连接的简单示例如下
# redir --syslog 192.168.1.5 80 80 &
为了更方便,您也可以从 inetd 启动 redir。
我偶尔会将从外部机器重定向的 X 终端发送到内部的“yoda”(当我没有运行 ssh 时)。我通常在“deathstar”上运行 X,所以我使用 6000 以上的端口进行重定向。例如,我以这种方式设置重定向
# redir --syslog 192.168.1.5 6001 6000 &
在外部主机上,我会将 xterm 显示发送到端口 6001。
xterm -display 204.192.48.109:1.0 &您不会希望向所有人开放此功能,因此最好实施一些关于传入伪装主机的流量的防火墙规则,以限制谁可以连接到您或从 inetd 启动 redir 并使用 tcpd 之类的东西来限制连接。
对于 UDP 流量,有一些程序可用于将流量从外部主机重定向到内部主机。udpspoof (http://www.america.com/~chrisf/web/udpspoof.c) 和 udprelay (ftp://ftp.wang.com/pub/fitz/udprelay-0.2.tar.Z) 是不错的选择。不过,可能最流行的是 ipautofw,它足够通用,可以处理 TCP 和 UDP 流量。它在 Linux 内核中作为 2.0.30 内核的一部分实现,它也是一个用于设置自动转发规则的命令接口。它可从 ftp://ftp.netis.com/pub/members/rlynch/ipautofw.tar.gz 获取。
ipautofw 命令在 /proc/net/ip_autofw 文件中设置规则,以自动转发伪装主机的包。例如,为了在内核模块实现之前处理 Real Audio 流量,您可以使用 ipautofw 发出命令
ipautofw -A -r udp 6970 7170 -c tcp 7070
这会将 TCP 控制连接 (-c<\!s>7070) 与一系列返回的 UDP 数据包(端口 6970 到 7170,包括端点)关联起来。
现在,假设我们的伪装主机后面有 Web 服务器。我们可以添加一个自动转发条目,例如
# ipautofw -A -r tcp 80 80 -h 195.168.1.5
此命令将 HTTP 请求转发到 yoda (195.168.1.5)。但是,ipautofw 一次只能满足一个请求。只要该连接存在伪装条目,所有其他连接请求都会发送 TCP “重置”,直到计时器过期。对于 Web 服务器来说,这不是一个好场景。
将流量重定向到多个主机是伪装重定向的另一个问题。许多站点在内部有多个 Web 服务器,并使用它们来负载均衡流量。到目前为止,我列出的实用程序都不支持这种情况。
IP 分片曾经是伪装连接的一个问题。由于后续分片不包含传输(TCP 或 UDP)标头信息,因此无法将数据报与现有连接相关联。配置菜单中的“始终进行碎片整理”选项如下所示
IP: always defragment (CONFIG_IP_ALWAYS_DEFRAG) [N/y/?] (NEW) y
此选项将导致分片数据报在伪装主机而不是目标主机处重新组装。
尽管如此,在数据传输“中间”执行重组的概念与 IP 交付的一般原则背道而驰。还存在其他方法可以帮助消除分片。其中两种是 MSS 协商和路径 MTU 发现。
MSS(最大段大小)协商是 IP 伪装可以改进的一个领域。我所说的最好通过一个例子来说明。
从图 1 中,让我们看一下从名为 falcon 的机器到外部机器的连接打开期间生成的 TCP 流量。列表 3 和 4 显示了流量。
列表 3. 从 falcon 到 deathstar (192.168.1.0) 的 TCP 三次握手流量。
我们可以看到,从伪装连接通告的 MSS (1326) 与从原始主机 falcon 发送的 MSS 完全相同。这里的关键是我如何设置从 deathstar 到 PPP 服务器的 PPP 连接。我知道如果不正确处理连接,就会发生分片,所以我将 MTU 设置为 296。一种利用 MSS 来消除分片的方法是让伪装主机 deathstar 根据其对下一跳连接的了解来重新调整 MSS。MSS 为 256(即 296-40)更合适。
您可能还会注意到图 4 中流量中的 (DF) 字段。这是 IP 标头中的“禁止分片”位。它指示如果数据报在其到达目标的途中必须分片,则该数据报将被丢弃,并且将 ICMP 错误消息发送回源。路径 MTU 发现通常负责设置 DF 位。这样做是为了查找那些 ICMP 错误消息,如果找到,它将调整放入 TCP 段中的数据量并重新发送。主机将继续执行此操作,直到找到一个段大小,使得源和目标之间所有数据链路的最大传输单元都可以容纳数据报而无需分片。
鉴于克服分片的多种方法,分片在伪装网络中不再是一个问题。
网络地址转换器 (NAT) 设备是一种执行地址隐藏的设备。NAT 的工作关系可以是 1:1、多:1 或 多:n;它还静态或动态地分配供外部使用的地址。
用户或公司可能拥有整个 C 类地址空间,而不是拥有单个 ISP 分配的 IP 地址。但是,内部网络可能仍然很大。使用 NAT,可以为不同的功能分配地址。例如,假设 199.1.1.0 是我们拥有的地址。此外,假设我们使用 172.16.0.0 到 172.31.255.255 作为我们的内部网络。我们可以分配以下内容
199.1.1.1-10:在 NAT 设备外部分配的永久地址
199.1.1.11-25:静态分配给相应的内部地址 172.16.1.11-25
199.1.1.26-254:动态分配给剩余的内部地址
IP 伪装是 NAT 的多对一静态分配案例
Linux 2.1.x 内核现在支持 NAT,作为路由表中的标记条目。据传,功能齐全的实现将在 2.1.x 开发期间的某个时候实现。对于 IP 伪装已经支持的许多异常协议,NAT 将不得不经历相同的成长阵痛。但是,它应该会带来更丰富、更灵活的地址隐藏环境。
Chris Kostick 是 Computer Sciences Corporation 网络安全部门的高级计算机科学家。他喜欢使用 Linux,从内核版本 1.1.18 开始。就计算机而言,他不确定自己是调试 TCP/IP 问题更有趣,还是射击 DOS 机器更有趣。可以通过 ckostick@csc.com 或大声喊“Chris”来联系他。