概述

IPv4 协议定义网络与网络之间的数据交换方式,具体来说,它定义了网络地址的概念,并且描述了网络设备之间如何根据网络地址来进行通信。IPv4 协议定义的网络地址也被称为 IPv4 地址,一个 IPv4 地址用一个 32 位的二进制数表示,因此 IPv4 地址的数量是有限的,随着网络设备数量的增加,IPv4 地址会变得不那么够用。

IPv6 同样是用于定义网络与网络之间的通信方式的,而且它也有网络地址的概念,但是与 IPv4 不同的是,它的网络地址长达 128 位,它的提出能够解决 IPv4 地址不够用的问题,换句话说,假如一下子把所有运行着 IPv4 协议的网络设备一下子升级成运行 IPv6 协议,那么网络地址是绝对够用的。

我们考察这样一种情形:设备 A 同时可触达 IPv6 网络和 IPv4 网络,设备 B 不能触及到 IPv6 网络上的任何一台但是能够接触 IPv4 网络上的设备 A, 可否在设备 A 和设备 B 之间建立一个隧道连接,使得设备 B 能够访问 IPv6 网络上的资源?

ipv4-ipv6.png

解决思路(方法一)

为了让一个 IPv4 only 网络中的某台设备也获得 IPv6 地址并且能够访问 IPv6 网络上的资源,我们使用 Linux 内核 sit 模块提供的 sit 隧道功能,它支持把 IPv6 分组封装在一个 IP 分组中:

ip-in-ip.png

从这个意义上说,它有那么一点点类似于 ipip 隧道协议,只不过它还还支持封装 IPv6 分组,而不只是 IPv4 分组。

思路是这样的,当一个无法直接触达 IPv6 网络的主机 A 想访问一个位于 IPv6 网络中的主机 C 时,它利用一个同时 IPv4, IPv6 可达的主机 B, 它事先向 B 获取到一个 IPv6 地址,比如说让 B 把自己多余用不完的地址拿出一个给 A 用,然后当 A 需要跟 C 通信时,它生成一个 IPv6 分组,sender 写自己(从 B 那借到的)IPv6 地址,receiver 写 C 的 IPv6 地址,以此生成 Inner IP(v6) Header, 然后数据作为 Inner IP(v6) Payload, 然后在 Outer IP Header 的 sender 写自己的真实 IPv4 地址,receiver 写 B 的 IPv4 地址,然后把这个包发给 B, B 再把这个包发给 C。当 C 需要和 A 通信时,C 不需要做任何封装。

这种方法要求:

  1. A,B 有相对固定的 IPv4 地址,例如 A, B 都有固定的公网 IPv4 地址,或者 A, B 能够通过内网通信,并且 A, B 的内网 IPv4 地址是相对固定的;
  2. A 没有相对固定的 IPv4 地址(无论是公网的还是私网的),但是 B 有相对固定的 IPv4 地址,并且 A 能够和 B 建立一个相对稳定的隧道,我们可以给隧道两端的虚拟网卡分配固定 IP,这时可以归结到情形 1;
  3. 在 1 或者 2 满足的前提下,B 有至少三个可以分配的公网 IPv6 地址,其中一个给 B 自己用,第二个用在隧道的 B 端,第三个用在隧道的 A 端;

过程

为了验证这个方案是可行的,我们在 AWS 云平台上通过建立 VPC, Subnet 和 EC2 实例来模拟这个环境,然后使用 ip 命令行工具建立隧道、分配地址并设置路由来实现上文中 A 与 C 的双向联通。

完成这个实验需要我们创建如下资源: