Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
级别: 中级

 

蒋 莹滢 (jiangyy@cn.ibm.com), 软件工程师, IBM
殷 一鸣 (yinym@cn.ibm.com), 软件工程师, IBM

2009 年 1 月 31 日

随着互联网技术的不断发展,传统的 IPv4 地址已不能满足用户的需要。新一代的 IPv6 协议也日益被广泛的接受和使用,越来越多的软件系统都要求支持 IPv6 网络协议。然而现有网络环境对 IPv6 的支持仍然非常有限,这给软件的开发和测试都带来了一定的困难。本文将介绍如何使用 Apache 在现有的 IPv4 网络中构建模拟的 IPv6 环境。

在 Linux 平台及 IPv4 环境中构建 IPv6 测试环境







1 IPv6简介

IPv6(Internet Protocol Version 6)作为 IPv4 的升级版本,它是作为一共软件升级安装在设备和
操作系统中。为什么需要使用 IPv6,一个最直接的答案就是目前广泛应用的 IPv4 已经无法提供足够的 IP 地址来满足迅速增长的网络。IPv4 采用32位地址长度,只有大约43亿个地址,很快就将被分配完毕。而 IPv6 采用128位的地址长度,几乎可以不受限制的提供地址。当然扩大地址空间只是 IPv6 的众多优势中的重要一项,除此之外,IPv6 还能够提高网络的整体吞吐量、改善服务质量(QoS)、安全性有更好的保证、支持即插即用和移动性、更好实现多播功能等等。

从1992年 IPNG 工作组成立,经历了十几年的发展,虽然 IPv6 离达到与 IPv4 相同的水平仍有距离,但已经有越来越多的支持 IPv6 的设备投入使用,越来越多的软件系统开始支持 IPv6。现在 IPv6 已经可以提供 DNS,Web,Email,Ftp,Telnet 等基本服务。Windows,Sun,Apple 等操作系统也都已经或即将支持 IPv6 协议。IBM 也一直致力于 IPv6 的发展,早在1997年 IBM 就发布了支持 IPv6 的 AIX。如今 DB2,Lotus,Rational,Tivoli 和 WebSphere 也都在逐步支持 IPv6 的应用。







2 在 IPv4 环境中模拟 IPv6 网络

正如上节中所述,目前许多与网络应用相关的软件已经加入了对 IPv6 的支持,更有大量的软件正在处于对 IPv6 支持的开发阶段。但是就开发而言,目前许多开发环境并没有对 IPv6 提供很好的支持,尤其当所开发的应用需要经过较老的路由甚至公共网络时。如果希望通过升级网络设备来支持开发环境,将是一笔不小的花费,有时甚至是不现实的(比如短期内升级公共网络支持 IPv6)。

研究如何在现有的 IPv4 网络环境中模拟出 IPv6 环境,使得开发和测试工作能够顺利进行,显得尤为重要。下面介绍一种在 Linux 平台上通过 Apache 服务器来模拟 IPv6 的 HTTP/HTTPS 网络开发测试环境。

2.1 IPv6 网络要求及现有的网络环境

图1显示了典型的 HTTP 网络应用,如果需要对这样的网络应用提供 IPv6 的支持,开发和测试人员可能会碰到如下三种情形:

客户端和服务器运行于同一个局域网中,如图1-a

客户端和服务器运行于同一个 Intranet 中,它们之间的网络通路需要经过路由,如图1-b

客户端和服务器分别处于不同的地域,它们之间由 Internet 提供连接,如图1-c。


图 1. 三种典型的 HTTP 网络应用
三种典型的 HTTP 网络应用

在这三种不同的情形下,IPv6 的网络环境要求是不同的。对于情形1,只需客户端和服务器所运行的操作系统支持 IPv6 即可通过 IPv6 协议进行通信,若需要提供 Global 地址的通信,则可以通过在局域网内的某台机器上运行一个软件 IPv6 路由来支持,因此其针对 IPv6 的开发和测试相对简单。 对于情形2,由于客户端和服务器之间经过运行于 IP 层的路由,因此要求网络通路上经过的所有路由器均支持 IPv6。 这可能是一个不小的挑战,因为很多 Intranet 环境并没有提供支持 IPv6 的路由。对于情形3,这就要求 Internet 提供 IPv6的支持,就短期看来,Internet 提供全面的 IPv6 支持还不太可能。

因此,在情形2和情形3的环境中,网络硬件支持将成为开发和测试支持 IPv6 的网络应用程序的最大障碍,在2.2节中将给出如何运用现有的 IPv4 网络来进行 IPv6 应用程序的开发和测试,同时又保证其在真实的 IPv6 环境中正常运行。

