IPv4 地址耗尽,为什么 IPv6 没有广泛将其取代?
我在过去的二十年里听说过 IPv6,但从未超越“一个为 IPv4 地址空间问题设计的过度工程解决方案”的认知。IPv6 甚至被描述为“每个原子都可以拥有自己的 IP 地址,不再有 IP 地址短缺的问题”,但我不知道这有多真实。偶尔我会在某些地方看到 IPv6 地址,因为几乎所有设备今天都支持 IPv6。我相信移动网络运营商甚至默认使用它,所以你可能正在使用 IPv6 设备阅读这篇文章。
上周,我决定了解一下 IPv6 是如何在幕后工作的,并且学到了不少有趣的事实。
免责声明:我不是 IPv6 或网络工程领域的专家。这是我过去几周个人阅读之旅的结果,如果我犯了任何错误,我非常愿意接受指正。请继续阅读 :)
IPv6 vs IPv4
IPv6 这个名字曾经让我感到困惑,因为我以为 IPv4 的名字来源于它用来表示32位的四个八位字节,所以 IPv6 应该叫做 IP16。但我了解到,这实际上是协议的版本号。在 IPv4 出现之前,显然有过 IPv1、IPv2 和IPv3。它们曾用于内部研究 IP 协议,后来被我们今天使用的 IPv4 取代。80 年代甚至有一个 IPv5 的提议,旨在优化实时通信,但最终被解决地址空间问题的 IPv6 取代。这就是为什么 IPv6 被称为 IPv6 的原因。它字面上就是 IP 版本 6。甚至曾有过创建 IPv7、IPv8 等的尝试,但这些都已被废弃或搁置。
和 IPv4 一样,IPv6 协议也有一个寻址方案。IPv6 使用 128 位地址,而不是 IPv4 的 32 位地址。但协议之间的差异远不止地址空间的大小。实际上,如果你到目前为止只使用过 IPv4,那么 IPv6 看起来就像外星科技,因为它具有一些古怪的特性,例如:
IPv6 没有子网掩码
IPv6 支持与 IPv4 类似的 CIDR(无类别域间路由)寻址,但从用户的角度来看,IPv6 地址要简单得多:前半部分是互联网(全球),后半部分是本地。这也是建议使用IPv6地址的方式。所以,当你访问一个显示你 IP 地址的网站时,它会显示如下的IP地址:
1111:2222:3333:4444:5555:6666:7777:8888
但是,你的 ISP 只知道你是 1111:2222:3333:4444,并将这一部分(/64)分配给你。地址的剩余部分对你网络中的每个设备都是唯一的。ISP 只需将任何以 1111:2222:3333:4444 开头的数据包转发到你的路由器,然后你的路由器将数据包传输到相应的设备。因此,地址的后半部分,即 5555:6666:7777:8888,我们从现在起称之为 INTERFACE_ID,是你设备独有的。这意味着,你的每个设备都有一个唯一的 IPv6 地址,并且可以从世界任何地方单独访问,因为:
IPv6 没有 NAT
我以前以为 IPv6 也可以做 NAT,只是因为害怕来自 HackerNews 社区的潜在反对而没人这么做。显然事实并非如此。实际上,没有任何发布的标准用于 IPv6 的 NAT。虽然有一个叫做 NAT66 的草案提议,但它尚未成形。
IPv6 不需要 NAT,因为它能够为地球上的每个设备提供一个单独的全球可访问地址。这对我来说感觉很奇怪,因为 NAT,尽管你在玩在线游戏时可能讨厌它,但它给人一种温暖的感觉,即你的本地设备从外部是不可访问的,除非你通过 UPnP 或端口转发明确允许它。这是一种很难摆脱的虚假安全感。
残酷的真相是,NAT 不是一个安全屏障。它只是一个替代的包转发机制。你的 IPv6 路由器默认情况下不应将外部的连接尝试转发到你的本地设备。因此,即使没有 NAT,你也能获得相同的安全性。事实上,你可以通过 IPv6 地址访问本地网络中的每个设备,而无需通过路由器或单独的 VPN 配置,这令人惊叹:只需进行身份验证,就可以了。假设,土耳其伊斯坦布尔的一把智能牙刷可以直接连接到加拿大安大略省的一个温度传感器,并创建世界上最具多样性的僵尸网络之一。
不过,使用 IPv6 时,有一个与安全相关的问题,这源于每个设备都有一个单独的 IPv6 地址的便利:你的设备可能会被指纹识别和单独追踪。这对隐私来说是个坏消息。因此,现代操作系统发明了临时 IPv6 地址的概念,这些地址会定期更改 INTERFACE_ID。你可以使用你的永久 IPv6 地址来监听外部连接,但在建立连接时,你的 IPv6 地址将显示为那个频繁更改的临时地址。
提到不需要绕过各种障碍来访问,IPv6 的另一个有趣特性是:
IPv6 地址是自配置的
IPv6 协议不需要 DHCP 服务器,也不需要手动网络配置来确定 IP 地址、子网掩码和网关地址。设备无需请求集中式服务器即可获得 IP 地址。这是通过称为 SLAAC 的协议实现的。它按照以下步骤逐步生成设备的 IPv6 地址:
-
操作系统(特别是操作系统的 IPv6 栈)生成一个 64 位设备标识符,通常是随机的,比如 5555:6666:7777:8888(通过公平的掷骰子决定),这构成了你的 IPv6 地址的 INTERFACE_ID 部分。
-
操作系统在 INTERFACE_ID 前加上 fe80,本地专用的 IPv6 网络前缀。所以,你的 IPv6 地址现在是:fe80::5555:6666:7777:8888。(注意“a::b”语法;它表示“在‘a’和‘b’之间是全零值段”。稍后会详细介绍)
-
你的设备现在向本地网络上的指定邻居多播组发送一个数据包,以确保没有其他设备使用相同的 IPv6 地址。这称为重复地址检测(DAD)。分配到重复地址的概率比宇宙突然因灾难性事件而崩溃的概率还小,但这正是你不想处理重复 IPv6 地址而错过所有乐趣的时候。
-
最后,设备将其获取的本地地址发送给路由器(与 IPv4 不同,IPv6 路由器总是可以通过多播组地址 ff02::2 访问),并通过发送 RS(路由器请求)ICMPv6 数据包请求路由器使用的实际前缀。在路由器用 RA(路由器通告)数据包响应后,它用路由器回复的实际前缀替换 fe80,并开始将其作为永久地址使用。这就是你的 IPv6 互联网地址。
无状态配置的优势在于减少了路由器的开销:它不必单独维护网络上每个设备的 IP 配置。这意味着在更大的网络中可以获得更好的性能。
IPv6 的误区
IPv6 也伴随着一些大胆的说法。让我们来揭穿它们:
你的设备有一个用于所有用途的 IPv6 地址
我的意思是,是的,你可以使用相同的 IPv6 地址进行本地和远程连接。但并不是“一个 IP 地址统治所有,一个 IP 地址找到它们”的说法是真的。如前所述,你的设备会为不同的范围声明多个 IPv6 地址,例如链路本地(记得 fe80::)和互联网。此外,你的设备还可能获取两个不同的互联网 IPv6 地址:永久和临时的。临时 IPv6 地址旨在保护你的隐私,因为它们会定期轮换。永久 IPv6 地址主要用于必须具有静态 IPv6 地址的服务器。
每个宇宙中的原子都有一个 IP 地址
远不及此。宇宙中大约有 2²⁷² 个原子。即使是地球也有 2¹⁶⁶ 个原子,所以我们至少需要 168 位(八位字节对齐)的地址空间来容纳它们。实际的 IPv6 地址空间也略小于 128 位:前 16 位是 IANA 保留的。你只有剩下的 112 位来识别设备。这仍然很多,远远超过我们在未来千年内在地球上能生产的所有设备,但不,我们不能给每个原子一个 IP 地址。但是,我们可以给地球上的每一粒沙子分配 IPv6 地址。我们甚至可以把它们都放在一个 /64 前缀内。
总的来说,是的,无论我们能用它来寻址多少任意粒子,IPv6 地址空间都是巨大的。
每个设备的通用连接性
是的,IPv6 没有 NAT。因此,不再需要端口转发或维护地址空间。但如果你想建立与远程主机的直接连接,仍然需要一种机制来开放设备的连接。请记住,默认情况下,你的路由器/防火墙会阻止任何连接尝试。那么你该怎么办呢?
就像在 UPnP/IGD 时代一样,如今的应用程序仍然需要使用类似 PCP(端口控制协议)这样的协议来以编程方式打开对端口的访问。因此,并不是说你突然拥有了具有全球+本地 IPv6 地址的通用连接性。你不必手动设置端口转发,但应用程序仍需要与路由器协作才能使自己可访问。
不仅仅是 IPv6 的好处被夸大了,还有一些情况下,IPv6 反而比 IPv4 更糟糕:
IPv6 的不足之处
在 IPv4 世界中,有一些我们认为理所当然的事情,但在 IPv6 中可能会让你怀念,比如:
你要完全听凭你的 ISP 分配子网
由于 IPv6 没有 NAT,美国许多 ISP 默认只向你的路由器转发一个单一的 64 位前缀(通常称为“/64”)。这意味着你的路由器没有空间将子网信息放入 IPv6 地址中。请记住:IPv6 地址由设备自动配置,因此,路由器无法强制这些设备使用少于 64 位的本地地址。这意味着,你的路由器将无法知道要将数据包转发到哪个子网。
实际上,你得听从 ISP 的安排,以获得比 64 位短的前缀,这样你的路由器才能使用剩余的位来识别它们需要转到哪个子网。 ISP 实际上可以通过简单分配 60 位前缀给家庭用户,至少给他们提供 16 个子网,但我不知道为什么他们不这么做。也许是 IPv4 地址空间短缺给他们留下了创伤后应激障碍?或者,他们只是想通过勒索客户来赚钱。“嘿,如果你想要更短的前缀,就多付钱给我们”。据我所知,Comcast Xfinity 和 AT&T 给他们的家庭用户提供的仅仅是一个简单的 /64 前缀:一个子网。
你可能会说,家庭用户根本不需要子网,但是,随着物联网设备的普及和我们对网络安全的更大依赖,隔离你不信任的设备变得更加重要。RIPE,欧洲 IP 地址分配的权威机构,建议家庭 ISP 客户使用 56 位前缀。这为每个客户提供了 256 个子网,这是欧洲人能想到的最贪婪、最保守的选项,而对于美国人来说,这只能是一个梦想。
IPv6 地址在 URI 中需要额外编码
还记得在浏览器中输入“http://192.168.0.1
”并访问你的路由器设置吗?我记得。因为在 URI 规范中,“:”字符被保留用于端口号,所以如果不进行额外编码,使用 IPv6 地址做同样的事情是不可能的。如果你想通过 IPv6 地址访问托管在设备上的网页,你必须使用这种语法:“http://[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]/path/?query
”,注意地址周围的方括号。但这甚至不是最糟糕的部分,因为:
当然,你可以手动配置每个设备的 IPv6 地址,并以这种方式为它们提供子网标识符,但这将是一项巨大的工程,特别是考虑到添加新设备的开销。你想把你的退休生活当成一个人类 DHCP 服务器吗?
无法记忆 IPv6 地址
我们本来就不应该记住 IP 地址,但现实是不同的。我仍然不确定在 IPv6 上可靠和一致地访问路由器时应该使用哪个地址。我肯定记不住它的完整 IP 地址。mDNS 能有所帮助,但它也并不总是可靠地工作。
十六进制比普通数字更难记。这就像试图记住 Windows XP 产品激活码一样。那个著名的是什么来着?FCKGW-RHQQ2-??嗯,随便了。
记住一个 IPv4 地址是一种可转移的技能;如果你愿意,可以称之为“跨平台”。由于普遍存在的 NAT,它甚至是普遍适用的:大多数时候是 192.168.1.1。我不必查找那个。在任意设备上找出你的路由器的 IPv6 地址需要不同的技能。
好的一面是,你现在知道 IPv6 地址的右边 64 位部分总是随机的,所以,你至少可以避免假设它会永远保持不变或者应该有意义。你甚至可以称这部分为 BLABLA 而不是 INTERFACE_ID。你可以记住你的 /64 前缀,至少可以找到你的路由器地址,通常是类似于 1111:2222:3333:4444::1 的东西。
IPv6 地址很复杂
不要误会,IPv4 地址也很复杂。你知道 2130706433 是一个有效的 IPv4 地址吗?或者,0x7F000001、0177.0000.0000.0001 和 127.1 也是。如果你不相信,尝试在 shell 中对它们进行 ping 测试。很难相信,但它们都等同于 127.0.0.1。
IPv6 地址在表示上具有类似的多样性。以下是它们的一些特点:
- IPv6 地址的表示由 8 个十六进制组成:称为段的十六位十六进制组。(“Hextet” 是 hexadectet 的错误称呼,但现在为时已晚。)无论如何,现在可以使用如下十六进制技巧:
-
十六进制分节中的前导零不显示。因此,2600:00ab 实际上显示为 2600:ab。
-
正如我之前提到的,值为零的十六进制分节可以完全从地址中移除,并用双冒号替换。因此,2600:ab:0:0:1234:5678:90ab:cdef 将显示为 2600:ab::1234:5678:90ab:cdef。看到双冒号了吗?然而,这只能在前一批零值十六进制分节上执行。因此,2600:ab:0:0:1234:0:0:cdef 仍然会呈现为 2600:ab::1234:0:0:cdef。此外,你不能压缩单个零值十六进制分节。因此,在 2600:0:1234:5678:abcd:ef01:2345:6789 中,0 仍然保持不变。
-
你可以指定区域标识符:通过“%”后缀和区域标识符来达到希望通过该网络接口到达该地址的目的。例如,你可以同时通过 WiFi 和以太网连接到网络,但可能想从局域网 ping 你的路由器。在这种情况下,你将“%”附加到地址并添加你的区域标识符(网络适配器标识符)。例如 fe80::1%eth0 或 fe80::1%3。问题在于,除了 IPv6 URI 中需要使用的括号外,你还必须在浏览器地址栏或其他需要在 URI 中使用区域标识符的地方将“%”转义为“%25”。
-
Pv6 地址还可以用于表示 IPv4 地址。因此,你可以使用 IPv6 地址语法 ping 127.0.0.1,方法是在其前面添加 IPv4 转换前缀,它将被视为 IPv4 地址:::ffff:127.0.0.1。但是,这并不意味着你的 IPv4 请求将通过 IPv6 网络进行。这只是告诉底层网络堆栈使用 IPv4 连接而已。如果你选择的前缀不是 ::ffff,IPv4 部分将成为最后两个十六进制分节的一部分,并且你将通过 IPv6 网络连接该 IP。例如,2600:1000:2000:3000::192.168.1.1 将被视为 2600:1000:2000:3000::c0a8:101,其中最后两个十六进制分节是 192.168.1.1 的十六进制等价形式。
这些都是有效的 IPv6 地址:
-
:: 这是所有零值的表示,即0:0:0:0:0:0:0:0。
-
2600:: 这相当于 2600:0:0:0:0:0:0:0。
-
::ffff:1.1.1.1 是等效于 1.1.1.1 的 IPv4 地址。
-
2607:f8b0:4005:80f::200e 是当我 ping google.com 时获得的地址。你知道这个流程;这相当于 2607:f8b0:4005:80f:0:0:0:200e。正如你所见,就像 Facebook 一样,Google 也选择了艰难的道路,决定为其 IPv6 地址手动指定 INTERFACE_ID。祝一切顺利。
最后,你在地址栏中写的 IPv6 地址可能像这样,作为一个人为的例子:
https://[542b:b2ae:ed5c:cb5a:e38b:2c49:123:192.168.1.1%25eth3]
我绝对不可能记住这个。
说了这些,我喜欢学习 IPv6!这次学习经历为我澄清了一些事情。例如,我不知道 IPv6 地址是通过无状态协议自动配置的。我不知道它没有 NAT。我不知道地址空间被方便地一分为二。
我希望我们有一个默认网关的快捷 IPv6 地址。我提议 fe80::1。IETF,请注意! :)
我记得 Windows 2000 中的 IPv6 支持是一个重要的进步,当时宣布时,我们都以为 IPv6 会在十年左右被广泛采用。我们可能错得更多吗?然而,了解它让我明白了为什么它没有迅速普及。
IPv6 对终端用户没有任何好处
尽管 IPv6 在技术上很先进,IPv4 仍然可用。即使在 NAT 背后,即使在多层 NAT 背后,即使在极其狭窄的地址空间、繁琐的 DHCP 和端口转发的情况下,它仍然可用。它一直在工作。当人们找到一种它不起作用的方式,而且永远不会起作用时,总会有人想出方法使其起作用。
IPv6 没有 NAT 可能会有一些延迟优势,但这对用户体验来说不足以产生影响。
因为 IPv6 没有提供任何实质性的好处,用户永远不会要求它,他们只会在不知不觉中被推向它,就像我们现在几乎总是在蜂窝网络上使用 IPv6 一样。
这意味着,当 ISP 因 IPv4 的限制感到足够的压力时,他们会立即转换到 IPv6。毫无疑问。
我希望 IPv6 能够启用一些功能,使一些在 IPv4 下不可能实现的特定场景成为可能,这样人们就可以要求使用 IPv6。然而,我喜欢 IPv6 网络的外星般特性,并期待着我们完全放弃 IPv4 并完全围绕 IPv6 构建一切的时刻的到来。