iOS 支持 IPv6 DNS64/NAT64 网络

原文:IOS支持IPv6 DNS64/NAT64网络html

从2016年6月1日起,iOS应用必须支持IPv6,不然审核将被拒。详见Supporting IPv6 DNS64/NAT64 Networks。本文是翻译稿。从本文中能够学到有关IPv6过分时期的网络架构和具体IOS应用如何兼容的知识。ios

随着IPv4地址池即将耗尽,企业和移动通讯供应商在逐步部署IPv6 DNS64/NAT64网络。IPv6 DNS64/NAT64是一个仅有IPv6的网络,且能经过转换继续支持IPv4。根据你app的性质,这样的转化会有不一样的影响:web

  • 若是你是编写客户端应用,而且使用高层次的网络API,如NSURLSession和CFNetwork框架,使用域名链接。那么你无需更改你的应用,便可工做在IPv6地址下。若是你不是采用域名链接,你可能须要看Avoid Resolving DNS Names Before Connecting to a Host。关于CFNetwork,参见CFNetwork Framework Reference编程

  • 若是你是编写服务器程序,或者是底层网络应用,你须要确保你的socket代码能同时在IPv4和IPv6地址下工做。参见[RFC4038: Application Aspects of IPv6 Transition.
    ](https://tools.ietf.org/html/rfc4038)浏览器

什么推进了IPv6

主要的网络供应商,包括美国的蜂窝移动网络供应商,在积极地推动和部署IPv6。这是由多方面因素形成的。安全

World IPv6 Launch是个追踪全球范围内部署活动的组织。访问World IPv6 Launch website能够看到近期的进程。服务器

IPv4地址逐渐耗尽

近几年,众所周知,IPv4地址最终将耗尽,无类域间路由(Classless Inter-Domain Routing)和网络地址转换(NAT)等技术延缓了这势在必行的趋势。然而,2011年1月31日,最上层的IPv4分配机构Internet Assigned Numbers Authority(IANA)宣布地址用尽。American Registry for Internet Numbers (ARIN)预计在2015年夏季用完IPv4地址。从这里查看倒计时。网络

IPv6比IPv4高效

除了能解决IPv4耗尽的问题,IPv6比IPv4更加高效,好比:架构

  • 无需网络地址转换(NAT)app

  • 使用简介的头部信息能够加快在网络中的路由

  • 避免网络数据包碎片

  • 相邻地址解析时避免使用广播 (Avoids broadcasting for neighbor address resolution)

4G开发

第四代移动通讯技术(4G)仅基于包交换,因为IPv4地址的限制,为了保证4G开发的扩展性,须要IPv6的支持

多媒体服务兼容性

IP Multimedia Core Network Subsystem (IMS) 容许一些服务经过IP传输,例如多媒体SMS消息和VoLTE。 有些服务提供商使用IMS时仅支持IPv6。

成本

业界在向IPv6迁移的过程当中,须要继续支持古老的IPv4网络,这使运营商产生了额外的操做和维护成本。

DNS64/NAT64转换流程

为了缓解IPv4地址的耗尽,许多IPv4网络采用NAT技术。尽管这种方案临时奏效,可是实践证实耗资巨大而且不够可靠。现在,随着愈来愈多的设备使用IPv6,运营商必须同时支持IPv4和IPv6,这种努力倒是花费巨大的。


图 10-1 蜂窝移动网络分别提供IPv4和IPv6连接

理想状况下,运营商但愿丢掉对IPv4的支持。然而,这么作会致使客户端没法访问基于IPv4的服务器,而IPv4的服务器依然是网络的重要组成部分。为了解决这个问题,大多数的网络供应商实现了一个叫DNS64/NAT64的转换流程。这是个纯IPv6网络,并经过转换也可继续访问IPv4的内容。


图 10-2 蜂窝移动网络用DNS64和NAT64来部署一个IPv6网络

在这个流程中,若是客户端向DNS64服务器发起一个DNS查询,当DNS找到一个基于IPv6的地址后,马上返回客户端。若是没法找到对应的IPv6地址,DNS64服务器将请求IPv4地址,而后DNS64服务器将IPv4做为前缀合成一个IPv6地址,而且将其返回给客户端。这样,客户端将老是得到一个IPv6目标地址,见图10-3。


图 10-3 DNS64 IPv4到IPv6转换过程

当客户端向服务端发送请求时,目标地址为合成后的IPv6地址会自动由NAT64网关路由过去。对于请求,网关做的是IPv6到IPv4的转换。一样的,对于服务器响应,网关做的是IPv4到IPv6的转换。见图10-4


图 10-4 DNS64/NAT64转化方案的流程

IPv6和App Store的要求

对IPv6 DNS64/NAT64网络的兼容性,将是App Store的提交时的必须条件,因此兼容对于app来讲是至关重要的。好消息是,大多数app已是IPv6兼容的了。对于这些app,进行按期的回归测试依旧是必要的。对于那些IPv6不兼容的应用在面对DNS64/NAT64网路时可能遇到麻烦。幸运的是,解决问题一般很简单,下面章节会讨论这个问题。

常见的阻碍IPv6支持的行为

有几个致使应用没法支持IPv6的场景。本节描述如何解决这些问题。

  • 嵌入IP地址的协议。许多通讯协议,像SIP, FTP, WebSockets, P2PP,均可能在协议的报文中包含了IP地址。例如,FTP参数命令DATA, PORT, PASSIVE的交换信息中包含了IP地址。相似的,IP地址值可能出如今SIP的头部,像To, FROM, Contact, Record-Route以及Via。参见Use High-Level Networking FrameworksDon’t Use IP Address Literals

  • 配置文件中使用IP地址。参见Don’t Use IP Address Literals

  • 网络状态监测。许多app试图主动的监测网络链接和wifi链接,却将IP地址做为参数而调用网络可达性相关的API。参见Connect Without Preflight

  • 使用底层网络接口。一些app直接使用socket和其余的低层次网络API,好比gethostbyname gethostbyname2inet_aton。这些API很容易由于错误使用而仅支持IPv4。好比,域名解析时使用AF_INET地址簇,而不是AF_UNSPEC地址簇。参见Use High-Level Networking Frameworks

  • 使用了小的地址簇存储容器。一些app和网络库,使用了例如unit32,in_addr,sockaddr_in这种32位或更小的容器来存储地址。参见Use Appropriately Sized Storage Containers

确保IPv6 DNS64/NAT64兼容性

附上下面的指导来确保IPv6 DNS64/NAT64的兼容性。

使用高层次的网络框架

app请求网络时,能够构建在高层次的网络框架上,也可使用底层的POSIX兼容的socket接口。在多数状况下,相比底层接口,高层次的接口效率高一些,兼容性好,容易使用,不容易掉入一般的编程错误陷阱中。


图 10-5 网络框架和API层次

  • WebKit。此框架提供一系列的类用来在窗口上显示web内容,并且实现了浏览器特性,诸如:连接、前进后退管理、最近访问历史。WebKit将加载网页的流程简化了,包括异步地从HTTP服务器上请求网页内容,这些服务器响应的数据包可能一点点送达,也可能以随机的顺序到达,甚至可能因为网络错误收不全。详见WebKit Framework Reference

  • Cocoa URL loading system。这个系统用于简单地经过网络发送和接收数据,却不须要提供显示的IP地址。数据的发送和接收使用这几个类中的一个:NSURLSession NSURLRequest NSURLConnection,这些类使用NSURL对象。NSURL对象容许你操做URL。建立一个NSURL对象时使用initWithString:方法,并传入一个指定的URL。调用NSURL类的checkResourceIsReachableAndReturnError:方法检测目标主机的可达性。详见URL Session Programming Guide

  • CFNetwork。这个核心服务框架提供了一个抽象网络协议的库。这个库提供了大量易用的网络操做,好比BSD socket,DNS解析,处理HTTP/HTTPS。调动CFHostCreateWithName方法,避免显示的使用IP地址来标识主机。调用CFStreamCreatePairWithSocketToCFHost与主机创建TCP连接。详见CFNetwork Programming Guide中的CFNetwork Concepts

若是你须要使用低层次的socket接口,参看以下指导:RFC4038: Application Aspects of IPv6 Transition

Getting Started with Networking, Internet, and WebNetworking Overview 提供详细的网络框架API的说明

不要使用IP地址

在许多API中请确保再也不使用点分十进制表示的IPv4地址,例如getaddrinfoSCNetworkReachabilityCreateWithName。取而代之,应该使用高层次网络框架和地址无关的API,例如在使用getaddrinfogetnameinfo时,传入主机名或域名。详见:getaddrinfo(3) Mac OS X Developer Tools Manual Page 和 getnameinfo(3) Mac OS X Developer Tools Manual Page。

从IOS9何OSX10.11开始,NSURLSessionCFNetwork会在本地自动将IPv4的地址合成IPv6地址,便于与DNS64/NAT64通讯。不过,你依旧不应使用IP地址串。

链接时无需网络预检

检测网络可达性的API(参见SCNetworkReachability Reference)用来在遇到链接异常时进行诊断。许多app错误的使用了API,它们每每经过调用SCNetworkReachabilityCreateWithAddress方法,并将IPv4地址0.0.0.0做为参数传入,来不断检查网络链接,实际表示是否至少可达一个路由(which indicates that there is a router on the network)。然而,即便有这样的路由也不保证互联网的链接存在。总之,避免进行网络可达性的检测。只须要直接进行链接,而且优雅的处理失败的状况。若是你确实须要检测网络可用性,需避免使用SCNetworkReachabilityCreateWithAddress,而是调用SCNetworkReachabilityCreateWithName,并传入主机名。

有些app还在调用SCNetworkReachabilityCreateWithAddress的时候传入IPv4地址169.254.0.0(一个自动分配的本地IP),试图检测Wi-Fi链接。若要检测Wi-Fi或蜂窝移动网络链接,参见网络可达标识kSCNetworkReachabilityFlagsIsWWAN

使用合适的Storage Container大小

使用Storage Container结构,如sockaddr_storage,用以有足够的空间存放IPv6地址。

检查代码不兼容IPv6 DNS64/NAT64的代码

查找并删除IPv4相关的API,如:

  • inet_addr()

  • inet_aton()

  • inet_lnaof()

  • inet_makeaddr()

  • inet_netof()

  • inet_network()

  • inet_ntoa()

  • inet_ntoa_r()

  • bindresvport()

  • getipv4sourcefilter()

  • setipv4sourcefitler()

若是你处理的IPv4的类型,去报同时处理对应的IPv6类型

IPv4 IPv6
AF_INET AF_INET6
PF_INET PF_INET6
struct in_addr struct in_addr6
struct sockaddr_in struct sockaddr_in6
kDNSServiceProtocol_IPv4 kDNSServiceProtocol_IPv6

使用系统API合成IPv6地址

若是你的app须要链接到仅支持IPv4的服务器,且不使用DNS域名解析,请使用getaddrinfo处理IPv4地址串(译注:getaddrinfo可经过传入一个IPv4或IPv6地址,获得一个sockaddr结构链表)。若是当前的网络接口不支持IPv4,仅支持IPv6,NAT64和DNS64,这样作能够获得一个合成的IPv6地址。

代码10-1展现了如何用getaddrinfo处理IPv4地址串。假设你内存中有一个4个字节的IPv4地址串(如{192,0,2,1}),这个示例代码将之转化为字符串("192.0.2.1"),使用getaddrinfo合成一个IPv6地址结构(struct sockaddr_in6包含IPv6地址串为"64:ff9b::192.0.2.1"),而后尝试链接到这个IPv6地址。

代码 10-1 使用getaddrinfo处理IPv4地址串

#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <err.h>
 
uint8_t ipv4[4] = {192, 0, 2, 1};
struct addrinfo hints, *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));
    /*NOTREACHED*/
}
s = -1;
for (res = res0; res; res = res->ai_next) {
    s = socket(res->ai_family, res->ai_socktype,
               res->ai_protocol);
    if (s < 0) {
        cause = "socket";
        continue;
    }

    if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
        cause = "connect";
        close(s);
        s = -1;
        continue;
    }

    break;  /* okay we got one */
}
if (s < 0) {
    err(1, "%s", cause);
    /*NOTREACHED*/
}
freeaddrinfo(res0);

