许多不熟悉IPv6的IT人士认为,部署IPv6的责任落在网络团队身上。然而,那些了解IPv6的人意识到,迁移到IPv6将涉及任何使用IP地址的系统。当网络团队准备增加IPv6的基础设施时,我们应该提醒我们的应用程序开发人员,确保他们准备好迎接即将到来的挑战。本文包含了应用程序开发人员在多协议环境中使应用程序正常运行时需要了解的一些关键问题。
即使网络工程师高度重视网络,我们也需要保持正确的态度。我们网络工程师意识到网络的作用是支持运行应用程序的计算机之间的端到端通信。应用程序、操作系统和计算机与网络的接口方式往往属于系统管理员和应用程序开发人员的范围。当我们变得熟悉IPv6,我们应该与我们组织中的其他人分享我们的知识。这意味着几乎IT组织中的每个人都将参与IPv6的部署。我们应该与我们的应用程序开发人员分享以下概念,以便他们意识到创建应用程序的细微差别,将在当前的IPv4网络上运行,并在不久的将来作为IPv6添加。
1.评估IPv6能力的当前代码
当应用程序开发人员为Y2K做准备时,他们仔细查看了他们的代码,因为这一年只有2个字符/数字。在那时,Y2K编程代码评估工具查看代码行,寻找包含2位数或4位数年份的数据结构。随着IPv6的加入,我们需要查看我们的TCP/IP应用程序代码,以便在任何地方输入、存储、访问或使用IP地址。如果我们使用的数据结构只分配32位,那么代码将需要修改以容纳128位的地址。
我们可以逐个文件、逐个模块地查看应用程序代码,寻找这样的数据结构,或者我们可以使用自动化的软件应用程序。幸运的是,有几个工具可以自动评估IPv4/v6调用的应用程序源代码。对于在微软平台上编写的主机,我们可以使用Checkv4.exe以确定源代码是否为ipv6就绪。有一个SourceForge工具叫做PortToIPv6.还有另外两个程序可以帮助你的IPv6代码评估,这两个程序都与C, Java, Perl和Python一起工作。EUChinaGrid项目创建了一个IPv6代码检查器和EGEE(为电子科学启用网格)小组已经创建了他们的IPv6-care实用程序。另一种选择是使用grep或其他解析工具来查看源代码。
2.创建独立于地址族且向后兼容IPv4的代码
当我们部署IPv6时,应用程序必须保持与IPv4向后兼容。创建两个版本的应用程序是不可行的。例如,创建一个适用于IPv4的应用程序版本和一个适用于IPv6的应用程序版本(例如program4.exe和program6.exe)是不明智的。此外,终端用户不需要知道使用哪个IP版本,然后选择正确的应用程序。但是,高级用户可能希望控制如何建立连接。因此,申请应该是家庭地址(AF)独立.这意味着无论使用哪个地址族(IPv4或IPv6),相同的应用程序将在所有情况下工作。
3.在使用这些连接方法的仅ipv4、双协议和仅ipv6操作系统上使用相同的应用程序
同样,独立于af的应用程序应该在任何类型的操作系统上运行,该系统运行在一台可以连接到仅使用ipv4、双协议或ipv6连接的网络的计算机上。单个程序应该处理任一协议的DNS查询,并且能够使用任一协议版本进行通信。应用程序应该能够执行正确的DNS查询,接收A或AAAA响应,并基于这两种协议创建连接。如果IPv6连接不可能,那么应用程序应该自动回退到IPv4。
4.支持128位IPv6地址存储,兼容32位IPv4地址
32位的IPv4地址字符串采用点分十进制格式,支持16个字符(4段3个十进制数字+ 3个句号+ 1个空字符)。128位的IPv6地址字符串由4个十六进制字符组成,以“:”隔开,共8段(最多46个字符)。应用程序必须使用可以接受IPv4地址、IPv6地址、主机名和完全限定主机名的数据输入字段。必须检查边界以验证输入,地址必须存储在适当大小的适当数据结构中。就像在登机的时候,经常有人试图把10磅的东西塞进一个5磅的行李架里。你也不应该尝试将128位的IPv6地址压缩到32位的内存空间中。
5.使用IPv6或IPv4传输的IPv6和IPv4 DNS查询
正如前面提到的,应用程序应该正确地处理DNS查询,因为对于128位IPv6地址,我们将需要更多地依赖DNS来保持IP地址的准确性。IETFRFC 4074常见的错误行为针对IPv6地址的DNS查询提供了如何正确做到这一点的指导。“在查询AAAA资源记录时,DNS权威服务器存在一些已知的不当行为。这种行为可能会阻塞本应可用的IPv4通信,导致名称解析的严重延迟,甚至导致拒绝服务攻击。”这意味着支持ipv6的节点应该先执行AAAA查询,然后执行A查询。此外,如果不存在AAAA,权威名称服务器应该返回RCODE=0,然后返回A记录响应。
应用程序可以对具有IPv4或IPv6网络连接的DNS服务器执行DNS查询。必要时,应用程序还应该正确地执行DNS正向和反向查找。的许多根域名服务器IPv6地址。去年的“我”根域名服务器收到AAAA记录,因此您的DNS服务器应该使用最新更新的named.root文件。必要时,应用程序还应该正确地执行DNS正向和反向查找。
6.处理FQDN主机名或IPv4/IPv6地址输入,输出格式正确
此外,IPv4和IPv6地址可以直接在URL中使用。我们都知道我们应该利用DNS和使用FQDNs,但有时我们就是忍不住。在URL中,IPv6地址可以用括号括起来,如:http://[2001:DB8:1001::BEEF]:8080/index.html。这对用户来说可能很麻烦,而且这种技术主要用于必要时的诊断目的。无论如何,应用程序应该遵循更新RFC 3986统一资源标识符:通用语法。当将存储在内存中的IP地址转换为字符串输出时,应用程序也应该正确地处理IPv4和IPv6。如果您的代码是使用inet_aton()、inet_addr()或inet_ntoa()函数编写的,那么您将遇到问题。您的代码应该尽可能使用inet_pton()和inet_ntop(),以使您的代码在所有情况下都能工作,并具有正确的输出格式。
7.使用IPv6和IPv4建立Socket连接
使用具有双协议能力的计算机和操作系统的应用程序,并且在一个具有两个IP版本地址的网络上,应该尽可能选择IPv6。应用程序应该首先尝试使用IPv6进行连接,如果不存在IPv6连接,则返回到IPv4。IETFRFC 4038IPv6过渡的应用方面提供了创建双协议应用的指导。这个RFC告诉我们实际上只有4种情况需要考虑。
案例1:双栈节点下仅ipv4应用。在节点中引入了IPv6协议,但应用程序还没有被移植到支持IPv6。
情况2:双栈节点下仅ipv4和ipv6应用。应用程序只支持ipv6。因此有两个类似的应用程序,每个协议版本对应一个(例如ping和ping6)。
案例3:双栈节点中同时支持IPv4和IPv6的应用。应用程序同时支持IPv4和IPv6。因此,可以删除现有的IPv4应用程序。
案例4:在IPv4-only节点中同时支持IPv4和IPv6的应用。应用程序被移植为IPv4和IPv6的支持,但同样的应用程序也可能不得不工作时IPv6不被使用(例如,从操作系统禁用)。从长远来看,前两种情况并不有趣;只有少数应用程序天生是IPv4或ipv6专用的,应该与这两种协议一起工作,而不必关心使用的是哪一种协议。因此,重点应该放在创建双协议应用程序上,这些应用程序既可以运行在使用协议的网络上,也可以运行在目前普遍存在的只使用ipv4的网络上。
8.利用ipv6支持的高级API: BSD Socket API, Perl Socket6, IO::Socket::INET6, Python Socket模块,Java Socket
IETF已经创建了几个rfc,为c语言IPv6套接字编程提供指导。
RFC 3493—IPv6的基本套接字接口扩展RFC 3542—IPv6的高级套接字应用程序接口(API)RFC 4038—IPv6过渡的应用方面RFC 5014—源地址选择的IPv6套接字API
Perl是一个典型的例子来说明如何做到这一点错误的方式.在Perl CORE中不支持IPv6。你可以使用Socket6和IO::Socket::INET6或者Socket和IO::Socket::INET。没有一个API可以用于仅ipv4、双协议和仅ipv6,由于这个事实,创建独立于af的代码并不容易。因此,您必须重写代码以获得ipv6支持。您可以使用以下命令轻松地检查您的Perl版本是否支持IPv6。
$ perl -MIO::Socket::INET6 -e1 . exe
如果您正在编写Java代码,那么您已经幸运地支持ipv6很多年了。J2SDK/JRE 1.4中增加了对IPv6的支持。Java支持地址类型Inet4Address和Inet6Address以及地址族独立的套接字。然而,有一些事情你需要知道。对于Java,默认情况下首选IPv6堆栈,但Java更喜欢DNS返回的IPv4地址。以下两个设置控制Java如何使用IP版本。
默认情况下,java.net.preferIPv6Addresses= < true|false > # false因此,您将希望将这些行添加到您的java选项。-Djava.net.preferIPv4Stack = false -Djava.net.preferIPv6Addresses = true
如果您正在使用Python,那么您很幸运。Python版本2.3和2.6对IPv6有很好的支持。Python 2.7.1的最新版本修复了一些bug,可能会让您的工作变得更轻松。Python有许多独立于地址族的函数,比如:socket。AF_INET,插座。AF_INET6,插座。getaddrinfo,插座。getnameinfo,插座。Socket ([family[, type[, proto]]])和Socket。inet_pton socket.inet_ntop。有一种简单的方法可以检查你的Python版本是否具有IPv6功能。只需输入以下几行即可。
# python >>> import socket >>> sockethas_ipv6真实
9.与路径MTU发现(PMTUD)工作良好
关于IPv6网络需要记住的另一件事是IPv6路由器不会对IPv6数据包进行分片。所有IPv6网络接口的最小IPv6 Link MTU为1280字节。当路由器被要求提出一个包太大的链接MTU会将数据包并发送回源ICMPv6包太大消息(类型2)。因此,结束节点必须执行路径MTU发现(PMTUD)和源必须创建合适的大小的包。中定义了IP版本6的路径MTU发现RFC 1981.碎片扩展头将被添加到碎片包(next-header 44)(RFC 2460)。
今天的许多应用程序不能正确地执行PMTUD,这将需要随着IPv6的引入而改变。隧道在IPv6中是普遍存在的,所以PMTUD比IPv4更需要。防火墙也不应该过滤PMTUD消息(供参考,ICMPv6使用IPv6扩展头#58 (RFC 2463))。
10.对应用程序进行广泛的测试
应用软件的测试永远不会过分。在创建了独立于地址族的应用程序之后,应该使用各种操作系统对其进行测试。这些计算机应该只使用ipv4、双协议和ipv6进行网络连接。您还应该在IPv4和IPv6的TCP和UDP端口53上使用A和AAAA记录测试DNS,并执行反向查找。你应该测试,测试,测试,然后再做更多的测试。相信我,这将带来更少的支持电话和一个您可以依赖的应用程序。
其他资源和参考资料