大师兄

08 | 局域网:NAT 是如何工作的?

广域网是由很多的局域网组成的,比如公司网络、家庭网络、校园网络等。之前我们一直在讨论广域网的设计,今天我们到微观层面,看看局域网是如何工作的。

IPv4 的地址不够,因此需要设计子网。当一个公司申请得到一个公网 IP 后,会在自己的公司内部设计一个局域网。这个局域网所有设备的 IP 地址,通常会以 192.168 开头。这个时候,假设你的职工小明,上班时间玩王者荣耀。当他用 UDP 协议向王者荣耀的服务器发送信息时,消息的源 IP 地址是一个内网 IP 地址,而王者荣耀的服务,是一个外网 IP 地址。

这里我先向你提一个问题,数据到王者荣耀服务器可以通过寻址和路由找到目的地,但是数据从王者荣耀服务器回来的时候,王者荣耀服务器如何知道192.168开头的地址应该如何寻址呢?

要想回答这个问题,就涉及网络地址转换协议(NAT 协议)。下面请你带着这个问题,开启今天的学习吧。

内部网络和外部网络

对一个组织、机构、家庭来说,我们通常把内部网络称为局域网,外部网络就叫作外网。下图是一个公司多个部门的网络架构。

图片11.png

我们会看到外网通过路由器接入整个公司的局域网,和路由器关联的是三台交换机,代表公司的三个部门。交换机,或者称为链路层交换机,通常工作在链路层;而路由器通常也具有交换机的能力,工作在网络层和链路层。关于它们的详细区别,我们会在本文的后续讨论。

光纤是一种透明的导光介质,多束光可以在一个介质中并行传播,不仅信号容量大,重量轻,并行度高而且传播距离远。当然,光纤不能弯曲,因此办公室里用来连接交换机和个人电脑的线路肯定不能是光纤,光线通常都用于主干网络

局域网数据交换(MAC 地址)

接下来我们讨论下同一个局域网中的设备如何交换消息。

首先,我们先明确一个概念,设备间通信的本质其实是设备拥有的网络接口(网卡)间的通信。为了区别每个网络接口,互联网工程任务组(IETF)要求每个设备拥有一个唯一的编号,这个就是 MAC 地址

你可能会问:IP 地址不也是唯一的吗?其实不然,一旦设备更换位置,比如你把你的电脑从北京邮寄的广州,那么 IP 地址就变了,而电脑网卡的 MAC 地址不会发生变化。总的来说,IP 地址更像现实生活中的地址,而 MAC 地址更像你的身份证号。

然后,我们再明确另一个基本的概念。在一个局域网中,我们不可以将消息从一个接口(网卡)发送到另一个接口(网卡),而是要通过交换机。为什么是这样呢?因为两个网卡间没有线啊!所以数据交换,必须经过交换机,毕竟线路都是由网卡连接交换机的。

图片2.png

总结下,数据的发送方,将自己的 MAC 地址、目的地 MAC 地址,以及数据作为一个分组(Packet),也称作 Frame 或者封包,发送给交换机。交换机再根据目的地 MAC 地址,将数据转发到目的地的网络接口(网卡)。

最后一个问题,你可能问,这个分组或者 Frame,是不是 IP 协议的分组呢?——不是,这里提到的是链路层的数据交换,它支持 IP 协议工作,是网络层的底层。所以,如果 IP 协议要传输数据,就要将数据转换成为链路层的分组,然后才可以在链路层传输

链路层分组大小受限于链路层的网络设备、线路以及使用了链路层协议的设计。你有时候可能会看到 MTU 这个缩写词,它指的是 Maximun Transmission Unit,最大传输单元,意思是链路层网络允许的最大传输数据分组的大小。因此 IP 协议要根据 MTU 拆分封包

