将 IPv6 照进现实,我们需要做些什么?

将 IPv6 照进现实,我们需要做些什么?

随着中共中央办公厅、国务院办公厅印发了《推进互联网协议第六版(IPv6)规模部署行动计划》后,整个 IPv6 产业链开始活跃起来。虽然目前我们距离世界上每一粒沙子都有一个地址的梦想还有点远,但加速推进的大趋势应该是不争的事实。但是我们在仰望星空的同时还需要脚踏实地,那么 IPv6 的现实是怎样的呢,我们还需要准备什么呢,这就是这篇文章想要表达的。

IPv6这个曾经以解决地址短缺问题而出现的技术存在了很久,但因为种种原因没在世界范围内普及,尤其是没在中国普及。今天的文章不是 IPv6 科普文章,也没有过多的涉及到网络如何改造,业务如何适配,更多的是从用的角度来看现状。另外从我个人角度,移动网 IPv6 化会走在固网 IPv6 的前面,移动网应该是双栈的策略,所以文章的分析都是以移动网为前提,固网暂不涉及。

手机支持双栈吗?

IPv6 在相当长一段时间内没能够在公众网中普及,很重要的一个原因就是各方的动力不足,虽然一直在宣传 IPv4 地址不够用了,但缝缝补补还是让互联网走了这么多年。如果抛开动力不足来看,IPv6 的普及其实是一个系统工程,需要的是端、管、云,三方的协同支持,那么我们先看下端,也就是手机的支持情况。

首先是苹果 iPhone,对于 v6 苹果早在几年前就强推 APP 对于 IPv6 only 的支持,如果不通过这个功能审核是不能上架 App Store 的。但当时对于 APP 开发者来说最为郁闷的是在国内很难找到一个商用的 IPv6 Only 环境进行测试,更多是 Mac 热点或者 WiFi APP 来模拟进行网络库的逻辑测试,在移动网下是没有办法做测试的。而这样的问题在目前 IPv6 改造期间一样面临,即在国内苹果 iPhone 在移动网下只能获得 v4 地址,没有 v6 地址。为什么呢,因为 iPhone 里面的 APN 设置是不能修改的,而内置 APN 中对于地址请求所携带的字段仅仅是 IPv4 类型,这样即使网络支持双栈,iPhone 还是只能获得v4地址,下图就是一个苹果手机在移动网内的信令请求:

将 IPv6 照进现实,我们需要做些什么?

上面标黄的地方显示 PDN type 为 IPv4。如果双栈的话,这里的 type 类型是IPv4IPv6。在国家机构,运营商的联合推动下,苹果手机从 iOS12.1 开始已经开启了默认双栈的支持。

下面该谈到 Android 了,安卓相对来说开放一些的,大多数的手机都可以支持 APN协议编辑,并且部分手机已经缺省设置变成了 IPv4IPv6 双栈协议支持,如下截图:

将 IPv6 照进现实,我们需要做些什么?

但在这里还有几个坑需要告知:

  1. 不是所有的安卓手机都可以编辑 APN 协议类型。
  2. 即使可以编辑 APN 协议类型,也不是所有的手机都会把 IPv4/IPv6 作为缺省协议。
  3. 有些手机尽管是支持双栈的,但从系统 API 里面是看不到所获得的 IPv6 地址,但如果你同时开了 WiFi,奇迹出现了,v6 地址又出来了。

碎片化的安卓带来了碎片化的双栈支持,这对客户端进行当前网络环境判断带来了很大挑战。

移动运营商现在支持双栈吗,手机得到的地址有什么玄机?

说完了端,下一步就需要看看管,即运营商到底对于 v6支持的现状如何,策略如何?如开篇所说抛开固网不谈,在移动网的场景下,三大运营商都已经开通了IPv4IPv6 的双栈支持。不过需要说明的是,这里的双栈支持管道特指下图中从空口到移动核心网这里,至于骨干网和阿里网络的双栈支持要根据各个运营商的互联情况来看。

将 IPv6 照进现实,我们需要做些什么?

下面看下在某运营商网络下终端拿到的地址信息:

将 IPv6 照进现实,我们需要做些什么?

一般用户回拿到 IPv4v6 双栈地址,v6地址的 DNS 不是必须的有些省份可能没有,但在双栈情况下只要 DNS 能支持 AAAA 记录的解析查询即可。

下面就是要进入重要的 IPv6 地址获得环节了,即以上的2409开头的 v6地址客户端是怎么获得到呢,这个地址有什么玄机吗?移动网内手机和网络通讯有两个面,一个是控制面也就是俗称的信令面,这个层面 APP 是感知不到的,另一个是用户面,即APP 正常的业务数据流都走在这里。在 IPv4 only 的场景下,手机地址的获得单纯通过控制面的信令交互即可,但在 IPv4 IPv6 双栈场景下,流程就发生了一些变化。先来看信令面:

