最近提交了一个新app到appstore,才知道人家苹果从2016.6就要求所有的app要支持ipv6-only,直接给拒了。网上找了几天相关解决方案,发现基本上都照搬照抄官方的文档,没有解决实际问题。
2017.1.13 UPDATE: 如果只是普通的web服务,一般不是ipv6的问题,是其他原因导致的,ipv6会自动兼容ipv4的网络。如果是依赖网络底层函数则有关系。
照搬照抄前有几点需要说明清楚:
1、官方的,不是你搭建好就可以用访问你的服务器的(启用共享的那台服务器),事实上是啥也访问不了,访问不了,访问不了。文档有个IMPORTANT的注释说明:
a Mac-Based IPv6 DNS64/NAT64 always generates synthesized IPv6 addresses. Therefore, it does not provide access to IPv6-only servers outside of your local network.
翻译过来的意思就是说:用mac搭建的IPV6的ip地址是自己合成的(就是说不是真正全球通用的ipv6地址,只是个局域网使用的地址),所以,你不能访问局域网之外的ipv6服务器。
关键在这里,很多人估计掉坑里去调网络的连通性问题。
看官网这张图
关键点在Router,如果你有路由器支持转换,确实你也是可以访问ipv4的服务的,但,像一般的小公司估计都没有这个能力去搞个路由器来搞开发吧?所以你的ipv6测试环境基本上是不能访问公网的,除非你有路由器支持ipv6与ipv4的转换功能。补充:或者启用代理(但如果是代理网站得用域名的方式,而手机上没法像电脑一样方便的设置hosts等解析,始终不太好用)。
2、那,这样的测试环境有啥用啊?有部分用处,如socket通讯的测试,web布署到共享网络机器上(且通过ipv6 ip去访问)。比如,如果你的服务端程序布署到这台开启ipv6-only的机器上,通过app与ipv6-onley机器之间的ipv6地址进行互通讯操作。但,如果你跑的是http/https协议的,可以用修改开发机的Hosts文件,把所有域名指向ipv6-onley机器,然后在开发机使用模拟器运行app进行通讯。
用哪个ip呢,通过下以下命令可以得到共享机的ipv6地址
#ifconfig |grep inet6 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet6 fe80::10bb:8bd6:7634:37f2%en0 prefixlen 64 secured scopeid 0x4 inet6 fe80::104f:3800:d408:de3f%en1 prefixlen 64 secured scopeid 0x5 inet6 fe80::4934:df78:3b8c:c7b3%utun0 prefixlen 64 scopeid 0xa inet6 fd57:e9ea:2268:154b:4934:df78:3b8c:c7b3 prefixlen 64 inet6 fe80::d836:ba88:cecf:cc32%utun1 prefixlen 64 scopeid 0xb inet6 2001:2:0:aab1::1 prefixlen 64 inet6 fe80::406c:8fff:fe65:8f64%bridge100 prefixlen 64 scopeid 0xe inet6 2001:2::aab1:1414:8420:8fe7:e378 prefixlen 64 autoconf secured inet6 2001:2::aab1:b9fd:1b1c:864b:5fbe prefixlen 64 autoconf temporary
注意最后两个就是局域网的地址,我是用倒数第二个连通进行访问的。在手机上使用safari或chrome访问以下ip
http://[2001:2:0:aab1:1414:8420:8fe7:e378]/
或者修改hosts文件,绑定域名和ip的映射关系,就可以用模拟器通过域名方式进行测试了。
3、一般app接口都是是跑http/https协议的,服务端要升级吗?
不需要,看官方论坛的回答。
3 — Will I need to update my server?That depends on where your server is running:If you have a server running on the wider Internet, the answer is no. Your server will be accessible to IPv6-only devices via DNS64/NAT64.
翻译过来的意思就是:我需要升级服务器吗?那得看你跑的是啥服务,如果你跑的是互联网服务,答案是:不需要。因为ipv6设备可以通过DNS64/NAT64转换方式来访问你的服务。
就是说,如果你的app只是跑http/https的,基本上啥也不用动。如果有跑其它服务的,像写死ip的啦,用底层socket方法的啦,就要参考逐个修改了(或)。
但是,很多人不升级服务端仍会出现失败的情况,如果是这样,看下面介绍服务器端的配置(如果有Ipv6地址更好)。
4、阿里云没有ipv6给你。问过他们的客服,就是我们还不提供ipv6的地址。这么大个厂家,这个竟然还不行考虑?干得过AWS吗?
5、要不要修改域名?
如果你没有ipv6地址就不需要。看到腾讯云有篇不靠谱的文章,说,但文章的内容竟然是教你怎么造一个ipv6地址出来,:D,事实上ipv6自己会做兼容,如果有ipv6的域名指向地址就使用ipv6,如果没有就转换成ipv4,所有完全没必要自己去造一个兼容ipv6的ipv4地址。除非哪天有一个正式的ipv6地址。(而且不知这知兼容地址实际使用上会不会有问题?是IETF的标准?)
说这个的是,不要去搞域名解析,走弯路(如果是在下面隧道的方式,因为有独立ipv6地址了,就要配置域名解析了,直接添加AAAA记录!)。
从上图可以看出,ipv6下我也是支持访问ipv4服务器的,如果不兼容,全球的ipv4服务都挂掉?而且要实现兼容,要在DNS64和NAT64一起配合使用才行。(但测试dnspod合成的ipv6地址是访问不了的!)
Some developers have attempted to synthesise an IPv6 address by combining an IPv4 address with the Well-Known Prefix (64:ff9b::/96). This will not work in the general case. For reliable results you must use getaddrinfo (or some higher-level API) to synthesise IPv6 addresses, as described in Use System APIs to Synthesize IPv6 Addresses.有些开发人员试图通过IP4来构造IPv6地址,常用的是加前缀如(64:ff9b::/96)。但这种一般不能正常工作。要得到稳定的效果你必须使用getaddrinfo(或其它高层API)来构造IPv6地址,像这个链接描述的一样https://developer.apple.com/library/mac/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-DontLinkElementID_4
6、用ipv6代理到ipv4方式可行吗?(修订:如果仅仅是为了过审可以考虑,大流量仍是走ipv4)
见有公众号文章,从境外购买了支持ipv6的空间,然后会代理的方式,绕回到国内ipv4服务器。这也是一种办法,但要改域名指向,而且多了一个花钱的地方,像租空间、买流量,都是成本,实在没办法的可以考虑。这里有个测试你的,测试方法2,是在你的域名后加上.ipv4.sixxs.org进行访问。
(AWS EC2是不支持ipv6的,要前面再挂一台负载均衡器)
7、其他可能导致被拒的问题排查?
有几点思路可以参考一下,列出app所有用到的第三组件,逐个排查是不是已经都支持ipv6-only,像微信登录sdk(其官方已经明确表明最新版sdk支持ipv6-only),如果没有表明支持的,就要先去掉这个组件,因为过不了审,加了也没用,等它们升级后再加上,只能牺牲一部分功能了:(。
因为ipv6-only涉及的都是网络层的问题,所以可以在电脑上安装一个防火墙软件,监控模拟器上的所有通讯,所有不支持ipv6的通讯组件去掉。
8、官方的论坛讨论可以多看看
9、12.15补充。服务端的配置支持ipv6。从第5点的图可以看出,如果使用了ipv6的网络访问ipv4的服务,也是使用ipv6的地址进行访问你的服务器的,所以,你的服务器要支持ipv6的访问!!像nginx做webserver的,要检查下有没有编译进--with-ipv6参数(99.9999%的没有,最新版本已经废弃这个参数了,默认开启了ipv6),没有的要重装编译nginx!!
#看下有没有ipv6的支持,没有就要重装nginx -V./configure --vith-ipv6 --prefix=/server/nginx --with-http_ssl_module --with-http_gunzip_module --with-http_gunzip_module --with-pcre --with-http_stub_status_module --with-stream
同时配置nginx.conf,监听ipv6网络
#同时监听ipv4和ipv6网络server {....listen 80;listen [::]:80 ipv6only=on;#如果你有ipv6地址,可以写成#listen [3608:f0f0:3002:31::1]:80;#然后在浏览器访问http://[3608:f0f0:3002:31::1]/...}
死变态的阿里云还限制了ipv6数据包!!
#先检查下有没有启动ipv6模块,如果没有输出,请参考附件的方式启用此模块lsmod|grep ipv6#vi /etc/sysctl.conf# Disable IPv6net.ipv6.conf.all.disable_ipv6 = 1net.ipv6.conf.default.disable_ipv6 = 1
将上面的改成0,重启服务器!
10.12.16更新。最后是通过he.net的隧道打通了ipv6的访问
He.net的隧道稳定性差些,经常出现连通不了的情况,要有保障的话建议购买有ipv6的vps主机做代理。
11.12.17更新。he.net隧道方案虽然打通,但经常不稳定,仍被拒,转成使用linode做代理。
linode默认有分配Ipv6地址,这里可以添加AAAA解析记录了(dnspod已经支持AAAA),添加完验证下解析是否正常。同时,怀疑是泛域名没加解析的问题,单独添加了各子域名的解析。
#要能输出正确的ANSWER段落内容,如$ dig +nocmd +nostats example.com AAAA;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3386;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0;; QUESTION SECTION:;example.com. IN AAAA;; ANSWER SECTION:example.com. 600 IN AAAA 2400:8901::f03c:92ff:fe59:1ca3
12. 12.20更新。发现坑爹的在于我们使用了dcloud 的 h5plus sdk上,根本无法访问ipv6的内网网站。最新的版本12.12的才支持,之前09.09以前的不行。
13. 发现某个链接未使用https,导致在ipad模拟器里打不开(12.21更新,跟http或https无关)(在iphone手机上一直没发现,但苹果审核人员会使用ipad进行审核!虽然你的app没有声明支持ipad),据苹果要求2017年始所有通讯要求使用https!
希望大家app都顺利过审!
参考
一、ipv6的隧道方案(试了下he.net不让国内ip注册了? 白天可以注册)
二、
三、
四、一些测试连接性的命令
curl -6 [2001:470:18:3a6::2]ping6 2001:470:18:3a6::2wget -6 http://[2001:470:18:3a6::2]
以上命令得在ipv6网络环境下才能使用
作者:350050183@qq.com