之前在“04 | TCP 的稳定性:滑动窗口和流速控制是怎么回事?”介绍 TCP 协议滑动窗口的时候,还提到过一个词,叫作 MSS,这里我们复习下。MSS(Maximun Segment Size,最大段大小)是 TCP 段,或者称为 TCP 分组(TCP Packet)的最大大小。MSS 是传输层概念,MTU 是链路层概念

聪明的同学可以能会意识到,这不就是下面这样一个数学关系吗?

MTU = MSS + TCP Header + IP Header

这个思路有一定道理,但是不对。先说说这个思路怎么来的,你可能会这么思考:TCP 传输数据大于 MSS,就拆包。每个封包加上 TCP Header ,之后经过 IP 协议,再加上 IP Header。于是这个加上 IP 头的分组(Packet)不能超过 MTU。固然这个思路很有道理,可惜是错的。因为 TCP 解决的是广域网的问题,MTU 是一个链路层的概念,要知道不同网络 MTU 是不同的,所以二者不可能产生关联。这也是为什么 IP 协议还可能会再拆包的原因

地址解析协议(ARP)

上面我们讨论了 MAC 地址,链路层通过 MAC 地址定位网络接口(网卡)。在一个网络接口向另一个网络接口发送数据的时候,至少要提供这样 3 个字段:

  1. 源 MAC 地址

  2. 目标 MAC 地址

  3. 数据

这里我们一起再来思考一个问题,对于一个网络接口,它如何能知道目标接口的 MAC 地址呢?我们在使用传输层协议的时候,清楚地知道目的地的 IP 地址,但是我们不知道 MAC 地址。这个时候,就需要一个中间服务帮助根据 IP 地址找到 MAC 地址——这就是地址解析协议(Address Resolution Protocol,ARP)。

整个工作过程和 DNS 非常类似,如果一个网络接口已经知道目标 IP 地址对应的 MAC 地址了,它会将数据直接发送给交换机,交换机将数据转发给目的地,这个过程如下图所示:

图片3.png

已知目的地 MAC 可以直接发送

那么如果网络接口不知道目的地地址呢?这个时候,地址解析协议就开始工作了。发送接口会发送一个广播查询给到交换机,交换机将查询转发给所有接口。

图片4.png

如果某个接口发现自己就是对方要查询的接口,则会将自己的 MAC 地址回传。接下来,会在交换机和发送接口的 ARP 表中,增加一个缓存条目。也就是说,接下来发送接口再次向 IP 地址 2.2.2.2 发送数据时,不需要再广播一次查询了。

图片5.png

前面提到这个过程和 DNS 非常相似,采用的是逐级缓存的设计减少 ARP 请求。发送接口先查询本地的 ARP 表,如果本地没有数据,然后广播 ARP 查询。这个时候如果交换机中有数据,那么查询交换机的 ARP 表;如果交换机中没有数据,才去广播消息给其他接口。注意,ARP 表是一种缓存,也要考虑缓存的设计。通常缓存的设计要考虑缓存的失效时间、更新策略、数据结构等。

比如可以考虑用 TTL(Time To Live)的设计,为每个缓存条目增加一个失效时间。另外,更新策略可以考虑利用老化(Aging)算法模拟 LRU。

最后请你思考路由器和交换机的异同点。不知道你有没有在网上订购过家用无线路由器,通常这种家用设备也会提供局域网,具备交换机的能力。同时,这种设备又具有路由器的能力。所以,很多同学可能会分不清路由器和交换机。

总的来说,家用的路由器,也具备交换机的功能。但是当 ARP 表很大的时候,就需要专门的、能够承载大量网络接口的交换设备。就好比,如果用数组实现 ARP 表,数据量小的时候,遍历即可;但如果数据量大的话,就需要设计更高效的查询结构和设计缓存。

详细的缓存设计原理的介绍,可以参考《重学操作系统》专栏中关于 CPU 缓存的设计,以及 MMU 中 TLB 的设计的内容,分别在以下 3 讲:

连接内网

有时候,公司内部有多个子网。这个时候一个子网如果要访问另一个子网,就需要通过路由器。

图片66.png