将 IPv6 照进现实,我们需要做些什么?

Create Session Request 是手机发给核心网的,里面携带了几个重要的信息:

将 IPv6 照进现实,我们需要做些什么?

PDN Type 字段需要是 IPv4/IPv6, PDN Address and Prefix(IPv6) 是全零。

Create Session Response 是核心网对手机的响应。

将 IPv6 照进现实,我们需要做些什么?

里面包含了类似 PDN AddressPrefix 和 DNS Server 的信息,但你可能会很奇怪发现这个 Prefix 不是一个真正的 Prefix,也和手机获得到的地址格式有很多差异。

这时候就需要再看一下用户面的消息:

将 IPv6 照进现实,我们需要做些什么?

根据 IPv6 地址分配规则,FE80开头的是链路单播地址,FF02::1是所有开启了 IPv6组播的主机,再来看下 Router Advertisement 消息:

将 IPv6 照进现实,我们需要做些什么?

这个消息就包含了重要的 Prefix 字段,这是基于 IPv6 stateless Autonomous Address-Configuration(SLACC) 的实现,从后续的数据流可以看到,手机收到了这个64位的前缀后补充了后面的64位组合成完整的128位IPv6地址作为源地址进行正常的业务访问。不过稍微有一点疑问的是这后面的64位地址是怎么生成的,从多次测试来看每次后64位都是变化的,由于在手机上构造包需要 root,所以后续条件具备情况下会进行通过构造不同后64位的数据报文来进行测试,看看网络是不是仅靠前64位来识别用户的。

接着就面临到了最后一个问题,即这个地址有玄机吗?128位的地址一方面让人很难记,另一方面也给地址扫描造成了巨大的难度,如果这些地址都是完全随机的,那么对于那些依赖地址信息的后端业务来说将是巨大的灾难。不过运营商帮我们在一定程度上解决了这个问题,但他们的出发点是为了更好的监管,也就是在文章片头的那句世界上的每一粒沙子都有一个地址后面要加上世界上每一粒沙子都是可被追踪的。

根据工信部2014年发布的《YD/T 2682-2014 IPv6接入地址编址编码技术要求》,其中对用户设备接入地址结构的指导性意见为:

将 IPv6 照进现实,我们需要做些什么?

其中:

  • PB 为 IPv6 接入地址块前缀,长度为 n 的比特串。
  • AI 是编址标识符,长度为 s+t 的比特串,包括长度为 s 的省份标识符和长度为 t 的接入类型表示符两部分。其中接入类型包括固网动态接入、固网静态接入、移动蜂窝接入。
  • CC 是区/县编码,长度为 8 位。在工信部的文件附录,明确了全国各区县的具体8位编码。
  • SSI 是子网标识符,长度为56-n-s-t。
  • IID 是接口标识符,长度64位。

国内三大运营商都基于此技术要求做了进一步的细化,这里不再描述细节,但从地址大段上来看中国移动使用的2409:8000::/20IPv6地址,中国联通使用的2408:8000::/20 IPv6地址,中国电信则有240E::/24、240E::/20、2001:0C68 ::/32、2001:07FA:0010::/48、2402:8800::/32 五块地址。

不过这里需要说明的是目前双栈仅在 4G 下开启,也就是说回到 2G 会变成 IPv4 only,这又该客户端对于当前网络环境判断增加了变数;还有就是由于目前地址具有了一定的位置属性,那么跨区县移动场景下的地址分配怎么处理还暂不明确。

Happy EyeBall 问题

在手机,网络和服务端全链路支持双栈的场景下,手机首先要面对的就是一个选择问题,即一个域名会解析出来 A 和 AAAA 记录,简化来说就是两个地址,同时返回两个地址,怎么选择?一个快,一个慢怎么选择?一个出问题怎么选择?地址选择好了才能有后续的建连,才会有业务发生,所以这个选择策略很重要。如果从体验角度出发,谁快连谁这是最简单的逻辑,但在当前 v4 网络好于 v6 的大环境下这样的逻辑只会让 v6 的普及变得更为艰难,因此针对这个问题,IET F先起了一个名字叫 Happy Eyeball,接着发布了两份 RFC 来描述推荐的处理逻辑,最新的是 RFC8305 Happy Eyeballs Version 2: Better Connectivity Using Concurrency,有兴趣的可以去阅读下,这里只摘抄出最重要的一段:

