随着IPv4地址池耗尽即将来临,企业和蜂窝提供商越来越多地部署IPv6 DNS64和NAT64网络。DNS64 / NAT64网络是一个仅IPv6网络,通过翻译继续提供对IPv4内容的访问。根据应用程序的性质,转换具有不同的含义:
如果您正在使用高级网络API(如NSURLSession
CFNetwork框架)编写客户端应用程序,并按名称进行连接,则不需要为应用程序更改任何内容以使用IPv6地址。如果你不是通过名字连接,你可能应该是。请参阅在连接主机之前避免解析DNS名称以了解如何操作。有关CFNetwork的信息,请参阅“ CFNetwork框架参考”。
如果您正在编写服务器端应用程序或其他低级网络应用程序,则需要确保您的套接字代码在IPv4地址和IPv6地址之间正常工作。参见RFC4038:IPv6过渡的应用方面。
主要的网络服务提供商,包括美国的主要蜂窝运营商正在积极推广和部署IPv6。这是由于各种因素。
注意: 世界IPv6发布是一个在全球范围内跟踪部署活动的组织。要查看最近的趋势,请访问世界IPv6发布网站。
数十年来,世界已经知道IPv4地址最终将耗尽。诸如无类别域间路由(CIDR)和网络地址转换(NAT)等技术有助于延迟不可避免。然而,2011年1月31日,互联网号码分配机构(IANA)IPv4地址的顶级池正式耗尽。美国互联网号码注册机构(ARIN)预计在2015年夏季将会用尽IPv4地址 - 这里提供倒计时。
除了解决IPv4耗尽问题外,IPv6比IPv4更有效率。例如,IPv6:
避免需要网络地址转换(NAT)
通过使用简化的标头提供更快的通过网络的路由
防止网络破碎
避免广播用于邻居地址解析
第四代移动通信技术(4G)仅基于分组交换。由于IPv4地址的供应有限,需要IPv6支持,以便4G部署可扩展。
IP多媒体核心网络子系统(IMS)允许多媒体短信和LTE语音(VoLTE)等服务通过IP传送。一些服务提供商使用的IMS仅与IPv6兼容。
服务提供商通过继续支持传统IPv4网络,同时业界继续迁移到IPv6,从而带来额外的运营和管理成本。
为了减缓IPv4地址的耗尽,在许多IPv4网络中实现了NAT。虽然这个解决方案暂时工作,但它证明是昂贵和脆弱的。今天,随着更多的客户端正在使用IPv6,供应商现在必须支持IPv4和IPv6。这是一项昂贵的工作。
提供单独的IPv4和IPv6连接的蜂窝网络理想情况下,提供商希望放弃对IPv4网络的支持。但是,这样做可以防止客户端访问代表互联网重要部分的IPv4服务器。为了解决这个问题,大多数主要的网络提供商正在实施一个DNS64 / NAT64过渡工作流程。这是一个仅IPv6网络,通过翻译继续提供对IPv4内容的访问。
使用DNS64和NAT64部署IPv6网络的蜂窝网络在这种类型的工作流程中,客户端向DNS64服务器发送DNS查询,DNS64服务器从DNS服务器请求IPv6地址。当找到一个IPv6地址时,它立即被传回给客户端。但是,当未找到IPv6地址时,DNS64服务器会请求IPv4地址。然后,DNS64服务器通过在IPv4地址前缀来合成IPv6地址,并将其传递给客户端。在这方面,客户端始终接收到IPv6就绪地址。参见图10-3。
DNS64 IPv4到IPv6的转换过程当客户端向服务器发送请求时,将通过NAT64网关自动路由目的地为合成地址的任何IPv6数据包。网关对请求执行IPv6到IPv4地址和协议转换。它还对服务器的响应执行IPv4到IPv6的转换。参见图10-4。
DNS64 / NAT64过渡解决方案的工作流程与IPv6 DNS64 / NAT64网络的兼容性将成为App Store提交的要求,因此应用程序必须确保兼容性。好消息是,大多数应用程序已经是IPv6兼容的。对于这些应用程序,定期测试应用程序以观察回归仍然很重要。不兼容IPv6的应用程序在DNS64 / NAT64网络上运行时可能会遇到问题。幸运的是,如本章所讨论的那样,解决这些问题通常很简单。
几种情况可能会阻止应用程序支持IPv6。以下部分介绍如何解决这些问题。
协议中嵌入的IP地址文字。许多通信协议,例如会话发起协议(SIP),文件传输协议(FTP),WebSockets和对等协议(P2PP),包括协议消息中的IP地址文字。例如,FTP
参数命令DATA PORT
和PASSIVE
交换包含IP地址文字的信息。类似地,IP地址文字可能出现在SIP报头字段,例如的值To
,From
,Contact
,Record-Route
,和Via
。请参阅使用高级网络框架和不使用IP地址面值。
嵌入在配置文件中的IP地址文字。配置文件通常包括IP地址文字。请参阅不要使用IP地址文字。
网络预检。许多应用程序尝试通过将IP地址文字传递到网络可达性API来主动检查Internet连接或活动的Wi-Fi连接。请参阅连接没有预检。
使用低级网络API。有些应用与插座等原始网络API,如直接工作gethostbyname
,gethostbyname2
和inet_aton
。这些API容易被滥用,或者它们仅支持IPv4,例如,解析AF_INET
地址族的主机名,而不是AF_UNSPEC
地址族。请参阅使用高级网络框架。
使用小地址家庭存储容器。一些应用程序和网络库使用地址存储容器-如uint32_t
,in_addr
,和sockaddr_in
-即是32位或更小。请参阅使用适当大小的存储容器。
遵守以下准则,以确保您的应用程序中的IPv6 DNS64 / NAT64兼容性。
需要联网的应用程序可以建立在高级网络框架或低级POSIX套接字API上。在大多数情况下,高级框架就足够了。它们具有能力,易于使用,并且不如低级API容易出现常见的陷阱。
网络框架和API层WebKit的。该框架提供了一组用于在Windows中显示Web内容的类,并且实现诸如以下链接之类的浏览器功能,管理后退列表以及管理最近访问的页面的历史。WebKit简化了加载网页的复杂过程,即从HTTP服务器异步请求Web内容,响应可以按照随机顺序递增执行,或部分由于网络错误。有关更多信息,请参阅WebKit框架参考。
可可URL加载系统。该系统是通过网络发送和接收数据而不提供显式IP地址的最简单方法。数据被发送并且使用几类-如之一接收NSURLSession
,NSURLRequest
以及NSURLConnection
与工作-即NSURL
物体。NSURL
对象让你的应用程序操纵URL和他们引用的资源。NSURL
通过调用该initWithString:
方法并传递一个URL说明符来创建一个对象。调用类的checkResourceIsReachableAndReturnError:
方法NSURL
来检查主机的可达性。有关更多信息,请参阅URL会话编程指南。
CFNetwork的。该核心服务框架提供了一个网络协议抽象库,可以轻松执行各种网络任务,例如使用BSD套接字,解析DNS主机以及使用HTTP / HTTPS。要定位没有显式IP地址的主机,请调用该CFHostCreateWithName
方法。要打开一对TCP套接字到主机,请调用该CFStreamCreatePairWithSocketToCFHost
方法。欲了解更多信息,请参见CFNetwork的概念在CFNetwork的编程指南。
如果您需要低级套接字API,请遵循RFC4038:IPv6过渡的应用方面的准则。
注意: 网络,互联网和Web和网络入门概述提供有关网络框架和API的详细信息。
确保你不及格的IPv4地址文字的点符号API,如getaddrinfo
和SCNetworkReachabilityCreateWithName
。相反,使用高级网络框架和地址不可知版本的API,例如getaddrinfo
和getnameinfo
,并传递他们的主机名或完全限定域名(FQDN)。看到getaddrinfo(3) Mac OS X Developer Tools Manual Page
和getnameinfo(3) Mac OS X Developer Tools Manual Page
。
注意: 在iOS 9和OS X 10.11及更高版本中,NSURLSession
并CFNetwork
在DNS64 / NAT64网络上运行的设备上本地从IPv4文字自动合成IPv6地址。但是,您仍然应该删除IP地址文字的代码。
可见性API(请参阅SCNetworkReachability参考)旨在用于诊断目的之后识别连接问题。许多应用程序不正确地使用这些API来主动检查Internet连接,SCNetworkReachabilityCreateWithAddress
方法是调用该方法并传递一个IPv4地址0.0.0.0
,这表示网络上有路由器。但是,路由器的存在并不能保证存在Internet连接。一般来说,避免提前检查网络的可达性。只是尝试建立一个连接,并优雅地处理故障。如果必须检查网络可用性,请避免调用该SCNetworkReachabilityCreateWithAddress
方法。调用该SCNetworkReachabilityCreateWithName
方法并将其传递给主机名。
一些应用程序还将该SCNetworkReachabilityCreateWithAddress
方法传递给169.254.0.0
一个自我分配的链路本地地址的IPv4地址,以检查活动的Wi-Fi连接。要检查Wi-Fi或蜂窝连接,请kSCNetworkReachabilityFlagsIsWWAN
改用网络可达性标志。
使用sockaddr_storage
足够大的地址存储容器来存储IPv6地址。
检查并消除IPv4特定的API,例如:
inet_addr()
inet_aton()
inet_lnaof()
inet_makeaddr()
inet_netof()
inet_network()
inet_ntoa()
inet_ntoa_r()
bindresvport()
getipv4sourcefilter()
setipv4sourcefilter()
如果您的代码处理IPv4类型,请确保处理IPv6等价物。
IPv4的 |
IPv6的 |
---|---|
|
|
|
|
|
|
|
|
|
|
如果您的应用程序需要连接到没有DNS主机名的纯IPv4服务器,请使用此方法getaddrinfo
来解析IPv4地址字面值。如果当前网络接口不支持IPv4,但是支持IPv6,NAT64和DNS64,则执行此任务将导致合成的IPv6地址。
清单10-1显示了如何解决使用的IPv4文字getaddrinfo
。假设您将IPv4地址存储在四个字节(如{192, 0, 2, 1}
)中,则此示例代码将其转换为字符串(例如"192.0.2.1"
),用于getaddrinfo
合成IPv6地址(例如struct sockaddr_in6
包含IPv6地址"64:ff9b::192.0.2.1"
),并尝试连接到那个IPv6地址。
getaddrinfo
,以解决IPv4地址文字
#include |
#include |
#include |
#include |
|
uint8_t ipv4 [4] = {192,0,2,1}; |
struct addrinfo提示,* res,* res0; |
int error,s; |
const char * cause = NULL; |
|
char ipv4_str_buf [INET_ADDRSTRLEN] = {0}; |
const char * ipv4_str = inet_ntop(AF_INET,&ipv4,ipv4_str_buf,sizeof(ipv4_str_buf)); |
|
memset(&hints,0,sizeof(hints)); |
hints.ai_family = PF_UNSPEC; |
hints.ai_socktype = SOCK_STREAM; |
hints.ai_flags = AI_DEFAULT; |
error = getaddrinfo(ipv4_str,“http”,&hints,&res0); |
if(error){ |
errx(1,“%s”,gai_strerror(error)); |
/*还没到*/ |
} |
s = -1; |
for(res = res0; res; res = res-> ai_next){ |
s = socket(res-> ai_family,res-> ai_socktype, |
水库> ai_protocol); |
if(s <0){ |
cause =“socket”; |
继续; |
} |
|
if(connect(s,res-> ai_addr,res-> ai_addrlen)<0){ |
cause =“connect”; |
关闭(多个); |
s = -1; |
继续; |
} |
|
打破; / *好吧,我们有一个* / |
} |
if(s <0){ |
err(1,“%s”,原因); |
/*还没到*/ |
} |
freeaddrinfo(RES0); |
注意:getaddrinfo
在iOS 9.2和OS X 10.11.2 中添加了合成IPv6地址的功能。但是,利用它不会破坏与旧系统版本的兼容性。见getaddrinfo(3) Mac OS X Developer Tools Manual Page
。
测试您的应用程序的最简单方法是IPv6 DNS64 / NAT64兼容性 - 这是大多数蜂窝运营商正在部署的网络类型 - 是使用Mac设置本地IPv6 DNS64 / NAT64网络。然后,您可以从其他设备连接到此网络进行测试。参见图10-6。
重要信息: IPv6 DNS64 / NAT64网络设置选项在OS X 10.11及更高版本中可用。此外,基于Mac的IPv6 DNS64 / NAT64网络与实施了对RFC6106的支持的客户端设备:DNS配置的IPv6路由器通告选项兼容。如果您的测试设备不是iOS或OS X设备,请确保它支持此RFC。请注意,与服务提供商部署的DNS64 / NAT64工作流不同,基于Mac的IPv6 DNS64 / NAT64始终生成合成的IPv6地址。因此,它不提供对本地网络之外的仅限IPv6的服务器的访问,如果您尝试提供支持IPv6的服务器但不支持IPv6,则可能会出现意外的方式。有关详细信息,请参阅本地测试的限制。
使用Mac设置本地IPv6 Wi-Fi网络
确保您的Mac连接到互联网,但不能通过Wi-Fi。
从Dock,LaunchPad或Apple菜单启动系统偏好设置。
按Option键,然后单击共享。不要释放Option键。
打开共享首选项在共享服务列表中选择Internet共享。
配置Internet共享释放Option键。
选中“创建NAT64网络”复选框。
使能本地IPv6 NAT64网络选择提供Internet连接的网络接口,如Thunderbolt以太网。
选择要共享的网络接口选中Wi-Fi复选框。
启用Wi-Fi上的共享单击Wi-Fi选项,并配置网络的网络名称和安全选项。
访问Wi-Fi网络选项 设置本地Wi-Fi网络选项选中“Internet共享”复选框以启用本地网络。
启用Internet共享当系统提示您确认要开始共享时,单击开始。
启动Internet共享共享激活后,您应该看到一个绿色状态指示灯和一个标签,表示Internet Sharing:On。在Wi-Fi菜单中,您还将看到一个小而微弱的箭头向上,表示启用了Internet共享。您现在有一个IPv6 NAT64网络,可以从其他设备连接到它,以测试您的应用程序。
互联网共享指标重要提示: 要确保测试严格在本地IPv6网络上进行,请确保测试设备没有其他活动的网络接口。例如,如果您正在使用iOS设备进行测试,请确保移动服务已禁用,因此您只能通过Wi-Fi进行测试。
基于Mac的IPv6 DNS64 / NAT64网络是在IPv6环境中测试应用程序的有用工具。然而,由于它总是生成合成的IPv6地址并使用IPv4在WAN侧传输数据,因此它不是由服务提供商提供的网络的精确副本。这些网络(以及在App Review中使用的网络)确实允许直接的IPv6到IPv6连接。如果您的服务器配置错误,这可能会导致您的应用程序在常规使用或审查期间的行为与本地测试中的行为不同。甚至可能导致在您自己的环境中难以重现的App Review失败。
特别是,如果您的服务器声称支持IPv6,您可能遇到麻烦,但实际上并不支持。在这种情况下,在初始测试期间,您的应用程序似乎通过IPv6路径与您的服务器进行通信,从而正常运行。但是,您的测试网络实际上是将您的应用程序生成的IPv6流量转换为WAN上的IPv4流量。因此,您实际上正在运行服务器的IPv4数据路径。后来在应用程序审查(或现实世界)期间,应用程序运行相同,但是网络直接连接到服务器的IPv6。如果您的服务器无法正确响应IPv6流量,您的应用程序无法按预期运行,并且可能会失败App Review。
为了避免这种情况,除了使用基于Mac的IPv6 DNS64 / NAT64测试网络验证您的应用程序外,还可以独立验证您的服务器是否正常工作为IPv6服务器。例如,确保服务器:
具有正确的DNS信息。除了检查服务器本身之外,您还可以使用dig(1)
Mac上的命令行工具查看服务器如何报告其AAAA记录。
实际上是在听IPv6。使用像ipv6-test.com这样的工具测试Web服务器(HTTP或HTTPS)。对于其他协议,您需要从本机IPv6网络进行验证。
正确响应IPv6请求。如果您有访问权限,请查看服务器日志以验证是否正确处理IPv6流量。如果没有,您将需要从本机IPv6网络进行测试。
有关实施网络的更多信息,请参阅:
网络编程主题
CFNetwork编程指南
NSURLSession类参考
WebKit框架参考
有关IPv6转换的更多信息,请参阅:
WWDC15视频:您的应用程序和下一代网络
RFC4038:IPv6过渡的应用方面
世界IPv6发射网站
美国互联网号码注册表(ARIN)IPv4耗尽倒计时
有关转换到IPv6时遇到的技术问题,请参阅:
苹果开发者论坛
开发者技术支持