Fork me on GitHub

FE80::1 is a Perfectly Valid IPv6 Default Gateway Address/FE80::1是一个完全有效的 IPv6 默认网关地址

最近正在学习 IPv6 的相关知识,有一篇比较不错的解析 IPv6 默认网关以及邻居发现协议(Neighbor Discovery Protocol)的文章,所以大体做下中文翻译,供查阅用。
文章地址:FE80::1 is a Perfectly Valid IPv6 Default Gateway Address


FE80::1 是一个完全有效的 IPv6 默认网关地址

最近我的一篇博文总结了一些关于 IPv6 的常见问题,但对于 IPv6 的讲师们来说,他们的学生经常问及有关 IPv6 链路本地地址以及其工作原理的问题。在这篇博文上,我会在 IPv6 的地址方面对一些新手会遇到的问题作出分析。

经常单播,偶尔多播,从不广播

单播

单播地址,顾名思义就是为了一对一通讯准备的地址。在理解了 IPv4 公共地址的基础上很容易理解 IPv6 的全球单播地址(Global Unicast Address,地址范围 2000::/3)。不管你当前使用的 IPv4 公共地址或 IPv6 全球单播地址是由区域互联网注册管理机构(RIR)或者你的上游 ISP 分配,它们都能正常的与全球的公共地址进行互联网通讯。

在大部分企业或小型组织中,他们使用 IPv4 私有地址块用来构建他们的内部网络;但对于 IPv6 来说,虽然有唯一区域地址(地址范围 FD00::/8)这种东西可以用在私有网络上,但是这种用法并不太好(或者说,不被官方推荐来做私有网络)。在RFC 4864, Local Network Protection for IPv6 这篇文档中详细阐述了在 IPv6 网络环境的内网下为什么不太需要私有网络地址或者 NAT 这种东西。Tom Coffeen 的博客也以“3 Ways to Ruin Your Future Network with IPv6 Unique Local Addresses”为题作了一篇博客(A面B面)。我们之前也在IPv6 COE Podcast #3讨论过。

多播

大多数人应该比较熟悉多播地址的工作原理。IPv4 多播地址(通常被叫做 Class D 地址)的范围是 224.0.0.0/4 。IPv6 多播地址以一个非常显眼的 “FF” 前缀开头,其地址范围是 FF00::/8。“FF”两个16进制数字之后的4位是标志位,再后面4位是多播消息的位数。IPv6 多播地址可以用来做链路本地的 LAN 通信,也可以用来做指定站点的通信,甚至可以用在公网通信上。一些常见的链路本地的信息通常以“FF02”作为 IPv6 多播地址的开头,而 FF02::1 是用作所有结点的链路本地多播地址。

广播

只有 IPv4 拥有广播这一技术。广播被用来向当前 LAN 内的所有结点发送一个包。无论是用 255.255.255.255(指定目标为广播域内所有主机)或者使用 192.168.1.255 这种限制在一个子网的广播地址,他们在二层网络都会被转换为 MAC 地址为 FF:FF:FF:FF:FF:FF 的帧。广播帧会被发送到所有以太网交换机的端口上。而对于 IPv6,不会使用广播这一发包方式,所以没有对应的广播地址概念。 IPv6 也不会在 LAN 网络上使用广播,但是使用 所有结点的链路本地多播组地址(FF02::1)是能达到类似的效果的。

链路本地地址与自动专用 IP(Automatic Private IP Addressing,APIPA)

单播、播与广播这些概念对于 IPv4 的网络专家来说可能很熟悉,但仍然有一个不那么常见的地址种类可以用来在私有 LAN 网络上进行单播通信,但他们只在本地被使用(也就是受限在单一 LAN 广播域中),从不用来通过三层网关接收或者发送三层的网络通信。

刚刚接触 IPv6 的人经常发现有一种地址,它虽然也存在与 IPv4 中,但是与 IPv4 中的同类地址的概念差别非常大,那就是链路本地地址。IPv6 的链路本地地址由“FE80”开头,而最后面的64位代表网络接口辨识符(Interface Identifier, IID)。取决于结点所安装的操作系统使用的 IID 算法, IID 可能来自于带有 SLAAC 的 EUI-64-改RFC 4941 中的私有地址方法,或是 RFC 8064 中最新发布的稳定 SLAAC IID 方法。

当一个主机启动时,它会自动将 FE80::/10 中的一个 IPv6 地址分配给它的网络接口。通常这个地址是以下这种形式:

FE80:0000:0000:0000:abcd:abcd:abcd:abcd

可以看到,这个地址以 FE80 开头,后面有54位的0,最后面是全局唯一的 64位 IID。