2.2 利用现有 IPv4 网络模拟 IPv6 环境

2.2.1 模拟环境构建的基本原理

图2 - 图3显示了 IPv6 模拟环境的框图,这里存在两种情形,但具体的配置是类似的。
对于开发客户端 IPv6 应用程序,其框图如图2;而对于开发服务器端 IPv6 应用程序,其框图如图3。其基本原理就是利用代理技术将原来被 IPv4 网络阻断的客户端或服务器端映射到位于同一局域网内的代理服务器上,这样“客户端”与“服务器端”就可以进行基于 IPv6 的网络通信了。 在图2中,我们需要代理服务器与客户端运行于同一局域网中,在客户端看来,此代理服务器是一个具备了 IPv6 支持能力的“服务器”,即使真正的服务器端并没有支持 IPv6 ,也可以进行客户端的开发和测试。在图3中,我们需要一台机器与服务器端运行于同一局域网中,在服务器端看来,此代理服务器是一个具备了 IPv6 支持能力的“客户端”。


图 2. 利用代理将服务器端映射到与客户端同一局域网内
利用代理将服务器端映射到与客户端同一局域网内

图 3. 利用代理将客户端映射到与服务器端同一局域网内
利用代理将客户端映射到与服务器端同一局域网内

下面仅以客户端的IPv6环境为例来讲述整个模拟环境的构建过程。

2.2.2 环境的建立

操作系统平台: Linux,内核需支持 IPv6,2.6以上版本最佳,

推荐使用 RedHat Enterprise Linux 5或SuSE Linux Enterprise Server 10

软件: radvd(Router ADVertisement Daemon),
这是一个运行于 Linux 平台之上的提供 IPv6 路由配置信息的软件,可以替代 IPv6 路由来进行无状态的地址自动配置。

Apache,这是目前应用最为广泛的 Web 服务器,要求版本2.0以上

openssl,运行于 Linux 平台上的提供实现 SSL v2/v3 协议的加解密工具包

2.2.3 启动 radvd

IPv6 的地址获取方式与 IPv4 有所不同。在 IPv4 中,主机 IP 地址的自动配置必须由 DHCP 服务器来支持,这被称为有状态的自动配置(StatefulAutoconfiguration);而在 IPv6 中,除了 DHCP 的 v6版本,还引入了无状态的自动配置( StatelessAutoconfiguration )。这项新技术无需 DHCP 服务器支持,所有支持 IPv6 的路由器都监听各主机发送的自动配置请求包, IPv6 路由器对这类请求包的回复里面包含了一些 IPv6 地址的前缀( prefix )信息,主机在收到这样的包以后,可以根据自己的一些已有信息(比如 MAC 地址),生成自己的 IPv6 地址。

本文是在现有的 IPv4 网络环境中模拟 IPv6 环境,自然不存在物理的 IPv6 路由器,但是通过 Linux 平台上的 radvd 工具也可以模拟无状态自动配置,它同样可以监听局域网内各 IPv6 主机发送的自动配置请求并作出响应,这样,这些主机就可以获得各自的 IPv6 地址,并利用这些地址进行相互间的通信。而图X中的客户端正是使用这种方式与代理服务器通信的。

这里以 SLES10 平台上的 radvd-0.9-13.2 为例来说明 radvd 的配置和启动过程。

  1. 从 SLES10 的安装光盘中找到 radvd-0.9-13.2.i586.rpm 进行安装
           # rpm -ivh radvd-0.9-13.2.i586.rpm
            

  1. 配置运行 radvd 的主机的 IPv6 地址信息

    # ip a a 2002:9ba:b4e:6::1/64 dev ethX

    # ip r a 2002:9ba:b4e:6::/64 dev ethX

这里的 ethX 表示的是此主机监听局域网数据包的网卡设备

  1. radvd 安装后其配置文件位于 /etc/radvd.conf ,在这个文件中加入配置信息
interface ethX
            {
            AdvSendAdvert on;
            MinRtrAdvInterval 5;
            MaxRtrAdvInterval 10;
            AdvDefaultPreference low;
            prefix 2002:9ba:b4e:6::/64
            {
            AdvOnLink on;
            AdvAutonomous on;
            AdvRouterAddr off;
            };
            };
            

同上,这里的 ethX 表示的是此主机监听局域网数据包的网卡设备。prefix 段表明了该局

域网配置 IPv6 地址的前缀。

  1. 确保系统启动了对 IPv6 数据包的转发功能

    # sysctl -w net.ipv6.conf.all.forwarding=1

  1. 启动 radvd

    # /etc/init.d/radvd start

