错误

最近苹果审核应用时, 被拒了, 才发现不支持IPv6
We discovered one or more bugs in your app when reviewed on iPad running iOS 10.3.2 on Wi-Fi connected to an IPv6 network.

解决

苹果从iOS9开始向IPv6的网络服务过渡。2016年初开始所有提交到App Store的应用必须支持IPv6。苹果于2016年5月4日告知开发者应用需要在6月1日前支持IPv6-only,也就是说在 6 月 1 日后发布的新版本是需要支持 IPv6-only. 所以需要后台服务器进行ipv6的设置。

苹果官方文档:
Supporting IPv6 DNS64/NAT64 Networks

拓展

IPV6-Only支持是啥?

首先IPV6,是对IPV4地址空间的扩充。目前当我们用iOS设备连接上Wifi、4G、3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部署IPV6 DNS64/NAT64网络之后,设备被分配的地址会变成IPV6的地址,而这些网络就是所谓的IPV6-Only网络,并且仍然可以通过此网络去获取IPV4地址提供的内容。客户端向服务器端请求域名解析,首先通过DNS64 Server查询IPv6的地址,如果查询不到,再向DNS Server查询IPv4地址,通过DNS64 Server合成一个IPV6的地址,最终将一个IPV6的地址返回给客户端。如图所示:



iOS支持 IPV6吗 苹果支持ipv6_iOS支持 IPV6吗


Apple如何审核支持IPV6-Only?

1.这里说的支持IPV6-Only网络,其实就是说让应用在 IPv6 DNS64/NAT64 网络环境下仍然能够正常运行。但是考虑到我们目前的实际网络环境仍然是IPV4网络,所以应用需要能够同时保证IPV4和IPV6环境下的可用性。从这点来说,苹果不会去扫描IPV4的专有API来拒绝审核通过,因为IPV4的API和IPV6的API调用都会同时存在于代码中(不过为了减小审核被拒风险,建议将IPV4专有API通过IPV6的兼容API来替换)。

2.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的兼容性即可。

3.只要应用的主流程支持IPV6,通过苹果审核即可。对于不支持IPV6的模块,考虑到我们现实IPV6网络的部署还需要一段时间,短时间内不会影响我们用户的使用。但随着4G网络IPV6的部署,这部分模块还是需要逐渐安排人力进行支持。

4.如果应用一直直接使用IPV4地址通过NSURLConenction或者NSURLSession进行网络请求(一般需要服务器允许,且客户端需要在header中伪装host);经测试,IPV6网络环境下,直接使用IPV4地址在iOS9及以上的系统仍然能够正常访问;在iOS8.4及以下不能正常访问;这一点苹果的解释和建议是这样的:

不建议使用底层的网络API

下图展示的蓝色部分的这些API都是不存在兼容性问题的,而我们平时自己用的包括那些第三方的网络库大部分都是用的这些API。



iOS支持 IPV6吗 苹果支持ipv6_ipv6_02


其中蓝色部分的高级API,其实都已经帮我们做好了IPv6的支持,我们使用的大多数第三方网络库也都是基于这些高级API的,所以这里我们不需要做什么改动。 需要注意的是下面的红色部分的底层的socket API需要做出适配支持。

不要用IP地址

确保您没有将点号符号的IPv4地址文字传递给API,例如getaddrinfo和SCNetworkReachabilityCreateWithName。 相反,使用高级网络框架和地址不可知版本的API,例如getaddrinfo和getnameinfo,并传递它们的主机名或完全限定的域名。

注意:在iOS 9和OS X 10.11及更高版本中,NSURLSession和CFNetwork会在本地在DNS64 / NAT64网络上运行的设备上自动从IPv4文字中综合IPv6地址。 但是,您仍然应该删除IP地址文字的代码。

检查不兼容IPv6的代码

搜一下工程里有没有下面的这些API,这些都是只针对IPv4做处理的,有的话就删了。

inet_addr() 
 inet_aton() 
 inet_lnaof() 
 inet_makeaddr() 
 inet_netof() 
 inet_network() 
 inet_ntoa() 
 inet_ntoa_r() 
 bindresvport() 
 getipv4sourcefilter() 
 setipv4sourcefilter()

如果用到了下面左边的这些IPv4的类型,那么它们相应的IPv6类型也需要做处理



iOS支持 IPV6吗 苹果支持ipv6_iOS支持 IPV6吗_03


搭建IPv6测试环境

首先通过Mac的共享网络共享一个IPv6的无线网,跟已往创建方式不同的是进入共享时需要按住Option键



iOS支持 IPV6吗 苹果支持ipv6_ipv6_04




iOS支持 IPV6吗 苹果支持ipv6_ipv6_05


需要使你的iPhone连接上分享出来的热点即可, 通过WiFi在连接网络。
注; 手机上面的 HTTP代理必须关闭