IPv6 的基本概念

        众所周知,32 位的 IPv4 地址已经耗竭,IPv6 采用 128 位的地址长度拥有更大的地址空间。首先我们先来认识一下 IPv6 到底长成什么样子。

初识 IPv6


上图是我们最熟悉的 ping 的 IPv6 版本 ICMP v6。可以看到,IPv6 数据报文和IPv4 有很大的差别:

1、数据链路层(L2)的 type字段标识为 0x86dd,表示承载的上层协议是 IPv6

      IPv4 对比:type字段为 0x0800

2、IPv6 的头部字段,和 IPv4 差别巨大可以猜测到,IPv6 和 IPv4无法兼容

      IPv6 的报文头部格式如下:

        IPv6 报文头部更精简了,字段更少了,对比起 IPv4,有以下几个地方值得注意:

        一、IPv6 报文头部是定长(固定为 40字节),IPv4 报文头部是变长的。这个意味着,写代码处理 IPv6 数据报文的效率会提高很多:)

        二、IPv6 中 Hop Limit 字段含义类似 IPv4 的 TTL。

        三、IPv6 中 的 Traffic Class 字段含义类似 IPv4 中的 TOS(Type Of Service)。

        四、IPv6 的报文头部取消了校验和字段。取消这个字段也是对 IPv4 协议的一个改进。当 IPv4 报文在网路间传输,每经过一个路由器转发就是修改 TTL字段,就需要重新计算校验和,而由于数据链路层 L2 和传输层 L4 的校验已经足够强壮,因此 IPv6 取消这个字段会提高路由器的转发效率。值得一提的是,在 IPv6 协议下,传输层 L4 协议 UDP、TCP 是强制需要进行校验和的(IPv4是可选的)。

        五、IPv6 报文头部中的 Next Header 字段表示“承载上一层的协议类型”或者“扩展头部类型”。这里的含义与IPv4有很大的差别,需要加以解释:

        当 IPv6 数据报文承载的是上层协议 ICMPv6、TCP、UDP 等的时候,Next Header的值分别为 58、6、17,这个时候和 IPv4 报文头部中的Protocol字段很类似。

        当不是以上 3 种协议类型的时候,IPv6 报文头部紧接的是扩展头部。扩展头部是 IPv6 引入的一个新的概念,每个 IPv6 的数据报文可以承载 0 个或多个扩展头部,扩展头部通过链表的形式组织起来。当 IPv6 数据报文承载着扩展头部的时候,Next Header 的数值为扩展头部的类型值。

        为什么要引入扩展头部这个概念,这里也是 IPv6 对 IPv4 改进的一个方面,用扩展头部取代了 IPv4 的可选项信息,精简了 IPv6 的头部,增强了 IPv6的扩展性。有同学会不会有疑问,IPv6 的分片数据报文怎么处理?其实就是使用了 IPv6 扩展头部。我们来抓一个 UDP 分片报文来看看。

        当发送一个分片 IPv6 数据报文的时候,IPv6 使用的是扩展头部的形式组织各个分片的信息,如图 IPv6 报文头部 Next Header 字段值为 44 表示存在扩展头部,扩展头部是 IPv6 分片数据信息。

        对比 IPv4,分片信息是记录在 IPv4 报文头部的分片字段中。

        IPv6 的扩展头部类型有很多种,除了上述的分片头部,还有路由头部、逐跳可选头部等,具体的可以参考 RFC 2460。

IPv6 的地址语法

        一个 IPv6 的地址使用冒号十六进制表示方法:128 位的地址每 16 位分成一段,每个 16 位的段用十六进制表示并用冒号分隔开,例如:

        一个普通公网IPv6地址:        2001:0D12:0000:0000:02AA:0987:FE29:9871

        IPv6 地址支持压缩前导零的表示方法,例如上面的地址可以压缩表示为:

        2001:D12:0:0:2AA:987:FE29:9871

        为了进一步精简 IPv6 地址,当冒号十六进制格式中出现连续几段数值 0 的位段时,这些段可以压缩为双冒号的表示,例如上面的地址还可以进一步精简表示为:

        2001:D12::2AA:987:FE29:9871        又例如 IPv6 的地址:

        FF80:0:0:0:FF:3BA:891:67C2         可以进一步精简表示为:

        FE80::FF:3BA:891:67C2 。

        这里值得注意的是,双冒号只能出现一次。

IPv6 地址的号段划分和前缀表示法

        IPv6 拥有 128 位巨大的地址空间,对于那么大的空间,也不是随意的划分,而是使用按照 bit 位进行号段划分。

        IPv6 的地址结构如下图:

        例如:RFC 4291中定义了 n=48, m=16,也就是子网和接口 ID与各占64位。

        IPv6 支持子网前缀标识方法,类似于 IPv4 的无分类域间路由 CIDR 机制(注意:IPv6 没有子网掩码 mask 的概念)。使用 “IPv6 地址/前缀长度” 表示方法,例如:2001:C3:0:2C6A::/64 表示一个子网,而2001:C3:0:2C6A:C9B4:FF12:48BC:1A22/64 表示该子网下的一个节点地址。

        可以看到,一个IPv6 的地址有子网前缀+接口 ID构成,子网前缀由地址分配和管理机构定义和分配,而接口 ID 可以由各操作系统实现生成。

