在最初学习计算机网络的时候,我首先学习了IPv4编址方式,紧接着学习了子网,CIDR,路由聚合,IP地址获取与NAT。但在思考和与朋友讨论的过程中,我发现我混淆了一些概念。因此我做了一些调查,在这篇笔记中按顺序梳理这几个概念,这个顺序也是互联网IP协议发展所采取的顺序。
路由器和网关
首先我们明确,这些设备全部都是用来调控网络流量的。那么,简单一点来说:
路由器在相同的网络中转发数据。路由器本身将会存储一个查找表。对于接受的数据包,路由器检查数据包内的数据是发给谁的,根据自己的查找表传递给下一台路由器/主机。网络中的数据包就是这样,经过多次跳跃,从一个主机到达另一个主机的。
网关在不同的网络中传递数据。如果两个网络使用了不同的网络协议,那么我们就需要网关为我们做协议转换。最常见的就是我们接下来要讲的NAT。
路由器和网关是可以重叠的。一个设备,可以既做数据包在同协议网络间的转发,又为网络间通信转换网络协议,此时他就是一个路由器和一个网关。
除此之外,还有一些互联网设备的概念,诸如交换机,接入点(AP),调制解调器(MODEM)等,因为对于理解本篇文章不重要,就不展开讲了。
子网与子网掩码
教科书上说,网络被分配到的一个IP地址由网络地址和子网掩码组成。IP地址由四段八比特二进制数组成,也可以写成点分的十进位形式。而子网掩码,其高比特位标志了该子网的地址,而低比特位标志了主机在子网中的地址。IP地址后用一个斜杠加一个数字,表示其前多少位是网络地址。我们举个例子。
1 | 十进制网络地址 192.168.1.100/24 |
IPv4协议是在1982年提出的,最开始的32位IPv4只用前8位确定网络地址,即主机连接到哪个网络,以及剩下的部分作为主机地址。这样的分类方式不能允许太多的独立网络。
为什么需要区分一个网络地址和一个主机地址?我的理解是,这实际上是为了控制网络的边界,方便管理与路由器寻址。假设不区分子网,那么路由器需要维护的查找表将会非常庞大,需要将IP地址的每一位都记录下来,并且计算保存最近距离的路由器。如果区分了子网,那么路由器只需要存储以哪些字段开头的数据发给某个路由器即可。
而伴随其提出的是如何为子网划分地址的模式。最开始,人们选择了比较简单的分级式寻址。网络被分为ABCDE五个类,不同的类使用他们的前三位来识别:
- A类地址,第一位是0,使用前8位作为网络位,剩下的作为主机位,A类地址可以构建出 128 个网络,每个网络容纳 16,777,214 个主机。
- B类地址,前两位是10,使用前16位作为网络位,剩下的作为主机位,B类地址可以构建出 16,384 个网络,每个网络容纳 65,534 个主机。
- C类地址,前三位是110,使用前24位作为网络位,剩下的作为主机位,B类地址可以构建出 2,097,152 个网络,每个网络容纳 254 个主机。
- D类群播地址,前四位是1110;和E类保留地址,前四位是1111。
实际上,这种分类模式就没有必要说明子网掩码,因为你总是可以从前n位推断出其子网掩码应该是多少。这种分类模式现在已经被废止,因为其立刻展现出了问题:对于一个小型网,C类地址的主机容量太小,B类地址又太大。
无类别区域间路由(CIDR)和路由聚合
为了解决刚刚提到的问题,我们使用CIDR。原理很简单,我们将IP地址重新设定为 a.b.c.d/x
,x代表了IP地址的网络号,可以为任意值。这样我们就可以在灵活分配子网大小的同时,简化我们路由保存的转发表。
在实践中,我们就得到了路由聚合的概念。我们的路由器只需要保存开头x位的某个IP地址应当转发给哪个子网,而不需要关心子网内数据包是如何传递的。可能在子网内存在其他子网,但是发包的路由器并不关心。这种情况我们就称作路由聚合。
顺便一提,某些IP地址是协议规定的保留地址。比如127.0.0.1 (01111111 00000000 00000000 00000001) 是环回地址,也就是当前所在的主机,也叫做 localhost
,实际上环回地址有 1,600,000 以上个,从127.0.0.1到127.255.255.255均为环回地址。
255.255.255.255是广播地址,向广播地址交付报文会让该报文被发送到该子网内的每个主机。当然,这是路由器的转发表保存的数据决定的,路由器在收到目的地是255.255.255.255地址的数据包之后,它会向它子网内的所有主机发该数据包。
IP地址获取
我们已经做好了如何给IP地址分类,接下来简单讲一下IP地址是如何获取的。最简单的是由你的互联网服务提供商(ISP)提供,ISP自己有一个地址段,而后他可以将地址段划分为子网并交付给用户。如下例子(尖括号的部分是主机号,而中括号的部分是子组织相较于ISP地址增加的网络号):
1 | ISP得到的地址 200.23.16.0/20 11001000 00010111 0001<0000 00000000> |
那么ISP的地址从哪儿来?答案是因特网名字和编号分配机构(ICANN)。ICANN是非营利组织,其不仅分配IP地址,也管理DNS根服务器,分配域名。
当然,还有一种方法,通常用于比较小的子网,就是动态主机配置协议(DHCP)。主机每次连接到配置了DHCP的网络,都会获得一个临时的IP地址。除此之外,主机还可以得到当前子网的子网掩码,第一跳路由地址(我们现在一般叫做默认网关),本地DNS服务器地址。现在打开你的手机,进入网络设置并查看连接的无线局域网信息,你就可以看到这些内容。连接学校的局域网,学校也会提前告知你要使用DHCP。
网络地址转换(NAT)
需要意识到的是,以上我们所有的工作都不过是在给我们的 4,294,967,296 个IP地址做分类,这也是我错误思想的来源。
子网并不代表整个网络中的某两台主机可以分配相同的IP地址。想象一个身份证号或者手机号,其内容是不能重复的,对其不同段做分类只是为了方便罢了。即使是划分了子网,不同子网间的IP地址也必须是不同的。这实际上很好理解,如果他们相同,那路由算法将会被破坏。路由器不知道应该向谁发包,或者总有一个主机收不到包,因为路由表在较短的网络号处截断并转发(想象路由器发送所有212.144.*.*到路由器A,路由器A是212.144.1.1/12,而路由器B是212.144.1.1/16)。
为了解决IP枯竭问题,人们从1993年开始使用了NAT技术,并通过RFC 1918协议定义了一部分IP地址使其专门用于NAT网络内部地址分配。这样的网络叫做专用网或者私有网。以下是RFC 1918规定的IP块:
1 | 规定区块名 IP地址区块 IP数量 |
专用网通过网关来完成地址转换。我们现在自己使用的,提供无线局域网连接服务的路由器都做了NAT地址转换,因此提供WiFi的路由器也就是该私有网的网关。拿我自己的路由器为例,在私有网,其IP地址是192.168.1.1,访问该地址也会进入路由器的管理界面。我的所有设备的网关都是192.168.1.1,每个设备通过DHCP获得自己在私有网络的地址,将数据包交给网关做转发。而查看路由器自己的设置,可以看到路由器在外部网络的地址是172.26.55.113,也是通过DHCP获得IP地址。根据RFC 1918,这个地址仍然是一个私有地址。实际上,这是大学校园私有网络的地址。并且,路由器的网关是172.26.0.1,这就是大学校园私有网络的流量出口。在此处,校园网私网地址被翻译成更高一级的公网地址进行通信。
私有网络必须要有不同于公网的IP,因为如果出现了公网IP,那么当一个主机要发给此IP时,网关的路由就不确定这个数据包到底是要给私网内的主机,还是转发出去。
那么,通信是如何完成的?以网络地址端口转换(NAPT)为例,假设现在的网络是我的路由器创建的私有网,从我的手机(192.168.1.101)发送的数据,到达网关(192.168.1.1)后,网关会将其转为(172.26.55.113:Port),再发往下一级路由。这样一层一层包裹,数据包能够最终到达公网。同样的,接收的数据会被网关根据端口号一层一层地解开,到学校局域网的一层时,学校网关(172.26.0.1)将会收到一个发往172.26.55.113:Port的包,那么学校网关将会把包路由到172.26.55.113,我的路由器则会根据Port将数据包路由回我的手机。
当然,如果私网内的某个IP用了两个端口,那么网关也会为其映射两个到外部的端口,以便进行通信。
NAT的好处在于,私网内的用户非常安全。如果不主动发送信息,那么公网将无法与其进行通信。而坏处是,NAT下的主机实际上没有真正的IP地址,不能参与某些网络协议,比如某些必须从外部建立的UDP协议。举例来说,任天堂说我的NAT类型是D不让我玩联机游戏。
结论
子网和私网不是一个概念。不过,路由器创建的网络仍然可以被称作一个子网,只不过这个子网并不属于一个大的互联网。如果要谈论获取公网IP,实际上我们谈论的是一个跳出NAT的过程。比较常用的是端口映射,也就是说我将私网内的IP固定映射到网关的公网地址的某个端口上去,这样其他用户就可以通过访问网关公网IP:Port
来进行通信。当然,这样的方法似乎只能跳出一层NAT。