在 radvd 启动成功后,通过 ps 命令可以看到系统中有一个 radvd 的 daemon 进程处于运行状态。若对局域网中的其他主机运行 ifconfig 命令可以看到这些主机已经自动配置了 IPv6 地址,其前缀( prefix )与 radvd 配置文件中的值一致。

2.2.4 配置 Apache 服务器

Apache 服务器是整个模拟 IPv6 环境的核心部分,它将监听来自 IPv6 网络连接的数据包,并将其通过 IPv4 网络转发到服务器端。这里使用了 Apache 服务器的 mod_proxy 模块,相信这一模块提供的 Forward Proxy 功能已为大家所熟知,并被广泛采用。这一模块同时还提供了 Reverse Proxy 功能,本文就采用了此技术来实现转发功能。运行 Reverse Proxy 的 Apache 服务器对于客户端而言就是一台实际的 Web 服务器,客户端将从该服务器获取和上传所有的数据,具体的配置方法如下文所述。

大多数的 Linux 平台已经安装了 Apache 服务器,对于已经安装了 Apache 服务器的平台,必须保证其支持 IPv6,并且加载了 mod_proxy和mod_ssl 模块。当然也可以从 Apache 的源代码开始编译一个新的 Apache 服务器。

首先需要确定 Apache 服务器监听 IPv6 地址,一般而言,在 httpd.conf 中有如下一条:

    Listen 80
            

这表明该 Apache 服务器监听所有的主机地址,自然也包括 IPv6 的地址。若原 Apache 服务器配置了监听一些特定的地址,确保这些地址中包含代理服务器与客户端通信使用的 IPv6 地址。

对于代理服务器的配置,这里需要使用 Apache 服务器的 mod_proxy 模块中的 ProxyPass 指示字,在 Apache 配置文件中加入如下的配置语句。

NameVirtualHost *:80
            <VirtualHost *:80>
            ServerAdmin webmaster@dummy-host.example.com
            ServerName ipv6-server-proxy
            ProxyRequests off
            <Proxy *>
            Order deny,allow
            Allow from all
            </Proxy>
            ProxyPass /request http://www.server.com/request
            ErrorLog "logs/proxypass-error_log"
            CustomLog "logs/proxypass-access_log" common
            </VirtualHost>
            

这里的 ProxyPass 指示语的含义是所有对此 Apache 服务器的 /request 目录的访问都将转发到 http://www.server.com/request。若此 Apache 服务器的 IPv6 地址为2002:9ba:b4e:6::3,则客户端若访问

http://[2002:9ba:b4e:6::3]/request
            

实际获得的数据将来自于

http://www.server.com/request
            

这样,在客户端看来,与其通信的服务器是一个支持 IPv6 的服务器端,而实际上是 Apache 代理将远程的服务器端映射到了本地的 IPv6 网络。在这种环境下,客户端就可以来开发和测试自身对 IPv6 的支持了,而无需考虑服务器端对此协议的支持。

上述语句添加的位置由 Apache 的配置文件结构决定,目前许多版本的 Apache 采用多个配置文件,即由一个主的配置文件 httpd.conf 来包含其他子项配置文件,如 httpd-vhosts.conf,httpd-ssl.conf 文件等,而不是所有的配置信息全部写在 httpd.conf 文件中。这里推荐将上述配置语句写入 httpd-vhosts.conf 文件中,然后在主配置文件 httpd.conf 文件加入下面这条包含此文件。

Include httpd-vhosts.conf
            

这里默认 httpd-vhosts.conf 与 httpd.conf 在同一目录下,多数情况下要加入 httpd-vhosts.conf 的相对路径。

对于需要使用 HTTPS 连接的应用程序,其 Apache 服务器的配置有所不同,参见下一节2.2.5中的具体介绍。

在配置好以后,即可启动/重启 Apache 服务器来使得刚才的配置生效。

# /etc/init.d/httpd restart
            

2.2.5 利用 openssl 生成 HTTPS 连接所需的认证信息

由于运行 Reverse Proxy 的 Apache 服务器在客户端看来是一台实际的 Web 服务器,因此在进行 HTTPS 连接时,客户端需要验证其 SSL 签名的有效性。这样,我们需要在上述配置好的 Apache 服务器中加入 SSL 认证信息,才能保证客户端的 HTTPS 应用程序能够正常运行。

自签名(self-signed)的 SSL 认证文件的生成

首先是生成根证书文件 ca.crt

