用快乐的方法搞定子网掩码和 IPv6 前缀

文章通过生动的故事和简单易懂的语言,解释了子网掩码和 IPv6 前缀的概念。通过类比家庭成员的名字,作者清晰地说明了 IPv4 和 IPv6 地址的区别,以及子网掩码如何帮助区分网络中的不同设备。文章还介绍了如何通过简单的计算方法快速理解子网掩码和 IPv6 前缀,避免了复杂的位运算。

其实在很久以前就有接触过子网掩码,但一直不太理解它具体的使用场景。这段时间闲鱼了一台 j4125 的四口软路由,花了两天时间折腾后,竟然意外地理解了子网掩码和 IPv6 前缀……

其实他们的概念并不算难,但网上的介绍文章大多都是繁杂的概念和计算,让人捉摸不透。在这片文章中,我将用最清晰易懂的语言和示例,带你理解子网掩码和 IPv6 前缀。

IPv4 和 IPv6 的区别

IPv4 地址通常表示为 4 个 8 位 2 进制数,也就是 4x8=32 位,比如 192.168.1.1,每个数字范围是 0 到 255(分别对应 00000000 和 11111111)。IPv6 地址更长,通常表示为 8 组 16 位 2 进制数(或 8 组 4 位 16 进制数,一回事),比如 2001:0db8:85a3:0000:0000:8a2e:0370:7334,看起来更复杂。

有些初学者难以理解为什么 IPv6 是 128 位的,他们会疑惑,每一位有 16 种状态,那么总共的位数不是 16 * 32= 512 位吗?

高手先不要笑话,真的有不少初学者有这样的疑惑。事实上应该把每个:之间的数字拆出来看,例如,4 位 16 进制数 2001。我们将其转换为 2 进制数,也就是 0010 0000 0000 0001,一共是 16 位,这样的 4 位 16 进制数一共有 8 组,因此一共是 16 * 8 = 128 位。

IPv4 和 IPv6 最大的区别就是地址空间不同,IPv4 一共只有 4 亿个,而 IPv6 是用之不竭的(理论上能用完,但实际很难,后面会再提到相关内容)。

从给孩子起名字说起

IP 地址是网络上设备的一个寻址符,因此,我们先讲公网 IP 可以看成是你在身份证上的名字,私网 IP 则是家里面爸妈叫你的小名。

假设你的爸爸叫毛利小五郎,让我们带入他。

在社会上(假设这个社会上每个人姓名不同,且都为 5 字名字),别人叫毛利小五郎,你都会答应,但有一天,你发现,有好几个人一起应答了这个名字。你们几个人都愣住了。

不是说好的不能重名吗?政府怎么登记的?你们去质问有关部门人员,但工作人员很委屈,他说,你们名字确实不一样啊。

你开始了自我介绍:我姓毛利,名叫小五郎

毛利小五郎 B:我姓毛,名叫利小五郎

毛利小五郎 C:我姓毛利小,名叫五郎

毛利小五郎 D:我姓毛利小五,名叫郎

毛利小五郎 E:我就叫毛利小五郎,没有名

原来是这样,难怪大家叫一样的名字。你们一合计,那我们就在名字后面加一个标识符,把姓的字数标记一下,这样的话,即使重名,大家也可以分出来了。政府一听,好主意,当即就给你们改了身份证。于是你们几个的名字变成了:

原先名字 现在名字
毛利小五郎 (A) 毛利小五郎/2
毛利小五郎 (B) 毛利小五郎/1
毛利小五郎 (C) 毛利小五郎/3
毛利小五郎 (D) 毛利小五郎/4
毛利小五郎 (E) 毛利小五郎/5

现在你们都清楚自己姓甚名谁了,以后大家都能分清了。、

这时,你们用奇怪的眼光看着 毛利小五郎/5,问到:“兄弟,你没有名,那你儿子不是起不了名字吗?毕竟这个世界不允许重复姓名。”

毛利小五郎/5 说:“我是女人,孩子不和我姓”。

IPv4 地址生娃

上面这个故事引出了今天的主题之一,子网掩码。

不过在 IPv4 世界里,每个单位的名字有 32 位,且每一位只能是 0 和 1。

子网掩码就标识出了这个 IP 地址中,哪一段是爸爸,哪一段是儿子。

回到刚刚的故事,毛利小五郎/2 想要给生一个孩子,在当前社会规则要求下,你最多能生几个呢?

首先,孩子也得姓毛利,这是不变的,所以儿子的名字只能在后面三个字里面选,常用的汉字有 6000 个,因此你最多生下 6000^3 个孩子。再多生的话,政府就没办法帮你上户口了,你只能另想办法(也就是 NAT)。

而毛利小五郎/1 就爽了,他能比你多生 6000 倍的孩子,可以生 6000 ^ 4 个,最惨的是毛利小五郎/5,他已经失去了生孩子的权利。

类比到 IPv4 地址,假设子网掩码为 x,那这个地址的姓就是 x 位,他最多能有 2^(32-x) 个儿子,也就是名称"子网"的来历。

举个例子,对于 IPv4 地址:10.0.0.9/8,则开头的 10.是爸爸,后面的 24 位都是儿子的名字空间,也就是说他可以生 2^24 个儿子,也就是地址 10.0.0.0~10.255.255.255。

由于点分十进制的特殊性,8、16、24、32 是比较重要的子网掩码,因为他们刚好分隔开了每个点号。。利用这一特性,我们可以快速计算子网。记住以下两个特性:

  • 子网掩码加 1,儿子减半
  • 子网掩码 -1,儿子加倍

例子:给定 IP 地址 10.67.55.134/10,计算其所属网段。