也就是说,图中的路由器,其实充当了两个子网通信的桥梁。在上述过程中,发送接口不能直接通过 MAC 地址发送数据到接收接口,因为子网 1 的交换机不知道子网 2 的接口。这个时候,发送接口需要通过 IP 协议,将数据发送到路由器,再由路由器转发信息到子网 2 的交换机。这里提一个问题,子网 2 的交换机如何根据 IP 地址找到接收接口呢?答案是通过查询 ARP 表。

连接外网(网络地址转换技术,NAT)

最后我们讨论下连接外网的问题。

IPv4 协议因为存在网络地址耗尽的问题,不能为一个公司提供足够的地址,因此内网 IP 可能会和外网重复。比如内网 IP 地址192.168.0.1发送信息给22.22.22.22,这个时候,其实是跨着网络的。

图片6.png

跨网络必然会通过多次路由,最终将消息转发到目的地。但是这里存在一个问题,寻找的目标 IP 地址22.22.22.22是一个公网 IP,可以通过正常的寻址 + 路由算法定位。当22.22.22.22寻找192.168.0.1的时候,是寻找一个私网 IP,这个时候是找不到的。解决方案就是网络地址转换技术(Network Address Translation)。

图片7.png

NAT 技术转换的是 IP 地址,私有 IP 通过 NAT 转换为公网 IP 发送到服务器。服务器的响应,通过 NAT 转换为私有 IP,返回给客户端。通过这种方式,就解决了内网和外网的通信问题。

总结

总结一下,链路层发送数据靠的是 MAC 地址,MAC 地址就好像人的身份证一样。局域网中,数据不可能从一个终端直达另一个终端,而是必须经过交换机交换。交换机也叫作链路层交换机,它的工作就是不断接收数据,然后转发数据。通常意义上,交换机不具有路由功能,路由器往往具有交换功能。但是往往路由器交换的效率,不如交换机。已知 IP 地址,找到 MAC 地址的协议,叫作地址解析协议(ARP)。

网络和网络的衔接,必须有路由器(或者等价的设备)。一个网络的设备不能直接发送链路层分组给另一个网络的设备,而是需要通过 IP 协议让路由器转发。

那么,通过这一讲的学习,你可以来回答本讲关联的面试题目:网络地址转换协议是如何工作的?

解析】网络地址解析协议(NAT)解决的是内外网通信的问题。NAT 通常发生在内网和外网衔接的路由器中,由路由器中的 NAT 模块提供网络地址转换能力。从设计上看,NAT 最核心的能力,就是能够将内网中某个 IP 地址映射到外网 IP,然后再把数据发送给外网的服务器。当服务器返回数据的时候,NAT 又能够准确地判断外网服务器的数据返回给哪个内网 IP。

你可以思考下 NAT 是如何做到这点的呢?需要做两件事。

  1. NAT 需要作为一个中间层替换 IP 地址。 发送的时候,NAT 替换源 IP 地址(也就是将内网 IP 替换为出口 IP);接收的时候,NAT 替换目标 IP 地址(也就是将出口 IP 替换回内网 IP 地址)。

  2. NAT 需要缓存内网 IP 地址和出口 IP 地址 + 端口的对应关系。也就是说,发送的时候,NAT 要为每个替换的内网 IP 地址分配不同的端口,确保出口 IP 地址+ 端口的唯一性,这样当服务器返回数据的时候,就可以根据出口 IP 地址 + 端口找到内网 IP。

思考题

最后再给你提一道需要查资料的思考题:IPv6 协议还需要 NAT 吗?

我建议你拿出几分钟的时间去查一下资料,然后把答案整理在留言区,我们一起讨论。如果你对本次课程有什么建议和疑问,可以在评论区留言。如果你有所收获,也可以推荐给你的朋友。

这一讲就到这里。发现求知的乐趣,我是林䭽。感谢你学习本次课程,下一讲我们将学习“09 | TCP 实战:如何进行 TCP 抓包调试?”再见!