The algorithm proceeds as follows: if a positive AAAA response (a responsewith at least one valid AAAA record) is received first, the first IPv6connection attempt is immediately started. If a positive A response is receivedfirst due to reordering, the client SHOULD wait a short time for the AAAAresponse to ensure that preference is given to IPv6 (it is common for the AAAAresponse to follow the A response by a few milliseconds). This delay will bereferred to as the "Resolution Delay". The recommended value for theResolution Delay is 50 milliseconds. If a positive AAAA response is receivedwithin the Resolution Delay period, the client immediately starts the IPv6connection attempt.

简单来说就是 RFC 建议优选 IPv6,且给 AAAA 记录的返回留50毫秒的容忍期。

由于系统的限制,这样选择逻辑的落地是客户端网络库无关的,基于网络材料来看目前各系统的具体实现:

苹果 iOS:在 v4 和 v6 双协议栈的情况下,从 ios9 开始苹果会发出 A 和 AAAA 记录的 DNS 请求,如果首先收到了 DNS 的 AAAA 记录返回,那么苹果会马上发出v6 的 syn,如果首先收到了 A 记录的返回,会有一个 25ms 的定时器,如果超时了就会发送 v4 syn,如果在这个定时器内收到 AAAA 就会发送 v6 的 syn。这个机制和 Happy Eyeball 基本一致,只是等待时长不同,苹果会不会修改到 RFC 建议值未知。

Android:优选 v6,但等待时长未知。

这样的机制从理论上就会出现由于这个等待时长造成业务体验的下降。

还有 NAT 吗,会有 PAT 吗,还有防火墙吗?

在移动网只有 IPv4 的场景下,手机用户访问服务端的整个链路中必不可少的一个中间设备就是运营商的防火墙,一方面为了应对 v4 地址稀缺的问题,设备会做公私网的地址翻译,为了更进一步的复用地址,还会做端口翻译,另一方面为了安全性考虑,设备会做一些类似 ACL 的安全策略,通常只会允许出方向的访问,同时为了降低对于设备的负荷,还会做一些超时的设置,断开那些空闲较长的连接。而这样的限制对于服务端某些过度依赖地址的应用,对于端口转换不友好的应用,对于需要长期保活的应用都会产生一定的影响,那么在 IPv4v6 双栈的场景下如何呢,我做了如下的测试:在一台有公网 IPv6 地址的服务器上简单用 python 写了一个开启80端口的服务端:

Server start at:2400:3200:1000:xx:::80

wait for connection...

在手机上执行busybox telnet 2400:3200:1000:xx:: 80 命令

这是服务端打出的日志

Connected by('2409:8928:84e:995:xxxx:xxxx:xxxx:xxxx', 34102, 0, 0)

其中 Connected by ('2409:8928:84e:995:xxxx:xxxx:xxxx:xxxx 为服务端看到的手机地址,34102为对应的端口号,那么这个地址和端口号是不是手机自身的呢,去手机上看一下:

odin:/ $ busyboxnetstat

Active Internet connections (w/o servers)

Proto Recv-Q Send-Q Local Address Foreign Address State

tcp 0 0 10.84.66.147:43623 111.13.134.131:443 CLOSE_WAIT

tcp 0 0 10.84.66.147:46051 140.205.34.21:443 ESTABLISHED

tcp 0 0 ::ffff:10.84.66.147:49856 ::ffff:112.13.64.13:5333 ESTABLISHED

tcp 0 0 ::ffff:10.84.66.147:37201 ::ffff:39.106.239.196:443 ESTABLISHED

tcp 0 0 ::ffff:10.84.66.147:55440 ::ffff:118.194.55.183:5223 ESTABLISHED

tcp 0 0 2409:8928:84e:995:3b4a:38ce:8ead:1972:34102 2400:3200:1000:xxxx:::80ESTABLISHED

从上面输出来看,运营商的中间设备没有做 NAT,也没有做 PAT,服务端看到了手机发出的原始的源地址和源端口,当然防火墙还是有的,主动从服务端还是不能访问手机。

MTU问题

从协议头来看 v4 和 v6 有一个比较重要的差异就是 Don’t Fragment bit 这个位一直开的,也就是由于一直是开的所以在 IPv6 的头里面就没有明示这个字段,如果有fragment 就会增加一个 Fragemention Header。由于网络中间支持 v6 的路由器不会对对 IPv6 包进行分片,所以如果一个包过大那么路由器会产生 ICMP6 Type2 数据包,内含 Packet Too Big (PTB) 和 MTU 信息返回给发送方,这样机制看上去比较好,但是由于中间设备可能会过滤掉 PTB 数据包造成这样的通知发送方收不到影响正常传输,因此发送方最好在开始的时候就不要发送过大的数据包,目前一个建议参考值 MTU 是1280字节。

将 IPv6 照进现实,我们需要做些什么?

相关推荐