首先找到 8,16,24,32 中最接近 22 的数,显然是 8。先找到 10.0.0.x/8 的网段,为 10.0.0.0~10.255.255.255,将子网掩码 +1,10.0.0.x/9 可以划分为 2 组:

  • 10.0.0.0~10.127.255.255
  • 10.128.0.0~10.255.255.255

再 +1,10.0.0.x/10 可以划分为 4 组

  • 10.0.0.0~10.63.255.255
  • 10.64.0.0~10.127.255.255
  • 10.128.0.0~10.191.255.255
  • 10.192.0.0~10.255.255.255

此时可以发现,10.67.55.134/10 属于第二个网段。

用计算器验算以下,正确,计算器去除了网络地址和广播地址:

例 2:给定 IP 地址 10.67.55.134/22,计算其所属网段。

首先找到 8,16,24,32 中最接近 22 的数,显然是 24。因此,首先计算 10.67.55.x/24 的网段

  • 10.67.55.0~10.67.55.255

然后,将子网掩码 -1,计算 10.67.55.x/23 的网段,由前文可知“子网掩码 -1,儿子加倍”,但这里的儿子显然不够用,因此需要向前一位去借,得到一个网段:

  • 10.67.54.0~10.67.55.255

这里需要注意,掩码 -1,是在扩容儿子的容量,网段的数量是不变的。那么问题来了,我怎么知道是向 54 借还是 56 借呢?

这里我们要理解,子网范围的分组,都是等分进行的,因此,在 0-255 的范围内,分一次(掩码 +1)必然是 0-127,,18-255,分 2 次(掩码 +2)必然是 0-63, 64-127, 128-191, 192-255,……,分 7 次(掩码 +7),也就是 0-1,2-3,4-5……,254-255,最多分八次(掩码加 8),也就是每个数单独为一组(这时候就要考虑到后面的范围了)。

所以,向前借还是向后借,只要对号入座就可以了。示例中对应的是分 7 次的情况,该条件下,0,2,4……,通项为

$a(n)=2n$

因此显然是 54-55。

这一块可能比较难理解,但学会之后计算很快,不用再去搞位运算了。

然后,我们再减少一次掩码,计算 10.67.55.x/23 的网段,这时对应的是分 6 次的情况,也就是 0-3, 4-7, 8-11,……,252-255。

显然 0,4,8 的通项为

$a(n)=4n$

最接近的是 4*13=52,因此 10.67.55.x/23 的网段为

  • 10.67.52.0~10.67.55.255

这也就是题目中 10.67.55.134/22 所属的网段,因为掩码 -1 属于扩充,因此扩充出的网段内一定是包含原 IP 的。就不用像 +1 那样子去匹配网段了。从示例也可以看出,扩充算法相比分组要难一些,但原理是一样的。

用计算器验算一下:

用这样的计算方法,我们完全规避了位运算,而是用简单的基本运算来实现计算,勤加练习的话,很快就可以掌握。

例 3:苹果手机热点默认分配的子网掩码为 255.255.255.240,问最多可以有多少个设备可以连接该手机?

这里涉及到了子网掩码的点分十进制表示,直接转换为 11111111.11111111.11111111.11110000,数 1 就行了,这里有 28 个,因此子网掩码十进制表示为 28。

也可以用数学公式计算

$N_0=32-(log_2(256-Z_1)+log_2(256-Z_2)+log_2(256-Z_3)+log_2(256-Z_4))$

例中,

$N_0=32-(log_2(256-255)+log_2(256-255)+log_2(256-255)+log_2(256-240)) =32-0-0-0-4 =28 $

可用设备为 $2^4-2=14$ 个,可见苹果真的抠搜。

IPv6 前缀简介

IPv6 前缀相比子网掩码就简单多了,首先理解 IPv6 的构成。

128 位的地址被分为了三个部分,站点前缀、子网 ID、接口。其中,站点前缀和子网 ID 加起来是 64 位。而接口则是用来标识设备的。

也就是说,在一个子网中,可以接入 2^64 个设备,已经远远超过了 IPv4 的总和(白花花的 IP 地址给穷人)。

并且子网 ID 不是必须的,事实上,在家用宽带中,往往给的前缀都是 64 位的,直接让你划不了子网(不过我家给的 56 位前缀,真神了)。

IPv6 前缀的灵活性非常高,对于两个相同的 IPv6 地址,前缀不同的话,他们寻址到的设备是不一样的。

例子:2001:0db8:85a3:0000:0000:8a2e:0370:7334/64 和 2001:0db8:85a3:0000:0000:8a2e:0370:7334/56 代表的设备是同一个吗?

在 IPv6 中,前缀后面的数字表示网络部分的位数。不同的前缀长度意味着不同的网络范围和不同的地址分配。

2001:0db8:85a3:0000:0000:8a2e:0370:7334/64 这个地址的前 64 位是网络部分,剩下的 64 位是主机部分。这意味着这个地址属于一个/64 的子网,这个子网内可以有 2^64 个可能的地址。

2001:0db8:85a3:0000:0000:8a2e:0370:7334/56 这个地址的前 56 位是网络部分,剩下的 72 位是主机部分。这意味着这个地址属于一个/56 的子网,这个子网内可以有 2^72 个可能的地址。

标黑的部分就是两个地址各自的前缀。

由于两个地址的网络部分不同(一个是前 64 位,另一个是前 56 位),它们属于不同的网络。即使具体的地址(接口标识符)相同,它们也被视为属于不同的网络,因此代表不同的设备或接口。

通俗来讲,他们虽然名字一样,但他们的爸爸是不一样的,也就类似于毛利小五郎/2,毛利小五郎/4 不是同一个人一样。

基于 IPv6 这一特性,实现去 NAT 化是完全可以的,并且对子网和网络地址的计算量也会远小于 IPv4,因此,早日拥抱 IPv6 吧。

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计