# openssl genrsa -des3 -out ca.key 4096
            # openssl req -new -x509 -days 365 -key ca.key -out ca.crt
            

第一步是生成一个根证书的 key 文件,系统会要求输入 pass phase, 记下输入的密码,这一密码会在后面多次用到。而第二步则将使用这个 key 文件来生成根证书,这一步执行时系统会要求输入许多根证书的信息,值得注意的是 Common Name(CN),这一步中输入的 CN 值应与下一步生成服务器证书时输入的不同。

接着需要生成服务器证书签名请求(Certificate Signing Request)文件 server.csr,步骤与生成根证书文件类似。

# openssl genrsa -des3 -out server.key 4096
            # openssl req -new -key server.key -out server.csr
            

同样,在第二步中会要求输入一系列的服务器信息,这里的 Common Name(CN) 应与客户端访问该服务器时使用的地址相同,例如:

客户端使用 http://proxyhost.com/ 访问该服务器时,这里的 CN 应为 proxyhost.com

客户端使用 http://[2002:9ba:b4e:6::3]/ 访问该服务器时,这里的 CN 应为 [2002:9ba:b4e:6::3]

为何需要相同,是因为客户端的 HTTPS 连接程序会验证该服务器提供的证书有效性,若证书中的 CN 与实际客户端访问的主机名不同,客户端会抛出 INVALID_CN 错误。

最后,利用前面生成的根证书文件 ca.crt 来签署(Sign)服务器证书签名请求 server.csr。

# openssl x509 -req -days 365 -in server.csr -CA ca.crt \
            -CAkey ca.key -set_serial 01 -out server.crt
            

将上述生成的四个证书相关文件(ca.crt,ca.key,server.crt,server.key)拷入 Apache 的配置文件夹中,接下来将会把这些文件的路径和一些配置信息加入到 Apache 配置文件中。

Listen 443
            AddType application/x-x509-ca-cert .crt
            AddType application/x-pkcs7-crl    .crl
            SSLPassPhraseDialog  builtin
            SSLSessionCache "shmcb:/usr/local/apache2/logs/ssl_scache(512000)"
            SSLSessionCacheTimeout  300
            SSLMutex  "file:logs/ssl_mutex"
            NameVirtualHost *:443
            <VirtualHost *:443>
            DocumentRoot "apache2/htdocs"
            ServerName ipv6-server-proxy
            ServerAdmin you@example.com
            ErrorLog "ssl-error_log"
            TransferLog "ssl-access_log"
            SSLEngine on
            SSLProtocol -all +TLSv1 +SSLv3
            SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM
            SSLCertificateFile "server.crt"
            SSLCertificateKeyFile "server.key"
            <Directory "/usr/local/apache2/cgi-bin">
            SSLOptions +StdEnvVars
            </Directory>
            BrowserMatch ".*MSIE.*" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
            CustomLog "logs/ssl_request_log" \
            "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
            SSLProxyEngine on
            ProxyRequests off
            <Proxy *>
            Order deny,allow
            Allow from all
            </Proxy>
            ProxyPass /request http://www.server.com/request
            </VirtualHost>
            

这里再次使用了 ProxyPass 来建立代理服务。

正如上一节2.2.4中所述,这里建议将这些配置信息写入 httpd-ssl.conf 中,然后在 httpd.conf 中加入如下一行将其包含。

Include httpd-ssl.conf
            

配置完成后,即可启动/重启 Apache 服务器来使得刚才的配置生效。

# /etc/init.d/httpd restart
            

客户端 HTTPS 连接的考虑

由于这里采用的是自签名(Self-signed)的方式来生成服务器的认证文件,客户端使用 HTTPS 连接到该代理服务器时,会出现认证错误的提示。这就需要将这里生成的证书加入到客户端的可信站点列表中。具体的添加方式因采用的系统不同而各异。就 Windows 平台的 IE 而言,可以将上述生成的 ca.crt 及 server.crt 文件加入到 IE 的可信站点中,这会影响到所有利用 IE 提供的 wininet 库进行 HTTP 应用开发的程序。

2.2.6 DNS 考虑

在网络应用中,客户端一般使用域名来访问服务器端。在测试 IPv6 的环境中,必须使用 IPv6 的地址来访问,这就需要一个支持 IPv6 的 DNS 域名服务器,对于一定的域名返回其 IPv6 的地址。目前可以使用在 Linux 平台的 BIND 9 来搭建这样的 DNS 服务器。但是其配置相对比较复杂,还可以使用一种相对简便的方法。即利用 Linux 和 Windows 平台均支持的 hosts 文件来配对域名与其相应的 IPv6 地址。这需要在客户端的相应 hosts 文件中加入一些 IPv6 地址的配置信息。