从IOS9.2和OSX10.11.2开始合成IPv6地址的功能才被加入到getaddrinfo。不过,这么用不会对旧的系统产生兼容性问题。参见getaddrinfo(3) Mac OS X Developer Tools Manual Page.

测试IPv6 DNS64/NAT64兼容性

大多数蜂窝移动供应商已经开始部署IPv6 DNS64/NAT64网络,测试这种网络最简单的的方法是用Mac创建一个本地的IPv6 DNS64/NAT64网络。你能够将其余设备连接到这个网络来测试。见图10-6

提示:IPv6 DNS64/NAT64网络仅在OSX 10.11及更高版本上能够设置。除此以外,基于Mac来创建的IPv6 DNS64/NAT64网络仅与支持RFC6106: IPv6 Router Advertisement Options for DNS Configuration的客户端设备兼容。若是你的设备不是iOS或OSX设备,请确保它支持RFC。还需注意的是:不一样于运营商提供的DNS64/NAT64网络,基于Mac系统的IPv6 DNS64/NAT64老是返回合成后的IPv6地址。所以,它不能用于访问你本地网络之外的纯IPv6网络。


图 10-6 本地的基于Mac的 IPv6 DNS64/NAT64 网络

使用你的Mac创建本地的IPv6 Wi-Fi网络

  1. 确保你的Mac链接到互联网,但不是经过Wi-Fi

  2. 启动System Preferences

  3. 按住Option键(标准键盘是Alt键)点击Sharing,不要放开Option键。

    图 10-7 打开Sharing preferences

  4. 在共享列表中选择Internet Sharing

    图 10-8 配置Internet Sharing

  5. 放开Option

  6. 勾选Create NAT64 Network复选框

    图 10-9 启用一个本地IPv6 NAT64网络

  7. 选择你用于互联链接的网络接口,例如蓝牙局域网(译者注:一般这里mac用以太网链接互联网,不多有用蓝牙的)

    图 10-10 选择共享的网络接口

  8. 选择Wi-Fi复选框

    图 10-11 经过Wi-Fi开启共享

  9. 点击Wi-Fi Options,配置你网络的网络名和安全选项

    图 10-12 设置Wi-Fi网络选项

  10. 勾选Internet Sharing复选框启动你的本地网络

    图 10-14 启动网络共享

  11. 当弹出确认是否开启共享时,点击Start

    图 10-15 开启网络共享

一旦共享启动后,你应该能够看到一个绿色的状态指示灯和一段话说明共享已开启。在Wi-Fi菜单中,你一样将看到一个小的向上的箭头,表示网络共享已经开启。如今你拥有了一个IPv6 NAT64的网络,其余设备能够链接这个网络来测试app。


图 10-16 网络共享开启图标

提示:为了确保测试时严格使用本地的IPv6网络,请确认测试设备没有其余的网络接口正在使用。例如,若是你在测试iOS设备,确保蜂窝移动网络服务是禁用的,这样才能确保经过Wi-Fi链接。

相关文章
相关标签/搜索