IPv6的地址类型

        IPv6地址分三种类型

        1、单播,对应于 IPv4 的普通公网和私网地址

        2、组播,对应于 IPv4 的组播(多播)地址

        3、任播,IPv6 新增的地址概念类型

        IPv6 没有广播地址,用组播地址实现广播的功能。实际上我们工作和生活最可能最多接触的就是单播地址,接下来本文重点会讲解单播地址的种类。组播和任播地址有兴趣的同学自行查阅相关 RFC 和文献。

IPv6 单播地址

        注意,大家如果在网上搜索 IPv6 的地址,可能都是千篇一律的把所有“出现过”的单播地址介绍出来,其实有一些单播地址类型已经在相关的 RFC 中被废除或者不建议使用,而本节会指出这类地址。同时,在介绍单播地址的时候,尽量与 IPv4 中对应的或者相类似的概念做对比,加深理解。

       IPv6 单播地址有以下几种:

1、全球单播地址

        前缀 2000::/3,相当于 IPv4 的公网地址( IPv6 的诞生根本上就是为了解决 IPv4 公网地址耗尽的问题)。这种地址在全球的路由器间可以路由。

2、链路本地地址

        前缀 FE80::/10,顾名思义,此类地址用于同一链路上的节点间的通信,主要用于自动配置地址和邻居节点发现过程。Windows 和 Linux 支持或开启IPv6 后,默认会给网卡接口自动配置一个链路本地地址。也就是说,一个接口一定有一个链路本地地址。如下图:

        值得说的是,每个接口必须至少有一个链路本地地址;每个接口可以配置1 个以上的单播地址,例如一个接口可以配置一个链路本地地址,同时也可以配置一个全球单播地址。

        注意,很容易会把链路本地地址和 IPv4 的私网/内网地址对应起来,其实链路本地地址对应于 IPv4 的 APIPA 地址,也就是 169.254 开头的地址(典型场景就是 Windows 开启自动获取地址而获取失败后自动分配一个 169.254 的地址)。而 IPv4 私网对应于 IPv6 的什么地址,在后面会介绍。

3、唯一本地地址

        前缀 FC00::/7,相当于 IPv4 的私网地址(10.0.0.0、172.16.0.0、192.168.0.0),在 RFC 4193中新定义的一种解决私网需求的单播地址类型,用来代替废弃使用的站点本地地址。

        可能看到这里,有同学会跳出来说:IPv6 不是为了解决 IPv4 地址耗尽的问题吗,既然 IPv6 的地址空间那么大,可以为每一个网络节点分配公网 IPv6 的节点,那为什么 IPv6 还需要支持私网?这里需要谈谈对 IPv6 下私网支持的认识。

        在 IPv4 中,利用 NAT 技术私网内的网络节点可以使用统一的公网出口访问互联网资源,大大节省了 IPv4 公网地址的消耗(IPv6 推进缓慢的原因之一)。另一方面,由于默认情况下私网内节点与外界通信的发起是单向的,网络访问仅仅能从私网内发起,外部发起的请求会被统一网关或者防火墙阻隔掉,这样的网络架构很好的保护了私网内的节点安全性和私密性。可以设想一下,如果内部每台办公电脑都配置了 IPv6 的公网地址上网,是多么可怕的事情,每台办公电脑都会面临被黑客入侵的威胁。

        因此,在安全性和私密性要求下,IPv6 中同样需要支持私网,并且也需要支持 NAT。在 Linux 内核 3.7 版本开始加入对 IPv6 NAT 的支持,实现的方式和 IPv4 下的差别不大。

4、站点本地地址

        前缀 FEC9::/48,以前是用来部署私网的,但 RFC 3879中已经不建议使用这类地址,建议使用唯一本地地址。大家知道有这么一回事就可以了。网上还有很多文章还提到这种地址,但是没有说明这种地址已经不再使用。

5、特殊地址:回环地址

        0:0:0:0:0:0:0:1或::1,等同于 IPv4 的127.0.0.1。

6、过渡地址:内嵌 IPv4 地址的 IPv6 地址

        就是在 IPv6 的某一些十六进制段内嵌这IPv4的地址,例如 IPv6 地址中64:ff9b::10.10.10.10,此 IPv6 地址最后4个字节内嵌一个 IPv4 的地址,这类地址主要用于 IPv6/IPv4 的过渡技术中。

  • IPv4 兼容地址

        0:0:0:0:0:0:w.x.y.z 或 ::w.x.y.z(其中 w.x.y.z是点分十进制的 IPv4 地址)。但在 RFC 4291中已经不推荐使用这类地址,大家知道有这么一回事就可以了。

  • 过渡地址:IPv4 映射地址

        0:0:0:0:0:FFFF:w.x.y.z 或 ::FFFF:w.x.y.z(其中 w.x.y.z是点分十进制的IPv4 地址),用于 IPv6 地址表示 IPv4 地址。主要用于某些场景下 IPv6 节点与 IPv4 节点通信,Linux 内核对这类地址很好地支持。

  • 过渡地址:特定过渡技术地址

        6to4 地址、ISATAP地址、Teredo 地址主要用于对应的过渡技术的地址。

原文出自:https://mp.weixin.qq.com/s/BithR9F3mzOYnPojBDs35w

发表评论

电子邮件地址不会被公开。