在 Linux 平台上,hosts 文件一般位于 /etc/hosts,在此文件中加入如下一行:

           2002:9ba:b4e:6::3    www.someipv6site.com
            

这样就指定了 www.someipv6site.com 的 IPv6 地址为 2002:9ba:b4e:6::3。而在 Windows 平台上 hosts 文件位于 %WINDIR%\System32\drivers\etc\hosts,其格式与 Linux 平台上相同。

2.3 IPv6 和 IPv4 混合环境兼容性测试

从 IPv4 到 IPv6 的过渡是一个漫长而复杂的过程,不可能在短期内实现完全转换,所以在产品的开发及测试过程中除了考虑 IPv6 网络内的通讯还需要充分考虑现实网络环境中很可能出现的 IPv6 网络和 IPv4 网络的混合环境,这就需要测试应用程序在此环境下的兼容性。 本节将介绍一些需要模拟的情况。

模拟以下3种网络情况首先都需要在现有的 IPv4 局域网环境中选择一台机器作为路由服务器,并按照2.2.3节的描述进行相关配置。这样与该路由连接于同一个 Switch 上的计算机都将会被自动分配一个 IPv6 的地址。如果仍然没有获得 IPv6 的地址,请关闭计算机和路由服务器上的防火墙。然后按照 2.2.4 节中的描述选择一台计算机设置为 ProxyPass。

2.3.1客户端和服务器端均运行于 IPv6 的网络环境

这种情况的验证相对比较简单,只需要在客户端将服务器的地址设为前面配置的 ProxyPass 的 IPv6 的地址便能实现客户端和服务器端 IPv6 到 IPv6 的交互。这就是2.2节介绍的情况。

图 4. 客户端和服务器端均运行于 IPv6 的网络环境


图 4. 客户端和服务器端均运行于 IPv6 的网络环境
客户端和服务器端均运行于 IPv6 的网络环境

2.3.2 客户端运行于 IPv6 网络,服务端运行于 IPv4 网络

对于客户端和服务器端分别处于 IPv6 和 IPv4 环境的情况,需要在局域网环境中增加代理 (proxy) 作为两者之间的桥梁,该代理与上述路由服务器位于同一个网络之中,因而也拥有 IPv6 的地址和 IPv4 的地址。客户端所设置的目的服务器端地址为 IPv4 的地址,设置的代理地址为该代理的 IPv6 的地址,这样客户通过 IPv6 协议与代理直接进行通讯,而代理接受到客户端所设置的 IPv4 格式的服务器地址后则通过 IPv4 协议与服务端交互,这样便模拟实现了客户端位于 IPv6 网络而服务器端位于 IPv4 网络的情况。

图5客户端运行于 IPv6 网络,服务端运行于 IPv4 网络


图 5. 客户端运行于 IPv6 网络,服务端运行于 IPv4 网络
客户端运行于 IPv6 网络,服务端运行于 IPv4 网络

2.3.3 客户端运行于 IPv4 网络,服务端运行于 IPv6 网络

模拟位于 IPv4 网络中的客户端与位于 IPv6 网络中的服务器端进行交互需要使用 Proxy 和 ProxyPass 来进行环境搭建。客户端将 ProxyPass 所在的 IPv6 的地址设置为服务器端的地址,将 Proxy 所在的 IPv4 的地址设置为代理的地址,这样客户端与代理之间通过 IPv4 协议进行通讯。代理在获取到客户端所配置的 IPv6 协议的 ProxyPass 地址后将通过 IPv6 协议与 ProxyPass 进行交互。ProxyPass 收到客户端发送的请求后将通过 IPv4 的协议发送给真正的位于 IPv4 网络中的服务器进行处理。这样在客户端就模拟实现了 IPv4 网络到 IPv6 网络的通讯。

图6客户端运行于 IPv4 网络,服务端运行于 IPv6 网络

Server


图 6. 利用代理将客户端映射到与服务器端同一局域网内
利用代理将客户端映射到与服务器端同一局域网内






3 总结

在本文中,我们通过使用现有的 IPv4 网络配合 Linux 平台上的 Apache 服务器,达到了模拟 IPv6 的 HTTP/HTTPS 网络环境的目的,从而可以在有限的硬件资源之下开发和测试网络应用软件对 IPv6 的支持。这项技术还可以应用到其他的网络协议之上,只需使用具备类似于 Apache 服务器转发技术的代理服务器。因此这项技术具有一定的通用性


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理