你可以阅读 Rick Graziani 的书 IPv6 Fundamentals: A Straightforward Approach to Understanding IPv6 来了解更多有关 IPv6 链路本地地址与其用途。

很多人第一次接触 IPv6 链路本地地址可能会感到困惑,因为 IPv4 中其实并没有与其对应的地址种类。但是 IPv4 中仍然有一个相关的概念,那就是 自动专用 IP。当一个处于 IPv4 网络环境下的主机 DHCP 失败时,他会给自己分配一个 APIPA 的地址,认定自己无法进行网络通信。我相信你一定见过一个拥有 169.254.0.0/16 范围内 IPv4 地址的主机吧。(详情参见 RFC 3927)。

链路本地地址作为默认网关

在任何一个启用 IPv6 的主机或路由器上都有链路本地地址,它是基于 LAN 的邻居发现协议的基础。某一主机通过 重复地址检测协议(Duplicate Address Detection, DAD确定它自身的链路本地地址在当前 LAN 下唯一之后,就会通过 ICMPv6 向外发送路由器请求(Router Solicitation, RS)。

路由器上也有 IPv6 链路本地地址。当路由器收到主机的路由器请求(主机通过路由器请求发现有无可用的路由器)之后,路由器就会通过 ICMPv6 返回一个 路由宣告(Router Advertisement)消息。这份路由宣告的消息,其源地址也是路由器自己的链路本地地址。当主机收到路由宣告消息时,主机读取其中的内容并按照包中的建议策略进行地址设置,当使用 SLAAC 的地址设置方法时,使用带路由宣告的掩码 /64 的 IPv6地址作为一个全球地址,并使用路由器的链路本地地址(也有RA 消息中的 MAC 信息)作为其默认网关。也就是说,主机此时使用路由器的链路本地地址作为其 IPv6 默认路由(0::/0)的下一跳地址。(新人可能会对于这件事非常诧异: IPv6 竟然会用一个链路本地地址作为其下一跳的路由!在这时候,请他们多多学习一下 IPv6 链路本地地址的相关内容。)

链路本地地址也可以理解为是某种程度上的中间地址(它定义了如何连接到下一跳)。当主机向外发包时,包的源地址仍然是主机的全球地址,目的地址也仍然是发送目标的全球地址,而路由表中的链路本地地址,就是用来在邻居信息缓存中映射下一跳的 MAC 地址。

所以路由器的链路本地地址其实是一个完全有效的下一跳地址,了解有关 IPv6 邻居信息缓存会帮助你加深这一概念,你也可以到实际的主机上查看你的 IPv6 单播路由表。路由器不会修改包的目的地址或者源地址(他们仍然是全球地址),但他们确实用链路本地地址来做包转发。

自主配置的链路本地地址

有人可能会发现,同一个 IPv6 链路本地地址可以用在一个主机的不同网络接口上。这是因为每个网络接口被认定是连接在不同的链路上。因此,对于这个地址来说,他在对应的网络区域里上是唯一的就可以了。

IPv6 结点会使用 EUI-64、私有地址方法或者 stable SLAAC 来生成 IID,但是 IID 不方便记忆,而且可能在手工的静态配置中需要复制粘贴。这种情况也会存在与路由器或者防火墙、负载均衡器等中间设备上。我们在固化网络配置的时候也会需要静态配置诸如下一跳 IP 这种情况。因此,我们需要让事情变得简单点。

一种方法是为上游路由器手动分配链路本地地址。如果你为路由器的每个网络接口设置 FE80::1 这一链路本地地址,并且这一地址在他们自身的网络上唯一,那这个路由器就会成为这些网络的默认网关。因此,在这些网络中 FE80::1 都会是默认路由的下一跳地址。下面的图片是一个大致的示意图,描述了使用手工配置的链路本地地址作为默认网关的情形。在这种情况下,手工分配的 IPv6 地址与默认网关就可以让这些工作简单一点了。

自助配置的链路本地地址示意图

小结

当你初学 IPv6,你可能会被链路本地地址这一概念所困扰,但是相信你很快就会熟悉其中的工作原理,包括使用链路本地地址作为静态路由的下一跳地址,或是作为路由表中的默认路由。你也可以通过自己配置的链路本地地址简化一些静态网络配置的工作。当你熟悉了相关的知识之后,你就会发现,这只是 IPv6 为了简化网络协议所做的微小的工作之一。


篇幅不长,主要是概述了 IPv6 链路本地地址的有效性,以及其在网络通讯中发挥的作用。有 IPv6 实验环境的人可以尝试自己观察一下相关的表现。下面的图片是 Linode 上某一带 IPv6 网络环境的结点相关网络配置:

真实环境中的 IPv6 链路本地地址配置