移动通信
果然是苹果打个哈欠,iOS行业内就得起一次风暴呀。自从去年5月初Apple明文规定所有开发者在6月1号以后提交新版本需要支持IPV6-Only的网络,大家便开始热火朝天的研究如何支持IPV6,以及应用中哪些模块目前不支持IPV6。
App Store策略是要求所有iOS应用必需包含IPv6-only网络的支持。从今年6月1日开始,所有提交至苹果App Store的应用必需要兼容面向硬件识别和网络路由的最新互联网协议——IPv6-only标准。这项措施是在2015年苹果WWDC开发者大会上提出的,iOS 9会率先向IPv6-only网络服务过渡。
根据苹果开发者网站声明,大部分现有的应用程序已经通过NSURLSession和CFNetwork APIs兼容该协议,不过依然使用IPv4 APIs的或者硬件编码IP地址的开发者将需要手工调整应用代码来适应苹果的最新策略。随着IPv4地址的枯竭,IPv6d的转移工作变得越来越重要。对于苹果来说,切换至IPv6能够带来更加广泛的行业接受协议,此外伴随着物联网的普及,同样能延续智能手机的健康发展。
以前,大家都在用 IPv4,就是地址看起来是 114.255.40.66 的样子。然而,这样的地址已经不够用了,就有了类似2001:da8:215:4009:250:56ff:fe97:40c7 这样的 IP 地址。
目前,一个网卡会同时使用这两张地址;在未来,一个网卡将仅有后面这样的 IPv6 地址。 使用这两种地址的设备是不能互相访问的,后来有了一些过渡技术让他们在某些情况下可以互相访问了。(如 DNS64/NAT64)
首先IPV6,是对IPV4地址空间的扩充。目前当我们用iOS设备连接上Wifi、4G、3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部署IPV6 DNS64/NAT64网络之后,设备被分配的地址会变成IPV6的地址,而这些网络就是所谓的IPV6-Only网络,并且仍然可以通过此网络去获取IPV4地址提供的内容。客户端向服务器端请求域名解析,首先通过DNS64 Server查询IPv6的地址,如果查询不到,再向DNS Server查询IPv4地址,通过DNS64 Server合成一个IPV6的地址,最终将一个IPV6的地址返回给客户端。如图所示:
在Mac OS 10.11+的双网卡的Mac机器(以太网口+无线网卡),我们可以通过模拟构建这么一个local IPv6 DNS64/NAT64 的网络环境去测试应用是否支持IPV6-Only网络,大概原理如下:
如何满足苹果要求?
苹果公司为什么要这么做?
现在有极小一部分用户处在IPv6-ONLY的环境中,未来这个比例会扩大。
苹果这样要求,对于大多数开发者而言,并不困难。目前大多数应用无需任何操作即可满足要求。
我不太懂这些,我该怎么做呢?
在你的应用中使用域名(如 www.bupt.edu.cn),不要在任何地方使用 IPv4地址(114.255.40.66)。
我的服务器必须有 IPv6 地址么?
不是的,服务器只需要有公网 IPv4 地址即可,但要求必须使用域名(FQDN)来表示服务器。
MacOS 提供了这个功能。 使用 Mac 把有线网络共享到 WiFi,中间勾选 创建NAT64网络 即可。
首先第一点:这里说的支持IPV6-Only网络,其实就是说让应用在 IPv6 DNS64/NAT64 网络环境下仍然能够正常运行。但是考虑到我们目前的实际网络环境仍然是IPV4网络,所以应用需要能够同时保证IPV4和IPV6环境下的可用性。从这点来说,苹果不会去扫描IPV4的专有API来拒绝审核通过,因为IPV4的API和IPV6的API调用都会同时存在于代码中(不过为了减小审核被拒风险,建议将IPV4专有API通过IPV6的兼容API来替换)。
其次第二点:Apple官方声明iOS9开始向IPV6支持过渡,在iOS9.2+支持通过getaddrInfo方法将IPV4地址合成IPV6地址(The ability to synthesize IPv6 addresses was added to getaddrinfo in iOS 9.2 and OS X 10.11.2)。其提供的Reachability库在iOS8系统下,当从IPV4切换到IPV6网络,或者从IPV6网络切换到IPV4,是无法监控到网络状态的变化。也有一些开发者针对这些Bug询问Apple的审核部门,给予的答复是只需要在苹果最新的系统上保证IPV6的兼容性即可。
最后第三点:只要应用的主流程支持IPV6,通过苹果审核即可。对于不支持IPV6的模块,考虑到我们现实IPV6网络的部署还需要一段时间,短时间内不会影响我们用户的使用。但随着4G网络IPV6的部署,这部分模块还是需要逐渐安排人力进行支持。
追加第四点:如果应用一直直接使用IPV4地址通过NSURLConenction或者NSURLSession进行网络请求(一般需要服务器允许,且客户端需要在header中伪装host);经测试,IPV6网络环境下,直接使用IPV4地址在iOS9及以上的系统仍然能够正常访问;在iOS8.4及以下不能正常访问;这一点苹果的解释和建议是这样的:
Note: In iOS 9 and OS X 10.11 and later, NSURLSession and CFNetwork automatically synthesize IPv6 addresses from IPv4 literals locally on devices operating on DNS64/NAT64 networks. However, you should still work to rid your code of IP address literals.
首先,这个是无法直接访问的,必须网络的提供商支持过渡技术。
第一步:DNS 污染
例如我们想要访问 example.com ,假设这个网站只有 IPv4 地址(93.184.216.34,用16进制表示为 5d b8 d8 22) 那么,被“污染”的DNS返回的 IP 地址是 64:ff9b::5db8:d822。 其中 `64:ff9b::/96`是IANA分配用于DNS64的前缀。
第二步:IPv6 转 IPv4
访问 64:ff9b::5db8:d822 时,IPv6 包头被替换为 IPv4 包头,继续访问。 同时回来的数据包会被做反向处理。
微信的DNS查询,使用的 HTTP 协议自己封装的,这样在 IPv4 网络下可以避免相当多的问题。 如图,微信直接查询 A 记录,即使我的设备在 IPv6-ONLY 的网络环境下。 因此,微信就跪掉
对于如何支持IPV6-Only,官方给出了如下几点标准:(这里就不对其进行解释了,大家看上面的参考链接即可)
1. Use High-Level Networking Frameworks;
2. Don’t Use IP Address Literals;
3. Check Source Code for IPv6 DNS64/NAT64 Incompatibilities;
4. Use System APIs to Synthesize IPv6 Addresses;
官方的这句话让我们疑惑顿生:
*** using high-level networking APIs such as NSURLSession and the CFNetwork frameworks and you connect by name, you should not need to change anything for your app to work with IPv6 addresses***
只说了NSURLSession和CFNetwork的API不需要改变,但是并没有提及到NSURLConnection。 从上文的参考资料中,我们看到NSURLSession、NSURLConnection同属于Cocoa的url loading system,可以猜测出NSURLConnection在ios9上是支持IPV6的。
应用里面的API网络请求,大家一般都会选择AFNetworking进行请求发送,由于历史原因,应用的代码基本上都深度引用了AFHTTPRequestOperation类,所以目前API网络请求均需要通过NSURLConnection发送出去,所以必须确认NSURLConnection是否支持IPV6. 经过测试,NSURLConnection在最新的iOS9系统上是支持IPV6的。
目前我们的应用最低版本还需要支持iOS7,虽然苹果只要求最新版本支持IPV6-Only,但是出于对用户负责的态度,我们仍然需要搞清楚在低版本上URL Loading System的API是否支持IPV6.
(to fix me, make some experiments)待续~~~
我们可以查到应用中大量使用了Reachability进行网络状态判断,但是在里面却使用了IPV4的专用API。
在Pods:Reachability中
AF_INET Files:Reachability.m
struct sockaddr_in Files:Reachability.h , Reachability.m
(1)目前Github的开源库Reachability的最新版本是3.2,苹果也出了一个Support IPV6 的Reachability的官方样例,我们比较了一下源码,跟Github上的Reachability没有什么差异。
(2)我们通常都是通过一个0.0.0.0 (ZeroAddress)去开启网络状态监控,经过我们测试,在iOS9以上的系统上IPV4和IPV6网络环境均能够正常使用;但是在iOS8上IPV4和IPV6相互切换的时候无法监控到网络状态的变化,可能是因为苹果在iOS8上还并没有对IPV6进行相关支持相关。(但是这仍然满足苹果要求在最新系统版本上支持IPV6的网络)。
(3)当大家都在要求Reachability添加对于IPV6的支持,其实苹果在iOS9以上对Zero Address进行了特别处理,官方发言是这样的:
reachabilityForInternetConnection: This monitors the address 0.0.0.0,
which reachability treats as a special token that causes it to actually
monitor the general routing status of the device, both IPv4 and IPv6.
+ (instancetype)reachabilityForInternetConnection {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress];
}
综上所述,Reachability不需要做任何修改,在iOS9上就可以支持IPV6和IPV4,但是在iOS9以下会存在bug,但是苹果审核并不关心。
全部0条评论
快来发表一下你的评论吧 !